From f9a2738d573ac29fa2d28ccf544965aad4a56553 Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Mon, 24 Jul 2017 22:15:30 +0300 Subject: [PATCH 001/139] Set version 7.0.0-alpha1 in the master branch (#4739) --- dev-tools/packer/version.yml | 2 +- libbeat/version/version.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev-tools/packer/version.yml b/dev-tools/packer/version.yml index a61305e07fa..5d5f902f661 100644 --- a/dev-tools/packer/version.yml +++ b/dev-tools/packer/version.yml @@ -1 +1 @@ -version: "6.0.0-beta1" +version: "7.0.0-alpha1" diff --git a/libbeat/version/version.go b/libbeat/version/version.go index 5aac8b75c35..395518b4f29 100644 --- a/libbeat/version/version.go +++ b/libbeat/version/version.go @@ -1,3 +1,3 @@ package version -const defaultBeatVersion = "6.0.0-beta1" +const defaultBeatVersion = "7.0.0-alpha1" From c0af60c0fb39eae3d90f2ff9403a967d572046af Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Mon, 24 Jul 2017 22:31:47 +0300 Subject: [PATCH 002/139] Set docs version in the master branch (#4741) --- libbeat/docs/version.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libbeat/docs/version.asciidoc b/libbeat/docs/version.asciidoc index ace56d23556..f3372a2a699 100644 --- a/libbeat/docs/version.asciidoc +++ b/libbeat/docs/version.asciidoc @@ -1,7 +1,7 @@ -:stack-version: 6.0.0-alpha2 +:stack-version: 7.0.0-alpha1 :doc-branch: master :go-version: 1.8.3 -:release-state: prerelease +:release-state: unreleased :python: 2.7.9 :docker: 1.12 :docker-compose: 1.11 From 52850a1f4b69b76a65d01d9e681f16e557a291c3 Mon Sep 17 00:00:00 2001 From: DeDe Morton Date: Tue, 25 Jul 2017 12:32:34 -0700 Subject: [PATCH 003/139] Restructure beats config options (#4716) * Restructure Filebeat and Libbeat config options * Restructure Heartbeat config options * Restructure Packetbeat config options * Experiment: show packetbeat.reference.yml in the docs * Restructure Winlogbeat config options * Restructure Metricbeat config options * Restructure Auditbeat config options * Add reference configs to the docs * Move include statement for general options for consistency --- .../docs/auditbeat-general-options.asciidoc | 7 + .../docs/auditbeat-modules-config.asciidoc | 2 +- auditbeat/docs/configuring-howto.asciidoc | 44 +- auditbeat/docs/configuring-logstash.asciidoc | 5 - auditbeat/docs/getting-started.asciidoc | 4 +- auditbeat/docs/index.asciidoc | 13 - auditbeat/docs/reload-configuration.asciidoc | 2 +- filebeat/docs/command-line.asciidoc | 2 +- filebeat/docs/configuring-howto.asciidoc | 67 ++- filebeat/docs/faq.asciidoc | 2 +- filebeat/docs/filebeat-filtering.asciidoc | 12 +- .../docs/filebeat-general-options.asciidoc | 121 +++++ .../docs/filebeat-modules-options.asciidoc | 65 +++ .../filebeat-options.asciidoc | 308 ++++------- filebeat/docs/getting-started.asciidoc | 15 +- filebeat/docs/how-filebeat-works.asciidoc | 10 +- filebeat/docs/index.asciidoc | 19 - filebeat/docs/load-balancing.asciidoc | 2 +- filebeat/docs/migration.asciidoc | 40 +- .../docs/module-development-guide.asciidoc | 2 +- .../docs/modules-getting-started.asciidoc | 34 +- filebeat/docs/modules-overview.asciidoc | 1 + filebeat/docs/multiline.asciidoc | 100 +++- filebeat/docs/multiple-prospectors.asciidoc | 2 +- filebeat/docs/overview.asciidoc | 6 +- .../docs/reference/configuration.asciidoc | 36 -- .../reload-configuration.asciidoc | 5 +- filebeat/docs/securing-filebeat.asciidoc | 6 +- filebeat/docs/troubleshooting.asciidoc | 4 +- heartbeat/docs/command-line.asciidoc | 2 +- heartbeat/docs/configuring-howto.asciidoc | 44 +- heartbeat/docs/configuring-logstash.asciidoc | 5 - heartbeat/docs/faq.asciidoc | 2 +- heartbeat/docs/getting-started.asciidoc | 17 +- heartbeat/docs/heartbeat-devguide.asciidoc | 4 +- heartbeat/docs/heartbeat-filtering.asciidoc | 2 +- .../docs/heartbeat-general-options.asciidoc | 8 + .../heartbeat-options.asciidoc | 115 +++-- heartbeat/docs/how-heartbeat-works.asciidoc | 6 +- heartbeat/docs/index.asciidoc | 16 - heartbeat/docs/overview.asciidoc | 12 +- .../docs/reference/configuration.asciidoc | 34 -- heartbeat/docs/securing-heartbeat.asciidoc | 6 +- heartbeat/docs/troubleshooting.asciidoc | 4 +- libbeat/docs/breaking.asciidoc | 14 +- libbeat/docs/communitybeats.asciidoc | 2 +- libbeat/docs/config-file-format.asciidoc | 14 +- libbeat/docs/dashboards.asciidoc | 2 +- libbeat/docs/dashboardsconfig.asciidoc | 28 +- libbeat/docs/generalconfig.asciidoc | 34 +- libbeat/docs/gettingstarted.asciidoc | 18 +- libbeat/docs/installing-beats.asciidoc | 2 +- libbeat/docs/loggingconfig.asciidoc | 47 +- libbeat/docs/outputconfig.asciidoc | 311 ++++++----- libbeat/docs/overview.asciidoc | 4 + libbeat/docs/processors-config.asciidoc | 23 - libbeat/docs/processors-using.asciidoc | 38 +- libbeat/docs/reference-yml.asciidoc | 31 ++ libbeat/docs/regexp.asciidoc | 2 +- libbeat/docs/shared-config-ingest.asciidoc | 6 +- libbeat/docs/shared-directory-layout.asciidoc | 2 +- libbeat/docs/shared-docker.asciidoc | 6 +- libbeat/docs/shared-env-vars.asciidoc | 4 +- libbeat/docs/shared-logstash-config.asciidoc | 14 +- libbeat/docs/shared-path-config.asciidoc | 19 +- .../docs/shared-ssl-logstash-config.asciidoc | 4 +- libbeat/docs/shared-template-load.asciidoc | 4 +- libbeat/docs/template-config.asciidoc | 16 +- libbeat/docs/upgrading.asciidoc | 14 +- libbeat/docs/visualizing-data.asciidoc | 4 +- libbeat/docs/yaml.asciidoc | 14 +- metricbeat/docs/command-line.asciidoc | 2 +- metricbeat/docs/configuring-howto.asciidoc | 133 ++--- metricbeat/docs/configuring-logstash.asciidoc | 5 - metricbeat/docs/faq.asciidoc | 3 +- metricbeat/docs/fields.asciidoc | 46 +- metricbeat/docs/gettingstarted.asciidoc | 18 +- metricbeat/docs/how-metricbeat-works.asciidoc | 16 +- metricbeat/docs/index.asciidoc | 15 - metricbeat/docs/metricbeat-filtering.asciidoc | 2 +- .../docs/metricbeat-general-options.asciidoc | 34 ++ metricbeat/docs/metricbeat-options.asciidoc | 139 +++++ metricbeat/docs/modules/aerospike.asciidoc | 8 +- metricbeat/docs/modules/apache.asciidoc | 4 +- metricbeat/docs/modules/ceph.asciidoc | 10 +- metricbeat/docs/modules/couchbase.asciidoc | 4 +- metricbeat/docs/modules/docker.asciidoc | 8 +- metricbeat/docs/modules/dropwizard.asciidoc | 6 +- .../docs/modules/elasticsearch.asciidoc | 8 +- metricbeat/docs/modules/golang.asciidoc | 10 +- metricbeat/docs/modules/haproxy.asciidoc | 4 +- metricbeat/docs/modules/http.asciidoc | 4 +- metricbeat/docs/modules/jolokia.asciidoc | 6 +- metricbeat/docs/modules/kafka.asciidoc | 8 +- metricbeat/docs/modules/kibana.asciidoc | 8 +- metricbeat/docs/modules/kubernetes.asciidoc | 6 +- metricbeat/docs/modules/memcached.asciidoc | 8 +- metricbeat/docs/modules/mongodb.asciidoc | 6 +- metricbeat/docs/modules/mysql.asciidoc | 6 +- metricbeat/docs/modules/nginx.asciidoc | 4 +- metricbeat/docs/modules/php_fpm.asciidoc | 15 +- metricbeat/docs/modules/postgresql.asciidoc | 4 +- metricbeat/docs/modules/prometheus.asciidoc | 4 +- metricbeat/docs/modules/rabbitmq.asciidoc | 8 +- metricbeat/docs/modules/redis.asciidoc | 6 +- metricbeat/docs/modules/system.asciidoc | 9 +- metricbeat/docs/modules/vsphere.asciidoc | 8 +- metricbeat/docs/modules/windows.asciidoc | 4 +- metricbeat/docs/modules/zookeeper.asciidoc | 4 +- metricbeat/docs/modules_list.asciidoc | 22 +- metricbeat/docs/overview.asciidoc | 10 +- .../docs/reference/configuration.asciidoc | 29 -- .../configuration/metricbeat-options.asciidoc | 100 ---- .../reload-configuration.asciidoc | 15 +- metricbeat/docs/running-on-docker.asciidoc | 4 +- metricbeat/docs/securing-metricbeat.asciidoc | 4 +- metricbeat/docs/troubleshooting.asciidoc | 4 +- metricbeat/metricbeat.reference.yml | 22 +- .../module/aerospike/_meta/docs.asciidoc | 4 +- metricbeat/module/aerospike/_meta/fields.yml | 4 +- .../aerospike/namespace/_meta/docs.asciidoc | 4 +- metricbeat/module/apache/_meta/docs.asciidoc | 2 +- .../module/apache/status/_meta/docs.asciidoc | 2 +- metricbeat/module/ceph/_meta/docs.asciidoc | 6 +- metricbeat/module/ceph/_meta/fields.yml | 4 +- .../ceph/cluster_disk/_meta/docs.asciidoc | 4 +- .../ceph/cluster_health/_meta/docs.asciidoc | 4 +- .../ceph/monitor_health/_meta/docs.asciidoc | 4 +- .../module/ceph/pool_disk/_meta/docs.asciidoc | 4 +- .../module/couchbase/_meta/docs.asciidoc | 2 +- .../couchbase/bucket/_meta/docs.asciidoc | 2 +- .../couchbase/cluster/_meta/docs.asciidoc | 2 +- .../module/couchbase/node/_meta/docs.asciidoc | 2 +- metricbeat/module/docker/_meta/docs.asciidoc | 6 +- .../docker/container/_meta/docs.asciidoc | 2 +- .../module/docker/cpu/_meta/docs.asciidoc | 2 +- .../module/docker/diskio/_meta/docs.asciidoc | 4 +- .../docker/healthcheck/_meta/docs.asciidoc | 2 +- .../module/docker/image/_meta/docs.asciidoc | 4 +- .../module/docker/info/_meta/docs.asciidoc | 4 +- .../module/docker/memory/_meta/docs.asciidoc | 4 +- .../module/docker/network/_meta/docs.asciidoc | 4 +- .../module/dropwizard/_meta/docs.asciidoc | 4 +- .../dropwizard/collector/_meta/docs.asciidoc | 4 +- .../module/elasticsearch/_meta/docs.asciidoc | 4 +- .../module/elasticsearch/_meta/fields.yml | 4 +- .../elasticsearch/node/_meta/docs.asciidoc | 4 +- .../node_stats/_meta/docs.asciidoc | 6 +- metricbeat/module/golang/_meta/docs.asciidoc | 5 +- metricbeat/module/golang/_meta/fields.yml | 4 +- .../module/golang/expvar/_meta/docs.asciidoc | 6 +- .../module/golang/heap/_meta/docs.asciidoc | 5 +- metricbeat/module/haproxy/_meta/docs.asciidoc | 2 +- .../module/haproxy/info/_meta/docs.asciidoc | 4 +- .../module/haproxy/stat/_meta/docs.asciidoc | 2 +- metricbeat/module/http/_meta/docs.asciidoc | 2 +- metricbeat/module/http/_meta/fields.yml | 2 +- .../module/http/json/_meta/docs.asciidoc | 4 +- metricbeat/module/jolokia/_meta/docs.asciidoc | 4 +- metricbeat/module/jolokia/_meta/fields.yml | 2 +- .../module/jolokia/jmx/_meta/docs.asciidoc | 6 +- metricbeat/module/kafka/_meta/docs.asciidoc | 4 +- metricbeat/module/kafka/_meta/fields.yml | 4 +- .../kafka/consumergroup/_meta/docs.asciidoc | 4 +- .../kafka/partition/_meta/docs.asciidoc | 4 +- metricbeat/module/kibana/_meta/docs.asciidoc | 4 +- metricbeat/module/kibana/_meta/fields.yml | 4 +- .../module/kibana/status/_meta/docs.asciidoc | 8 +- .../module/kubernetes/_meta/docs.asciidoc | 2 +- metricbeat/module/kubernetes/_meta/fields.yml | 4 +- .../kubernetes/container/_meta/docs.asciidoc | 4 +- .../kubernetes/event/_meta/docs.asciidoc | 4 +- .../kubernetes/node/_meta/docs.asciidoc | 4 +- .../module/kubernetes/pod/_meta/docs.asciidoc | 4 +- .../state_container/_meta/docs.asciidoc | 4 +- .../state_deployment/_meta/docs.asciidoc | 4 +- .../kubernetes/state_node/_meta/docs.asciidoc | 4 +- .../kubernetes/state_pod/_meta/docs.asciidoc | 4 +- .../state_replicaset/_meta/docs.asciidoc | 4 +- .../kubernetes/system/_meta/docs.asciidoc | 4 +- .../kubernetes/volume/_meta/docs.asciidoc | 4 +- .../module/memcached/_meta/docs.asciidoc | 4 +- metricbeat/module/memcached/_meta/fields.yml | 4 +- .../memcached/stats/_meta/docs.asciidoc | 4 +- metricbeat/module/mongodb/_meta/docs.asciidoc | 4 +- .../mongodb/dbstats/_meta/docs.asciidoc | 4 +- .../module/mongodb/status/_meta/docs.asciidoc | 2 +- metricbeat/module/mysql/_meta/docs.asciidoc | 4 +- .../module/mysql/status/_meta/docs.asciidoc | 2 +- metricbeat/module/nginx/_meta/docs.asciidoc | 2 +- .../nginx/stubstatus/_meta/docs.asciidoc | 2 +- metricbeat/module/php_fpm/_meta/docs.asciidoc | 11 +- metricbeat/module/php_fpm/_meta/fields.yml | 2 +- .../module/php_fpm/pool/_meta/docs.asciidoc | 4 +- .../module/postgresql/_meta/docs.asciidoc | 2 +- .../postgresql/activity/_meta/docs.asciidoc | 4 +- .../postgresql/bgwriter/_meta/docs.asciidoc | 4 +- .../postgresql/database/_meta/docs.asciidoc | 4 +- .../module/prometheus/_meta/docs.asciidoc | 2 +- .../prometheus/collector/_meta/docs.asciidoc | 2 +- .../prometheus/stats/_meta/docs.asciidoc | 2 +- .../module/rabbitmq/_meta/docs.asciidoc | 4 +- metricbeat/module/rabbitmq/_meta/fields.yml | 4 +- .../module/rabbitmq/node/_meta/docs.asciidoc | 4 +- metricbeat/module/redis/_meta/docs.asciidoc | 4 +- .../module/redis/info/_meta/docs.asciidoc | 2 +- .../module/redis/keyspace/_meta/docs.asciidoc | 2 +- metricbeat/module/system/_meta/docs.asciidoc | 7 +- .../module/system/core/_meta/docs.asciidoc | 2 +- .../module/system/cpu/_meta/docs.asciidoc | 2 +- .../module/system/diskio/_meta/docs.asciidoc | 2 +- .../system/filesystem/_meta/docs.asciidoc | 2 +- .../module/system/fsstat/_meta/docs.asciidoc | 2 +- .../module/system/load/_meta/docs.asciidoc | 2 +- .../module/system/memory/_meta/docs.asciidoc | 2 +- .../module/system/network/_meta/docs.asciidoc | 2 +- .../module/system/process/_meta/docs.asciidoc | 8 +- .../process_summary/_meta/docs.asciidoc | 6 +- .../module/system/socket/_meta/docs.asciidoc | 2 +- metricbeat/module/vsphere/_meta/docs.asciidoc | 4 +- metricbeat/module/vsphere/_meta/fields.yml | 4 +- .../vsphere/datastore/_meta/docs.asciidoc | 4 +- .../module/vsphere/host/_meta/docs.asciidoc | 4 +- .../virtualmachine/_meta/docs.asciidoc | 4 +- metricbeat/module/windows/_meta/docs.asciidoc | 2 +- .../windows/perfmon/_meta/docs.asciidoc | 4 +- .../module/zookeeper/_meta/docs.asciidoc | 2 +- .../module/zookeeper/mntr/_meta/docs.asciidoc | 2 +- metricbeat/scripts/docs_collector.py | 2 +- packetbeat/docs/capturing.asciidoc | 52 -- packetbeat/docs/command-line.asciidoc | 6 +- packetbeat/docs/configuring-howto.asciidoc | 64 ++- packetbeat/docs/configuring-logstash.asciidoc | 5 - packetbeat/docs/faq.asciidoc | 2 +- packetbeat/docs/filtering.asciidoc | 16 +- packetbeat/docs/flows.asciidoc | 80 --- packetbeat/docs/gettingstarted.asciidoc | 19 +- packetbeat/docs/index.asciidoc | 23 - packetbeat/docs/overview.asciidoc | 16 +- packetbeat/docs/packetbeat-filtering.asciidoc | 2 +- .../docs/packetbeat-general-options.asciidoc | 8 + packetbeat/docs/packetbeat-geoip.asciidoc | 18 +- .../packetbeat-options.asciidoc | 486 ++++++++++++++---- .../docs/packetbeat-reference-yml.asciidoc | 11 + .../docs/reference/configuration.asciidoc | 33 -- .../configuration => }/runconfig.asciidoc | 6 +- packetbeat/docs/running-on-docker.asciidoc | 4 +- packetbeat/docs/securing-packetbeat.asciidoc | 4 +- packetbeat/docs/thrift.asciidoc | 67 --- packetbeat/docs/troubleshooting.asciidoc | 6 +- .../docs/visualizing-data-packetbeat.asciidoc | 6 +- winlogbeat/docs/command-line.asciidoc | 2 +- winlogbeat/docs/configuring-howto.asciidoc | 43 +- winlogbeat/docs/faq.asciidoc | 2 +- winlogbeat/docs/getting-started.asciidoc | 16 +- winlogbeat/docs/index.asciidoc | 11 - winlogbeat/docs/overview.asciidoc | 6 +- .../docs/reference/configuration.asciidoc | 34 -- winlogbeat/docs/securing-winlogbeat.asciidoc | 4 +- winlogbeat/docs/troubleshooting.asciidoc | 4 +- winlogbeat/docs/winlogbeat-filtering.asciidoc | 2 +- .../docs/winlogbeat-general-options.asciidoc | 7 + .../winlogbeat-options.asciidoc | 57 +- 263 files changed, 2239 insertions(+), 1974 deletions(-) create mode 100644 auditbeat/docs/auditbeat-general-options.asciidoc delete mode 100644 auditbeat/docs/configuring-logstash.asciidoc create mode 100644 filebeat/docs/filebeat-general-options.asciidoc create mode 100644 filebeat/docs/filebeat-modules-options.asciidoc rename filebeat/docs/{reference/configuration => }/filebeat-options.asciidoc (69%) delete mode 100644 filebeat/docs/reference/configuration.asciidoc rename filebeat/docs/{reference/configuration => }/reload-configuration.asciidoc (93%) delete mode 100644 heartbeat/docs/configuring-logstash.asciidoc create mode 100644 heartbeat/docs/heartbeat-general-options.asciidoc rename heartbeat/docs/{reference/configuration => }/heartbeat-options.asciidoc (92%) delete mode 100644 heartbeat/docs/reference/configuration.asciidoc delete mode 100644 libbeat/docs/processors-config.asciidoc create mode 100644 libbeat/docs/reference-yml.asciidoc delete mode 100644 metricbeat/docs/configuring-logstash.asciidoc create mode 100644 metricbeat/docs/metricbeat-general-options.asciidoc create mode 100644 metricbeat/docs/metricbeat-options.asciidoc delete mode 100644 metricbeat/docs/reference/configuration.asciidoc delete mode 100644 metricbeat/docs/reference/configuration/metricbeat-options.asciidoc rename metricbeat/docs/{reference/configuration => }/reload-configuration.asciidoc (84%) delete mode 100644 packetbeat/docs/capturing.asciidoc delete mode 100644 packetbeat/docs/configuring-logstash.asciidoc delete mode 100644 packetbeat/docs/flows.asciidoc create mode 100644 packetbeat/docs/packetbeat-general-options.asciidoc rename packetbeat/docs/{reference/configuration => }/packetbeat-options.asciidoc (69%) create mode 100644 packetbeat/docs/packetbeat-reference-yml.asciidoc delete mode 100644 packetbeat/docs/reference/configuration.asciidoc rename packetbeat/docs/{reference/configuration => }/runconfig.asciidoc (87%) delete mode 100644 packetbeat/docs/thrift.asciidoc delete mode 100644 winlogbeat/docs/reference/configuration.asciidoc create mode 100644 winlogbeat/docs/winlogbeat-general-options.asciidoc rename winlogbeat/docs/{reference/configuration => }/winlogbeat-options.asciidoc (94%) diff --git a/auditbeat/docs/auditbeat-general-options.asciidoc b/auditbeat/docs/auditbeat-general-options.asciidoc new file mode 100644 index 00000000000..8183ec5405e --- /dev/null +++ b/auditbeat/docs/auditbeat-general-options.asciidoc @@ -0,0 +1,7 @@ +[[configuration-general-options]] +== Specify general settings + +You can specify settings in the +{beatname_lc}.yml+ config file to control the +general behavior of {beatname_uc}. + +include::../../libbeat/docs/generalconfig.asciidoc[] diff --git a/auditbeat/docs/auditbeat-modules-config.asciidoc b/auditbeat/docs/auditbeat-modules-config.asciidoc index 12fbe3e72ac..cdec30f6114 100644 --- a/auditbeat/docs/auditbeat-modules-config.asciidoc +++ b/auditbeat/docs/auditbeat-modules-config.asciidoc @@ -1,5 +1,5 @@ [id="configuration-{beatname_lc}"] -=== Specify which modules to run +== Specify which modules to run To enable specific modules and metricsets, you add entries to the `auditbeat.modules` list in the +{beatname_lc}.yml+ config file. Each entry in diff --git a/auditbeat/docs/configuring-howto.asciidoc b/auditbeat/docs/configuring-howto.asciidoc index 381b7ef1fdf..cdda8c0e21b 100644 --- a/auditbeat/docs/configuring-howto.asciidoc +++ b/auditbeat/docs/configuring-howto.asciidoc @@ -20,22 +20,15 @@ _Beats Platform Reference_ for more about the structure of the config file. The following topics describe how to configure {beatname_uc}: * <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> +* <> +* <<{beatname_lc}-configuration-reloading>> +* <> +* <> +* <> * <> * <> +* <> * <> -* <> -* <> -* <> -* <> * <> * <> @@ -44,26 +37,31 @@ pick up the changes. -- -[[configuration-container]] -== Configuration Options - -This section describes configuration options. - -//REVIEWERS: THIS CONTAINER IS A TEMPORARY PLACEHOLDER SO I CAN GET THE AUDITBEAT DOCS BUILDING WITHOUT ERRORS. I PLAN TO REMOVE THIS CONTAINER AND POP EVERYTHING UP A LEVEL IN THE HIERARCHY TO CREATE A STRUCTURE SIMILAR TO THE ONE DESCRIBED IN THIS FILEBEAT ISSUE: https://github.com/elastic/beats/issues/4422 - include::./auditbeat-modules-config.asciidoc[] -include::../../libbeat/docs/generalconfig.asciidoc[] +include::./auditbeat-general-options.asciidoc[] -include::../../libbeat/docs/processors-config.asciidoc[] +include::./reload-configuration.asciidoc[] +:allplatforms: include::../../libbeat/docs/outputconfig.asciidoc[] +include::./auditbeat-filtering.asciidoc[] + +include::../../libbeat/docs/shared-config-ingest.asciidoc[] + include::../../libbeat/docs/shared-path-config.asciidoc[] include::../../libbeat/docs/setup-config.asciidoc[] include::../../libbeat/docs/loggingconfig.asciidoc[] -include::./reload-configuration.asciidoc[] +:standalone: +include::../../libbeat/docs/shared-env-vars.asciidoc[] + +:standalone: +:allplatforms: +include::../../libbeat/docs/yaml.asciidoc[] + +include::../../libbeat/docs/reference-yml.asciidoc[] diff --git a/auditbeat/docs/configuring-logstash.asciidoc b/auditbeat/docs/configuring-logstash.asciidoc deleted file mode 100644 index c8e5f9f336e..00000000000 --- a/auditbeat/docs/configuring-logstash.asciidoc +++ /dev/null @@ -1,5 +0,0 @@ -[id="config-{beatname_lc}-logstash"] -== Configuring {beatname_uc} to use Logstash - -:allplatforms: -include::../../libbeat/docs/shared-logstash-config.asciidoc[] diff --git a/auditbeat/docs/getting-started.asciidoc b/auditbeat/docs/getting-started.asciidoc index f861d77c34a..72ec51d8906 100644 --- a/auditbeat/docs/getting-started.asciidoc +++ b/auditbeat/docs/getting-started.asciidoc @@ -176,8 +176,8 @@ output.elasticsearch: hosts: ["192.168.1.42:9200"] ---------------------------------------------------------------------- + -If you are sending output to Logstash, see <> -instead. +If you are sending output to Logstash, see +<> instead. . If you plan to use the sample Kibana dashboards provided with {beatname_uc}, configure the Kibana endpoint: diff --git a/auditbeat/docs/index.asciidoc b/auditbeat/docs/index.asciidoc index 649701e059d..a1dc9e14dc5 100644 --- a/auditbeat/docs/index.asciidoc +++ b/auditbeat/docs/index.asciidoc @@ -33,19 +33,6 @@ include::../../libbeat/docs/repositories.asciidoc[] include::./configuring-howto.asciidoc[] -include::./auditbeat-filtering.asciidoc[] - -include::../../libbeat/docs/shared-config-ingest.asciidoc[] - -include::./configuring-logstash.asciidoc[] - -:standalone: -include::../../libbeat/docs/shared-env-vars.asciidoc[] - -:standalone: -:allplatforms: -include::../../libbeat/docs/yaml.asciidoc[] - include::./modules.asciidoc[] include::./fields.asciidoc[] diff --git a/auditbeat/docs/reload-configuration.asciidoc b/auditbeat/docs/reload-configuration.asciidoc index b0e346b91f2..ae3dd8b2cbd 100644 --- a/auditbeat/docs/reload-configuration.asciidoc +++ b/auditbeat/docs/reload-configuration.asciidoc @@ -1,5 +1,5 @@ [id="{beatname_lc}-configuration-reloading"] -=== Reload the configuration dynamically +== Reload the configuration dynamically beta[] diff --git a/filebeat/docs/command-line.asciidoc b/filebeat/docs/command-line.asciidoc index 60eabbbca35..8582ec8a806 100644 --- a/filebeat/docs/command-line.asciidoc +++ b/filebeat/docs/command-line.asciidoc @@ -1,5 +1,5 @@ [[command-line-options]] -=== Command Line Options +=== Command line options The following command line option is specific to Filebeat. diff --git a/filebeat/docs/configuring-howto.asciidoc b/filebeat/docs/configuring-howto.asciidoc index 29f8f3be464..ffb77b715a0 100644 --- a/filebeat/docs/configuring-howto.asciidoc +++ b/filebeat/docs/configuring-howto.asciidoc @@ -3,30 +3,73 @@ [partintro] -- -After following the <> in the -Getting Started, you might want to fine tune the behavior of Filebeat. This section -describes some common use cases for changing configuration options. +Before modifying configuration settings, make sure you've completed the +<> in the Getting Started. +This section describes some common use cases for changing configuration options. -To configure {beatname_uc}, you edit the configuration file. For rpm and deb, you’ll find the default configuration file at -+/etc/{beatname_lc}/{beatname_lc}.yml+. There's also a full example configuration file at -+/etc/{beatname_lc}/{beatname_lc}.reference.yml+ that shows all non-deprecated options. For mac and win, look in the archive that you extracted. +To configure {beatname_uc}, you edit the configuration file. For rpm and deb, +you’ll find the configuration file at +/etc/{beatname_lc}/{beatname_lc}.yml+. +There's also a full example configuration file at ++/etc/{beatname_lc}/{beatname_lc}.reference.yml+ that shows all non-deprecated +options. For mac and win, look in the archive that you extracted. -See the -{libbeat}/config-file-format.html[Config File Format] section of the +The {beatname_uc} configuration file uses http://yaml.org/[YAML] for its syntax. +See the {libbeat}/config-file-format.html[Config File Format] section of the _Beats Platform Reference_ for more about the structure of the config file. The following topics describe how to configure Filebeat: -* <> -* <> +* <> * <> +* <> +* <> +* <> +* <> * <> +* <> +* <> +* <> +* <> * <> -* <> * <> * <> * <> -- -include::reference/configuration.asciidoc[] +include::./filebeat-options.asciidoc[] + +include::./multiple-prospectors.asciidoc[] + +include::./multiline.asciidoc[] + +include::./filebeat-general-options.asciidoc[] + +include::./reload-configuration.asciidoc[] + +:allplatforms: +include::../../libbeat/docs/outputconfig.asciidoc[] + +include::./load-balancing.asciidoc[] + +include::./filebeat-filtering.asciidoc[] + +include::../../libbeat/docs/shared-config-ingest.asciidoc[] + +include::../../libbeat/docs/shared-path-config.asciidoc[] + +include::../../libbeat/docs/setup-config.asciidoc[] + +include::../../libbeat/docs/loggingconfig.asciidoc[] + +:standalone: +include::../../libbeat/docs/shared-env-vars.asciidoc[] + +:standalone: +:allplatforms: +include::../../libbeat/docs/yaml.asciidoc[] + +include::../../libbeat/docs/regexp.asciidoc[] + +include::../../libbeat/docs/reference-yml.asciidoc[] + diff --git a/filebeat/docs/faq.asciidoc b/filebeat/docs/faq.asciidoc index 5878fb54465..778e00d8b48 100644 --- a/filebeat/docs/faq.asciidoc +++ b/filebeat/docs/faq.asciidoc @@ -1,5 +1,5 @@ [[faq]] -== Frequently Asked Questions +== Frequently asked questions This section contains frequently asked questions about Filebeat. Also check out the https://discuss.elastic.co/c/beats/filebeat[Filebeat discussion forum]. diff --git a/filebeat/docs/filebeat-filtering.asciidoc b/filebeat/docs/filebeat-filtering.asciidoc index 00c34594829..f2d1250f7fa 100644 --- a/filebeat/docs/filebeat-filtering.asciidoc +++ b/filebeat/docs/filebeat-filtering.asciidoc @@ -1,5 +1,5 @@ [[filtering-and-enhancing-data]] -== Filtering and Enhancing the Exported Data +== Filter and enhance the exported data Your use case might require only a subset of the data exported by Filebeat, or you might need to enhance the exported data (for example, by adding metadata). @@ -11,9 +11,9 @@ This allows you to specify different filtering criteria for each prospector. To do this, you use the <>, <>, and <> options under the `filebeat.prospectors` section of the config file (see -<>). The -disadvantage of this approach is that you need to implement a configuration -option for each filtering criteria that you need. +<>). The disadvantage of this approach is that +you need to implement a configuration option for each filtering criteria that +you need. Another approach (the one described here) is to define processors to configure global processing across all data exported by Filebeat. @@ -27,7 +27,7 @@ include::../../libbeat/docs/processors.asciidoc[] [float] [[drop-event-example]] -==== Drop Event Example +==== Drop event example The following configuration drops all the DEBUG messages. @@ -53,7 +53,7 @@ processors: [float] [[decode-json-example]] -==== Decode JSON Example +==== Decode JSON example In the following example, the fields exported by Filebeat include a field, `inner`, whose value is a JSON object encoded as a string: diff --git a/filebeat/docs/filebeat-general-options.asciidoc b/filebeat/docs/filebeat-general-options.asciidoc new file mode 100644 index 00000000000..704c85e589c --- /dev/null +++ b/filebeat/docs/filebeat-general-options.asciidoc @@ -0,0 +1,121 @@ +[[configuration-general-options]] +== Specify general settings + +You can specify settings in the +{beatname_lc}.yml+ config file to control the +general behavior of {beatname_uc}. This includes: + +* <> that control things like +publisher behavior and the location of some files. + +* <> that are supported by all Elastic +Beats. + +[float] +[[configuration-global-options]] +=== Global Filebeat configuration options + +These options are in the `filebeat` namespace. + +[float] +==== `spool_size` + +The event count spool threshold. This setting forces a network flush if the number of events in the spooler exceeds +the specified value. + +[source,yaml] +------------------------------------------------------------------------------------- +filebeat.spool_size: 2048 +------------------------------------------------------------------------------------- + +See <> for more information about how this setting affects load balancing. + +[float] +==== `publish_async` + +experimental[] +deprecated[5.3.0] + +If enabled, the publisher pipeline in Filebeat operates in async mode preparing +a new batch of lines while waiting for ACK. This option can improve load-balancing +throughput at the cost of increased memory usage. The default value is false. + +See <> for more information about how this setting affects load balancing. + +[float] +==== `idle_timeout` + +A duration string that specifies how often the spooler is flushed. After the +`idle_timeout` is reached, the spooler is flushed even if the `spool_size` has not been reached. + +[source,yaml] +------------------------------------------------------------------------------------- +filebeat.idle_timeout: 5s +------------------------------------------------------------------------------------- + + +[float] +==== `registry_file` + +The name of the registry file. If a relative path is used, it is considered relative to the +data path. See the <> section for details. The default is `${path.data}/registry`. + +[source,yaml] +------------------------------------------------------------------------------------- +filebeat.registry_file: registry +------------------------------------------------------------------------------------- + +It is not possible to use a symlink as registry file. + +NOTE: The registry file is only updated when new events are flushed and not on a predefined period. +That means in case there are some states where the TTL expired, these are only removed when new event are processed. + + +[float] +==== `config_dir` + +The full path to the directory that contains additional prospector configuration files. +Each configuration file must end with `.yml`. Each config file must also specify the full Filebeat +config hierarchy even though only the prospector part of the file is processed. All global +options, such as `spool_size`, are ignored. + +The `config_dir` option MUST point to a directory other than the directory where the main Filebeat config file resides. + +If the specified path is not absolute, it is considered relative to the configuration path. See the +<> section for details. + +[source,yaml] +------------------------------------------------------------------------------------- +filebeat.config_dir: path/to/configs +------------------------------------------------------------------------------------- + +[float] +[[shutdown-timeout]] +==== `shutdown_timeout` + +How long Filebeat waits on shutdown for the publisher to finish sending events +before Filebeat shuts down. + +By default, this option is disabled, and Filebeat does not wait for the +publisher to finish sending events before shutting down. This means that any +events sent to the output, but not acknowledged before Filebeat shuts down, +are sent again when you restart Filebeat. For more details about how this +works, see <>. + +You can configure the `shutdown_timeout` option to specify the maximum amount +of time that Filebeat waits for the publisher to finish sending events before +shutting down. If all events are acknowledged before `shutdown_timeout` is +reached, Filebeat will shut down. + +There is no recommended setting for this option because determining the correct +value for `shutdown_timeout` depends heavily on the environment in which +Filebeat is running and the current state of the output. + +Example configuration: + +[source,yaml] +------------------------------------------------------------------------------------- +filebeat.shutdown_timeout: 5s +------------------------------------------------------------------------------------- + +include::../../libbeat/docs/generalconfig.asciidoc[] + diff --git a/filebeat/docs/filebeat-modules-options.asciidoc b/filebeat/docs/filebeat-modules-options.asciidoc new file mode 100644 index 00000000000..865abec98bc --- /dev/null +++ b/filebeat/docs/filebeat-modules-options.asciidoc @@ -0,0 +1,65 @@ +[[configuration-filebeat-modules]] +== Specify which modules to run + +//REVIEWERS: I created this topic because I think it might be confusing to have no mention of this modules config section in the docs. However, I think that adding the info might also be confusing becasue users might try to configure othe things (like prospectors). Note that this topic uses the old command syntax, but would be updated to reflect the new. + +Filebeat <> provide a quick way for you to get started +processing common log formats. They contain default configurations, +Elasticsearch ingest node pipeline definitions, and Kibana dashboards to help +you implement and deploy a log monitoring solution. + +Using modules is optional. You may decide to configure Filebeat manaully if +you are using a log file type that isn't supported or you want to use a +different setup. + +To enable specific modules, you can add entries to the `filebeat.modules` list +in the +{beatname_lc}.yml+ config file. Each entry in the list begins with a dash +(-) and is followed by settings for that module. + +Filebeat also provides command-line options for enabling and disabling modules. +See <> for more about running modules. + +The following example shows a configuration that runs the `nginx`,`mysql`, and +`system` modules. + +//QUESTION: Are we doing something like the modules.d layout for Filebeat? + +[source,yaml] +---- +filebeat.modules: +- module: nginx +- module: mysql +- module: system +---- + +To enable this same configuration from the command line, you use: + +[source,shell] +---- +./filebeat -e -modules=nginx,mysql,system +---- + +The configuration in the example assumes that the logs you’re harvesting are +in the location expected for your OS and that the default behavior of Filebeat +is appropriate for your environment. Each module provides variables that you +can set to fine tune the behavior of Filebeat, including the location +where it looks for log files. For example, the following configuration sets +the path for `nginx` log files: + +[source,yaml] +---- +filebeat.modules: +- module: nginx + access: + var.paths: ["/var/log/nginx/access.log*"] +---- + +To set the same configuration from the command line, you use: + +[source,shell] +---- +./filebeat -e -modules=nginx -M "nginx.access.var.paths=[/var/log/nginx/access.log*]" +---- + +See the <> you are using for +more information. diff --git a/filebeat/docs/reference/configuration/filebeat-options.asciidoc b/filebeat/docs/filebeat-options.asciidoc similarity index 69% rename from filebeat/docs/reference/configuration/filebeat-options.asciidoc rename to filebeat/docs/filebeat-options.asciidoc index 6c5320ffd14..7e72e9e8caf 100644 --- a/filebeat/docs/reference/configuration/filebeat-options.asciidoc +++ b/filebeat/docs/filebeat-options.asciidoc @@ -1,10 +1,13 @@ [[configuration-filebeat-options]] -=== Filebeat Prospectors +== Set up prospectors -The `filebeat` section of the +{beatname_lc}.yml+ config file specifies a list of `prospectors` that Filebeat -uses to locate and process log files. Each prospector item begins with a dash (-) -and specifies prospector-specific configuration options, including -the list of paths that are crawled to locate log files. +Filebeat uses prospectors to locate and process files. To configure Filebeat, +you specify a list of prospectors in the `filebeat.prospectors` section of the ++{beatname_lc}.yml+ config file. + +Each item in the list begins with a dash (-) and specifies prospector-specific +configuration options, including the list of paths that are crawled to locate +the files. Here is a sample configuration: @@ -21,9 +24,11 @@ filebeat.prospectors: - /var/log/*.log ------------------------------------------------------------------------------------- -==== Options +[float] +=== Configuration options -===== type +[float] +==== `type` One of the following input types: @@ -33,8 +38,9 @@ One of the following input types: The value that you specify here is used as the `type` for each event published to Logstash and Elasticsearch. +[float] [[prospector-paths]] -===== paths +==== `paths` A list of glob-based paths that should be crawled and fetched. All patterns supported by https://golang.org/pkg/path/filepath/#Glob[Golang Glob] are also @@ -43,13 +49,14 @@ subdirectories, the following pattern can be used: `/var/log/*/*.log`. This fetches all `.log` files from the subfolders of `/var/log`. It does not fetch log files from the `/var/log` folder itself. It is possible to recursively fetch all files in all subdirectories of a directory -using the optional <> settings. +using the optional <> settings. Filebeat starts a harvester for each file that it finds under the specified paths. You can specify one path per line. Each line begins with a dash (-). +[float] [[recursive_glob]] -===== recursive_glob +==== `recursive_glob` *`enabled`*:: Enable expanding `**` into recursive glob patterns. With this feature enabled, the rightmost `**` in each path is expanded into a fixed @@ -57,7 +64,8 @@ number of glob patterns. For example: `/foo/**` expands to `/foo`, `/foo/*`, `/foo/*/*`, and so on. The feature is disabled by default, and if enabled it expands a single `**` into a 8-level deep `*` pattern. -===== encoding +[float] +==== `encoding` The file encoding to use for reading files that contain international characters. See the encoding names http://www.w3.org/TR/encoding/[recommended by the W3C for use in HTML5]. @@ -69,12 +77,13 @@ Here are some sample encodings from W3C recommendation: The `plain` encoding is special, because it does not validate or transform any input. +[float] [[exclude-lines]] -===== exclude_lines +==== `exclude_lines` A list of regular expressions to match the lines that you want Filebeat to exclude. Filebeat drops any lines that match a regular expression in the list. By default, no lines are dropped. -If <> is also specified, each multiline message is combined into a single line before the lines are filtered by `exclude_lines`. +If <> is also specified, each multiline message is combined into a single line before the lines are filtered by `exclude_lines`. The following example configures Filebeat to drop any lines that start with "DBG". @@ -88,12 +97,13 @@ filebeat.prospectors: See <> for a list of supported regexp patterns. +[float] [[include-lines]] -===== include_lines +==== `include_lines` A list of regular expressions to match the lines that you want Filebeat to include. Filebeat exports only the lines that match a regular expression in the list. By default, all lines are exported. -If <> is also specified, each multiline message is combined into a single line before the lines are filtered by `include_lines`. +If <> is also specified, each multiline message is combined into a single line before the lines are filtered by `include_lines`. The following example configures Filebeat to export any lines that start with "ERR" or "WARN": @@ -119,8 +129,9 @@ The following example exports all Apache log lines except the debugging messages See <> for a list of supported regexp patterns. +[float] [[exclude-files]] -===== exclude_files +==== `exclude_files` A list of regular expressions to match the files that you want Filebeat to ignore. By default no files are excluded. @@ -133,7 +144,8 @@ The following example configures Filebeat to ignore all the files that have a `g See <> for a list of supported regexp patterns. -===== tags +[float] +==== `tags` A list of tags that the Beat includes in the `tags` field of each published event. Tags make it easy to select specific events in Kibana or apply @@ -149,8 +161,9 @@ filebeat.prospectors: tags: ["json"] -------------------------------------------------------------------------------- +[float] [[configuration-fields]] -===== 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 @@ -169,16 +182,18 @@ filebeat.prospectors: app_id: query_engine_12 -------------------------------------------------------------------------------- +[float] [[fields-under-root]] -===== fields_under_root +==== `fields_under_root` -If this option is set to true, the custom <> are stored as +If this option is set to true, the custom <> 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 Filebeat, then the custom fields overwrite the other fields. +[float] [[ignore-older]] -===== ignore_older +==== `ignore_older` If this option is enabled, Filebeat ignores any files that were modified before the specified timespan. Configuring `ignore_older` can be especially useful if you keep log files for a long time. For example, if you want to start Filebeat, but only want to send the newest files and files from last week, you can configure this option. @@ -202,14 +217,16 @@ Before a file can be ignored by the prospector, it must be closed. To ensure a f If a file that's currently being harvested falls under `ignore_older`, the harvester will first finish reading the file and close it after `close_inactive` is reached. Then, after that, the file will be ignored. +[float] [[close-options]] -===== close_* +==== `close_*` The `close_*` configuration options are used to close the harvester after a certain criteria or time. Closing the harvester means closing the file handler. If a file is updated after the harvester is closed, the file will be picked up again after `scan_frequency` has elapsed. However, if the file is moved or deleted while the harvester is closed, Filebeat will not be able to pick up the file again, and any data that the harvester hasn't read will be lost. +[float] [[close-inactive]] -===== close_inactive +==== `close_inactive` When this option is enabled, Filebeat closes the file handle if a file has not been harvested for the specified duration. The counter for the defined period starts when the last log line was read by the harvester. It is not based on the modification time of the file. If the closed file changes again, a new harvester is started and the latest changes will be picked up after `scan_frequency` has elapsed. @@ -221,8 +238,9 @@ The timestamp for closing a file does not depend on the modification time of the You can use time strings like 2h (2 hours) and 5m (5 minutes). The default is 5m. +[float] [[close-renamed]] -===== close_renamed +==== `close_renamed` WARNING: Only use this option if you understand that data loss is a potential side effect. @@ -230,8 +248,9 @@ When this option is enabled, Filebeat closes the file handler when a file is ren WINDOWS: If your Windows log rotation system shows errors because it can't rotate the files, you should enable this option. +[float] [[close-removed]] -===== close_removed +==== `close_removed` When this option is enabled, Filebeat closes the harvester when a file is removed. Normally a file should only be removed after it's inactive for the duration specified by `close_inactive`. However, if a file is removed early and you don't enable `close_removed`, Filebeat keeps the file open to make sure the harvester has completed. If this setting results in files that are not completely read because they are removed from disk too early, disable this option. @@ -239,15 +258,17 @@ This option is enabled by default. If you disable this option, you must also dis WINDOWS: If your Windows log rotation system shows errors because it can't rotate files, make sure this option is enabled. +[float] [[close-eof]] -===== close_eof +==== `close_eof` WARNING: Only use this option if you understand that data loss is a potential side effect. When this option is enabled, Filebeat closes a file as soon as the end of a file is reached. This is useful when your files are only written once and not updated from time to time. For example, this happens when you are writing every single log event to a new file. This option is disabled by default. +[float] [[close-timeout]] -===== close_timeout +==== `close_timeout` WARNING: Only use this option if you understand that data loss is a potential side effect. Another side effect is that multiline events might not be completely sent before the timeout expires. @@ -262,13 +283,15 @@ The `close_timeout` setting won't apply if your output is stalled and no further This option is set to 0 by default which means it is disabled. +[float] [[clean-options]] -===== clean_* +==== `clean_*` The `clean_*` options are used to clean up the state entries in the registry file. These settings help to reduce the size of the registry file and can prevent a potential <>. +[float] [[clean-inactive]] -===== clean_inactive +==== `clean_inactive` WARNING: Only use this option if you understand that data loss is a potential side effect. @@ -280,8 +303,9 @@ This config option is also useful to prevent Filebeat problems resulting from in NOTE: Every time a file is renamed, the file state is updated and the counter for `clean_inactive` starts at 0 again. +[float] [[clean-removed]] -===== clean_removed +==== `clean_removed` When this option is enabled, Filebeat cleans files from the registry if they cannot be found on disk anymore under the last known name. This means also files which were renamed after the harvester was finished will be removed. This option is enabled by default. @@ -289,8 +313,9 @@ If a shared drive disappears for a short period and appears again, all files wil You must disable this option if you also disable `close_removed`. +[float] [[scan-frequency]] -===== scan_frequency +==== `scan_frequency` How often the prospector checks for new files in the paths that are specified for harvesting. For example, if you specify a glob like `/var/log/*`, the @@ -303,39 +328,42 @@ If you require log lines to be sent in near real time do not use a very low `sca The default setting is 10s. +[float] [[scan-sort]] -===== scan.sort +==== `scan.sort` -[]experimental +experimental[] - If you specify a value other than the empty string for this setting you can determine whether to use ascending or descending order using `scan.order`. Possible values are `modtime` and `filename`. To sort by file modification time, use `modtime`, otherwise use `filename`. Leave this option empty to disable it. +If you specify a value other than the empty string for this setting you can determine whether to use ascending or descending order using `scan.order`. Possible values are `modtime` and `filename`. To sort by file modification time, use `modtime`, otherwise use `filename`. Leave this option empty to disable it. If you specify a value for this setting, you can use `scan.order` to configure whether files are scanned in ascending or descending order. The default setting is disabled. - +[float] [[scan-order]] -===== scan.order +==== `scan.order` -[]experimental +experimental[] Specifies whether to use ascending or descending order when `scan.sort` is set to a value other than none. Possible values are `asc` or `desc`. The default setting is `asc`. - -===== harvester_buffer_size +[float] +==== `harvester_buffer_size` The size in bytes of the buffer that each harvester uses when fetching a file. The default is 16384. -===== max_bytes +[float] +==== `max_bytes` The maximum number of bytes that a single log message can have. All bytes after `max_bytes` are discarded and not sent. This setting is especially useful for multiline log messages, which can get large. The default is 10MB (10485760). +[float] [[config-json]] -===== json +==== `json` These options make it possible for Filebeat to decode logs structured as JSON messages. Filebeat processes the logs line by line, so the JSON decoding only works if there is one JSON object per line. @@ -368,66 +396,13 @@ key must be at the top level in the JSON object and the value associated with the key must be a string, otherwise no filtering or multiline aggregation will occur. +[float] +==== `multiline` -[[multiline]] -===== multiline - -IMPORTANT: If you are sending multiline events to Logstash, use the options described here to handle multiline events -before sending the event data to Logstash. Trying to implement multiline event handling in Logstash (for example, by -using the Logstash multiline codec) may result in the mixing of streams and corrupted data. - -Options that control how Filebeat deals with log messages that span multiple lines. Multiline messages are common in files that contain Java stack traces. - -The following example shows how to configure Filebeat to handle a multiline message where the first line of the message begins with a bracket (`[`). - -[source,yaml] -------------------------------------------------------------------------------------- -multiline.pattern: '^\[' -multiline.negate: true -multiline.match: after - -------------------------------------------------------------------------------------- - -Filebeat takes all the lines that do not start with `[` and combines them with the previous line that does. For example, you could use this configuration to join the following lines of a multiline message into a single event: - -["source","sh",subs="attributes,callouts"] -------------------------------------------------------------------------------------- -[beat-logstash-some-name-832-2015.11.28] IndexNotFoundException[no such index] - at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver$WildcardExpressionResolver.resolve(IndexNameExpressionResolver.java:566) - at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver.concreteIndices(IndexNameExpressionResolver.java:133) - at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver.concreteIndices(IndexNameExpressionResolver.java:77) - at org.elasticsearch.action.admin.indices.delete.TransportDeleteIndexAction.checkBlock(TransportDeleteIndexAction.java:75) -------------------------------------------------------------------------------------- - -See <> for more configuration examples. - -You specify the following settings under `multiline` to control how Filebeat combines the lines in the message: - -*`pattern`*:: Specifies the regular expression pattern to match. Note that the regexp patterns supported by Filebeat differ -somewhat from the patterns supported by Logstash. See <> for a list of supported regexp patterns. +Options that control how Filebeat deals with log messages that span multiple lines. See <> for more information about configuring multiline options. -*`negate`*:: Defines whether the pattern is negated. The default is `false`. - -*`match`*:: Specifies how Filebeat combines matching lines into an event. The settings are `after` or `before`. The behavior of these settings depends on what you specify for `negate`: -+ -[options="header"] -|======================= -|Setting for `negate` | Setting for `match` | Result | Example `pattern: ^b` -|`false` | `after` | Consecutive lines that match the pattern are appended to the previous line that doesn't match. | image:./images/false-after-multi.png[Lines a b b c b b become "abb" and "cbb"] -|`false` | `before` | Consecutive lines that match the pattern are prepended to the next line that doesn't match. | image:./images/false-before-multi.png[Lines b b a b b c become "bba" and "bbc"] -|`true` | `after` | Consecutive lines that don't match the pattern are appended to the previous line that does match. | image:./images/true-after-multi.png[Lines b a c b d e become "bac" and "bde"] -|`true` | `before` | Consecutive lines that don't match the pattern are prepended to the next line that does match. | image:./images/true-before-multi.png[Lines a c b d e b become "acb" and "deb"] -|======================= -+ -NOTE: The `after` setting is equivalent to `previous` in https://www.elastic.co/guide/en/logstash/current/plugins-codecs-multiline.html[Logstash], and `before` is equivalent to `next`. - -*`max_lines`*:: The maximum number of lines that can be combined into one event. If -the multiline message contains more than `max_lines`, any additional -lines are discarded. The default is 500. - -*`timeout`*:: After the specified timeout, Filebeat sends the multiline event even if no new pattern is found to start a new event. The default is 5s. - -===== tail_files +[float] +==== `tail_files` If this option is set to true, Filebeat starts reading new files at the end of each file instead of the beginning. When this option is used in combination with log rotation, it's possible that the first log entries in a new file might be skipped. The default setting is false. @@ -435,7 +410,8 @@ This option applies to files that Filebeat has not already processed. If you ran NOTE: You can use this setting to avoid indexing old log lines when you run Filebeat on a set of log files for the first time. After the first run, we recommend disabling this option, or you risk losing lines during file rotation. -===== pipeline +[float] +==== `pipeline` The Ingest Node pipeline ID to set for the events generated by this prospector. @@ -443,7 +419,8 @@ NOTE: The pipeline ID can also be configured in the Elasticsearch output, but th option usually results in simpler configuration files. If the pipeline is configured both in the prospector and in the output, the option from the prospector is the one used. -===== symlinks +[float] +==== `symlinks` The `symlinks` option allows Filebeat to harvest symlinks in addition to regular files. When harvesting symlinks, Filebeat opens and reads the original file even though it reports the path of the symlink. @@ -453,7 +430,8 @@ The `symlinks` option can be useful if symlinks to the log files have additional Because this option may lead to data loss, it is disabled by default. -===== backoff +[float] +==== `backoff` The backoff options specify how aggressively Filebeat crawls open files for updates. You can use the default values in most cases. @@ -463,7 +441,8 @@ waits before checking a file again after EOF is reached. The default is 1s, whic the file is checked every second if new lines were added. This enables near real-time crawling. Every time a new line appears in the file, the `backoff` value is reset to the initial value. The default is 1s. -===== max_backoff +[float] +==== `max_backoff` The maximum time for Filebeat to wait before checking a file again after EOF is reached. After having backed off multiple times from checking the file, the wait time @@ -473,7 +452,8 @@ backed off multiple times. The default is 10s. Requirement: max_backoff should always be set to `max_backoff <= scan_frequency`. In case `max_backoff` should be bigger, it is recommended to close the file handler instead let the prospector pick up the file again. -===== backoff_factor +[float] +==== `backoff_factor` This option specifies how fast the waiting time is increased. The bigger the backoff factor, the faster the `max_backoff` value is reached. The backoff factor @@ -482,8 +462,9 @@ the backoff algorithm is disabled, and the `backoff` value is used for waiting f lines. The `backoff` value will be multiplied each time with the `backoff_factor` until `max_backoff` is reached. The default is 2. +[float] [[harvester-limit]] -===== harvester_limit +==== `harvester_limit` The `harvester_limit` option limits the number of harvesters that are started in parallel for one prospector. This directly relates to the maximum number of file handlers that are opened. The default for `harvester_limit` is 0, which means there is no limit. This @@ -498,122 +479,9 @@ Currently if a new harvester can be started again, the harvester is picked rando This configuration option applies per prospector. You can use this option to indirectly set higher priorities on certain prospectors by assigning a higher limit of harvesters. -===== enabled +[float] +==== `enabled` The `enabled` option can be used with each prospector to define if a prospector is enabled or not. By default, enabled is set to true. -[[configuration-global-options]] -=== Filebeat Global - -You can specify configuration options in the +{beatname_lc}.yml+ config file to control Filebeat behavior at a global level. - -==== Options - -===== spool_size - -The event count spool threshold. This setting forces a network flush if the number of events in the spooler exceeds -the specified value. - -[source,yaml] -------------------------------------------------------------------------------------- -filebeat.spool_size: 2048 -------------------------------------------------------------------------------------- - -See <> for more information about how this setting affects load balancing. - -===== publish_async - -experimental[] -deprecated[5.3.0] - -If enabled, the publisher pipeline in Filebeat operates in async mode preparing -a new batch of lines while waiting for ACK. This option can improve load-balancing -throughput at the cost of increased memory usage. The default value is false. - -See <> for more information about how this setting affects load balancing. - -===== idle_timeout - -A duration string that specifies how often the spooler is flushed. After the -`idle_timeout` is reached, the spooler is flushed even if the `spool_size` has not been reached. - -[source,yaml] -------------------------------------------------------------------------------------- -filebeat.idle_timeout: 5s -------------------------------------------------------------------------------------- - - -===== registry_file - -The name of the registry file. If a relative path is used, it is considered relative to the -data path. See the <> section for details. The default is `${path.data}/registry`. - -[source,yaml] -------------------------------------------------------------------------------------- -filebeat.registry_file: registry -------------------------------------------------------------------------------------- - -It is not possible to use a symlink as registry file. - -NOTE: The registry file is only updated when new events are flushed and not on a predefined period. -That means in case there are some states where the TTL expired, these are only removed when new event are processed. - - -===== config_dir - -The full path to the directory that contains additional prospector configuration files. -Each configuration file must end with `.yml`. Each config file must also specify the full Filebeat -config hierarchy even though only the prospector part of the file is processed. All global -options, such as `spool_size`, are ignored. - -The `config_dir` option MUST point to a directory other than the directory where the main Filebeat config file resides. - -If the specified path is not absolute, it is considered relative to the configuration path. See the -<> section for details. - -[source,yaml] -------------------------------------------------------------------------------------- -filebeat.config_dir: path/to/configs -------------------------------------------------------------------------------------- - -[[shutdown-timeout]] -===== shutdown_timeout - -How long Filebeat waits on shutdown for the publisher to finish sending events -before Filebeat shuts down. - -By default, this option is disabled, and Filebeat does not wait for the -publisher to finish sending events before shutting down. This means that any -events sent to the output, but not acknowledged before Filebeat shuts down, -are sent again when you restart Filebeat. For more details about how this -works, see <>. - -You can configure the `shutdown_timeout` option to specify the maximum amount -of time that Filebeat waits for the publisher to finish sending events before -shutting down. If all events are acknowledged before `shutdown_timeout` is -reached, Filebeat will shut down. - -There is no recommended setting for this option because determining the correct -value for `shutdown_timeout` depends heavily on the environment in which -Filebeat is running and the current state of the output. - -Example configuration: - -[source,yaml] -------------------------------------------------------------------------------------- -filebeat.shutdown_timeout: 5s -------------------------------------------------------------------------------------- - -include::../../../../libbeat/docs/generalconfig.asciidoc[] - -include::../../../../libbeat/docs/processors-config.asciidoc[] - -include::./reload-configuration.asciidoc[] - -include::../../../../libbeat/docs/outputconfig.asciidoc[] - -include::../../../../libbeat/docs/shared-path-config.asciidoc[] - -include::../../../../libbeat/docs/setup-config.asciidoc[] -include::../../../../libbeat/docs/loggingconfig.asciidoc[] diff --git a/filebeat/docs/getting-started.asciidoc b/filebeat/docs/getting-started.asciidoc index 321d0586b72..a2135c71aef 100644 --- a/filebeat/docs/getting-started.asciidoc +++ b/filebeat/docs/getting-started.asciidoc @@ -20,9 +20,10 @@ After installing the Elastic Stack, read the following topics to learn how to in * <> * <> * <> +* <> [[filebeat-installation]] -=== Step 1: Installing Filebeat +=== Step 1: Install Filebeat Before running Filebeat, you need to install and configure the Elastic stack. See {libbeat}/getting-started.html[Getting Started with Beats and the Elastic Stack]. @@ -138,7 +139,7 @@ NOTE: If script execution is disabled on your system, you need to set the execut endif::[] [[filebeat-configuration]] -=== Step 2: Configuring Filebeat +=== Step 2: Configure Filebeat TIP: <> provide the fastest getting started experience for common log formats. See <> @@ -203,22 +204,22 @@ installed from DEB or RPM packages, run +./filebeat.sh -configtest -e+. Before starting Filebeat, you should look at the configuration options in the configuration file, for example `C:\Program Files\Filebeat\filebeat.yml` or `/etc/filebeat/filebeat.yml`. For more information about these options, -see <>. +see <>. [[config-filebeat-logstash]] -=== Step 3: Configuring Filebeat to Use Logstash +=== Step 3: Configure Filebeat to use Logstash :allplatforms: include::../../libbeat/docs/shared-logstash-config.asciidoc[] [[filebeat-template]] -=== Step 4: Loading the Index Template in Elasticsearch +=== Step 4: Load the index template in Elasticsearch :allplatforms: include::../../libbeat/docs/shared-template-load.asciidoc[] [[filebeat-starting]] -=== Step 5: Starting Filebeat +=== Step 5: Start Filebeat Start Filebeat by issuing the appropriate command for your platform. @@ -271,7 +272,7 @@ By default, Windows log files are stored in `C:\ProgramData\filebeat\Logs`. Filebeat is now ready to send log files to your defined output. [[filebeat-index-pattern]] -=== Step 6: Loading the Kibana Index Pattern +=== Step 6: Load the Kibana index pattern We don't offer prebuilt dashboards for visualizing Filebeat data. However, to make it easier for you to explore Filebeat data in Kibana, we've created a Filebeat index pattern: `filebeat-*`. To load this pattern, you can use the script diff --git a/filebeat/docs/how-filebeat-works.asciidoc b/filebeat/docs/how-filebeat-works.asciidoc index 1f7faea7739..21a6673d320 100644 --- a/filebeat/docs/how-filebeat-works.asciidoc +++ b/filebeat/docs/how-filebeat-works.asciidoc @@ -1,5 +1,5 @@ [[how-filebeat-works]] -== How Filebeat Works +== How Filebeat works In this topic, you learn about the key building blocks of Filebeat and how they work together. Understanding these concepts will help you make informed decisions about configuring Filebeat for specific use cases. @@ -8,7 +8,7 @@ Filebeat consists of two main components: <> and <> is reached. @@ -22,7 +22,7 @@ To control when a harvester is closed, use the <> confi [float] [[prospector]] -=== What is a Prospector? +=== What is a prospector? A prospector is responsible for managing the harvesters and finding all sources to read from. @@ -44,7 +44,7 @@ Filebeat currently supports two `prospector` types: `log` and `stdin`. Each pros NOTE: Filebeat prospectors can only read local files. There is no functionality to connect to remote hosts to read stored files or logs. [float] -=== How Does Filebeat Keep the State of Files? +=== How does Filebeat keep the state of files? Filebeat keeps the state of each file and frequently flushes the state to disk in the registry file. The state is used to remember the last offset a harvester was reading from and to ensure all log lines are sent. If the output, such as Elasticsearch or Logstash, is not reachable, Filebeat keeps track of the last lines sent and will continue reading the files as soon as the output becomes available again. While Filebeat is running, the state information is also kept in memory by each prospector. When Filebeat is restarted, data from the registry file is used to rebuild the state, and Filebeat continues each harvester at the last known position. @@ -54,7 +54,7 @@ If your use case involves creating a large number of new files every day, you mi [float] [[at-least-once-delivery]] -=== How Does Filebeat Ensure At-Least-Once Delivery? +=== How does Filebeat ensure at-least-once delivery? Filebeat guarantees that events will be delivered to the configured output at least once and with no data loss. Filebeat is able to achieve this behavior diff --git a/filebeat/docs/index.asciidoc b/filebeat/docs/index.asciidoc index 0dd149122a8..17701f9d677 100644 --- a/filebeat/docs/index.asciidoc +++ b/filebeat/docs/index.asciidoc @@ -41,25 +41,6 @@ include::./how-filebeat-works.asciidoc[] include::./configuring-howto.asciidoc[] -include::./filebeat-filtering.asciidoc[] - -include::./multiline.asciidoc[] - -include::../../libbeat/docs/shared-config-ingest.asciidoc[] - -:standalone: -include::../../libbeat/docs/shared-env-vars.asciidoc[] - -include::./multiple-prospectors.asciidoc[] - -include::./load-balancing.asciidoc[] - -:standalone: -:allplatforms: -include::../../libbeat/docs/yaml.asciidoc[] - -include::../../libbeat/docs/regexp.asciidoc[] - include::./modules.asciidoc[] include::./fields.asciidoc[] diff --git a/filebeat/docs/load-balancing.asciidoc b/filebeat/docs/load-balancing.asciidoc index c024b406c57..7b091a12d84 100644 --- a/filebeat/docs/load-balancing.asciidoc +++ b/filebeat/docs/load-balancing.asciidoc @@ -1,5 +1,5 @@ [[load-balancing]] -== Load Balancing +=== Load balance the output hosts Filebeat provides configuration options that you can use to fine tune load balancing when sending events to multiple hosts. diff --git a/filebeat/docs/migration.asciidoc b/filebeat/docs/migration.asciidoc index 9a53e493d86..328e8c5ec1e 100644 --- a/filebeat/docs/migration.asciidoc +++ b/filebeat/docs/migration.asciidoc @@ -27,7 +27,7 @@ https://github.com/elastic/logstash-forwarder[Logstash Forwarder] to Filebeat: -- [[migration-input-plugin]] -== Migrating to the Beats Input Plugin for Logstash +== Migrate to the Beats input plugin for Logstash Filebeat requires the https://www.elastic.co/guide/en/logstash/current/plugins-inputs-beats.html[Beats input plugin for Logstash]. For information about getting started with this plugin, see {libbeat}/logstash-installation.html#logstash-setup[Setting up Logstash]. @@ -54,7 +54,7 @@ version 2.2.8 or later. * SSL must be explicitly enabled in the Beats input plugin (`ssl => true`) because SSL is on by default with Logstash Forwarder. The SSL/TLS configs should be the same for both the Logstash Forwarder and Filebeat instances. [[migration-registry-file]] -== Updating the Registry File +== Update the registry file The registry file stores the state and location information that Filebeat uses to track where it was last reading. Under Logstash Forwarder, this file was called `.logstash-fowarder`. For Filebeat, @@ -78,7 +78,7 @@ Using this approach allows you to keep the old Logstash Forwarder running and th slowly migrate over to Filebeat. [[migration-configuration]] -== Migrating Your Configuration +== Migrate your configuration Although Filebeat is based on Logstash Forwarder, Filebeat uses YAML for its configuration file, rather than the JSON+comments language used by Logstash Forwarder. This means that you @@ -90,11 +90,11 @@ where the main Filebeat config file resides. You specify the location of the con `config_dir` option to configure the path to the directory. In most cases, you can do a one-to-one conversion to create a Filebeat config file for each Logstash Forwarder config file. -Before migrating your config files, we recommend that you first read the <> +Before migrating your config files, we recommend that you first read the <> section to understand the Filebeat options. [float] -=== Migrating the "files" Section +=== Migrate the "files" section To migrate the `files` section from the Logstash Forwarder configuration, create a `prospectors` section in the Filebeat config file. For example, assuming that you start with this configuration in Logstash Forwarder: @@ -158,10 +158,10 @@ options can be migrated mechanically. The Filebeat configuration gives you more control over how each prospector behaves by allowing you to configure options that were previously global in Logstash Forwarder -and set them separately for each prospector. See <>. +and set them separately for each prospector. See <>. [float] -=== Migrating the "network" Section +=== Migrate the "network" section Like Logstash Forwarder, Filebeat can communicate directly with Logstash. Filebeat can also insert log entries directly @@ -225,7 +225,7 @@ output.logstash: [[changed-configuration-options]] [float] -=== Changed Configuration File Options +=== Changed configuration file options With the refactoring of the configuration file, the following options were removed or renamed: @@ -244,10 +244,10 @@ With the refactoring of the configuration file, the following options were remov |Both options were removed and replaced by logging options in libbeat. |=== -For more information about these options, see <>. +For more information about these options, see <>. [float] -=== A Complete Example +=== A complete example Let's see a simple, but complete example of a Logstash Forwarder configuration and its equivalent for Filebeat. @@ -289,7 +289,7 @@ output.elasticsearch: ------------------------------------------------------------------------------------- [[migration-changed-cli]] -== Changes to Command Line Options +== Changes to command line options Most command line options available in Logstash Forwarder have been removed and migrated to config file options. The only mandatory command line option for @@ -302,7 +302,7 @@ these options, see <>. [[renamed-options]] [float] -=== Renamed Options +=== Renamed options The following command line options have been renamed and moved to the config file. Also see <> for a list of configuration file options that were completely removed or @@ -348,7 +348,7 @@ The `config_dir` option specifies the path to the directory that contains additi |=== [[migration-changed-fields]] -== Changes to the Output Fields +== Changes to the output fields In the default configuration, Filebeat structures its output documents a little differently from the Logstash Forwarder. This section discusses the differences @@ -356,7 +356,7 @@ and the options you have in case you want compatibility with the Logstash Forwarder. [float] -=== Custom Fields are Grouped Under a "fields" Dictionary +=== Custom fields are grouped under a "fields" dictionary The custom fields (added from the configuration file) are set as top-level fields in Logstash Forwarder but are grouped together under a `fields` @@ -375,7 +375,7 @@ filebeat.prospectors: ------------------------------------------------------------------------------------- [float] -=== Filebeat uses "beat.hostname" for Sending the Hostname of the Server +=== Filebeat uses "beat.hostname" for sending the hostname of the server While the Logstash Forwarder sends the hostname of the server it's running on in the `host` field, Filebeat uses the `beat.hostname` field for the same purpose. @@ -383,7 +383,7 @@ Because `host` is commonly used in the Logstash plugin ecosystem, the Beats input plugin automatically copies `beat.hostname` into `host`. [float] -=== The "file" Field Was Renamed to "source" +=== The "file" field was renamed to "source" The `file` field was renamed to `source`. If you rely on this field being named `file`, you can rename it by using the mutate filter in Logstash. For @@ -401,14 +401,14 @@ filter { ------------------------------------------------------------------------------------- [float] -=== The "line" Field Was Removed +=== The "line" field was removed The `line` field was removed. This field wasn't correct after restarts, and making it correct would have resulted in a performance penalty. We recommend using the `offset` field instead. [[migration-other-changes]] -== Other Changes +== Other changes The following list of implementation changes should not affect your experience migrating from Logstash Forwarder, but you should be aware of the changes. Please post GitHub issues @@ -430,13 +430,13 @@ type: * `c:\ProgramData\filebeat\registry` for the Windows zip file [float] -=== Publisher Improvements +=== Publisher improvements Behind the scenes, Filebeat uses a sightly improved protocol for communicating with Logstash. [float] -=== SSL Is Off by Default +=== SSL is off by default If you follow the section on migrating the configuration, you will have SSL enabled. However, you must be aware that if the `ssl` section is missing from the diff --git a/filebeat/docs/module-development-guide.asciidoc b/filebeat/docs/module-development-guide.asciidoc index 977b56b5fa2..67e7a10f0db 100644 --- a/filebeat/docs/module-development-guide.asciidoc +++ b/filebeat/docs/module-development-guide.asciidoc @@ -1,4 +1,4 @@ -= Filebeat Modules Developer Guide += Filebeat modules developer guide This guide describes the process of creating a new Filebeat module. diff --git a/filebeat/docs/modules-getting-started.asciidoc b/filebeat/docs/modules-getting-started.asciidoc index 926133d4748..4256205e213 100644 --- a/filebeat/docs/modules-getting-started.asciidoc +++ b/filebeat/docs/modules-getting-started.asciidoc @@ -1,5 +1,5 @@ [[filebeat-modules-quickstart]] -=== Quick Start for Common Log Formats +=== Quick start for common log formats beta[] @@ -45,9 +45,9 @@ You need to restart Elasticsearch after running these commands. ready to receive data from Filebeat. [[running-modules-quickstart]] -==== Running Filebeat with Modules Enabled +==== Running Filebeat with modules enabled -To run one or more Filebeat modules, you issue the following command: +To set up and run one or more Filebeat modules, you issue the following command: [source,shell] ---------------------------------------------------------------------- @@ -56,8 +56,10 @@ To run one or more Filebeat modules, you issue the following command: Where `MODULES` is the name of the module (or a comma-separated list of modules) that you want to enable. The `-e` flag is optional and sends output -to standard error instead of syslog. The `-setup` flag is a one-time setup step. -For subsequent runs of Filebeat, do not specify this flag. +to standard error instead of syslog. + +The `-setup` flag is a one-time setup step. For subsequent runs of Filebeat, +do not specify this flag. The following example starts Filebeat with the `system` module enabled and loads the sample Kibana dashboards: @@ -99,14 +101,26 @@ TIP: In a production environment, you'll probably want to use a configuration file, rather than command-line flags, to specify which modules to run. See the detailed documentation for more about configuring and running modules. -These examples assume that the logs you're harvesting are in the location +[[setting-variables]] +==== Setting the path variable + +The examples here assume that the logs you're harvesting are in the location expected for your OS and that the default behavior of Filebeat is appropriate -for your environment. Each module provides a set of variables that you can set -to fine tune the behavior of Filebeat, including the location where it looks -for log files. See <> for more info. +for your environment. Each module provides variables that you can set to fine +tune the behavior of Filebeat, including the location where it looks for log +files. For example, the following command sets the path for the Nginx access +logs: + +[source,shell] +---- +./filebeat -e -modules=nginx -M "nginx.access.var.paths=[/var/log/nginx/access.log*]" +---- + +See the <> for more information about setting variables and +advanced options. [[visualizing-data]] -==== Visualizing the Data in Kibana +==== Visualizing the data in Kibana After you've confirmed that Filebeat is sending events to Elasticsearch, launch the Kibana web interface by pointing your browser to port 5601. For example, diff --git a/filebeat/docs/modules-overview.asciidoc b/filebeat/docs/modules-overview.asciidoc index 3d005338fdb..0f9c363e58f 100644 --- a/filebeat/docs/modules-overview.asciidoc +++ b/filebeat/docs/modules-overview.asciidoc @@ -34,6 +34,7 @@ Node. Filebeat modules require Elasticsearch 5.2 or later. +[[modules-tutorial]] === Tutorial This tutorial assumes you have Elasticsearch and Kibana installed and diff --git a/filebeat/docs/multiline.asciidoc b/filebeat/docs/multiline.asciidoc index 8070588d59c..783abc805fc 100644 --- a/filebeat/docs/multiline.asciidoc +++ b/filebeat/docs/multiline.asciidoc @@ -1,38 +1,82 @@ [[multiline-examples]] -== Managing Multiline Messages +== Manage multiline messages The files harvested by {beatname_uc} may contain messages that span multiple lines of text. In order to correctly handle these multiline events, you need to configure `multiline` settings in the +{beatname_lc}.yml+ file to specify which -lines are part of a single event. +lines are part of a single event. IMPORTANT: If you are sending multiline events to Logstash, use the options described here to handle multiline events before sending the event data to Logstash. Trying to implement multiline event handling in Logstash (for example, by -using the Logstash multiline codec) may result in the mixing of streams and corrupted data. +using the Logstash multiline codec) may result in the mixing of streams and corrupted data. -At a minimum, you need to configure these `multiline` options: +Also read <> and <> to avoid common mistakes. -* the `pattern` option, which specifies a regular expression. Depending on how you configure other multiline options, -lines that match the specified regular expression are considered either continuations of a previous line or the start of a new multiline event. You can set the `negate` option to negate the pattern. +[float] +[[multiline-options]] +=== Configuration options -* the `match` option, which specifies how Filebeat combines matching lines into an event. You can specify `before` or `after`. +You can specify the following options in the `filebeat.prospectors` section of the +{beatname_lc}.yml+ config file: -* the `flush_pattern` option, which specifies a regular expression, in which the current multiline will be flushed from memory, ending the multline-message. +[float] +[[multiline]] +==== `multiline` -See the full documentation for <> to learn more about these options. Also read <> and -<> to avoid common mistakes. +Options that control how Filebeat deals with log messages that span multiple lines. Multiline messages are common in files that contain Java stack traces. -[float] -=== Testing Your Regexp Pattern for Multiline +The following example shows how to configure Filebeat to handle a multiline message where the first line of the message begins with a bracket (`[`). -To make it easier for you to test the regexp patterns in your multiline config, we've created a -https://play.golang.org/p/uAd5XHxscu[Go Playground]. You can simply plug in the regexp pattern along with -the `negate` setting that you plan to use, and paste a sample message between the content backticks (` `). -Then click Run, and you'll see which lines in the message match your specified configuration. For example: +[source,yaml] +------------------------------------------------------------------------------------- +multiline.pattern: '^\[' +multiline.negate: true +multiline.match: after -image:images/go-playground.png[] +------------------------------------------------------------------------------------- -[float] -=== Examples of Multiline Configuration +Filebeat takes all the lines that do not start with `[` and combines them with the previous line that does. For example, you could use this configuration to join the following lines of a multiline message into a single event: + +["source","sh",subs="attributes,callouts"] +------------------------------------------------------------------------------------- +[beat-logstash-some-name-832-2015.11.28] IndexNotFoundException[no such index] + at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver$WildcardExpressionResolver.resolve(IndexNameExpressionResolver.java:566) + at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver.concreteIndices(IndexNameExpressionResolver.java:133) + at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver.concreteIndices(IndexNameExpressionResolver.java:77) + at org.elasticsearch.action.admin.indices.delete.TransportDeleteIndexAction.checkBlock(TransportDeleteIndexAction.java:75) +------------------------------------------------------------------------------------- + +You specify the following settings under `multiline` to control how Filebeat combines the lines in the message: + +*`pattern`*:: Specifies the regular expression pattern to match. Note that the regexp patterns supported by Filebeat +differ somewhat from the patterns supported by Logstash. See <> for a list of supported regexp patterns. +Depending on how you configure other multiline options, lines that match the specified regular expression are considered +either continuations of a previous line or the start of a new multiline event. You can set the `negate` option to negate +the pattern. + +*`negate`*:: Defines whether the pattern is negated. The default is `false`. + +*`match`*:: Specifies how Filebeat combines matching lines into an event. The settings are `after` or `before`. The behavior of these settings depends on what you specify for `negate`: ++ +[options="header"] +|======================= +|Setting for `negate` | Setting for `match` | Result | Example `pattern: ^b` +|`false` | `after` | Consecutive lines that match the pattern are appended to the previous line that doesn't match. | image:./images/false-after-multi.png[Lines a b b c b b become "abb" and "cbb"] +|`false` | `before` | Consecutive lines that match the pattern are prepended to the next line that doesn't match. | image:./images/false-before-multi.png[Lines b b a b b c become "bba" and "bbc"] +|`true` | `after` | Consecutive lines that don't match the pattern are appended to the previous line that does match. | image:./images/true-after-multi.png[Lines b a c b d e become "bac" and "bde"] +|`true` | `before` | Consecutive lines that don't match the pattern are prepended to the next line that does match. | image:./images/true-before-multi.png[Lines a c b d e b become "acb" and "deb"] +|======================= ++ +NOTE: The `after` setting is equivalent to `previous` in https://www.elastic.co/guide/en/logstash/current/plugins-codecs-multiline.html[Logstash], and `before` is equivalent to `next`. + +*`flush_pattern`*:: Specifies a regular expression, in which the current multiline will be flushed from memory, ending the multline-message. + +*`max_lines`*:: The maximum number of lines that can be combined into one event. If +the multiline message contains more than `max_lines`, any additional +lines are discarded. The default is 500. + +*`timeout`*:: After the specified timeout, Filebeat sends the multiline event even if no new pattern is found to start a new event. The default is 5s. + + +=== Examples of multiline configuration The examples in this section cover the following use cases: @@ -41,7 +85,7 @@ The examples in this section cover the following use cases: * Combining multiple lines from time-stamped events [float] -==== Java Stack Traces +==== Java stack traces Java stack traces consist of multiple lines, with each line after the initial line beginning with whitespace, as in this example: @@ -65,7 +109,7 @@ multiline.match: after This configuration merges any line that begins with whitespace up to the previous line. -Here's a Java stack trace that presents a slightly more complex example: +Here's a Java stack trace that presents a slightly more complex example: ["source","sh",subs="attributes,callouts"] ------------------------------------------------------------------------------------- @@ -93,9 +137,9 @@ In this example, the pattern matches the following lines: * a line that begins with the words `Caused by:` [float] -==== Line Continuations +==== Line continuations -Several programming languages use the backslash (`\`) character at the end of a line to denote that the line continues, +Several programming languages use the backslash (`\`) character at the end of a line to denote that the line continues, as in this example: [source,c] @@ -136,7 +180,7 @@ multiline.negate: true multiline.match: after ------------------------------------------------------------------------------------- -This configuration uses the `negate: true` and `match: after` settings to specify that any line that does not match the +This configuration uses the `negate: true` and `match: after` settings to specify that any line that does not match the specified pattern belongs to the previous line. [float] @@ -163,5 +207,13 @@ multiline.flush_pattern: 'End event' The 'flush_pattern' option, specifies a regex at which the current multiline will be flushed. If you think of the 'pattern' option specifying the beginning of an event, the 'flush_pattern' option will specify the end or last line of the event. +=== Test your regexp pattern for multiline + +To make it easier for you to test the regexp patterns in your multiline config, we've created a +https://play.golang.org/p/uAd5XHxscu[Go Playground]. You can simply plug in the regexp pattern along with +the `negate` setting that you plan to use, and paste a sample message between the content backticks (` `). +Then click Run, and you'll see which lines in the message match your specified configuration. For example: + +image:images/go-playground.png[] diff --git a/filebeat/docs/multiple-prospectors.asciidoc b/filebeat/docs/multiple-prospectors.asciidoc index 57ae3dbbe51..11b9f3871bf 100644 --- a/filebeat/docs/multiple-prospectors.asciidoc +++ b/filebeat/docs/multiple-prospectors.asciidoc @@ -1,5 +1,5 @@ [[multiple-prospectors]] -== Specifying Multiple Prospectors +=== Specify multiple prospectors When you need to collect lines from multiple files, you can simply configure a single prospector and specify multiple paths to start a harvester for each file. However, if you want to apply additional prospector-specific diff --git a/filebeat/docs/overview.asciidoc b/filebeat/docs/overview.asciidoc index 619391487c1..8db37a4cc87 100644 --- a/filebeat/docs/overview.asciidoc +++ b/filebeat/docs/overview.asciidoc @@ -1,5 +1,9 @@ [[filebeat-overview]] -== Overview +== Filebeat overview + +++++ +Overview +++++ Filebeat is a log data shipper for local files. Installed as an agent on your servers, Filebeat monitors the log directories or specific log files, tails the files, and forwards them either to https://www.elastic.co/products/elasticsearch[Elasticsearch] or https://www.elastic.co/products/logstash[Logstash] for indexing. diff --git a/filebeat/docs/reference/configuration.asciidoc b/filebeat/docs/reference/configuration.asciidoc deleted file mode 100644 index 30fd9ee202f..00000000000 --- a/filebeat/docs/reference/configuration.asciidoc +++ /dev/null @@ -1,36 +0,0 @@ - -[[filebeat-configuration-details]] -== Configuration Options (Reference) - -Before modifying configuration settings, make sure you've completed the -<> in the Getting Started. - -The {beatname_uc} configuration file, +{beatname_lc}.yml+, uses http://yaml.org/[YAML] for its syntax. See the -{libbeat}/config-file-format.html[Config File Format] section of the -_Beats Platform Reference_ for more about the structure of the config file. - -The configuration options are described in the following sections. After changing -configuration settings, you need to restart {beatname_uc} to pick up the changes. - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> - -include::configuration/filebeat-options.asciidoc[] - - - - diff --git a/filebeat/docs/reference/configuration/reload-configuration.asciidoc b/filebeat/docs/reload-configuration.asciidoc similarity index 93% rename from filebeat/docs/reference/configuration/reload-configuration.asciidoc rename to filebeat/docs/reload-configuration.asciidoc index ef7932a1108..4244910c22f 100644 --- a/filebeat/docs/reference/configuration/reload-configuration.asciidoc +++ b/filebeat/docs/reload-configuration.asciidoc @@ -1,5 +1,5 @@ [[filebeat-configuration-reloading]] -=== Reload Configuration +== Reload the configuration dynamically beta[] @@ -13,7 +13,8 @@ This feature is especially useful in container environments where one container is used to tail logs for services running in other containers on the same host. To enable dynamic config reloading, you specify the `path` and `reload` options -in the main `filebeat.yml` config file. For example: +in the `filebeat.config.prospectors` section of the main `filebeat.yml` config +file. For example: [source,yaml] ------------------------------------------------------------------------------ diff --git a/filebeat/docs/securing-filebeat.asciidoc b/filebeat/docs/securing-filebeat.asciidoc index d1ccfbb66ca..618bb3a495a 100644 --- a/filebeat/docs/securing-filebeat.asciidoc +++ b/filebeat/docs/securing-filebeat.asciidoc @@ -14,13 +14,13 @@ The following topics describe how to secure communication between Filebeat and o -- [[securing-communication-elasticsearch]] -== Securing Communication With Elasticsearch +== Secure communication with Elasticsearch include::../../libbeat/docs/https.asciidoc[] //sets block macro for shared-ssl-logstash-config.asciidoc included in next section [[configuring-ssl-logstash]] -== Securing Communication With Logstash by Using SSL +== Secure communication with Logstash by using SSL -include::../../libbeat/docs/shared-ssl-logstash-config.asciidoc[] \ No newline at end of file +include::../../libbeat/docs/shared-ssl-logstash-config.asciidoc[] diff --git a/filebeat/docs/troubleshooting.asciidoc b/filebeat/docs/troubleshooting.asciidoc index ea6f8a57131..1a109e57ea5 100644 --- a/filebeat/docs/troubleshooting.asciidoc +++ b/filebeat/docs/troubleshooting.asciidoc @@ -15,14 +15,14 @@ following tips: -- [[getting-help]] -== Getting Help +== Get help include::../../libbeat/docs/getting-help.asciidoc[] //sets block macro for debugging.asciidoc included in next section [[enable-filebeat-debugging]] -== Debugging +== Debug include::../../libbeat/docs/debugging.asciidoc[] diff --git a/heartbeat/docs/command-line.asciidoc b/heartbeat/docs/command-line.asciidoc index 4e3fb5a71fa..86ddf90da28 100644 --- a/heartbeat/docs/command-line.asciidoc +++ b/heartbeat/docs/command-line.asciidoc @@ -1,5 +1,5 @@ [[command-line-options]] -=== Command Line Options +=== Command line options Heartbeat does not have any Heartbeat-specific command line options. Instead, you configure the behaviour of Heartbeat by specifying options in diff --git a/heartbeat/docs/configuring-howto.asciidoc b/heartbeat/docs/configuring-howto.asciidoc index 047b60f578b..12731b11a7e 100644 --- a/heartbeat/docs/configuring-howto.asciidoc +++ b/heartbeat/docs/configuring-howto.asciidoc @@ -3,8 +3,8 @@ [partintro] -- -After following the <> in the -Getting Started, you might want to fine tune the behavior of Heartbeat. +Before modifying configuration settings, make sure you've completed the +<> in the Getting Started. This section describes some common use cases for changing configuration options. To configure Heartbeat, you edit the configuration file. For rpm and deb, @@ -14,21 +14,53 @@ configuration file at +/etc/heartbeat/heartbeat.reference.yml+ that shows all non-deprecated options. For mac and win, look in the archive that you extracted. +The Heartbeat configuration file uses http://yaml.org/[YAML] for its syntax. See the {libbeat}/config-file-format.html[Config File Format] section of the _Beats Platform Reference_ for more about the structure of the config file. The following topics describe how to configure Heartbeat: -* <> -* <> +* <> +* <> +* <> * <> * <> -* <> +* <> +* <> +* <> +* <> * <> * <> * <> -- -include::reference/configuration.asciidoc[] +include::./heartbeat-options.asciidoc[] + +include::./heartbeat-general-options.asciidoc[] + +:allplatforms: +include::../../libbeat/docs/outputconfig.asciidoc[] + +include::./heartbeat-filtering.asciidoc[] + +include::../../libbeat/docs/shared-config-ingest.asciidoc[] + +include::../../libbeat/docs/shared-path-config.asciidoc[] + +include::../../libbeat/docs/setup-config.asciidoc[] + +include::../../libbeat/docs/loggingconfig.asciidoc[] + +:standalone: +include::../../libbeat/docs/shared-env-vars.asciidoc[] + +:standalone: +:allplatforms: +include::../../libbeat/docs/yaml.asciidoc[] + +include::../../libbeat/docs/regexp.asciidoc[] + +include::../../libbeat/docs/reference-yml.asciidoc[] + diff --git a/heartbeat/docs/configuring-logstash.asciidoc b/heartbeat/docs/configuring-logstash.asciidoc deleted file mode 100644 index 4da66693378..00000000000 --- a/heartbeat/docs/configuring-logstash.asciidoc +++ /dev/null @@ -1,5 +0,0 @@ -[[config-heartbeat-logstash]] -== Configuring Heartbeat to Use Logstash - -:allplatforms: -include::../../libbeat/docs/shared-logstash-config.asciidoc[] diff --git a/heartbeat/docs/faq.asciidoc b/heartbeat/docs/faq.asciidoc index ca89bb4db33..27c3f665e8e 100644 --- a/heartbeat/docs/faq.asciidoc +++ b/heartbeat/docs/faq.asciidoc @@ -1,5 +1,5 @@ [[faq]] -== Frequently Asked Questions +== Frequently asked questions This section contains frequently asked questions about Heartbeat. Also check out the diff --git a/heartbeat/docs/getting-started.asciidoc b/heartbeat/docs/getting-started.asciidoc index 96f4d1dc30d..26c2fe82e1f 100644 --- a/heartbeat/docs/getting-started.asciidoc +++ b/heartbeat/docs/getting-started.asciidoc @@ -23,7 +23,7 @@ install, configure, and run Heartbeat: [[heartbeat-installation]] -=== Step 1: Installing Heartbeat +=== Step 1: Install Heartbeat Unlike most Beats, which you install on edge nodes, you typically install Heartbeat as part of monitoring service that runs on a separate machine @@ -151,10 +151,10 @@ endif::[] Before starting Heartbeat, you should look at the configuration options in the configuration file, for example +C:\Program Files\Heartbeat\heartbeat.yml+ or +/etc/heartbeat/heartbeat.yml+. For more information about these -options, see <>. +options, see <>. [[heartbeat-configuration]] -=== Step 2: Configuring Heartbeat +=== Step 2: Configure Heartbeat include::../../libbeat/docs/shared-configuring.asciidoc[] @@ -200,7 +200,7 @@ was started. Heartbeat adds the `@every` keyword to the syntax provided by the <3> The `mode` specifies whether to ping one IP (`any`) or all resolvable IPs (`all`). + -See <> for a full description of each +See <> for a full description of each configuration option. . If you are sending output to Elasticsearch, set the IP address and port where @@ -212,8 +212,7 @@ output.elasticsearch: hosts: ["192.168.1.42:9200"] ---------------------------------------------------------------------- + -If you are sending output to Logstash, see <> -instead. +If you are sending output to Logstash, see <> instead. TIP: To test your configuration file, change to the directory where the Heartbeat binary is installed, and run Heartbeat in the foreground with @@ -223,13 +222,13 @@ your config files are in the path expected by Heartbeat +./heartbeat.sh -configtest -e+. [[heartbeat-template]] -=== Step 3: Loading the Index Template in Elasticsearch +=== Step 3: Load the index template in Elasticsearch :allplatforms: include::../../libbeat/docs/shared-template-load.asciidoc[] [[heartbeat-starting]] -=== Step 4: Starting Heartbeat +=== Step 4: Start Heartbeat Start Heartbeat by issuing the appropriate command for your platform. @@ -276,7 +275,7 @@ Heartbeat is now ready to check the status of your services and send events to your defined output. [[heartbeat-sample-dashboards]] -=== Step 5: Loading Sample Kibana Dashboards +=== Step 5: Load sample Kibana dashboards To make it easier for you to visualize the status of your services, we have created sample Heartbeat dashboards. The dashboards are provided as diff --git a/heartbeat/docs/heartbeat-devguide.asciidoc b/heartbeat/docs/heartbeat-devguide.asciidoc index 137ce0aaf2f..c61e99fd02a 100644 --- a/heartbeat/docs/heartbeat-devguide.asciidoc +++ b/heartbeat/docs/heartbeat-devguide.asciidoc @@ -1,5 +1,5 @@ [[heartbeat-developer-guide]] -= Heartbeat Developer Guide += Heartbeat developer guide [partintro] -- @@ -24,4 +24,4 @@ and new Beats based on Heartbeat: Heartbeat consists of monitors that.... -//TODO: Add developer guide content when Heartbeat is further along \ No newline at end of file +//TODO: Add developer guide content when Heartbeat is further along diff --git a/heartbeat/docs/heartbeat-filtering.asciidoc b/heartbeat/docs/heartbeat-filtering.asciidoc index 29149ed8024..3e27b7edc80 100644 --- a/heartbeat/docs/heartbeat-filtering.asciidoc +++ b/heartbeat/docs/heartbeat-filtering.asciidoc @@ -1,5 +1,5 @@ [[filtering-and-enhancing-data]] -== Filtering and Enhancing the Exported Data +== Filter and Enhance the exported data include::../../libbeat/docs/processors.asciidoc[] diff --git a/heartbeat/docs/heartbeat-general-options.asciidoc b/heartbeat/docs/heartbeat-general-options.asciidoc new file mode 100644 index 00000000000..0347b3b2dcf --- /dev/null +++ b/heartbeat/docs/heartbeat-general-options.asciidoc @@ -0,0 +1,8 @@ +[[configuration-general-options]] +== Specify general settings + +You can specify settings in the +{beatname_lc}.yml+ config file to control the +general behavior of {beatname_uc}. + +include::../../libbeat/docs/generalconfig.asciidoc[] + diff --git a/heartbeat/docs/reference/configuration/heartbeat-options.asciidoc b/heartbeat/docs/heartbeat-options.asciidoc similarity index 92% rename from heartbeat/docs/reference/configuration/heartbeat-options.asciidoc rename to heartbeat/docs/heartbeat-options.asciidoc index 280b020cd18..785ef4042bb 100644 --- a/heartbeat/docs/reference/configuration/heartbeat-options.asciidoc +++ b/heartbeat/docs/heartbeat-options.asciidoc @@ -1,8 +1,12 @@ [[configuration-heartbeat-options]] -=== Heartbeat +== Set up monitors -The `heartbeat` section of the +heartbeat.yml+ config file specifies the -list of `monitors` that Heartbeat uses to check your remote hosts to +++++ +Set up Heartbeat monitors +++++ + +The `heartbeat.monitors` section of the +heartbeat.yml+ config file specifies +the list of `monitors` that Heartbeat uses to check your remote hosts to determine if they are available. Each `monitor` item begins with a dash (-) and specifies the type of monitor to use, the hosts to check, and other settings that control Heartbeat behavior. @@ -29,17 +33,18 @@ heartbeat.scheduler: limit: 10 ---------------------------------------------------------------------- +[float] [[monitor-options]] -==== Monitor Options +=== Monitor options -You can specify the following options in the `monitors` section of the +You can specify the following options in the `heartbeat.monitors` section of the +heartbeat.yml+ config file. 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 +==== `type` The type of monitor to run. One of: @@ -54,21 +59,24 @@ The `tcp` and `http` monitor types both support SSL/TLS and some proxy settings. +[float] [[monitor-name]] -===== name +==== `name` The monitor name. This value appears in the <> under the `monitor` field as the job name and the `type` field as the job type. +[float] [[monitor-enabled]] -===== 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 +==== `schedule` A cron-like expression that specifies the task schedule. For example: @@ -80,28 +88,32 @@ 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. +[float] [[monitor-ipv4]] -===== 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 +==== `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 +==== `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-timieout]] -===== 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). @@ -110,8 +122,9 @@ If the timeout is exceeded, Heartbeat 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-watch-poll-file]] -===== watch.poll_file +==== `watch.poll_file` experimental[] @@ -164,33 +177,38 @@ restarts it with a schedule of 15 seconds between checks. <2> Heartbeat starts a new monitor that uses a TLS-based connection with a custom CA certificate. +[float] [[monitor-icmp-options]] -==== ICMP Options +=== ICMP options These options configure Heartbeat to use ICMP (v4 and v6) Echo Requests to check the configured hosts. These options are valid when the <> is `icmp`. +[float] [[monitor-icmp-hosts]] -===== hosts +==== `hosts` A list of hosts to ping. +[float] [[monitor-icmp-wait]] -===== wait +==== `wait` The duration to wait before emitting another ICMP Echo Request. The default is 1 second (1s). +[float] [[monitor-tcp-options]] -==== TCP Options +=== TCP options These options configure Heartbeat to connect via TCP and optionally verify the endpoint by sending and/or receiving a custom payload. These options are valid when the <> is `tcp`. +[float] [[monitor-tcp-hosts]] -===== hosts +==== `hosts` A list of hosts to ping. The entries in the list can be: @@ -212,8 +230,9 @@ system defaults are used (currently not supported on Windows). ** `port` is the port number. If `port` is missing in the URL, the <> setting is required. +[float] [[monitor-tcp-ports]] -===== ports +==== `ports` A list of ports to ping if the host specified in <> does not contain a port number. @@ -228,8 +247,9 @@ Example configuration: ports: [80, 9200, 5044] ------------------------------------------------------------------------------- +[float] [[monitor-tcp-check]] -===== 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 @@ -251,8 +271,9 @@ Example configuration: ------------------------------------------------------------------------------- +[float] [[monitor-tcp-proxy-url]] -===== 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://. @@ -269,15 +290,17 @@ 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 +==== `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 +==== `ssl` The TLS/SSL connection settings. If the monitor is <>, it will attempt an SSL @@ -299,15 +322,17 @@ Example configuration: ------------------------------------------------------------------------------- +[float] [[monitor-http-options]] -==== HTTP Options +=== HTTP options These options configure Heartbeat to connect via HTTP and optionally verify that the host returns the expected response. These options are valid when the <> is `http`. +[float] [[monitor-http-urls]] -===== urls +==== `urls` A list of URLs to ping. @@ -321,14 +346,16 @@ Example configuration: ------------------------------------------------------------------------------- +[float] [[monitor-http-proxy-url]] -===== proxy_url +==== `proxy_url` The HTTP proxy URL. This setting is optional. If not set, the HTTP_PROXY environment variable is used. +[float] [[monitor-http-username]] -===== username +==== `username` The username for authenticating with the server. The credentials are passed with the request. This setting is optional. @@ -337,13 +364,15 @@ 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 +==== `password` The password for authenticating with the server. This setting is optional. +[float] [[monitor-http-tls-ssl]] -===== ssl +==== `ssl` The TLS/SSL connection settings for use with the HTTPS endpoint. If you don't specify settings, the system defaults are used. @@ -362,8 +391,9 @@ Example configuration: ------------------------------------------------------------------------------- +[float] [[monitor-http-check]] -===== check +==== `check` An optional `request` to send to the remote host and the expected `response`. @@ -411,10 +441,11 @@ check.response: ------------------------------------------------------------------------------- +[float] [[monitors-scheduler]] -==== Scheduler Options +=== Scheduler options -You specify options under `scheduler` to control the behavior of the task +You specify options under `heartbeat.scheduler` to control the behavior of the task scheduler. Example configuration: @@ -430,8 +461,9 @@ 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 +==== `limit` The number of concurrent I/O tasks that Heartbeat is allowed to execute. If set to 0, there is no limit. The default is 0. @@ -441,20 +473,11 @@ 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 +==== `location` The timezone for the scheduler. By default the scheduler uses localtime. -include::../../../../libbeat/docs/generalconfig.asciidoc[] - -include::../../../../libbeat/docs/processors-config.asciidoc[] - -include::../../../../libbeat/docs/outputconfig.asciidoc[] - -include::../../../../libbeat/docs/shared-path-config.asciidoc[] - -include::../../../../libbeat/docs/setup-config.asciidoc[] -include::../../../../libbeat/docs/loggingconfig.asciidoc[] diff --git a/heartbeat/docs/how-heartbeat-works.asciidoc b/heartbeat/docs/how-heartbeat-works.asciidoc index cbaf7b7439a..5869eca33ba 100644 --- a/heartbeat/docs/how-heartbeat-works.asciidoc +++ b/heartbeat/docs/how-heartbeat-works.asciidoc @@ -1,10 +1,10 @@ [[how-heartbeat-works]] -== How Heartbeat Works +== How Heartbeat works In this topic, you learn about the key building blocks of Heartbeat and how they work together. Understanding these concepts will help you make informed -decisions about configuring Heartbeat for specific use cases. +decisions about configuring Heartbeat for specific use cases. -//TODO: Add details to this topic when the architecture is more stable. +//TODO: Add details to this topic. diff --git a/heartbeat/docs/index.asciidoc b/heartbeat/docs/index.asciidoc index 842740fa77f..79b305286e3 100644 --- a/heartbeat/docs/index.asciidoc +++ b/heartbeat/docs/index.asciidoc @@ -41,22 +41,6 @@ include::./running-on-docker.asciidoc[] include::./configuring-howto.asciidoc[] -include::./heartbeat-filtering.asciidoc[] - -include::../../libbeat/docs/shared-config-ingest.asciidoc[] - -//points to shared topic because configuring-logstash.asciidoc is just a wrapper -include::./configuring-logstash.asciidoc[] - -:standalone: -include::../../libbeat/docs/shared-env-vars.asciidoc[] - -:standalone: -:allplatforms: -include::../../libbeat/docs/yaml.asciidoc[] - -include::../../libbeat/docs/regexp.asciidoc[] - include::./fields.asciidoc[] include::./securing-heartbeat.asciidoc[] diff --git a/heartbeat/docs/overview.asciidoc b/heartbeat/docs/overview.asciidoc index a259c46be86..9bdc8118dc4 100644 --- a/heartbeat/docs/overview.asciidoc +++ b/heartbeat/docs/overview.asciidoc @@ -1,5 +1,9 @@ [[heartbeat-overview]] -== Overview +== Heartbeat overview + +++++ +Overview +++++ Heartbeat is a lightweight daemon that you install on a remote server to periodically check the status of your services and determine whether they are @@ -24,11 +28,11 @@ minutes, and a different monitor to run between the hours of 9:00 and 17:00. Heartbeat currently supports monitors for checking hosts via: * ICMP (v4 and v6) Echo Requests. Use the `icmp` monitor when you simply want to -check whether a service is available. This monitor requires root access. +check whether a service is available. This monitor requires root access. * TCP. Use the `tcp` monitor to connect via TCP. You can optionally configure this -monitor to verify the endpoint by sending and/or receiving a custom payload. +monitor to verify the endpoint by sending and/or receiving a custom payload. * HTTP. Use the `http` monitor to connect via HTTP. You can optionally configure this monitor to verify that the service returns the expected response, such as a specific status code, response header, or content. -The `tcp` and `http` monitors both support SSL/TLS and some proxy settings. +The `tcp` and `http` monitors both support SSL/TLS and some proxy settings. diff --git a/heartbeat/docs/reference/configuration.asciidoc b/heartbeat/docs/reference/configuration.asciidoc deleted file mode 100644 index b73f6854040..00000000000 --- a/heartbeat/docs/reference/configuration.asciidoc +++ /dev/null @@ -1,34 +0,0 @@ - -[[heartbeat-configuration-details]] -== Configuration Options (Reference) - -Before modifying configuration settings, make sure you've completed the -<> in the Getting Started. - -The Heartbeat configuration file, +heartbeat.yml+, uses http://yaml.org/[YAML] for its syntax. See the -{libbeat}/config-file-format.html[Config File Format] section of the -_Beats Platform Reference_ for more about the structure of the config file. - -The configuration options are described in the following sections. After changing -configuration settings, you need to restart Heartbeat to pick up the changes. - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> - -include::configuration/heartbeat-options.asciidoc[] - - - - diff --git a/heartbeat/docs/securing-heartbeat.asciidoc b/heartbeat/docs/securing-heartbeat.asciidoc index fe777ebe8d8..56d5a5cd835 100644 --- a/heartbeat/docs/securing-heartbeat.asciidoc +++ b/heartbeat/docs/securing-heartbeat.asciidoc @@ -15,13 +15,13 @@ and other products in the Elastic stack: -- [[securing-communication-elasticsearch]] -== Securing Communication With Elasticsearch +== Secure communication with Elasticsearch include::../../libbeat/docs/https.asciidoc[] //sets block macro for shared-ssl-logstash-config.asciidoc included in next section [[configuring-ssl-logstash]] -== Securing Communication With Logstash by Using SSL +== Secure communication with Logstash by using SSL -include::../../libbeat/docs/shared-ssl-logstash-config.asciidoc[] \ No newline at end of file +include::../../libbeat/docs/shared-ssl-logstash-config.asciidoc[] diff --git a/heartbeat/docs/troubleshooting.asciidoc b/heartbeat/docs/troubleshooting.asciidoc index 2eba169918e..3bf94fb9993 100644 --- a/heartbeat/docs/troubleshooting.asciidoc +++ b/heartbeat/docs/troubleshooting.asciidoc @@ -15,14 +15,14 @@ following tips: -- [[getting-help]] -== Getting Help +== Get help include::../../libbeat/docs/getting-help.asciidoc[] //sets block macro for debugging.asciidoc included in next section [[enable-heartbeat-debugging]] -== Debugging +== Debug include::../../libbeat/docs/debugging.asciidoc[] diff --git a/libbeat/docs/breaking.asciidoc b/libbeat/docs/breaking.asciidoc index 22c43c2275f..78156627471 100644 --- a/libbeat/docs/breaking.asciidoc +++ b/libbeat/docs/breaking.asciidoc @@ -1,5 +1,5 @@ [[breaking-changes]] -== Breaking Changes +== Breaking changes As a general rule, we strive to keep backwards compatibility between minor versions (e.g. 5.x to 5.y) so you can upgrade without any configuration file @@ -12,18 +12,18 @@ We also list the breaking changes at the top of the <>. While this necessarily causes a few breaking changes, we @@ -57,7 +57,7 @@ changed or replaced with options from the `close_*` group. See the {filebeat}/how-filebeat-works.html[How Filebeat Works] docs for details. These changes are not made automatically by the migration script. -==== Field Renames +==== Field renames Beats 5.0 also comes with several changes in the exported fields. If you are using these fields in Kibana dashboards, you will likely need to adjust the @@ -81,7 +81,7 @@ Changes: In addition, the unused `count` field was removed from all Packetbeat modules. -==== Installation Paths +==== Installation paths For 5.0 we have refactored the {filebeat}/directory-layout.html[directory layout] of the Beats, so they are more consistent and in-line with the best diff --git a/libbeat/docs/communitybeats.asciidoc b/libbeat/docs/communitybeats.asciidoc index 64889566cc6..6c96aa53a3b 100644 --- a/libbeat/docs/communitybeats.asciidoc +++ b/libbeat/docs/communitybeats.asciidoc @@ -4,7 +4,7 @@ ////////////////////////////////////////////////////////////////////////// [[community-beats]] -== Community Beats +== Community beats The open source community has been hard at work developing new Beats. You can check out some of them here. diff --git a/libbeat/docs/config-file-format.asciidoc b/libbeat/docs/config-file-format.asciidoc index 4789b7045af..8f1f0dc0335 100644 --- a/libbeat/docs/config-file-format.asciidoc +++ b/libbeat/docs/config-file-format.asciidoc @@ -119,7 +119,7 @@ output.elasticsearch.hosts: ["http://localhost:9200"] ------------------------------------------------------------------------------ [[config-file-format-type]] -=== Config file Data Types +=== Config file data types Values of configuration settings are interpreted as required by beats. If a value can not be correctly interpreted as the required type - for example a @@ -180,7 +180,7 @@ duration2: 6h duration_disabled: -1s ------------------------------------------------------------------------------ -==== Regular Expression +==== Regular expression Regular expressions are special strings getting compiled into regular expressions at load time. @@ -211,12 +211,12 @@ format-string-with-date: '%{[fieldname]}-%{+yyyy.MM.dd}' [[config-file-format-env-vars]] -=== Environment Variables +=== Environment variables include::shared-env-vars.asciidoc[] [[config-gile-format-refs]] -=== Reference Variables +=== Reference variables Beats settings can reference other settings splicing multiple optionally custom named settings into new values. References use the same syntax as @@ -281,7 +281,7 @@ when using plain references. [[config-file-permissions]] -=== Config File Ownership and Permissions +=== Config file ownership and permissions NOTE: This section does not apply to Windows or other non-POSIX operating systems. @@ -317,7 +317,7 @@ permissions use: 'chmod go-w /etc/{beatname}/{beatname}.yml') To correct this problem, use `chmod go-w /etc/{beatname}/{beatname}.yml` to remove write privileges from anyone other than the owner. -==== Disabling Strict Permission Checks +==== Disabling strict permission checks You can disable strict permission checks from the command line by using `-strict.perms=false`, but we strongly encourage you to leave the checks enabled. @@ -372,7 +372,7 @@ output.console: [[config-file-format-tips]] -=== YAML Tips and Gotchas +=== YAML tips and gotchas :allplatforms: include::yaml.asciidoc[] diff --git a/libbeat/docs/dashboards.asciidoc b/libbeat/docs/dashboards.asciidoc index 479f3e70f6e..b7ca678ceae 100644 --- a/libbeat/docs/dashboards.asciidoc +++ b/libbeat/docs/dashboards.asciidoc @@ -65,7 +65,7 @@ PS > {beatname_lc} setup [[view-kibana-dashboards]] -==== Opening the Dashboards in Kibana +==== Open the dashboards in Kibana After loading the dashboards, launch the Kibana web interface by pointing your browser to port 5601. For example, http://127.0.0.1:5601[http://127.0.0.1:5601]. diff --git a/libbeat/docs/dashboardsconfig.asciidoc b/libbeat/docs/dashboardsconfig.asciidoc index f6a03fcb002..2eb4c8fb1ce 100644 --- a/libbeat/docs/dashboardsconfig.asciidoc +++ b/libbeat/docs/dashboardsconfig.asciidoc @@ -11,7 +11,7 @@ ////////////////////////////////////////////////////////////////////////// [[configuration-dashboards]] -=== Dashboards +== Load Kibana dashboards beta[] @@ -35,12 +35,14 @@ Here is an example configuration: dashboards.enabled: true ------------------------------------------------------------------------------ -==== Dashboards Loading Options +[float] +=== Configuration options You can specify the following options in the `dashboards` section of the +{beatname_lc}.yml+ config file: -===== enabled +[float] +==== `enabled` If this option is set to true, {beatname_uc} loads the sample Kibana dashboards automatically on startup. If no other options are set, the dashboard are loaded @@ -49,40 +51,46 @@ from the local `kibana` directory in the home path of the installation. To load dashboards from a different location, you can configure one of the following options: <>, or <>. +[float] [[directory-option]] -===== directory +==== `directory` The directory that contains the dashboards to load. The default is the `kibana` folder in the home path. +[float] [[url-option]] -===== url +==== `url` The URL to use for downloading the dashboard archive. If this option is set, {beatname_uc} downloads the dashboard archive from the specified URL instead of using the local directory. - +[float] [[file-option]] -===== file +==== `file` The file archive (zip file) that contains the dashboards to load. If this option is set, {beatname_uc} looks for a dashboard archive in the specified path instead of using the local directory. -===== beat +[float] +==== `beat` In case the archive contains the dashboards for multiple Beats, this setting lets you select the Beat for which you want to load dashboards. To load all the dashboards in the archive, set this option to an empty string. The default is +"{beatname_lc}"+. -===== kibana_index +[float] +==== `kibana_index` The name of the Kibana index to use for setting the configuration. The default is `".kibana"` -===== index + +[float] +==== `index` The Elasticsearch index name. This setting overwrites the index name defined in the dashboards and index pattern. Example: `"testbeat-*"` diff --git a/libbeat/docs/generalconfig.asciidoc b/libbeat/docs/generalconfig.asciidoc index 36473f30477..db07e820cf1 100644 --- a/libbeat/docs/generalconfig.asciidoc +++ b/libbeat/docs/generalconfig.asciidoc @@ -10,11 +10,12 @@ //// Make sure this content appears below a level 2 heading. ////////////////////////////////////////////////////////////////////////// +[float] [[configuration-general]] -=== General +=== General configuration options -The general section of the +{beatname_lc}.yml+ config file contains configuration options for the Beat and some -general settings that control its behaviour. +These options are supported by all Elastic Beats. Because they are common +options, they are not namespaced. Here is an example configuration: @@ -24,11 +25,8 @@ name: "my-shipper" tags: ["service-X", "web-tier"] ------------------------------------------------------------------------------ -==== General Options - -You can specify the following options: - -===== name +[float] +==== `name` The name of the Beat. If this option is empty, the `hostname` of the server is used. The name is included as the `beat.name` field in each published transaction. You can @@ -41,7 +39,8 @@ Example: name: "my-shipper" ------------------------------------------------------------------------------ -===== tags +[float] +==== `tags` A list of tags that the Beat includes in the `tags` field of each published transaction. Tags make it easy to group servers by different logical properties. @@ -56,8 +55,9 @@ Example: tags: ["my-service", "hardware", "test"] -------------------------------------------------------------------------------- +[float] [[libbeat-configuration-fields]] -===== fields +==== `fields` Optional fields that you can specify to add additional information to the output. Fields can be scalar values, arrays, dictionaries, or any nested @@ -72,9 +72,10 @@ Example: fields: {project: "myproject", instance-id: "574734885120952459"} ------------------------------------------------------------------------------ -===== fields_under_root +[float] +==== `fields_under_root` -If this option is set to true, the custom <> are +If this option is set to true, the custom <> 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, then the custom fields overwrite the other fields. @@ -89,16 +90,19 @@ fields: region: us-east-1 ------------------------------------------------------------------------------ -===== queue_size +[float] +==== `queue_size` The internal queue size for single events in the processing pipeline. The default value is 1000. -===== bulk_queue_size +[float] +==== `bulk_queue_size` (DO NOT TOUCH) The internal queue size for bulk events in the processing pipeline. The default value is 0. -===== max_procs +[float] +==== `max_procs` Sets the maximum number of CPUs that can be executing simultaneously. The default is the number of logical CPUs available in the system. diff --git a/libbeat/docs/gettingstarted.asciidoc b/libbeat/docs/gettingstarted.asciidoc index fd10d933f5e..002c0adf4f8 100644 --- a/libbeat/docs/gettingstarted.asciidoc +++ b/libbeat/docs/gettingstarted.asciidoc @@ -1,5 +1,5 @@ [[getting-started]] -== Getting Started with Beats and the Elastic Stack +== Getting started with Beats and the Elastic Stack Looking for an "ELK tutorial" that shows how to set up the Elastic stack for Beats? You've come to the right place. The topics in this section describe how to install and configure @@ -24,7 +24,7 @@ a cluster. You'll probably also want to automate the installation process. [[elasticsearch-installation]] -=== Installing Elasticsearch +=== Install Elasticsearch https://www.elastic.co/products/elasticsearch[Elasticsearch] is a real-time, distributed storage, search, and analytics engine. It can be used for many @@ -134,7 +134,7 @@ endif::[] You can learn more about installing, configuring, and running Elasticsearch in the https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html[Elasticsearch Reference]. -==== Making Sure Elasticsearch is Up and Running +==== Make sure Elasticsearch is up and running To test that the Elasticsearch daemon is up and running, try sending an HTTP GET @@ -167,7 +167,7 @@ You should see a response similar to this: ---------------------------------------------------------------------- [[logstash-installation]] -=== Installing Logstash (Optional) +=== Install Logstash (Optional) The simplest architecture for the Beats platform setup consists of one or more Beats, Elasticsearch, and Kibana. This architecture is easy to get started @@ -264,7 +264,7 @@ Don't start Logstash yet. You need to set a couple of configuration options firs endif::[] [[logstash-setup]] -==== Setting Up Logstash +==== Set up Logstash In this setup, the Beat sends events to Logstash. Logstash receives these events by using the @@ -318,7 +318,7 @@ To use this setup, you'll also need to configure your Beat to use Logstash. For more information, see the documentation for the Beat. [[logstash-input-update]] -===== Updating the Beats Input Plugin for Logstash +===== Update the Beats input plugin for Logstash Plugins have their own release cycle and are often released independent of Logstash’s core release cycle. To ensure that you have the latest version of @@ -345,7 +345,7 @@ with input plugins in Logstash are available https://www.elastic.co/guide/en/logstash/current/working-with-plugins.html[here]. -==== Starting Logstash +==== Start Logstash Now you can start Logstash. Use the command that works with your system. If you installed Logstash as a deb or rpm package, make sure the config file is in the @@ -386,7 +386,7 @@ You can learn more about installing, configuring, and running Logstash https://www.elastic.co/guide/en/logstash/current/getting-started-with-logstash.html[here]. [[kibana-installation]] -=== Installing Kibana +=== Install Kibana https://www.elastic.co/products/kibana[Kibana] is a visualization application that gets its data from Elasticsearch. It provides a customizable and @@ -475,7 +475,7 @@ endif::[] You can find Kibana binaries for other operating systems on the https://www.elastic.co/downloads/kibana[Kibana downloads page]. -==== Launching the Kibana Web Interface +==== Launch the Kibana web interface To launch the Kibana web interface, point your browser to port 5601. For example, http://127.0.0.1:5601[http://127.0.0.1:5601]. diff --git a/libbeat/docs/installing-beats.asciidoc b/libbeat/docs/installing-beats.asciidoc index 6d99e75e0a1..01e9c02482c 100644 --- a/libbeat/docs/installing-beats.asciidoc +++ b/libbeat/docs/installing-beats.asciidoc @@ -15,7 +15,7 @@ //////////////////////////////////////////////////////////////////// [[installing-beats]] -=== Installing Beats +=== Install Beats After <> the Elastic stack, you need to install and configure your Beat. diff --git a/libbeat/docs/loggingconfig.asciidoc b/libbeat/docs/loggingconfig.asciidoc index e7635a8d00f..3383f0c2d59 100644 --- a/libbeat/docs/loggingconfig.asciidoc +++ b/libbeat/docs/loggingconfig.asciidoc @@ -11,7 +11,7 @@ ////////////////////////////////////////////////////////////////////////// [[configuration-logging]] -=== Logging +== Set up logging The `logging` section of the +{beatname_lc}.yml+ config file contains options for configuring the Beats logging output. The logging system can write logs to @@ -34,15 +34,18 @@ TIP: In addition to setting logging options in the config file, you can modify the logging output configuration from the command line. See <>. -==== Logging Options +[float] +=== Configuration options You can specify the following options in the `logging` section of the +{beatname_lc}.yml+ config file: -===== to_syslog +[float] +==== `to_syslog` When true, writes all logging output to the syslog. -===== to_files +[float] +==== `to_files` When true, writes all logging output to files. The log files are automatically rotated when the log file size limit is reached. @@ -51,8 +54,9 @@ NOTE: {beatname_uc} only creates a log file if there is logging output. For example, if you set the log <> to `error` and there are no errors, there will be no log file in the directory specified for logs. +[float] [[level]] -===== level +==== `level` Minimum log level. One of `debug`, `info`, `warning`, `error`, or `critical`. The default log level is `info`. @@ -73,8 +77,9 @@ that are published. Also logs any warnings, errors, or critical errors. `critical`:: Logs critical errors only. +[float] [[selectors]] -===== selectors +==== `selectors` The list of debugging-only selector tags used by different Beats components. Use `*` to enable debug output for all components. For example add `publish` to display @@ -82,7 +87,8 @@ all the debug messages related to event publishing. When starting the Beat, selectors can be overwritten using the `-d` command line option (`-d` also sets the debug log level). -===== metrics.enabled +[float] +==== `metrics.enabled` If enabled, {beatname_uc} periodically logs its internal metrics that have changed in the last period. For each metric that changed, the delta from the @@ -100,44 +106,51 @@ Note that we currently offer no backwards compatible guarantees for the internal metrics and for this reason they are also not documented. -===== metrics.period +[float] +==== `metrics.period` The period after which to log the internal metrics. The default is 30s. -===== files.path +[float] +==== `files.path` The directory that log files are written to. The default is the logs path. See the <> section for details. -===== files.name +[float] +==== `files.name` The name of the file that logs are written to. By default, the name of the Beat is used. -===== files.rotateeverybytes +[float] +==== `files.rotateeverybytes` The maximum size of a log file. If the limit is reached, a new log file is generated. The default size limit is 10485760 (10 MB). -===== files.keepfiles +[float] +==== `files.keepfiles` The number of most recent rotated log files to keep on disk. Older files are deleted during log rotation. The default value is 7. The `keepfiles` options has to be in the range of 2 to 1024 files. -===== files.permissions +[float] +==== `files.permissions` The permission mask to apply when rotating log files. The default value is 0600. The - `permissions` options must be a valid Unix-style file permissions mask expressed + `permissions` options must be a valid Unix-style file permissions mask expressed in octal notation. In Go, numbers in octal notation must start with '0'. - + Examples: * 0644: give read and write access to the file owner, and read access to all others. * 0600: give read and write access to the file owner, and no access to all others. -* 0664: give read and write access to the file owner and members of the group +* 0664: give read and write access to the file owner and members of the group associated with the file, as well as read access to all other users. -==== Logging Format +[float] +=== Logging format The logging format is different for each logging type: diff --git a/libbeat/docs/outputconfig.asciidoc b/libbeat/docs/outputconfig.asciidoc index 6e0966f79e7..19a78151438 100644 --- a/libbeat/docs/outputconfig.asciidoc +++ b/libbeat/docs/outputconfig.asciidoc @@ -10,8 +10,27 @@ //// Make sure this content appears below a level 2 heading. ////////////////////////////////////////////////////////////////////////// +[[configuring-output]] +== Configure the output + +You configure {beatname_uc} to write to a specific output by setting options +in the `output` section of the +{beatname_lc}.yml+ config file. + +The following topics describe how to configure each supported output: + +* <> +* <> +* <> +* <> +* <> +* <> + [[elasticsearch-output]] -=== Elasticsearch Output +=== Configure the Elasticsearch output + +++++ +Elasticsearch +++++ When you specify Elasticsearch for the output, the Beat sends the transactions directly to Elasticsearch by using the Elasticsearch HTTP API. @@ -58,11 +77,11 @@ output.elasticsearch: This output works with all compatible versions of Elasticsearch. See "Supported Beats Versions" in the https://www.elastic.co/support/matrix#show_compatibility[Elastic Support Matrix]. -==== Elasticsearch Output Options +==== Configuration options You can specify the following options in the `elasticsearch` section of the +{beatname_lc}.yml+ config file: -===== enabled +===== `enabled` The enabled config is a boolean setting to enable or disable the output. If set to false, the output is disabled. @@ -71,7 +90,7 @@ The default value is true. [[hosts-option]] -===== hosts +===== `hosts` The list of Elasticsearch nodes to connect to. The events are distributed to these nodes in round robin order. If one node becomes unreachable, the event is @@ -80,7 +99,7 @@ For example: `http://192.15.3.2`, `https://es.found.io:9230` or `192.24.3.2:9300 If no port is specified, `9200` is used. NOTE: When a node is defined as an `IP:PORT`, the _scheme_ and _path_ are taken from the -<> and <> config options. +<> and <> config options. [source,yaml] ------------------------------------------------------------------------------ @@ -93,7 +112,7 @@ output.elasticsearch: In the previous example, the Elasticsearch nodes are available at `https://10.45.3.2:9220/elasticsearch` and `https://10.45.3.1:9230/elasticsearch`. -===== compression_level +===== `compression_level` The gzip compression level. Setting this value to 0 disables compression. The compression level must be in the range of 1 (best speed) to 9 (best compression). @@ -102,40 +121,40 @@ Increasing the compression level will reduce the network usage but will increase The default value is 0. -===== worker +===== `worker` The number of workers per configured host publishing events to Elasticsearch. This is best used with load balancing mode enabled. Example: If you have 2 hosts and 3 workers, in total 6 workers are started (3 for each host). -===== username +===== `username` The basic authentication username for connecting to Elasticsearch. -===== password +===== `password` The basic authentication password for connecting to Elasticsearch. -===== parameters +===== `parameters` Dictionary of HTTP parameters to pass within the url with index operations. [[protocol-option]] -===== protocol +===== `protocol` The name of the protocol Elasticsearch is reachable on. The options are: `http` or `https`. The default is `http`. However, if you specify a URL for -<>, the value of `protocol` is overridden by whatever scheme you +<>, the value of `protocol` is overridden by whatever scheme you specify in the URL. [[path-option]] -===== path +===== `path` An HTTP path prefix that is prepended to the HTTP API calls. This is useful for the cases where Elasticsearch listens behind an HTTP reverse proxy that exports the API under a custom prefix. -===== headers +===== `headers` Custom HTTP headers to add to each request created by the Elasticsearch output. Example: @@ -149,7 +168,7 @@ output.elasticsearch.headers: It is generally possible to specify multiple header values for the same header name by separating them with a comma. -===== proxy_url +===== `proxy_url` The URL of the proxy to use when connecting to the Elasticsearch servers. The value may be either a complete URL or a "host[:port]", in which case the "http" @@ -158,11 +177,11 @@ then proxy environment variables are used. See the https://golang.org/pkg/net/http/#ProxyFromEnvironment[golang documentation] for more information about the environment variables. -===== index +===== `index` The index name to write events to. The default is "{beatname_lc}-%{+yyyy.MM.dd}" (for example, "{beatname_lc}-2015.04.26"). -===== indices +===== `indices` Array of index selector rules supporting conditionals, format string based field access and name mappings. The first rule matching will be used to @@ -195,7 +214,7 @@ output.elasticsearch: message: "ERR" ------------------------------------------------------------------------------ -===== pipeline +===== `pipeline` A format string value that specifies the ingest node pipeline to write events to. @@ -208,7 +227,7 @@ output.elasticsearch: For more information, see <>. -===== pipelines +===== `pipelines` Similar to the `indices` array, this is an array of pipeline selector configurations supporting conditionals, format string based field access @@ -240,7 +259,7 @@ output.elasticsearch: fields.type: "normal" ------------------------------------------------------------------------------ -===== max_retries +===== `max_retries` The number of times to retry publishing an event after a publishing failure. After the specified number of retries, the events are typically dropped. @@ -251,7 +270,7 @@ Set `max_retries` to a value less than 0 to retry until all events are published The default is 3. -===== bulk_max_size +===== `bulk_max_size` The maximum number of events to bulk in a single Elasticsearch bulk API index request. The default is 50. @@ -269,17 +288,17 @@ Beats that publish single events (such as Packetbeat) send each event directly t Elasticsearch. Beats that publish data in batches (such as Filebeat) send events in batches based on the spooler size. -===== timeout +===== `timeout` The http request timeout in seconds for the Elasticsearch request. The default is 90. -===== flush_interval +===== `flush_interval` The number of seconds to wait for new events between two bulk API index requests. If `bulk_max_size` is reached before this interval expires, additional bulk index requests are made. -===== ssl +===== `ssl` Configuration options for SSL parameters like the certificate authority to use for HTTPS-based connections. If the `tls` section is missing, the host CAs are used for HTTPS connections to @@ -289,25 +308,19 @@ See <> for more information. [[logstash-output]] -=== Logstash Output +=== Configure the Logstash output -*Prerequisite:* To use Logstash as an output, you must -{libbeat}/logstash-installation.html#logstash-setup[install and configure] the Beats input -plugin for Logstash. +++++ +Logstash +++++ -The Logstash output sends the events directly to Logstash by using the lumberjack +The Logstash output sends events directly to Logstash by using the lumberjack protocol, which runs over TCP. Logstash allows for additional processing and routing of generated events. -Here is an example of how to configure {beatname_uc} to use Logstash: - -["source","yaml",subs="attributes"] ------------------------------------------------------------------------------- -output.logstash: - hosts: ["localhost:5044"] ------------------------------------------------------------------------------- +include::../../libbeat/docs/shared-logstash-config.asciidoc[] -==== Accessing Metadata Fields +==== Accessing metadata fields Every event sent to Logstash contains the following metadata fields that you can use in Logstash for indexing and filtering: @@ -372,12 +385,12 @@ will be similar to events directly indexed by Beats into Elasticsearch. This output works with all compatible versions of Logstash. See "Supported Beats Versions" in the https://www.elastic.co/support/matrix#show_compatibility[Elastic Support Matrix]. -==== Logstash Output Options +==== Configuration options You can specify the following options in the `logstash` section of the +{beatname_lc}.yml+ config file: -===== enabled +===== `enabled` The enabled config is a boolean setting to enable or disable the output. If set to false, the output is disabled. @@ -385,16 +398,16 @@ to false, the output is disabled. The default value is true. [[hosts]] -===== hosts +===== `hosts` The list of known Logstash servers to connect to. If load balancing is disabled, but multiple hosts are configured, one host is selected randomly (there is no precedence). If one host becomes unreachable, another one is selected randomly. All entries in this list can contain a port number. If no port number is given, the -value specified for <> is used as the default port number. +value specified for <> is used as the default port number. -===== compression_level +===== `compression_level` The gzip compression level. Setting this value to 0 disables compression. The compression level must be in the range of 1 (best speed) to 9 (best compression). @@ -403,21 +416,21 @@ Increasing the compression level will reduce the network usage but will increase The default value is 3. -===== worker +===== `worker` The number of workers per configured host publishing events to Logstash. This is best used with load balancing mode enabled. Example: If you have 2 hosts and 3 workers, in total 6 workers are started (3 for each host). [[loadbalance]] -===== loadbalance +===== `loadbalance` If set to true and multiple Logstash hosts are configured, the output plugin load balances published events onto all Logstash hosts. If set to false, the output plugin sends all events to only one host (determined at random) and will switch to another host if the selected one becomes unresponsive. The default value is false. -===== ttl +===== `ttl` Time to live for a connection to Logstash after which the connection will be re-established. Useful when Logstash hosts represent load balancers. Since the connections to Logstash hosts @@ -437,7 +450,7 @@ output.logstash: index: {beatname_lc} ------------------------------------------------------------------------------ -===== pipelining +===== `pipelining` Configures number of batches to be send asynchronously to logstash while waiting for ACK from logstash. Output only becomes blocking once number of `pipelining` @@ -445,14 +458,14 @@ batches have been written. Pipelining is disabled if a values of 0 is configured. The default value is 0. [[port]] -===== port +===== `port` deprecated[5.0.0] -The default port to use if the port number is not given in <>. The default port number +The default port to use if the port number is not given in <>. The default port number is 10200. -===== proxy_url +===== `proxy_url` The URL of the SOCKS5 proxy to use when connecting to the Logstash servers. The value must be a URL with a scheme of `socks5://`. The protocol used to @@ -463,7 +476,7 @@ password can be embedded in the URL as shown in the example. When using a proxy, hostnames are resolved on the proxy server instead of on the client. You can change this behavior by setting the -<> option. +<> option. ["source","yaml",subs="attributes"] ------------------------------------------------------------------------------ @@ -473,30 +486,30 @@ output.logstash: ------------------------------------------------------------------------------ [[logstash-proxy-use-local-resolver]] -===== proxy_use_local_resolver +===== `proxy_use_local_resolver` The `proxy_use_local_resolver` option determines if Logstash hostnames are resolved locally when using a proxy. The default value is false which means that when a proxy is used the name resolution occurs on the proxy server. [[logstash-index]] -===== index +===== `index` The index root name to write events to. The default is the Beat name. For example "{beatname_lc}" generates "[{beatname_lc}-]YYYY.MM.DD" indexes (for example, "{beatname_lc}-2015.04.26"). -===== ssl +===== `ssl` Configuration options for SSL parameters like the root CA for Logstash connections. See <> for more information. To use SSL, you must also configure the https://www.elastic.co/guide/en/logstash/current/plugins-inputs-beats.html[Beats input plugin for Logstash] to use SSL/TLS. -===== timeout +===== `timeout` The number of seconds to wait for responses from the Logstash server before timing out. The default is 30 (seconds). -===== max_retries +===== `max_retries` The number of times to retry publishing an event after a publishing failure. After the specified number of retries, the events are typically dropped. @@ -507,7 +520,7 @@ Set `max_retries` to a value less than 0 to retry until all events are published The default is 3. -===== bulk_max_size +===== `bulk_max_size` The maximum number of events to bulk in a single Logstash request. The default is 2048. @@ -526,7 +539,11 @@ Elasticsearch. Beats that publish data in batches (such as Filebeat) send events spooler size. [[kafka-output]] -=== Kafka Output +=== Configure the Kafka output + +++++ +Kafka +++++ The Kafka output sends the events to Apache Kafka. @@ -554,23 +571,23 @@ NOTE: Events bigger than <> will be This output works with Kafka 0.8, 0.9, and 0.10. -==== Kafka Output Options +==== Configuration options You can specify the following options in the `kafka` section of the +{beatname_lc}.yml+ config file: -===== enabled +===== `enabled` -The enabled config is a boolean setting to enable or disable the output. If set +The `enabled` config is a boolean setting to enable or disable the output. If set to false, the output is disabled. The default value is true. -===== hosts +===== `hosts` The list of Kafka broker addresses from where to fetch the cluster metadata. The cluster metadata contain the actual Kafka brokers events are published to. -===== version +===== `version` Kafka version ${beatname_lc} is assumed to run against. Defaults to oldest supported stable version (currently version 0.8.2.0). @@ -580,21 +597,21 @@ Event timestamps will be added, if version 0.10.0.0+ is enabled. Valid values are `0.8.2.0`, `0.8.2.1`, `0.8.2.2`, `0.8.2`, `0.8`, `0.9.0.0`, `0.9.0.1`, `0.9.0`, `0.9`, `0.10.0.0`, `0.10.0`, and `0.10`. -===== username +===== `username` The username for connecting to Kafka. If username is configured, the password must be configured as well. Only SASL/PLAIN is supported. -===== password +===== `password` The password for connecting to Kafka. -===== topic +===== `topic` The Kafka topic used for produced events. The setting can be a format string using any event field. To set the topic from document type use `%{[type]}`. -===== topics +===== `topics` Array of topic selector rules supporting conditionals, format string based field access and name mappings. The first rule matching will be used to @@ -612,11 +629,11 @@ Rule settings: *`when`*: Condition which must succeed in order to execute the current rule. -===== key +===== `key` Optional Kafka event key. If configured, the event key must be unique and can be extracted from the event using a format string. -===== partition +===== `partition` Kafka output broker event partitioning strategy. Must be one of `random`, `round_robin`, or `hash`. By default the `hash` partitioner is used. @@ -642,21 +659,21 @@ available partitions only. NOTE: Publishing to a subset of available partitions potentially increases resource usage because events may become unevenly distributed. -===== client_id +===== `client_id` The configurable ClientID used for logging, debugging, and auditing purposes. The default is "beats". -===== worker +===== `worker` The number of concurrent load-balanced Kafka output workers. -===== codec +===== `codec` Output codec configuration. If the `codec` section is missing, events will be json encoded. See <> for more information. -===== metadata +===== `metadata` Kafka metadata update settings. The metadata do contain information about brokers, topics, partition, and active leaders to use for publishing. @@ -667,7 +684,7 @@ brokers, topics, partition, and active leaders to use for publishing. *`retry.backoff`*:: Waiting time between retries during leader elections. Default is 250ms. -===== max_retries +===== `max_retries` The number of times to retry publishing an event after a publishing failure. After the specified number of retries, the events are typically dropped. @@ -678,53 +695,57 @@ Set `max_retries` to a value less than 0 to retry until all events are published The default is 3. -===== bulk_max_size +===== `bulk_max_size` The maximum number of events to bulk in a single Kafka request. The default is 2048. -===== timeout +===== `timeout` The number of seconds to wait for responses from the Kafka brokers before timing out. The default is 30 (seconds). -===== broker_timeout +===== `broker_timeout` The maximum duration a broker will wait for number of required ACKs. The default is 10s. -===== channel_buffer_size +===== `channel_buffer_size` Per Kafka broker number of messages buffered in output pipeline. The default is 256. -===== keep_alive +===== `keep_alive` The keep-alive period for an active network connection. If 0s, keep-alives are disabled. The default is 0 seconds. -===== compression +===== `compression` Sets the output compression codec. Must be one of `none`, `snappy` and `gzip`. The default is `gzip`. [[kafka-max_message_bytes]] -===== max_message_bytes +===== `max_message_bytes` The maximum permitted size of JSON-encoded messages. Bigger messages will be dropped. The default value is 1000000 (bytes). This value should be equal to or less than the broker's `message.max.bytes`. -===== required_acks +===== `required_acks` The ACK reliability level required from broker. 0=no response, 1=wait for local commit, -1=wait for all replicas to commit. The default is 1. Note: If set to 0, no ACKs are returned by Kafka. Messages might be lost silently on error. -===== flush_interval +===== `flush_interval` The number of seconds to wait for new events between two producer API calls. -===== ssl +===== `ssl` Configuration options for SSL parameters like the root CA for Kafka connections. See <> for more information. [[redis-output]] -=== Redis Output +=== Configure the Redis output + +++++ +Redis +++++ The Redis output inserts the events into a Redis list or a Redis channel. This output plugin is compatible with @@ -746,18 +767,18 @@ output.redis: This output works with Redis 3.2.4. -==== Redis Output Options +==== Configuration options You can specify the following options in the `redis` section of the +{beatname_lc}.yml+ config file: -===== enabled +===== `enabled` The enabled config is a boolean setting to enable or disable the output. If set to false, the output is disabled. The default value is true. -===== hosts +===== `hosts` The list of Redis servers to connect to. If load balancing is enabled, the events are distributed to the servers in the list. If one server becomes unreachable, the events are @@ -765,20 +786,20 @@ distributed to the reachable servers only. You can define each Redis server by s `HOST` or `HOST:PORT`. For example: `"192.15.3.2"` or `"test.redis.io:12345"`. If you don't specify a port number, the value configured by `port` is used. -===== port +===== `port` deprecated[5.0.0] The Redis port to use if `hosts` does not contain a port number. The default is 6379. -===== index +===== `index` deprecated[5.0.0,The `index` setting is renamed to `key`] The name of the Redis list or channel the events are published to. The default is "{beatname_lc}". -===== key +===== `key` The name of the Redis list or channel the events are published to. The default is "{beatname_lc}". @@ -796,7 +817,7 @@ output.redis: key: "%{[fields.list]:fallback}" ------------------------------------------------------------------------------ -===== keys +===== `keys` Array of key selector configurations supporting conditionals, format string based field access and name mappings. The first rule matching will be used to @@ -834,15 +855,15 @@ output.redis: "mysql": "backend_list" ------------------------------------------------------------------------------ -===== password +===== `password` The password to authenticate with. The default is no authentication. -===== db +===== `db` The Redis database number where the events are published. The default is 0. -===== datatype +===== `datatype` The Redis data type to use for publishing events.If the data type is `list`, the Redis RPUSH command is used and all events are added to the list with the key defined under `key`. @@ -850,46 +871,46 @@ If the data type `channel` is used, the Redis `PUBLISH` command is used and mean are pushed to the pub/sub mechanism of Redis. The name of the channel is the one defined under `key`. The default value is `list`. -===== codec +===== `codec` Output codec configuration. If the `codec` section is missing, events will be json encoded. See <> for more information. -===== host_topology +===== `host_topology` deprecated[5.0.0] The Redis host to connect to when using topology map support. Topology map support is disabled if this option is not set. -===== password_topology +===== `password_topology` deprecated[5.0.0] The password to use for authenticating with the Redis topology server. The default is no authentication. -===== db_topology +===== `db_topology` deprecated[5.0.0] The Redis database number where the topology information is stored. The default is 1. -===== worker +===== `worker` The number of workers to use for each host configured to publish events to Redis. Use this setting along with the `loadbalance` option. For example, if you have 2 hosts and 3 workers, in total 6 workers are started (3 for each host). -===== loadbalance +===== `loadbalance` If set to true and multiple hosts or workers are configured, the output plugin load balances published events onto all Redis hosts. If set to false, the output plugin sends all events to only one host (determined at random) and will switch to another host if the currently selected one becomes unreachable. The default value is true. -===== timeout +===== `timeout` The Redis connection timeout in seconds. The default is 5 seconds. -===== max_retries +===== `max_retries` The number of times to retry publishing an event after a publishing failure. After the specified number of retries, the events are typically dropped. @@ -900,7 +921,7 @@ Set `max_retries` to a value less than 0 to retry until all events are published The default is 3. -===== bulk_max_size +===== `bulk_max_size` The maximum number of events to bulk in a single Redis request or pipeline. The default is 2048. @@ -919,13 +940,13 @@ Packetbeat) send each event directly to Redis. Beats that publish data in batches (such as Filebeat) send events in batches based on the spooler size. -===== ssl +===== `ssl` Configuration options for SSL parameters like the root CA for Redis connections guarded by SSL proxies (for example https://www.stunnel.org[stunnel]). See <> for more information. -===== proxy_url +===== `proxy_url` The URL of the SOCKS5 proxy to use when connecting to the Redis servers. The value must be a URL with a scheme of `socks5://`. You cannot use a web proxy @@ -936,16 +957,20 @@ a username and password in the URL. When using a proxy, hostnames are resolved on the proxy server instead of on the client. You can change this behavior by setting the -<> option. +<> option. [[redis-proxy-use-local-resolver]] -===== proxy_use_local_resolver +===== `proxy_use_local_resolver` This option determines whether Redis hostnames are resolved locally when using a proxy. The default value is false, which means that name resolution occurs on the proxy server. [[file-output]] -=== File Output +=== Configure the File output + +++++ +File +++++ The File output dumps the transactions into a file where each transaction is in a JSON format. Currently, this output is used for testing, but it can be used as input for @@ -960,11 +985,11 @@ output.file: #number_of_files: 7 ------------------------------------------------------------------------------ -==== File Output Options +==== Configuration options You can specify the following options in the `file` section of the +{beatname_lc}.yml+ config file: -===== enabled +===== `enabled` The enabled config is a boolean setting to enable or disable the output. If set to false, the output is disabled. @@ -972,35 +997,39 @@ to false, the output is disabled. The default value is true. [[path]] -===== path +===== `path` The path to the directory where the generated files will be saved. This option is mandatory. -===== filename +===== `filename` The name of the generated files. The default is set to the Beat name. For example, the files generated by default for {beatname_uc} would be "{beatname_lc}", "{beatname_lc}.1", "{beatname_lc}.2", and so on. -===== rotate_every_kb +===== `rotate_every_kb` The maximum size in kilobytes of each file. When this size is reached, the files are rotated. The default value is 10240 KB. -===== number_of_files +===== `number_of_files` -The maximum number of files to save under <>. When this number of files is reached, the +The maximum number of files to save under <>. When this number of files is reached, the oldest file is deleted, and the rest of the files are shifted from last to first. The default is 7 files. -===== codec +===== `codec` Output codec configuration. If the `codec` section is missing, events will be json encoded. See <> for more information. [[console-output]] -=== Console Output +=== Configure the Console output + +++++ +Console +++++ The Console output writes events in JSON format to stdout. @@ -1010,29 +1039,29 @@ output.console: pretty: true ------------------------------------------------------------------------------ -==== Console Output Options +==== Configuration options You can specify the following options in the `console` section of the +{beatname_lc}.yml+ config file: -===== pretty +===== `pretty` If `pretty` is set to true, events written to stdout will be nicely formatted. The default is false. -===== codec +===== `codec` Output codec configuration. If the `codec` section is missing, events will be json encoded using the `pretty` option. See <> for more information. -===== enabled +===== `enabled` The enabled config is a boolean setting to enable or disable the output. If set to false, the output is disabled. The default value is true. -===== bulk_max_size +===== `bulk_max_size` The maximum number of events to buffer internally during publishing. The default is 2048. @@ -1043,7 +1072,11 @@ Setting `bulk_max_size` to 0 disables buffering in libbeat. [[configuration-output-ssl]] -=== SSL +=== Configure SSL options + +++++ +SSL options +++++ You can specify SSL options for any output that supports SSL. @@ -1058,11 +1091,13 @@ output.elasticsearch: ssl.key: "/etc/pki/client/cert.key" ------------------------------------------------------------------------------ -==== SSL Options +Also see <>. + +==== Configuration options You can specify the following options in the `ssl` section of the +{beatname_lc}.yml+ config file: -===== enabled +===== `enabled` The `enabled` setting can be used to disable the ssl configuration by setting it to `false`. The default value is `true`. @@ -1070,13 +1105,13 @@ it to `false`. The default value is `true`. Note: SSL settings are disabled if either `enabled` is set to `false` or the `ssl` section is missing. -===== certificate_authorities +===== `certificate_authorities` The list of root certificates for server verifications. If `certificate_authorities` is empty or not set, the trusted certificate authorities of the host system are used. [[certificate]] -===== certificate: "/etc/pki/client/cert.pem" +===== `certificate: "/etc/pki/client/cert.pem"` The path to the certificate for SSL client authentication. If the certificate is not specified, client authentication is not available. The connection @@ -1084,18 +1119,18 @@ might fail if the server requests client authentication. If the SSL server does require client authentication, the certificate will be loaded, but not requested or used by the server. -When this option is configured, the <> option is also required. +When this option is configured, the <> option is also required. [[certificate_key]] -===== key: "/etc/pki/client/cert.key" +===== `key: "/etc/pki/client/cert.key"` -The client certificate key used for client authentication. This option is required if <> is specified. +The client certificate key used for client authentication. This option is required if <> is specified. -===== key_passphrase +===== `key_passphrase` The passphrase used to decrypt an encrypted key stored in the configured `key` file. -===== supported_protocols +===== `supported_protocols` List of allowed SSL/TLS versions. If SSL/TLS server decides for protocol versions not configured, the connection will be dropped during or after the handshake. The @@ -1104,7 +1139,7 @@ setting is a list of allowed protocol versions: The default value is `[TLSv1.0, TLSv1.1, TLSv1.2]`. -===== verification_mode +===== `verification_mode` This option controls whether the client verifies server certificates and host names. The values `none` and `full` can be used. If `verification_mode` is set @@ -1114,7 +1149,7 @@ option for testing only. The default is `full`. -===== cipher_suites +===== `cipher_suites` The list of cipher suites to use. The first entry has the highest priority. If this option is omitted, the Go crypto library's default @@ -1168,7 +1203,7 @@ Here is a list of acronyms used in defining the cipher suites: Cipher suites using SHA-1, SHA-256 or SHA-384. -===== curve_types +===== `curve_types` The list of curve types for ECDHE (Elliptic Curve Diffie-Hellman ephemeral key exchange). @@ -1179,7 +1214,11 @@ The following elliptic curve types are available: * P-521 [[configuration-output-codec]] -=== Output Codec +=== Configure the ouput codec + +++++ +Output codec +++++ For outputs that do not require a specific encoding, you can change the encoding by using the codec configuration. You can specify either the `json` or `format` diff --git a/libbeat/docs/overview.asciidoc b/libbeat/docs/overview.asciidoc index fa2c1cd8cec..48088777b56 100644 --- a/libbeat/docs/overview.asciidoc +++ b/libbeat/docs/overview.asciidoc @@ -1,5 +1,9 @@ == Overview +++++ +Beats overview +++++ + The _Beats_ are open source data shippers that you install as _agents_ on your servers to send different types of operational data to https://www.elastic.co/products/elasticsearch[Elasticsearch]. Beats can diff --git a/libbeat/docs/processors-config.asciidoc b/libbeat/docs/processors-config.asciidoc deleted file mode 100644 index 37e91374103..00000000000 --- a/libbeat/docs/processors-config.asciidoc +++ /dev/null @@ -1,23 +0,0 @@ -////////////////////////////////////////////////////////////////////////// -//// This content is shared by all Elastic Beats. Make sure you keep the -//// descriptions here generic enough to work for all Beats that include -//// this file. When using cross references, make sure that the cross -//// references resolve correctly for any files that include this one. -//// Use the appropriate variables defined in the index.asciidoc file to -//// resolve Beat names: beatname_uc and beatname_lc. -//// Use the following include to pull this content into a doc file: -//// include::../../libbeat/docs/processors-config.asciidoc[] -//// Make sure this content appears below a level 2 heading. -////////////////////////////////////////////////////////////////////////// - -[[configuration-processors]] -=== Processors - -You can specify processors in the +{beatname_lc}.yml+ file to filter and -enhance the data before sending events to the configured output. - -See <> for information about specifying -processors in your config. - - - diff --git a/libbeat/docs/processors-using.asciidoc b/libbeat/docs/processors-using.asciidoc index 4620e9bc2f5..7fc0c14dd0c 100644 --- a/libbeat/docs/processors-using.asciidoc +++ b/libbeat/docs/processors-using.asciidoc @@ -1,5 +1,5 @@ [[defining-processors]] -=== Defining Processors +=== Define processors You define processors in the +{beatname_lc}.yml+ file to filter and enhance the data before sending events to the configured output. @@ -24,13 +24,13 @@ processors: Where: -* specifies a <> that performs some kind +* `` specifies a <> that performs some kind of action, such as selecting the fields that are exported or adding metadata to the event. -* specifies an optional <>. If the +* `` specifies an optional <>. If the condition is present, then the action is executed only if the condition is fulfilled. If no condition is passed, then the action is always executed. -* is the list of parameters to pass to the processor. +* `` is the list of parameters to pass to the processor. [[processors]] ==== Processors @@ -72,7 +72,7 @@ The supported conditions are: [float] [[condition-equals]] -===== equals +===== `equals` With the `equals` condition, you can compare if a field has a certain value. The condition accepts only an integer or a string value. @@ -88,7 +88,7 @@ equals: [float] [[condition-contains]] -===== contains +===== `contains` The `contains` condition checks if a value is part of a field. The field can be a string or an array of strings. The condition accepts only a string value. @@ -104,7 +104,7 @@ contains: [float] [[condition-regexp]] -===== regexp +===== `regexp` The `regexp` condition checks the field against a regular expression. The condition accepts only strings. @@ -120,7 +120,7 @@ regexp: [float] [[condition-range]] -===== range +===== `range` The `range` condition checks if the field is in a certain range of values. The condition supports `lt`, `lte`, `gt` and `gte`. The condition accepts only @@ -158,7 +158,7 @@ range: [float] [[condition-or]] -===== OR +===== `or` The `or` operator receives a list of conditions. @@ -186,7 +186,7 @@ or: [float] [[condition-and]] -===== AND +===== `and` The `and` operator receives a list of conditions. @@ -226,7 +226,7 @@ or: [float] [[condition-not]] -===== NOT +===== `not` The `not` operator receives the condition to negate. @@ -247,7 +247,7 @@ not: ------ [[add-cloud-metadata]] -=== Adding Cloud Metadata +=== Add cloud metadata The `add_cloud_metadata` processor enriches each event with instance metadata from the machine's hosting provider. At startup it will detect the hosting @@ -366,7 +366,7 @@ ECS instance. ------------------------------------------------------------------------------- [[add-locale]] -=== Adding the Local Time Zone +=== Add the local time zone The `add_locale` processor enriches each event with the machine's time zone offset from UTC or with the name of the time zone. It supports one configuration @@ -398,7 +398,7 @@ regular time. [[decode-json-fields]] -=== Decoding JSON Fields +=== Decode JSON fields The `decode_json_fields` processor decodes fields containing JSON strings and replaces the strings with valid JSON objects. @@ -429,7 +429,7 @@ exist in the event are overwritten by keys from the decoded JSON object. The default value is false. [[drop-event]] -=== Dropping Events +=== Drop events The `drop_event` processor drops the entire event if the associated condition is fulfilled. The condition is mandatory, because without one, all the events @@ -446,7 +446,7 @@ processors: See <> for a list of supported conditions. [[drop-fields]] -=== Dropping Fields from Events +=== Drop fields from events The `drop_fields` processor specifies which fields to drop if a certain condition is fulfilled. The condition is optional. If it's missing, the @@ -468,7 +468,7 @@ NOTE: If you define an empty list of fields under `drop_fields`, then no fields are dropped. [[include-fields]] -=== Adding Additional Fields to Events +=== Add additional fields to events The `include_fields` processor specifies which fields to export if a certain condition is fulfilled. The condition is optional. If it's missing, the @@ -493,7 +493,7 @@ NOTE: If you define an empty list of fields under `include_fields`, then only the required fields, `@timestamp` and `type`, are exported. [[add-kubernetes-metadata]] -=== Adding Kubernetes Metadata +=== Add Kubernetes metadata The `add_kubernetes_metadata` processor annotates each event with relevant metadata based on which Kubernetes pod the event originated from. Each event is @@ -563,7 +563,7 @@ processors: ------------------------------------------------------------------------------- [[add-docker-metadata]] -=== Adding Docker metadata +=== Add Docker metadata The `add_docker_metadata` processor annotates each event with relevant metadata from Docker containers: diff --git a/libbeat/docs/reference-yml.asciidoc b/libbeat/docs/reference-yml.asciidoc new file mode 100644 index 00000000000..7f9b1854d9b --- /dev/null +++ b/libbeat/docs/reference-yml.asciidoc @@ -0,0 +1,31 @@ +[id="{beatname_lc}-reference-yml"] +== {beatname_lc}.reference.yml + +//REVIEWERS: Right now, I'm referencing the path to the file in the beats repo, but to make sure we don't expose new config options prematurely (for example, for 6.0.1) I'll need to make a copy of the file and put in the docs directory. + +The following reference file is available with your {beatname_uc} installation. It +shows all non-deprecated {beatname_uc} options. You can copy from this file and paste +configurations into the +{beatname_lc}.yml+ file to customize it. + +ifeval::["{beatname_lc}"!="auditbeat"] + +TIP: For rpm and deb, you'll find the reference configuration file at +/etc/{beatname_lc}/{beatname_lc}.reference.yml+. Under +Docker, it's located at +/usr/share/{beatname_lc}/{beatname_lc}.reference.yml+. For mac and win, +look in the archive that you just extracted. + +endif::[] + +ifeval::["{beatname_lc}"=="auditbeat"] + +TIP: For rpm and deb, you'll find the reference configuration file at +/etc/{beatname_lc}/{beatname_lc}.reference.yml+. Under +Docker, it's located at +/usr/share/{beatname_lc}/{beatname_lc}.reference.yml+. For mac and win, +look in the archive that you just extracted. + +endif::[] + +The contents of the file are included here for your convenience. + +[source,yaml] +-- +include::../../{beatname_lc}/{beatname_lc}.reference.yml[] +-- diff --git a/libbeat/docs/regexp.asciidoc b/libbeat/docs/regexp.asciidoc index 37955127268..469931de91f 100644 --- a/libbeat/docs/regexp.asciidoc +++ b/libbeat/docs/regexp.asciidoc @@ -10,7 +10,7 @@ ////////////////////////////////////////////////////////////////////////// [[regexp-support]] -== Regular Expression Support +== Regular expression support {beatname_uc} regular expression support is based on https://godoc.org/regexp/syntax[RE2]. diff --git a/libbeat/docs/shared-config-ingest.asciidoc b/libbeat/docs/shared-config-ingest.asciidoc index a86db676900..6004158dd1b 100644 --- a/libbeat/docs/shared-config-ingest.asciidoc +++ b/libbeat/docs/shared-config-ingest.asciidoc @@ -10,17 +10,17 @@ ////////////////////////////////////////////////////////////////////////// [[configuring-ingest-node]] -== Configuring {beatname_uc} to Use Ingest Node +== Parse logs by using ingest node When you use Elasticsearch for output, you can configure {beatname_uc} to use {elasticsearch}/ingest.html[ingest node] to pre-process documents before the actual indexing takes place in Elasticsearch. Ingest node is a convenient processing option when you want to do some extra processing on your data, but you do not require the full power of Logstash. For example, you can create an ingest node pipeline in Elasticsearch that consists of one processor -that removes a field in a document followed by another processor that renames a field. +that removes a field in a document followed by another processor that renames a field. After defining the pipeline in Elasticsearch, you simply configure your Beat to use the pipeline. To configure -{beatname_uc}, you specify the pipeline ID in the `parameters` option under `elasticsearch` in the +{beatname_uc}, you specify the pipeline ID in the `parameters` option under `elasticsearch` in the +{beatname_lc}.yml+ file: [source,yaml] diff --git a/libbeat/docs/shared-directory-layout.asciidoc b/libbeat/docs/shared-directory-layout.asciidoc index 0d9b1887b1a..73dffd3e287 100644 --- a/libbeat/docs/shared-directory-layout.asciidoc +++ b/libbeat/docs/shared-directory-layout.asciidoc @@ -10,7 +10,7 @@ ////////////////////////////////////////////////////////////////////////// [[directory-layout]] -=== Directory Layout +=== Directory layout The directory layout of an installation is as follows: diff --git a/libbeat/docs/shared-docker.asciidoc b/libbeat/docs/shared-docker.asciidoc index f0113d385ee..02de5e91f30 100644 --- a/libbeat/docs/shared-docker.asciidoc +++ b/libbeat/docs/shared-docker.asciidoc @@ -25,7 +25,7 @@ code can be found on https://github.com/elastic/beats-docker/tree/{doc-branch}[GitHub]. [float] -=== Configuring {beatname_uc} on Docker +=== Configure {beatname_uc} on Docker The Docker image provides several methods for configuring {beatname_uc}. The conventional approach is to provide a configuration file via a bind-mounted @@ -33,7 +33,7 @@ volume, but it's also possible to create a custom image with your configuration included. [float] -==== Bind-Mounted Configuration +==== Bind-mounted configuration One way to configure {beatname_uc} on Docker is to provide +{beatname_lc}.yml+ via bind-mounting. With +docker run+, the bind-mount can be specified like this: @@ -46,7 +46,7 @@ docker run \ -------------------------------------------- [float] -==== Custom Image Configuration +==== Custom image configuration It's possible to embed your {beatname_uc} configuration in a custom image. Here is an example Dockerfile to achieve this: diff --git a/libbeat/docs/shared-env-vars.asciidoc b/libbeat/docs/shared-env-vars.asciidoc index 8400d54e93e..d04b7b6df03 100644 --- a/libbeat/docs/shared-env-vars.asciidoc +++ b/libbeat/docs/shared-env-vars.asciidoc @@ -15,7 +15,7 @@ ifdef::standalone[] [[using-environ-vars]] -== Using Environment Variables in the Configuration +== Use environment variables in the configuration endif::[] @@ -78,7 +78,7 @@ and what each configuration looks like after replacement: |================================== [float] -=== Specifying Complex Objects in Environment Variables +=== Specify complex objects in environment variables You can specify complex objects, such as lists or dictionaries, in environment variables by using a JSON-like syntax. diff --git a/libbeat/docs/shared-logstash-config.asciidoc b/libbeat/docs/shared-logstash-config.asciidoc index 3024d04ddec..071b51e2bd1 100644 --- a/libbeat/docs/shared-logstash-config.asciidoc +++ b/libbeat/docs/shared-logstash-config.asciidoc @@ -9,15 +9,17 @@ //// include::../../libbeat/docs/shared-logstash-config.asciidoc[] ////////////////////////////////////////////////////////////////////////// -*Prerequisite:* To use Logstash as an output, you must also -{libbeat}/logstash-installation.html#logstash-setup[set up Logstash] to receive events -from Beats. +[IMPORTANT] +.Prerequisite +To use Logstash as an output, you must +{libbeat}/logstash-installation.html#logstash-setup[install and configure] the Beats input +plugin for Logstash. If you want to use Logstash to perform additional processing on the data collected by {beatname_uc}, you need to configure {beatname_uc} to use Logstash. To do this, you edit the {beatname_uc} configuration file to disable the Elasticsearch -output by commenting it out and enable the Logstash output by uncommenting the +output by commenting it out and enable the Logstash output by uncommenting the logstash section: [source,yaml] @@ -35,7 +37,7 @@ because the options for auto loading the template are only available for the Ela ifdef::allplatforms[] -TIP: To test your configuration file, change to the directory where the {beatname_uc} +TIP: To test your configuration file, change to the directory where the {beatname_uc} binary is installed, and run {beatname_uc} in the foreground with the following options specified: +./{beatname_lc} -configtest -e+. Make sure your config files are in the path expected by {beatname_uc} (see <>). If you @@ -45,7 +47,7 @@ endif::allplatforms[] ifdef::win[] -TIP: To test your configuration file, change to the directory where the {beatname_uc} +TIP: To test your configuration file, change to the directory where the {beatname_uc} binary is installed, and run {beatname_uc} in the foreground with the following options specified: +.\winlogbeat.exe -c .\winlogbeat.yml -configtest -e+. diff --git a/libbeat/docs/shared-path-config.asciidoc b/libbeat/docs/shared-path-config.asciidoc index b29e5addcd8..1b1c6e6230d 100644 --- a/libbeat/docs/shared-path-config.asciidoc +++ b/libbeat/docs/shared-path-config.asciidoc @@ -11,7 +11,9 @@ ////////////////////////////////////////////////////////////////////////// [[configuration-path]] -=== Paths +== Set up project paths + +//REVIEWERS: I'm not sure if "project paths" is the right way to describe these settings, but I want to differentiate the path users set here from other paths (like the prospector setting). The `path` section of the +{beatname_lc}.yml+ config file contains configuration options that define where the Beat looks for its files. For example, all Beats @@ -33,11 +35,13 @@ path.logs: /var/log/ Note that it is possible to override these options by using command line flags. -==== Path Options +[float] +=== Configuration options You can specify the following options in the `path` section of the +{beatname_lc}.yml+ config file: -===== home +[float] +==== `home` The home path for the {beatname_uc} installation. This is the default base path for all other path settings and for miscellaneous files that come with the distribution (for example, the @@ -51,7 +55,8 @@ Example: path.home: /usr/share/beats ------------------------------------------------------------------------------ -===== config +[float] +==== `config` The configuration path for the {beatname_uc} installation. This is the default base path for configuration files, including the main YAML configuration file and the @@ -65,7 +70,8 @@ Example: path.config: /usr/share/beats/config ------------------------------------------------------------------------------ -===== data +[float] +==== `data` The data path for the {beatname_uc} installation. This is the default base path for all the files in which {beatname_uc} needs to store its data. If not set by a CLI @@ -80,7 +86,8 @@ Example: path.data: /var/lib/beats ------------------------------------------------------------------------------ -===== logs +[float] +==== `logs` The logs path for a {beatname_uc} installation. This is the default location for the Beat's log files. If not set by a CLI flag or in the configuration file, the default diff --git a/libbeat/docs/shared-ssl-logstash-config.asciidoc b/libbeat/docs/shared-ssl-logstash-config.asciidoc index 0434b2ba830..e902c150ca4 100644 --- a/libbeat/docs/shared-ssl-logstash-config.asciidoc +++ b/libbeat/docs/shared-ssl-logstash-config.asciidoc @@ -74,7 +74,7 @@ https://www.elastic.co/guide/en/logstash/current/plugins-inputs-beats.html[docum [float] [[testing-ssl-logstash]] -=== Validating the Logstash Server's Certificate +=== Validate the Logstash server's certificate Before running {beatname_uc}, you should validate the Logstash server's certificate. You can use `curl` to validate the certificate even though the protocol used to communicate with Logstash is not based on HTTP. For example: @@ -126,7 +126,7 @@ curl: (51) SSL: certificate verification failed (result: 5) See the <> for info about resolving this issue. [float] -=== Testing the Beats to Logstash Connection +=== Test the Beats to Logstash connection If you have {beatname_uc} running as a service, first stop the service. Then test your setup by running {beatname_uc} in the foreground so you can quickly see any errors that occur: diff --git a/libbeat/docs/shared-template-load.asciidoc b/libbeat/docs/shared-template-load.asciidoc index 12f8ff2c0e0..02af4f54698 100644 --- a/libbeat/docs/shared-template-load.asciidoc +++ b/libbeat/docs/shared-template-load.asciidoc @@ -33,7 +33,7 @@ For more information, see: * <> - required for Logstash output [[load-template-auto]] -==== Configuring Template Loading +==== Configure template loading By default, {beatname_uc} automatically loads the recommended template file, +fields.yml+, if Elasticsearch output is enabled. You can configure {beatname_lc} to load a different template @@ -57,7 +57,7 @@ The options for auto loading the template are not supported if you are using the Logstash output. [[load-template-manually]] -==== Loading the Template Manually +==== Load the template manually If you disable automatic template loading, you need to run the following command to load the template: diff --git a/libbeat/docs/template-config.asciidoc b/libbeat/docs/template-config.asciidoc index a27b2fd9ebb..f6ee654d563 100644 --- a/libbeat/docs/template-config.asciidoc +++ b/libbeat/docs/template-config.asciidoc @@ -1,10 +1,10 @@ [[configuration-template]] -=== Template +== Load the Elasticsearch index template -The http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html[index -template] to use for setting mappings in Elasticsearch. By default, template loading is -enabled. +The `setup.template` section of the +{beatname_lc}.yml+ config file specifies the +{elasticsearch}/indices-templates.html[index template] to use for setting mappings in +Elasticsearch. You can adjust the following settings to load your own template or overwrite an existing one: @@ -23,9 +23,9 @@ is false. *`settings.index`*:: A dictionary of settings to place into the `settings.index` dictionary of the Elasticsearch template. For more details about the available Elasticsearch mapping options, please see the Elasticsearch {elasticsearch}/mapping.html[mapping reference]. - ++ Example: - ++ ["source","yaml",subs="attributes,callouts"] ---------------------------------------------------------------------- setup.template.name: "{beatname_lc}" @@ -38,9 +38,9 @@ setup.template.settings: *`settings._source`*:: A dictionary of settings for the `_source` field. For the available settings, please see the Elasticsearch {elasticsearch}/mapping-source-field.html[reference]. - ++ Example: - ++ ["source","yaml",subs="attributes,callouts"] ---------------------------------------------------------------------- setup.template.name: "{beatname_lc}" diff --git a/libbeat/docs/upgrading.asciidoc b/libbeat/docs/upgrading.asciidoc index b69ed007c61..57c5aeae267 100644 --- a/libbeat/docs/upgrading.asciidoc +++ b/libbeat/docs/upgrading.asciidoc @@ -8,7 +8,7 @@ This section gives general recommendations for upgrading the Beats: * <> [[upgrading-minor-versions]] -=== Upgrading Between Minor Versions +=== Upgrade between minor versions As a general rule, upgrading between minor versions (e.g. 5.x to 5.y, where x < y) can be done by simply installing the new release and restarting the Beat @@ -25,14 +25,14 @@ Please see the <> section for possible strategies in upgrading the Elasticsearch mapping templates. [[upgrading-1-to-5]] -=== Upgrading from 1.x to 5.x +=== Upgrade from 1.x to 5.x Before upgrading your Beats, please review the <> doc. In addition to the subsections here, please read <>. -==== Migrating Configuration Files +==== Migrate configuration files Beats 5.0 comes with several backwards incompatible configuration changes. However, we provide a script that can automatically fixup the most common @@ -70,7 +70,7 @@ The script will automatically create a backup file and overwrite the input file with the upgraded version. You can also use the `--dry` option, which doesn't modify the input file, but outputs the upgraded version to stdout instead. -==== Filebeat Registry File Location and Format +==== Filebeat registry file location and format Filebeat stores the read offset in a registry file that it persists to disk. The format of this file has changed in version 5.0, but Filebeat automatically @@ -88,11 +88,11 @@ the registry file has changed. In version 1.x it was by default named `data/registry` relative to the binary location. For upgrading in this case, we recommend copying the `.filebeat` file to `data/registry`. -==== Upgrading Topbeat to Metricbeat +==== Upgrade Topbeat to Metricbeat NOTE: When upgrading to Metricbeat, keep in mind that any data you've collected with Topbeat is not compatible with the 5.0 version of the Beats dashboards -because the underlying event data structures have changed. +because the underlying event data structures have changed. With the Beats 5.0 release, Topbeat is replaced by Metricbeat, which offers more functionality. More precisely, the Topbeat functionality is roughly equivalent @@ -164,7 +164,7 @@ The remaining configuration options (outputs, name, tags) stay the same or can be upgraded using the migration script. [[upgrade-mapping-template]] -=== Upgrading the Elasticsearch Mapping Template +=== Upgrade the Elasticsearch mapping template By default, the Elasticsearch mapping template that comes with the Beats is not re-installed if it already exists. This means that if the new Beats version diff --git a/libbeat/docs/visualizing-data.asciidoc b/libbeat/docs/visualizing-data.asciidoc index 8760de66f65..71935d19f8d 100644 --- a/libbeat/docs/visualizing-data.asciidoc +++ b/libbeat/docs/visualizing-data.asciidoc @@ -1,8 +1,8 @@ [[visualizing-data]] -== Visualizing Your Data in Kibana +== Visualizing your data in Kibana This section describes how to load the sample Beats dashboards. After loading -the dashboards in Kibana, you can modify them to meet your needs. +the dashboards in Kibana, you can modify them to meet your needs. This section includes the following topics: diff --git a/libbeat/docs/yaml.asciidoc b/libbeat/docs/yaml.asciidoc index a11e3e38e61..5d535d9d660 100644 --- a/libbeat/docs/yaml.asciidoc +++ b/libbeat/docs/yaml.asciidoc @@ -15,7 +15,7 @@ ifdef::standalone[] [[yaml-tips]] -== YAML Tips and Gotchas +== YAML tips and gotchas endif::[] @@ -23,7 +23,7 @@ The configuration file uses http://yaml.org/[YAML] for its syntax. When you edit file to modify configuration settings, there are a few things that you should know. [float] -=== Use Spaces for Indentation +=== Use spaces for indentation Indentation is meaningful in YAML. Make sure that you use spaces, rather than tab characters, to indent sections. @@ -31,7 +31,7 @@ In the default configuration files and in all the examples in the documentation, we use 2 spaces per indentation level. We recommend you do the same. [float] -=== Look at the Default Config File for Structure +=== Look at the default config file for structure The best way to understand where to define a configuration option is by looking at the provided sample configuration files. The configuration files contain most @@ -39,7 +39,7 @@ of the default configurations that are available for the Beat. To change a setti simply uncomment the line and change the values. [float] -=== Test Your Config File +=== Test your config file You can test your configuration file to verify that the structure is valid. Simply change to the directory where the binary is installed, and run @@ -66,7 +66,7 @@ endif::win[] You'll see a message if the Beat finds an error in the file. [float] -=== Wrap Regular Expressions in Single Quotation Marks +=== Wrap regular expressions in single quotation marks If you need to specify a regular expression in a YAML file, it's a good idea to wrap the regular expression in single quotation marks to work around YAML's tricky rules for string escaping. @@ -74,7 +74,7 @@ For more information about YAML, see http://yaml.org/. [float] [[wrap-paths-in-quotes]] -=== Wrap Paths in Single Quotation Marks +=== Wrap paths in single quotation marks Windows paths in particular sometimes contain spaces or characters, such as drive letters or triple dots, that may be misinterpreted by the YAML parser. @@ -83,7 +83,7 @@ To avoid this problem, it's a good idea to wrap paths in single quotation marks. [float] [[avoid-leading-zeros]] -=== Avoid Using Leading Zeros in Numeric Values +=== Avoid using leading zeros in numeric values If you use a leading zero (for example, `09`) in a numeric field without wrapping the value in single quotation marks, the value may be interpreted diff --git a/metricbeat/docs/command-line.asciidoc b/metricbeat/docs/command-line.asciidoc index 2643c2aed53..b72411a9241 100644 --- a/metricbeat/docs/command-line.asciidoc +++ b/metricbeat/docs/command-line.asciidoc @@ -1,5 +1,5 @@ [[command-line-options]] -=== Command Line Options +=== Command line options The following command line options are available for Metricbeat. To use these options, you need to start Metricbeat in the foreground. diff --git a/metricbeat/docs/configuring-howto.asciidoc b/metricbeat/docs/configuring-howto.asciidoc index 0ff071165e4..1eb0666418c 100644 --- a/metricbeat/docs/configuring-howto.asciidoc +++ b/metricbeat/docs/configuring-howto.asciidoc @@ -3,100 +3,71 @@ [partintro] -- -After following the <> in the -Getting Started, you might want to fine tune the behavior of {beatname_uc}. +Before modifying configuration settings, make sure you've completed the +<> in the Getting Started. This section describes some common use cases for changing configuration options. -To configure {beatname_uc}, you edit the configuration file. For rpm and deb, you’ll find the configuration file at -+/etc/{beatname_lc}/{beatname_lc}.yml+. There's also a full example configuration file at -+/etc/{beatname_lc}/{beatname_lc}.reference.yml+ that shows all non-deprecated options. -For mac and win, look in the archive that you extracted. +To configure {beatname_uc}, you edit the configuration file. For rpm and deb, +you’ll find the configuration file at +/etc/{beatname_lc}/{beatname_lc}.yml+. +There's also a full example configuration file at ++/etc/{beatname_lc}/{beatname_lc}.reference.yml+ that shows all non-deprecated +options. For mac and win, look in the archive that you extracted. -See the -{libbeat}/config-file-format.html[Config File Format] section of the +The {beatname_uc} configuration file uses http://yaml.org/[YAML] for its syntax. +See the {libbeat}/config-file-format.html[Config File Format] section of the _Beats Platform Reference_ for more about the structure of the config file. The following topics describe how to configure Metricbeat: -* <> +* <> +* <> +* <> +* <> * <> * <> -* <> +* <> +* <> +* <> +* <> * <> * <> * <> -[float] -== Basic configuration - -A Metricbeat configuration contains a list of modules. Each module contains the following config options: - -* `module`: The name of the module to run. For documentation about each module, see the <> section. -* `metricsets`: A list of metricsets to execute. For a list of available metricsets, see the documentation for the module. -* `enabled`: Specifies whether the module is enabled. -* `period`: How often the metricsets are executed. -* `hosts`: A list of hosts to fetch information from. For some modules, such as the System module, this setting is not required. -* `fields`: A dictionary of fields that will be sent with the metricset event. This setting is optional. -* `tags`: A list of tags that will be sent with the metricset event. This setting is optional. -* `filters`: With filters you can reduce the amount of data that is sent in the event. For more about the available filter options, see <>. This setting is optional. - -The following example shows a basic configuration for the Apache module: - -[source,yaml] ----- -metricbeat: - modules: - - module: apache - metricsets: ["status"] - hosts: ["http://127.0.0.1/"] - period: 10s - enabled: true - fields: - dc: west - tags: ["tag"] - filters: - .... ----- - -[float] -== Configuration Combinations - -You can specify a configuration that uses different combinations of modules, metricsets, periods, and hosts. In the following example, the Redis host is crawled for `stats` information every second because this is critical data, but the full list of Apache metricsets is only fetched every 30 seconds because the metrics are less critical. - -[source,yaml] ----- -metricbeat: - modules: - - module: redis - metricsets: ["info"] - hosts: ["host1"] - period: 1s - enabled: true - - module: apache - metricsets: ["info"] - hosts: ["host1"] - period: 30s - enabled: true ----- - -For a module with multiple metricsets defined, it's possible to define the module twice and specify -a different period to use for each metricset. For the following example, the `set1` metricset will be fetched every -10 seconds, while the `set2` metricset will be fetched every 2 minutes: - -[source,yaml] ----- -metricbeat: - modules: - - module: example - metricsets: ["set1"] - hosts: ["host1"] - period: 10s - - module: example - metricsets: ["set2"] - hosts: ["host1"] - period: 2m ----- +//REVIEWERS: I removed the "basic configuration" section because we were duplicating content, and it was getting out of sync + +//REVIEWERS: Moved section about config combinations because it seems premature to talk about detailed config settings in an overview. I think users will expect to see this info under the section called "Specify which modules to run". -- -include::reference/configuration.asciidoc[] +include::./metricbeat-options.asciidoc[] + +include::./metricbeat-general-options.asciidoc[] + +include::./reload-configuration.asciidoc[] + +:allplatforms: +include::../../libbeat/docs/outputconfig.asciidoc[] + +include::./metricbeat-filtering.asciidoc[] + +include::../../libbeat/docs/shared-config-ingest.asciidoc[] + +include::../../libbeat/docs/shared-path-config.asciidoc[] + +include::../../libbeat/docs/setup-config.asciidoc[] + +include::../../libbeat/docs/loggingconfig.asciidoc[] + +:standalone: +include::../../libbeat/docs/shared-env-vars.asciidoc[] + +:standalone: +:allplatforms: +include::../../libbeat/docs/yaml.asciidoc[] + +include::../../libbeat/docs/regexp.asciidoc[] + +include::../../libbeat/docs/reference-yml.asciidoc[] + + + diff --git a/metricbeat/docs/configuring-logstash.asciidoc b/metricbeat/docs/configuring-logstash.asciidoc deleted file mode 100644 index de9cb87f05a..00000000000 --- a/metricbeat/docs/configuring-logstash.asciidoc +++ /dev/null @@ -1,5 +0,0 @@ -[[config-metricbeat-logstash]] -== Configuring Metricbeat to Use Logstash - -:allplatforms: -include::../../libbeat/docs/shared-logstash-config.asciidoc[] diff --git a/metricbeat/docs/faq.asciidoc b/metricbeat/docs/faq.asciidoc index 4a46867c483..ecd05a7718b 100644 --- a/metricbeat/docs/faq.asciidoc +++ b/metricbeat/docs/faq.asciidoc @@ -1,5 +1,5 @@ [[faq]] -== Frequently Asked Questions +== Frequently asked questions This section contains frequently asked questions about Metricbeat. Also check out the https://discuss.elastic.co/c/beats/metricbeat[Metricbeat discussion forum]. @@ -21,4 +21,5 @@ sudo mount -t linprocfs /dev/null /compat/linux/proc ---- include::../../libbeat/docs/faq-limit-bandwidth.asciidoc[] + include::../../libbeat/docs/shared-faq.asciidoc[] diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 88be564434f..822daaa6e7d 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -47,10 +47,10 @@ grouped in the following categories: -- [[exported-fields-aerospike]] -== aerospike Fields +== Aerospike Fields []experimental -aerospike Module +Aerospike module @@ -766,10 +766,10 @@ Error type. [[exported-fields-ceph]] -== ceph Fields +== Ceph Fields beta[] -ceph Module +Ceph module @@ -2216,10 +2216,10 @@ Stats collected from Dropwizard. [[exported-fields-elasticsearch]] -== elasticsearch Fields +== Elasticsearch Fields []experimental -elasticsearch Module +Elasticsearch module @@ -2520,9 +2520,9 @@ type: long [[exported-fields-golang]] -== golang Fields +== Golang Fields -golang Module +Golang module @@ -3766,7 +3766,7 @@ The average queue time in ms over the last 1024 requests. [[exported-fields-http]] == HTTP Fields -http Module +HTTP module @@ -3848,7 +3848,7 @@ json metricset == Jolokia Fields []beta -Jolokia Module +Jolokia module @@ -3859,9 +3859,9 @@ jolokia contains metrics exposed via jolokia agent [[exported-fields-kafka]] -== kafka Fields +== Kafka Fields -kafka Module +Kafka module beta[] @@ -4091,10 +4091,10 @@ Broker address [[exported-fields-kibana]] -== kibana Fields +== Kibana Fields []experimental -kibana Module +Kibana module @@ -4239,10 +4239,10 @@ Kubernetes container image [[exported-fields-kubernetes]] -== kubernetes Fields +== Kubernetes Fields beta[] -kubernetes metrics +Kubernetes metrics @@ -5415,10 +5415,10 @@ Total inodes [[exported-fields-memcached]] -== memcached Fields +== Memcached Fields []beta -memcached Module +Memcached module @@ -6728,7 +6728,7 @@ The current number of idle client connections waiting for a request. [[exported-fields-php_fpm]] -== php_fpm Fields +== PHP-FPM Fields beta[] PHP-FPM server status metrics collected from PHP-FPM. @@ -7273,10 +7273,10 @@ Number of memory chunks that are not yet persisted to disk. [[exported-fields-rabbitmq]] -== rabbitmq Fields +== RabbitMQ Fields []experimental -rabbitmq Module +RabbitMQ module @@ -10101,9 +10101,9 @@ Name of the user running the process. [[exported-fields-vsphere]] -== vsphere Fields +== vSphere Fields -vsphere Module +vSphere module diff --git a/metricbeat/docs/gettingstarted.asciidoc b/metricbeat/docs/gettingstarted.asciidoc index 81336491bf6..b534fb51690 100644 --- a/metricbeat/docs/gettingstarted.asciidoc +++ b/metricbeat/docs/gettingstarted.asciidoc @@ -1,5 +1,5 @@ [[metricbeat-getting-started]] -== Getting Started With Metricbeat +== Getting started with Metricbeat Metricbeat helps you monitor your servers and the services they host by collecting metrics from the operating system and services. @@ -24,7 +24,7 @@ After installing the Elastic Stack, read the following topics to learn how to in * <> [[metricbeat-installation]] -=== Step 1: Installing Metricbeat +=== Step 1: Install Metricbeat You should install Metricbeat as close as possible to the service you want to monitor. For example, if you have four servers with MySQL running, it's @@ -152,10 +152,10 @@ endif::[] Before starting Metricbeat, you should look at the configuration options in the configuration file, for example `C:\Program Files\Metricbeat\metricbeat.yml`. For more information about these options, see -<>. +<>. [[metricbeat-configuration]] -=== Step 2: Configuring Metricbeat +=== Step 2: Configure Metricbeat include::../../libbeat/docs/shared-configuring.asciidoc[] @@ -223,17 +223,17 @@ output.elasticsearch: hosts: ["192.168.1.42:9200"] ---------------------------------------------------------------------- + -If you are sending output to Logstash, see <> +If you are sending output to Logstash, see <> instead. [[metricbeat-template]] -=== Step 3: Loading the Index Template in Elasticsearch +=== Step 3: Load the index template in Elasticsearch :allplatforms: include::../../libbeat/docs/shared-template-load.asciidoc[] [[metricbeat-starting]] -=== Step 4: Starting Metricbeat +=== Step 4: Start Metricbeat Run Metricbeat by issuing the appropriate command for your platform. @@ -286,7 +286,7 @@ By default the log files are stored in `C:\ProgramData\metricbeat\Logs`. NOTE: On Windows, statistics about system load and swap usage are currently not captured. -==== Testing the Metricbeat Installation +==== Test the Metricbeat installation To verify that your server's statistics are present in Elasticsearch, issue the following command: @@ -303,7 +303,7 @@ On Windows, if you don't have cURL installed, simply point your browser to the URL. [[metricbeat-sample-dashboards]] -=== Step 5: Loading Sample Kibana Dashboards +=== Step 5: Load sample Kibana dashboards To make it easier for you to start monitoring your servers in Kibana, we have created sample Metricbeat dashboards. The dashboards are provided as diff --git a/metricbeat/docs/how-metricbeat-works.asciidoc b/metricbeat/docs/how-metricbeat-works.asciidoc index 667bb589a05..24399b1388f 100644 --- a/metricbeat/docs/how-metricbeat-works.asciidoc +++ b/metricbeat/docs/how-metricbeat-works.asciidoc @@ -1,5 +1,5 @@ [[how-metricbeat-works]] -== How Metricbeat Works +== How Metricbeat works Metricbeat consists of modules and metricsets. A Metricbeat _module_ defines the basic logic for collecting data from a specific service, such as Redis, MySQL, @@ -41,7 +41,7 @@ The following topics provide more detail about the structure of Metricbeat event For more about the benefits of using Metricbeat, see <>. [[metricbeat-event-structure]] -=== Event Structure +=== Event structure Every event sent by Metricbeat has the same basic structure. It contains the following fields: @@ -79,7 +79,7 @@ For example: For more information about the exported fields, see <>. [[error-event-structure]] -=== Error Event Structure +=== Error event structure Metricbeat sends an error event when the service is not reachable. The error event has the same structure as the <>, but also @@ -114,7 +114,7 @@ reachable: ---- [[key-features]] -=== Key Metricbeat Features +=== Key metricbeat features Metricbeat has some key features that are critical to how it works: @@ -124,7 +124,7 @@ Metricbeat has some key features that are critical to how it works: * <> [[metricbeat-error-events]] -==== Metricbeat Error Events +==== Metricbeat error events Metricbeat sends more than just metrics. When it cannot retrieve metrics, it sends error events. The error is not simply a flag, but a full error string that is @@ -140,7 +140,7 @@ retrieve metrics for more than one interval, you can infer that there is potenti something wrong with the host or host connectivity. [[no-aggregations]] -==== No Aggregations When Data is Fetched +==== No aggregations when data is fetched Metricbeat doesn't do aggregations like gauge, sum, counters, and so on. Metricbeat sends the raw data retrieved from the host to the output for processing. When using @@ -149,7 +149,7 @@ Elasticsearch host for drilling down into the details, and the data can be reprocessed at any time. It also reduces the complexity of Metricbeat. [[more-than-numbers]] -==== Sends More Than Just Numbers +==== Sends more than just numbers Metricbeat sends more than just numbers. The metrics that Metricbeat sends can also contain strings to report status information. This is useful when you're using @@ -161,7 +161,7 @@ Basic meta information about each metric (such as the host) is also sent as part of each event. [[multiple-events-in-one]] -==== Multiple Metrics in One Event +==== Multiple metrics in one event Rather than containing a single metric, each event created by Metricbeat contains a list of metrics. This means that you can retrieve all the metrics diff --git a/metricbeat/docs/index.asciidoc b/metricbeat/docs/index.asciidoc index 032b3f7f9bd..9e3c0af9c60 100644 --- a/metricbeat/docs/index.asciidoc +++ b/metricbeat/docs/index.asciidoc @@ -36,21 +36,6 @@ include::./how-metricbeat-works.asciidoc[] include::./configuring-howto.asciidoc[] -include::./metricbeat-filtering.asciidoc[] - -include::../../libbeat/docs/shared-config-ingest.asciidoc[] - -include::./configuring-logstash.asciidoc[] - -:standalone: -include::../../libbeat/docs/shared-env-vars.asciidoc[] - -:standalone: -:allplatforms: -include::../../libbeat/docs/yaml.asciidoc[] - -include::../../libbeat/docs/regexp.asciidoc[] - include::./modules.asciidoc[] include::./fields.asciidoc[] diff --git a/metricbeat/docs/metricbeat-filtering.asciidoc b/metricbeat/docs/metricbeat-filtering.asciidoc index 96904b97517..16d889c9a64 100644 --- a/metricbeat/docs/metricbeat-filtering.asciidoc +++ b/metricbeat/docs/metricbeat-filtering.asciidoc @@ -1,5 +1,5 @@ [[filtering-and-enhancing-data]] -== Filtering and Enhancing the Exported Data +== Filter and enhance the exported data include::../../libbeat/docs/processors.asciidoc[] diff --git a/metricbeat/docs/metricbeat-general-options.asciidoc b/metricbeat/docs/metricbeat-general-options.asciidoc new file mode 100644 index 00000000000..3ad493a09f3 --- /dev/null +++ b/metricbeat/docs/metricbeat-general-options.asciidoc @@ -0,0 +1,34 @@ +[[configuration-general-options]] +== Specify general settings + +You can specify settings in the +{beatname_lc}.yml+ config file to control the +general behavior of {beatname_uc}. This includes: + +* <> that control things like +the maximum random delay to apply to the startup of a metricset. + +* <> that are supported by all Elastic +Beats. + +[float] +[[configuration-global-options]] +=== Global Metricbeat configuration options + +These options are in the `metricbeat` namespace. + +[float] +==== `metricbeat.max_start_delay` + +The maximum random delay to apply to the startup of a metricset. Random delays +ranging from [0, _max_start_delay_) are applied to reduce the thundering herd +effect that can occur if a fleet of machines running Metricbeat are restarted at +the same time. Specifying a value of 0 disables the startup delay. The default +is 10s. + +[source,yaml] +---- +metricbeat.max_start_delay: 10s +---- + + +include::../../libbeat/docs/generalconfig.asciidoc[] diff --git a/metricbeat/docs/metricbeat-options.asciidoc b/metricbeat/docs/metricbeat-options.asciidoc new file mode 100644 index 00000000000..97ba20c2acd --- /dev/null +++ b/metricbeat/docs/metricbeat-options.asciidoc @@ -0,0 +1,139 @@ +[[configuration-metricbeat]] +== Specify which modules to run + +To enable specific modules and metricsets, you add entries to the `modules` list in of the +{beatname_lc}.yml+ config file. Each entry in the list begins with a dash (-) and is followed by settings for that <>. + +//REVIWERS: Using "list" here instead of "array" to match the terminology we use in the Platform Ref to describe the config file + +The following example shows a basic configuration for the Apache module: + +[source,yaml] +---- +metricbeat: + modules: + - module: apache + metricsets: ["status"] + hosts: ["http://127.0.0.1/"] + period: 10s + enabled: true + fields: + dc: west + tags: ["tag"] + filters: + .... +---- + + +The following example shows a configuration where the Apache and MySQL modules are enabled: + +[source,yaml] +------------------------------------------------------------------------------ +metricbeat.modules: + +#---------------------------- Apache Status Module --------------------------- +- module: apache + metricsets: ["status"] + enabled: true + period: 1s + hosts: ["http://127.0.0.1/"] + +#---------------------------- MySQL Status Module ---------------------------- +- module: mysql + metricsets: ["status"] + enabled: true + period: 2s + hosts: ["root@tcp(127.0.0.1:3306)/"] +------------------------------------------------------------------------------ + +[float] +== Configuration combinations + +You can specify a configuration that uses different combinations of modules, metricsets, periods, and hosts. In the following example, the Redis host is crawled for `stats` information every second because this is critical data, but the full list of Apache metricsets is only fetched every 30 seconds because the metrics are less critical. + +[source,yaml] +---- +metricbeat: + modules: + - module: redis + metricsets: ["info"] + hosts: ["host1"] + period: 1s + enabled: true + - module: apache + metricsets: ["info"] + hosts: ["host1"] + period: 30s + enabled: true +---- + +For a module with multiple metricsets defined, it's possible to define the module twice and specify +a different period to use for each metricset. For the following example, the `set1` metricset will be fetched every +10 seconds, while the `set2` metricset will be fetched every 2 minutes: + +[source,yaml] +---- +metricbeat: + modules: + - module: example + metricsets: ["set1"] + hosts: ["host1"] + period: 10s + - module: example + metricsets: ["set2"] + hosts: ["host1"] + period: 2m +---- + + +[float] +=== Standard config options + +You can specify the following options for any Metricbeat module. Some modules +require additional configuration settings. See the <> section for more information. + +[float] +==== `module` + +The name of the module to run. For documentation about each module, see the <> section. + +[float] +==== `metricsets` + +A list of metricsets to execute. Make sure that you only list metricsets +that are available in the module. It is not possible to reference metricsets from other modules. For a list of available metricsets, see the documentation for the module. + +[float] +==== `enabled` + +A Boolean value that specifies whether the module is enabled. If you use the default config file, `metricbeat.yml`, +the System module is enabled (set to `enabled: true`) by default. If the `enabled` option is missing from the +configuration block, the module is enabled by default. + +[float] +[[metricset-period]] +==== `period` + +How often the metricsets are executed. If a system is not reachable, Metricbeat returns an error for each period. This setting is required. + +[float] +==== `hosts` + +A list of hosts to fetch information from. For some metricsets, such as the System module, this setting is optional. + +[float] +==== `fields` + +A dictionary of fields that will be sent with the metricset event. This setting is optional. + +[float] +==== `tags` + +A list of tags that will be sent with the metricset event. This setting is optional. + +[float] +==== `filters` + +deprecated[5.1,This option will be renamed and changed in a future release] + +A list of filters to apply to the data generated by the module. + diff --git a/metricbeat/docs/modules/aerospike.asciidoc b/metricbeat/docs/modules/aerospike.asciidoc index 03e404873a4..39e5b90f7aa 100644 --- a/metricbeat/docs/modules/aerospike.asciidoc +++ b/metricbeat/docs/modules/aerospike.asciidoc @@ -3,9 +3,9 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-aerospike]] -== aerospike Module +== Aerospike module -This is the aerospike Module. It uses http://www.aerospike.com/docs/reference/info[Info command] to collect metrics. +The Aerospike module uses the http://www.aerospike.com/docs/reference/info[Info command] to collect metrics. [float] === Compatibility @@ -14,9 +14,9 @@ The Aeropsike metricsets were tested with Aerospike 3.9 and are expected to work [float] -=== Example Configuration +=== Example configuration -The aerospike module supports the standard configuration options that are described +The Aerospike module supports the standard configuration options that are described in <>. Here is an example configuration: [source,yaml] diff --git a/metricbeat/docs/modules/apache.asciidoc b/metricbeat/docs/modules/apache.asciidoc index b22ac468e35..635960b2971 100644 --- a/metricbeat/docs/modules/apache.asciidoc +++ b/metricbeat/docs/modules/apache.asciidoc @@ -3,7 +3,7 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-apache]] -== Apache Module +== Apache module This module periodically fetches metrics from https://httpd.apache.org/[Apache HTTPD] servers. @@ -24,7 +24,7 @@ image::./images/apache_httpd_server_status.png[] [float] -=== Example Configuration +=== Example configuration The Apache module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/ceph.asciidoc b/metricbeat/docs/modules/ceph.asciidoc index 6606fc8d847..c011ad1e1dc 100644 --- a/metricbeat/docs/modules/ceph.asciidoc +++ b/metricbeat/docs/modules/ceph.asciidoc @@ -3,18 +3,18 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-ceph]] -== ceph Module +== Ceph module beta[] -This is the ceph Module. Metrics are collected submitting HTTP GET requests to ceph-rest-api. -Reference: http://docs.ceph.com/docs/master/man/8/ceph-rest-api/ +The Ceph module collects metrics by submitting HTTP GET requests to +the http://docs.ceph.com/docs/master/man/8/ceph-rest-api/[ceph-rest-api]. [float] -=== Example Configuration +=== Example configuration -The ceph module supports the standard configuration options that are described +The Ceph module supports the standard configuration options that are described in <>. Here is an example configuration: [source,yaml] diff --git a/metricbeat/docs/modules/couchbase.asciidoc b/metricbeat/docs/modules/couchbase.asciidoc index cc98537b568..730b4356be3 100644 --- a/metricbeat/docs/modules/couchbase.asciidoc +++ b/metricbeat/docs/modules/couchbase.asciidoc @@ -3,7 +3,7 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-couchbase]] -== Couchbase Module +== Couchbase module beta[] @@ -12,7 +12,7 @@ servers. [float] -=== Example Configuration +=== Example configuration The Couchbase module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/docker.asciidoc b/metricbeat/docs/modules/docker.asciidoc index 4a9b7e33800..ebd885c91b0 100644 --- a/metricbeat/docs/modules/docker.asciidoc +++ b/metricbeat/docs/modules/docker.asciidoc @@ -3,16 +3,16 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-docker]] -== Docker Module +== Docker module beta[] This module fetches metrics from https://www.docker.com/[Docker] containers. -The docker module is currently not tested on Windows. +The Docker module is currently not tested on Windows. [float] -=== Module-Specific Configuration Notes +=== Module-specific configuration notes It is strongly recommended that you run Docker metricsets with a <> that is 3 seconds or longer. The request to the @@ -22,7 +22,7 @@ requests. [float] -=== Example Configuration +=== Example configuration The Docker module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/dropwizard.asciidoc b/metricbeat/docs/modules/dropwizard.asciidoc index 91ef03032ae..0e3a17609b9 100644 --- a/metricbeat/docs/modules/dropwizard.asciidoc +++ b/metricbeat/docs/modules/dropwizard.asciidoc @@ -3,14 +3,14 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-dropwizard]] -== dropwizard Module +== Dropwizard module -This is the http://dropwizard.io[Dropwizard] Module. +This is the http://dropwizard.io[Dropwizard] module. [float] -=== Example Configuration +=== Example configuration The Dropwizard module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/elasticsearch.asciidoc b/metricbeat/docs/modules/elasticsearch.asciidoc index 0ae9c1be33c..6d252ec2958 100644 --- a/metricbeat/docs/modules/elasticsearch.asciidoc +++ b/metricbeat/docs/modules/elasticsearch.asciidoc @@ -3,15 +3,15 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-elasticsearch]] -== Elasticsearch Module +== Elasticsearch module -This is the Elasticsearch Module. The Elasticsearch module contains a minimal set of metrics to enable monitoring of Elasticsearch across multiple versions. To monitor more Elasticsearch metrics, use our {monitoringdoc}/xpack-monitoring.html[X-Pack monitoring] which is available under a free basic license. +The Elasticsearch module contains a minimal set of metrics to enable monitoring of Elasticsearch across multiple versions. To monitor more Elasticsearch metrics, use our {monitoringdoc}/xpack-monitoring.html[X-Pack monitoring] which is available under a free basic license. [float] -=== Example Configuration +=== Example configuration -The elasticsearch module supports the standard configuration options that are described +The Elasticsearch module supports the standard configuration options that are described in <>. Here is an example configuration: [source,yaml] diff --git a/metricbeat/docs/modules/golang.asciidoc b/metricbeat/docs/modules/golang.asciidoc index 57663c5a0cf..f156e14030f 100644 --- a/metricbeat/docs/modules/golang.asciidoc +++ b/metricbeat/docs/modules/golang.asciidoc @@ -3,15 +3,15 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-golang]] -== golang Module +== Golang module + +The golang module collects metrics by submitting HTTP GET requests to https://golang.org/pkg/expvar/[golang-expvar-api]. -This is the golang Module. Metrics are collected submitting HTTP GET requests to golang-expvar-api. -Reference: https://golang.org/pkg/expvar/ [float] -=== Example Configuration +=== Example configuration -The golang module supports the standard configuration options that are described +The Golang module supports the standard configuration options that are described in <>. Here is an example configuration: [source,yaml] diff --git a/metricbeat/docs/modules/haproxy.asciidoc b/metricbeat/docs/modules/haproxy.asciidoc index b45c528f88c..4587d037684 100644 --- a/metricbeat/docs/modules/haproxy.asciidoc +++ b/metricbeat/docs/modules/haproxy.asciidoc @@ -3,7 +3,7 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-haproxy]] -== HAProxy Module +== HAProxy module This module collects stats from http://www.haproxy.org/[HAProxy]. To configure HAProxy to collect stats, you must enable the stats socket via TCP. For example, @@ -22,7 +22,7 @@ The HAProxy metricsets were tested with HAProxy 1.6 and are expected to work wit [float] -=== Example Configuration +=== Example configuration The HAProxy module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/http.asciidoc b/metricbeat/docs/modules/http.asciidoc index 3de4f5da909..5c6bef9e3e5 100644 --- a/metricbeat/docs/modules/http.asciidoc +++ b/metricbeat/docs/modules/http.asciidoc @@ -3,7 +3,7 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-http]] -== HTTP Module +== HTTP module The HTTP module is a Metricbeat module used to call arbitrary HTTP endpoints for which a dedicated Metricbeat module is not available. @@ -15,7 +15,7 @@ This is often necessary in security restricted network setups, where Logstash is [float] -=== Example Configuration +=== Example configuration The HTTP module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/jolokia.asciidoc b/metricbeat/docs/modules/jolokia.asciidoc index 10ade8625fd..d796f3297dd 100644 --- a/metricbeat/docs/modules/jolokia.asciidoc +++ b/metricbeat/docs/modules/jolokia.asciidoc @@ -3,16 +3,16 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-jolokia]] -== Jolokia Module +== Jolokia module beta[] -This is the Jolokia Module. +This is the Jolokia module. [float] -=== Example Configuration +=== Example configuration The Jolokia module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/kafka.asciidoc b/metricbeat/docs/modules/kafka.asciidoc index 6541affa237..926feffa323 100644 --- a/metricbeat/docs/modules/kafka.asciidoc +++ b/metricbeat/docs/modules/kafka.asciidoc @@ -3,18 +3,18 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-kafka]] -== kafka Module +== Kafka module beta[] -This is the kafka Module. +This is the Kafka module. [float] -=== Example Configuration +=== Example configuration -The kafka module supports the standard configuration options that are described +The Kafka module supports the standard configuration options that are described in <>. Here is an example configuration: [source,yaml] diff --git a/metricbeat/docs/modules/kibana.asciidoc b/metricbeat/docs/modules/kibana.asciidoc index ee6e8f82619..58077c0dff4 100644 --- a/metricbeat/docs/modules/kibana.asciidoc +++ b/metricbeat/docs/modules/kibana.asciidoc @@ -3,15 +3,15 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-kibana]] -== Kibana Module +== Kibana module -This is the Kibana Module and only tracks the high level metrics. To monitor more Kibana metrics, use our {monitoringdoc}/xpack-monitoring.html[X-Pack monitoring] which is available under a free basic license. +The Kibana module only tracks the high-level metrics. To monitor more Kibana metrics, use our {monitoringdoc}/xpack-monitoring.html[X-Pack monitoring] which is available under a free basic license. [float] -=== Example Configuration +=== Example configuration -The kibana module supports the standard configuration options that are described +The Kibana module supports the standard configuration options that are described in <>. Here is an example configuration: [source,yaml] diff --git a/metricbeat/docs/modules/kubernetes.asciidoc b/metricbeat/docs/modules/kubernetes.asciidoc index f142f015204..855c0187467 100644 --- a/metricbeat/docs/modules/kubernetes.asciidoc +++ b/metricbeat/docs/modules/kubernetes.asciidoc @@ -3,7 +3,7 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-kubernetes]] -== kubernetes Module +== Kubernetes module beta[] @@ -16,9 +16,9 @@ example configuration on how to do it. [float] -=== Example Configuration +=== Example configuration -The kubernetes module supports the standard configuration options that are described +The Kubernetes module supports the standard configuration options that are described in <>. Here is an example configuration: [source,yaml] diff --git a/metricbeat/docs/modules/memcached.asciidoc b/metricbeat/docs/modules/memcached.asciidoc index cf17cb99626..bf4e362020c 100644 --- a/metricbeat/docs/modules/memcached.asciidoc +++ b/metricbeat/docs/modules/memcached.asciidoc @@ -3,16 +3,16 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-memcached]] -== memcached Module +== Memcached module -This is the memcached Module. These metricsets were tested with memcached version 1.4.35. +This is the Memcached module. These metricsets were tested with Memcached version 1.4.35. [float] -=== Example Configuration +=== Example configuration -The memcached module supports the standard configuration options that are described +The Memcached module supports the standard configuration options that are described in <>. Here is an example configuration: [source,yaml] diff --git a/metricbeat/docs/modules/mongodb.asciidoc b/metricbeat/docs/modules/mongodb.asciidoc index c6c5cd9293c..a142f87802c 100644 --- a/metricbeat/docs/modules/mongodb.asciidoc +++ b/metricbeat/docs/modules/mongodb.asciidoc @@ -3,13 +3,13 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-mongodb]] -== MongoDB Module +== MongoDB module This module periodically fetches metrics from https://www.mongodb.com[MongoDB] servers. [float] -=== Module-Specific Configuration Notes +=== Module-specific configuration notes When configuring the `hosts` option, you must use MongoDB URLs of the following format: @@ -55,7 +55,7 @@ work with all versions >= 2.8. [float] -=== Example Configuration +=== Example configuration The MongoDB module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/mysql.asciidoc b/metricbeat/docs/modules/mysql.asciidoc index 39c2f124f9e..98255785f15 100644 --- a/metricbeat/docs/modules/mysql.asciidoc +++ b/metricbeat/docs/modules/mysql.asciidoc @@ -3,13 +3,13 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-mysql]] -== MySQL Module +== MySQL module This module periodically fetches metrics from https://www.mysql.com/[MySQL] servers. [float] -=== Module-Specific Configuration Notes +=== Module-specific configuration notes When configuring the `hosts` option, you must use a MySQL Data Source Name (DSN) of the following format: @@ -38,7 +38,7 @@ all versions >= 5.7.0. [float] -=== Example Configuration +=== Example configuration The MySQL module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/nginx.asciidoc b/metricbeat/docs/modules/nginx.asciidoc index f240267f1ad..f1036b070d9 100644 --- a/metricbeat/docs/modules/nginx.asciidoc +++ b/metricbeat/docs/modules/nginx.asciidoc @@ -3,7 +3,7 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-nginx]] -== Nginx Module +== Nginx module This module periodically fetches metrics from https://nginx.org/[Nginx] servers. @@ -16,7 +16,7 @@ The Nginx metricsets were tested with Nginx 1.9 and are expected to work with al [float] -=== Example Configuration +=== Example configuration The Nginx module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/php_fpm.asciidoc b/metricbeat/docs/modules/php_fpm.asciidoc index 5ece5e82472..53ffdf0809b 100644 --- a/metricbeat/docs/modules/php_fpm.asciidoc +++ b/metricbeat/docs/modules/php_fpm.asciidoc @@ -3,7 +3,7 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-php_fpm]] -== PHP-FPM Module +== PHP-FPM module beta[] @@ -11,14 +11,16 @@ This module periodically fetches metrics from https://php-fpm.org[PHP-FPM] servers. [float] -=== Module-Specific Configuration Notes +=== Module-specific configuration notes You need to enable the PHP-FPM status page by properly configuring `pm.status_path`. Here is a sample nginx configuration to forward requests to the PHP-FPM status page (assuming `pm.status_path` is configured with default value `/status`): -```nginx + +---- +nginx location ~ /status { allow 127.0.0.1; deny all; @@ -26,7 +28,8 @@ location ~ /status { fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass 127.0.0.1:9000; } -``` +---- + [float] === Compatibility @@ -36,9 +39,9 @@ work with all versions >= 5. [float] -=== Example Configuration +=== Example configuration -The php_fpm module supports the standard configuration options that are described +The PHP-FPM module supports the standard configuration options that are described in <>. Here is an example configuration: [source,yaml] diff --git a/metricbeat/docs/modules/postgresql.asciidoc b/metricbeat/docs/modules/postgresql.asciidoc index 7adc4f2cc27..ed6976dadd0 100644 --- a/metricbeat/docs/modules/postgresql.asciidoc +++ b/metricbeat/docs/modules/postgresql.asciidoc @@ -9,7 +9,7 @@ This module periodically fetches metrics from https://www.postgresql.org/[PostgreSQL] servers. [float] -=== Module-Specific Configuration Notes +=== Module-specific configuration notes When configuring the `hosts` option, you must use Postgres URLs of the following format: @@ -55,7 +55,7 @@ versions >= 9. [float] -=== Example Configuration +=== Example configuration The PostgreSQL module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/prometheus.asciidoc b/metricbeat/docs/modules/prometheus.asciidoc index d84e2dc5f65..9dc8be6fe48 100644 --- a/metricbeat/docs/modules/prometheus.asciidoc +++ b/metricbeat/docs/modules/prometheus.asciidoc @@ -3,7 +3,7 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-prometheus]] -== Prometheus Module +== Prometheus module beta[] @@ -12,7 +12,7 @@ https://prometheus.io/docs/[Prometheus]. [float] -=== Example Configuration +=== Example configuration The Prometheus module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/rabbitmq.asciidoc b/metricbeat/docs/modules/rabbitmq.asciidoc index 4eb9c1617d8..9a30a23f133 100644 --- a/metricbeat/docs/modules/rabbitmq.asciidoc +++ b/metricbeat/docs/modules/rabbitmq.asciidoc @@ -3,16 +3,16 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-rabbitmq]] -== rabbitmq Module +== RabbitMQ module -This is the rabbitmq Module. It uses http://www.rabbitmq.com/management.html [HTTP API] created by the management plugin to collect metrics. +The RabbitMQ module uses http://www.rabbitmq.com/management.html[HTTP API] created by the management plugin to collect metrics. [float] -=== Example Configuration +=== Example configuration -The rabbitmq module supports the standard configuration options that are described +The RabbitMQ module supports the standard configuration options that are described in <>. Here is an example configuration: [source,yaml] diff --git a/metricbeat/docs/modules/redis.asciidoc b/metricbeat/docs/modules/redis.asciidoc index 343a58c14fa..c5607051652 100644 --- a/metricbeat/docs/modules/redis.asciidoc +++ b/metricbeat/docs/modules/redis.asciidoc @@ -3,12 +3,12 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-redis]] -== Redis Module +== Redis module This module periodically fetches metrics from http://redis.io/[Redis] servers. [float] -=== Module-Specific Configuration Notes +=== Module-specific configuration notes The Redis module has these additional config options: @@ -32,7 +32,7 @@ The Redis metricsets were tested with Redis 3.2.4 and are expected to work with [float] -=== Example Configuration +=== Example configuration The Redis module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/system.asciidoc b/metricbeat/docs/modules/system.asciidoc index 4fad8617d31..d5b9a50f447 100644 --- a/metricbeat/docs/modules/system.asciidoc +++ b/metricbeat/docs/modules/system.asciidoc @@ -3,19 +3,18 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-system]] -== System Module +== System module The System module allows you to monitor your servers. Because the System module always applies to the local server, the `hosts` config option is not needed. [float] -=== Module-Specific Configuration Notes +=== Module-specific configuration notes The System module has these additional config options: *`processes`*:: When the `process` metricset is enabled, you can use the `processes` option to define a list of -regexp expressions to filter the processes that are reported. For more complex filtering, you should use the -<> configuration option. +regexp expressions to filter the processes that are reported. For more complex filtering, you should use the `processors` configuration option. See <> for more information. + The following example config returns metrics for all processes: + @@ -77,7 +76,7 @@ image::./images/metricbeat_system_dashboard.png[] [float] -=== Example Configuration +=== Example configuration The System module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/vsphere.asciidoc b/metricbeat/docs/modules/vsphere.asciidoc index 9211ea6364e..829b103d451 100644 --- a/metricbeat/docs/modules/vsphere.asciidoc +++ b/metricbeat/docs/modules/vsphere.asciidoc @@ -3,16 +3,16 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-vsphere]] -== vsphere Module +== vSphere module -This is the vsphere Module that uses the library Govmomi (https://github.com/vmware/govmomi) to collect metrics from any Vmware SDK URL (ESXi/VCenter). This library is built for and tested against ESXi and vCenter 5.5, 6.0 and 6.5. +The vSphere module uses the https://github.com/vmware/govmomi[Govmomi] library to collect metrics from any Vmware SDK URL (ESXi/VCenter). This library is built for and tested against ESXi and vCenter 5.5, 6.0 and 6.5. [float] -=== Example Configuration +=== Example configuration -The vsphere module supports the standard configuration options that are described +The vSphere module supports the standard configuration options that are described in <>. Here is an example configuration: [source,yaml] diff --git a/metricbeat/docs/modules/windows.asciidoc b/metricbeat/docs/modules/windows.asciidoc index ec923ac71ed..6f5d4f963a3 100644 --- a/metricbeat/docs/modules/windows.asciidoc +++ b/metricbeat/docs/modules/windows.asciidoc @@ -3,13 +3,13 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-windows]] -== Windows Module +== Windows module This is the Windows module. [float] -=== Example Configuration +=== Example configuration The Windows module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules/zookeeper.asciidoc b/metricbeat/docs/modules/zookeeper.asciidoc index 733240437e2..3f0e63174a3 100644 --- a/metricbeat/docs/modules/zookeeper.asciidoc +++ b/metricbeat/docs/modules/zookeeper.asciidoc @@ -3,7 +3,7 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-zookeeper]] -== ZooKeeper Module +== ZooKeeper module The ZooKeeper module fetches statistics from the ZooKeeper service. @@ -15,7 +15,7 @@ The ZooKeeper metricsets were tested with ZooKeeper 3.4.8 and are expected to wo [float] -=== Example Configuration +=== Example configuration The ZooKeeper module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/metricbeat/docs/modules_list.asciidoc b/metricbeat/docs/modules_list.asciidoc index 2c070cd896f..9952718e900 100644 --- a/metricbeat/docs/modules_list.asciidoc +++ b/metricbeat/docs/modules_list.asciidoc @@ -2,31 +2,31 @@ This file is generated! See scripts/docs_collector.py //// - * <> + * <> * <> - * <> + * <> * <> * <> * <> - * <> - * <> + * <> + * <> * <> * <> * <> - * <> - * <> - * <> - * <> + * <> + * <> + * <> + * <> * <> * <> * <> - * <> + * <> * <> * <> - * <> + * <> * <> * <> - * <> + * <> * <> * <> diff --git a/metricbeat/docs/overview.asciidoc b/metricbeat/docs/overview.asciidoc index 1676d50fa9b..a4b4715496e 100644 --- a/metricbeat/docs/overview.asciidoc +++ b/metricbeat/docs/overview.asciidoc @@ -1,5 +1,9 @@ [[metricbeat-overview]] -== Overview +== Metricbeat overview + +++++ +Overview +++++ Metricbeat is a lightweight shipper that you can install on your servers to periodically collect metrics from the operating system and from services running @@ -7,7 +11,7 @@ on the server. Metricbeat takes the metrics and statistics that it collects and ships them to the output that you specify, such as Elasticsearch or Logstash. Metricbeat helps you monitor your servers by collecting metrics from the system -and the following services: +and services running on the server, such as: * <> * <> @@ -19,5 +23,7 @@ and the following services: * <> * <> +See <> for the complete list of supported services. + Metricbeat can insert the collected metrics directly into Elasticsearch or send them to Logstash, Redis, or Kafka. diff --git a/metricbeat/docs/reference/configuration.asciidoc b/metricbeat/docs/reference/configuration.asciidoc deleted file mode 100644 index 5133ada7a2c..00000000000 --- a/metricbeat/docs/reference/configuration.asciidoc +++ /dev/null @@ -1,29 +0,0 @@ -[[metricbeat-configuration-options]] -== Configuration Options (Reference) - -Before modifying configuration settings, make sure you've completed the -<> in the Getting Started. - -The {beatname_uc} configuration file, +{beatname_lc}.yml+, uses http://yaml.org/[YAML] for its syntax. See the -{libbeat}/config-file-format.html[Config File Format] section of the -_Beats Platform Reference_ for more about the structure of the config file. - -The configuration options are described in the following sections. After changing -configuration settings, you need to restart {beatname_uc} to pick up the changes. - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> - -include::configuration/metricbeat-options.asciidoc[] diff --git a/metricbeat/docs/reference/configuration/metricbeat-options.asciidoc b/metricbeat/docs/reference/configuration/metricbeat-options.asciidoc deleted file mode 100644 index 39ba49300c1..00000000000 --- a/metricbeat/docs/reference/configuration/metricbeat-options.asciidoc +++ /dev/null @@ -1,100 +0,0 @@ -[[configuration-metricbeat]] -=== Modules - -The `metricbeat.modules` section of the +{beatname_lc}.yml+ config file contains an array with the enabled <>. The following example shows a configuration where the Apache and MySQL modules are enabled: - -[source,yaml] ------------------------------------------------------------------------------- -metricbeat.modules: - -#---------------------------- Apache Status Module --------------------------- -- module: apache - metricsets: ["status"] - enabled: true - period: 1s - hosts: ["http://127.0.0.1/"] - -#---------------------------- MySQL Status Module ---------------------------- -- module: mysql - metricsets: ["status"] - enabled: true - period: 2s - hosts: ["root@tcp(127.0.0.1:3306)/"] ------------------------------------------------------------------------------- - -==== General Options - -===== max_start_delay - -The maximum random delay to apply to the startup of a metricset. Random delays -ranging from [0, _max_start_delay_) are applied to reduce the thundering herd -effect that can occur if a fleet of machines running Metricbeat are restarted at -the same time. Specifying a value of 0 disables the startup delay. The default -is 10s. - -[source,yaml] ----- -metricbeat.max_start_delay: 10s ----- - -==== Module Options - -You can specify the following options in the `metricbeat` section of the +{beatname_lc}.yml+ config file. These options -are the same for all modules. Each module may have additional configuration options that are specific to that module. -See the <> section for more info about the available modules, the metricsets that they support, -and any additional module-specific configuration info. - -===== module - -The name of the module to run. - -===== metricsets - -A list of metricsets to execute. Make sure that you only list metricsets -that are available in the module. It is not possible to reference metricsets from other modules. - -===== enabled - -A Boolean value that specifies whether the module is enabled. If you use the default config file, `metricbeat.yml`, -the System module is enabled (set to `enabled: true`) by default. If the `enabled` option is missing from the -configuration block, the module is enabled by default. - -[[metricset-period]] -===== period - -How often the metricsets are executed. If a system is not reachable, Metricbeat returns an error for each period. This setting is required. - -===== hosts - -A list of hosts to fetch information from. For some metricsets, this setting is optional. - -===== fields - -A dictionary of fields that will be sent with the metricset event. This setting is optional. - -===== tags - -A list of tags that will be sent with the metricset event. This setting is optional. - -===== filters - -deprecated[5.1,This option will be renamed and changed in a future release] - -A list of filters to apply to the data generated by the module. - - - -include::../../../../libbeat/docs/generalconfig.asciidoc[] - -include::../../../../libbeat/docs/processors-config.asciidoc[] - -include::../../../../libbeat/docs/outputconfig.asciidoc[] - -include::../../../../libbeat/docs/shared-path-config.asciidoc[] - -include::../../../../libbeat/docs/setup-config.asciidoc[] - -include::../../../../libbeat/docs/loggingconfig.asciidoc[] - -include::./reload-configuration.asciidoc[] - diff --git a/metricbeat/docs/reference/configuration/reload-configuration.asciidoc b/metricbeat/docs/reload-configuration.asciidoc similarity index 84% rename from metricbeat/docs/reference/configuration/reload-configuration.asciidoc rename to metricbeat/docs/reload-configuration.asciidoc index e0e37d3e7ee..2a3e86c1859 100644 --- a/metricbeat/docs/reference/configuration/reload-configuration.asciidoc +++ b/metricbeat/docs/reload-configuration.asciidoc @@ -1,10 +1,10 @@ [[metricbeat-configuration-reloading]] -=== Reload Configuration +== Reload the configuration dynamically beta[] You can configure Metricbeat to dynamically reload configuration files when -there are changes. To do this, you specify a path +there are changes. To do this, you specify a path (https://golang.org/pkg/path/filepath/#Glob[Glob]) to watch for module configuration changes. When the files found by the Glob change, new modules are started/stopped according to changes in the configuration files. @@ -13,10 +13,11 @@ This feature is especially useful in container environments where one container is used to monitor all services running in other containers on the same host. Because new containers appear and disappear dynamically, you may need to change the Metricbeat configuration frequently to specify which modules are needed and -which hosts must be monitored. +which hosts must be monitored. To enable dynamic config reloading, you specify the `path` and `reload` options -in the main `metricbeat.yml` config file. For example: +under `metricbeat.config.modules` in the main `metricbeat.yml` config file. +For example: [source,yaml] ------------------------------------------------------------------------------ @@ -26,15 +27,15 @@ metricbeat.config.modules: reload.period: 10s ------------------------------------------------------------------------------ -`path`:: A Glob that defines the files to check for changes. -`reload.enabled`:: When set to `true`, enables dynamic config reload. +`path`:: A Glob that defines the files to check for changes. +`reload.enabled`:: When set to `true`, enables dynamic config reload. `reload.period`:: Specifies how often the files are checked for changes. Do not set the `period` to less than 1s because the modification time of files is often stored in seconds. Setting the `period` to less than 1s will result in unnecessary overhead. Each file found by the Glob must contain a list of one or more module -definitions. For example: +definitions. For example: [source,yaml] ------------------------------------------------------------------------------ diff --git a/metricbeat/docs/running-on-docker.asciidoc b/metricbeat/docs/running-on-docker.asciidoc index f9c5c7d50a4..295d9b92d26 100644 --- a/metricbeat/docs/running-on-docker.asciidoc +++ b/metricbeat/docs/running-on-docker.asciidoc @@ -2,7 +2,7 @@ include::../../libbeat/docs/shared-docker.asciidoc[] [float] [[monitoring-host]] -=== Monitoring the Host Machine +=== Monitor the host machine When executing Metricbeat in a container, there are some important things to be aware of if you want to monitor the host machine or other containers. Let's walk-through some examples using Docker as our container @@ -48,7 +48,7 @@ fail on Windows and MacOS. [float] [[monitoring-service]] -=== Monitoring a Service in Another Container +=== Monitor a service in another container Next, let's look at an example of monitoring a containerized service from a Metricbeat container. diff --git a/metricbeat/docs/securing-metricbeat.asciidoc b/metricbeat/docs/securing-metricbeat.asciidoc index 8c92870c772..03c5198b530 100644 --- a/metricbeat/docs/securing-metricbeat.asciidoc +++ b/metricbeat/docs/securing-metricbeat.asciidoc @@ -15,11 +15,11 @@ The following topics describe how to secure communication between -- [[securing-communication-elasticsearch]] -== Securing Communication With Elasticsearch +== Secure communication with Elasticsearch include::../../libbeat/docs/https.asciidoc[] //sets block macro for shared-ssl-logstash-config.asciidoc included in next section [[configuring-ssl-logstash]] -== Securing Communication With Logstash by Using SSL +== Secure communication with Logstash by using SSL include::../../libbeat/docs/shared-ssl-logstash-config.asciidoc[] diff --git a/metricbeat/docs/troubleshooting.asciidoc b/metricbeat/docs/troubleshooting.asciidoc index 8c578683d2b..1ed03ae68f8 100644 --- a/metricbeat/docs/troubleshooting.asciidoc +++ b/metricbeat/docs/troubleshooting.asciidoc @@ -14,13 +14,13 @@ If you have issues installing or running {beatname_uc}, read the following tips: -- [[getting-help]] -== Getting Help +== Get help include::../../libbeat/docs/getting-help.asciidoc[] //sets block macro for debugging.asciidoc included in next section [[enable-metricbeat-debugging]] -== Debugging +== Debug include::../../libbeat/docs/debugging.asciidoc[] diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index 83cef2f00fb..4638e747573 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -83,7 +83,7 @@ metricbeat.modules: #socket.reverse_lookup.success_ttl: 60s #socket.reverse_lookup.failure_ttl: 60s -#------------------------------ aerospike Module ----------------------------- +#------------------------------ Aerospike Module ----------------------------- - module: aerospike metricsets: ["namespace"] enabled: false @@ -107,7 +107,7 @@ metricbeat.modules: # Password of hosts. Empty by default #password: password -#-------------------------------- ceph Module -------------------------------- +#-------------------------------- Ceph Module -------------------------------- - module: ceph metricsets: ["cluster_disk", "cluster_health", "monitor_health", "pool_disk"] period: 10s @@ -139,13 +139,13 @@ metricbeat.modules: metrics_path: /metrics/metrics namespace: example -#---------------------------- elasticsearch Module --------------------------- +#---------------------------- Elasticsearch Module --------------------------- - module: elasticsearch metricsets: ["node", "node_stats"] period: 10s hosts: ["localhost:9200"] -#------------------------------- golang Module ------------------------------- +#------------------------------- Golang Module ------------------------------- - module: golang metricsets: ["expvar","heap"] period: 10s @@ -184,7 +184,7 @@ metricbeat.modules: jmx.application: jmx.instance: -#-------------------------------- kafka Module ------------------------------- +#-------------------------------- Kafka Module ------------------------------- - module: kafka metricsets: ["partition"] period: 10s @@ -211,13 +211,13 @@ metricbeat.modules: #username: "" #password: "" -#------------------------------- kibana Module ------------------------------- +#------------------------------- Kibana Module ------------------------------- - module: kibana metricsets: ["status"] period: 10s hosts: ["localhost:5601"] -#----------------------------- kubernetes Module ----------------------------- +#----------------------------- Kubernetes Module ----------------------------- # Node metrics, from kubelet: - module: kubernetes metricsets: @@ -247,7 +247,7 @@ metricbeat.modules: metricsets: - event -#------------------------------ memcached Module ----------------------------- +#------------------------------ Memcached Module ----------------------------- - module: memcached metricsets: ["stats"] period: 10s @@ -302,7 +302,7 @@ metricbeat.modules: # Path to server status. Default server-status #server_status_path: "server-status" -#------------------------------- php_fpm Module ------------------------------ +#------------------------------- PHP-FPM Module ------------------------------ - module: php_fpm metricsets: ["pool"] period: 10s @@ -343,7 +343,7 @@ metricbeat.modules: metrics_path: /metrics #namespace: example -#------------------------------ rabbitmq Module ------------------------------ +#------------------------------ RabbitMQ Module ------------------------------ - module: rabbitmq metricsets: ["node"] period: 10s @@ -383,7 +383,7 @@ metricbeat.modules: # Redis AUTH password. Empty by default. #password: foobared -#------------------------------- vsphere Module ------------------------------ +#------------------------------- vSphere Module ------------------------------ - module: vsphere metricsets: ["datastore, host, virtualmachine"] period: 10s diff --git a/metricbeat/module/aerospike/_meta/docs.asciidoc b/metricbeat/module/aerospike/_meta/docs.asciidoc index 369df65eaff..569696acb3a 100644 --- a/metricbeat/module/aerospike/_meta/docs.asciidoc +++ b/metricbeat/module/aerospike/_meta/docs.asciidoc @@ -1,6 +1,6 @@ -== aerospike Module +== Aerospike module -This is the aerospike Module. It uses http://www.aerospike.com/docs/reference/info[Info command] to collect metrics. +The Aerospike module uses the http://www.aerospike.com/docs/reference/info[Info command] to collect metrics. [float] === Compatibility diff --git a/metricbeat/module/aerospike/_meta/fields.yml b/metricbeat/module/aerospike/_meta/fields.yml index cb3bb8d1416..184eaaa4772 100644 --- a/metricbeat/module/aerospike/_meta/fields.yml +++ b/metricbeat/module/aerospike/_meta/fields.yml @@ -1,9 +1,9 @@ - key: aerospike - title: "aerospike" + title: "Aerospike" description: > []experimental - aerospike Module + Aerospike module fields: - name: aerospike type: group diff --git a/metricbeat/module/aerospike/namespace/_meta/docs.asciidoc b/metricbeat/module/aerospike/namespace/_meta/docs.asciidoc index 262f7e5928f..66dba46f161 100644 --- a/metricbeat/module/aerospike/namespace/_meta/docs.asciidoc +++ b/metricbeat/module/aerospike/namespace/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== aerospike namespace MetricSet +=== Aerospike namespace metricset -This is the namespace metricset of the module aerospike. +This is the `namespace` metricset of the Aerospike module. diff --git a/metricbeat/module/apache/_meta/docs.asciidoc b/metricbeat/module/apache/_meta/docs.asciidoc index 016646f6b72..55aade0fa9b 100644 --- a/metricbeat/module/apache/_meta/docs.asciidoc +++ b/metricbeat/module/apache/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -== Apache Module +== Apache module This module periodically fetches metrics from https://httpd.apache.org/[Apache HTTPD] servers. diff --git a/metricbeat/module/apache/status/_meta/docs.asciidoc b/metricbeat/module/apache/status/_meta/docs.asciidoc index 9184fef25c0..f1009089a96 100644 --- a/metricbeat/module/apache/status/_meta/docs.asciidoc +++ b/metricbeat/module/apache/status/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== Apache Status Metricset +=== Apache status metricset The Apache `status` metricset collects data from the Apache https://httpd.apache.org/docs/current/mod/mod_status.html[mod_status] module. It diff --git a/metricbeat/module/ceph/_meta/docs.asciidoc b/metricbeat/module/ceph/_meta/docs.asciidoc index 7cfa7e0014f..ab8acb915cf 100644 --- a/metricbeat/module/ceph/_meta/docs.asciidoc +++ b/metricbeat/module/ceph/_meta/docs.asciidoc @@ -1,6 +1,6 @@ -== ceph Module +== Ceph module beta[] -This is the ceph Module. Metrics are collected submitting HTTP GET requests to ceph-rest-api. -Reference: http://docs.ceph.com/docs/master/man/8/ceph-rest-api/ +The Ceph module collects metrics by submitting HTTP GET requests to +the http://docs.ceph.com/docs/master/man/8/ceph-rest-api/[ceph-rest-api]. diff --git a/metricbeat/module/ceph/_meta/fields.yml b/metricbeat/module/ceph/_meta/fields.yml index 8b4800963b4..1247ed6a741 100644 --- a/metricbeat/module/ceph/_meta/fields.yml +++ b/metricbeat/module/ceph/_meta/fields.yml @@ -1,9 +1,9 @@ - key: ceph - title: "ceph" + title: "Ceph" description: > beta[] - ceph Module + Ceph module short_config: false fields: - name: ceph diff --git a/metricbeat/module/ceph/cluster_disk/_meta/docs.asciidoc b/metricbeat/module/ceph/cluster_disk/_meta/docs.asciidoc index 4709f85b3cb..141b20312ce 100644 --- a/metricbeat/module/ceph/cluster_disk/_meta/docs.asciidoc +++ b/metricbeat/module/ceph/cluster_disk/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== ceph cluster_disk MetricSet +=== Ceph cluster_disk metricset -This is the cluster_disk metricset of the module ceph. +This is the `cluster_disk` metricset of the Ceph module. diff --git a/metricbeat/module/ceph/cluster_health/_meta/docs.asciidoc b/metricbeat/module/ceph/cluster_health/_meta/docs.asciidoc index 8a878d05a14..19b8c06bbe4 100644 --- a/metricbeat/module/ceph/cluster_health/_meta/docs.asciidoc +++ b/metricbeat/module/ceph/cluster_health/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== ceph cluster_health MetricSet +=== Ceph cluster_health metricset -This is the cluster_health metricset of the module ceph. +This is the `cluster_health` metricset of the Ceph module. diff --git a/metricbeat/module/ceph/monitor_health/_meta/docs.asciidoc b/metricbeat/module/ceph/monitor_health/_meta/docs.asciidoc index f27bcd604a7..25818b5fa70 100644 --- a/metricbeat/module/ceph/monitor_health/_meta/docs.asciidoc +++ b/metricbeat/module/ceph/monitor_health/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== ceph monitor_health MetricSet +=== Ceph monitor_health metricset -This is the monitor_health metricset of the module ceph. +This is the `monitor_health` metricset of the Ceph module. diff --git a/metricbeat/module/ceph/pool_disk/_meta/docs.asciidoc b/metricbeat/module/ceph/pool_disk/_meta/docs.asciidoc index cb12795c757..d311dc38a69 100644 --- a/metricbeat/module/ceph/pool_disk/_meta/docs.asciidoc +++ b/metricbeat/module/ceph/pool_disk/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== ceph pool_disk MetricSet +=== Ceph pool_disk metricset -This is the pool_disk metricset of the module ceph. +This is the `pool_disk` metricset of the Ceph module. diff --git a/metricbeat/module/couchbase/_meta/docs.asciidoc b/metricbeat/module/couchbase/_meta/docs.asciidoc index 5095995dec7..3190b40b061 100644 --- a/metricbeat/module/couchbase/_meta/docs.asciidoc +++ b/metricbeat/module/couchbase/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -== Couchbase Module +== Couchbase module beta[] diff --git a/metricbeat/module/couchbase/bucket/_meta/docs.asciidoc b/metricbeat/module/couchbase/bucket/_meta/docs.asciidoc index e7f208b8057..069f23085b4 100644 --- a/metricbeat/module/couchbase/bucket/_meta/docs.asciidoc +++ b/metricbeat/module/couchbase/bucket/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== Couchbase Bucket Metricset +=== Couchbase bucket metricset The Couchbase `bucket` metricset collects data from the Couchbase Buckets Rest API `http://couchbasehost:8091/pools/default/buckets`. diff --git a/metricbeat/module/couchbase/cluster/_meta/docs.asciidoc b/metricbeat/module/couchbase/cluster/_meta/docs.asciidoc index cab2d3a901b..3a3d388d66e 100644 --- a/metricbeat/module/couchbase/cluster/_meta/docs.asciidoc +++ b/metricbeat/module/couchbase/cluster/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== Couchbase Cluster Metricset +=== Couchbase cluster metricset The Couchbase `cluster` metricset collects data from Couchbase pools Rest API `http://couchbasehost:8091/pools/default` and creates an event diff --git a/metricbeat/module/couchbase/node/_meta/docs.asciidoc b/metricbeat/module/couchbase/node/_meta/docs.asciidoc index e9e5970a8e9..ffa84354d3e 100644 --- a/metricbeat/module/couchbase/node/_meta/docs.asciidoc +++ b/metricbeat/module/couchbase/node/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== Couchbase Node Metricset +=== Couchbase node metricset The Couchbase `node` metricset collects data from Couchbase pools Rest API `http://couchbasehost:8091/pools/default` and creates an event for diff --git a/metricbeat/module/docker/_meta/docs.asciidoc b/metricbeat/module/docker/_meta/docs.asciidoc index 5618ca37acf..df27e8a5bbf 100644 --- a/metricbeat/module/docker/_meta/docs.asciidoc +++ b/metricbeat/module/docker/_meta/docs.asciidoc @@ -1,13 +1,13 @@ -== Docker Module +== Docker module beta[] This module fetches metrics from https://www.docker.com/[Docker] containers. -The docker module is currently not tested on Windows. +The Docker module is currently not tested on Windows. [float] -=== Module-Specific Configuration Notes +=== Module-specific configuration notes It is strongly recommended that you run Docker metricsets with a <> that is 3 seconds or longer. The request to the diff --git a/metricbeat/module/docker/container/_meta/docs.asciidoc b/metricbeat/module/docker/container/_meta/docs.asciidoc index 3c095e4e9c0..82ff6977e29 100644 --- a/metricbeat/module/docker/container/_meta/docs.asciidoc +++ b/metricbeat/module/docker/container/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== Docker Container Metricset +=== Docker container metricset The Docker `container` metricset collects information and statistics about running Docker containers. diff --git a/metricbeat/module/docker/cpu/_meta/docs.asciidoc b/metricbeat/module/docker/cpu/_meta/docs.asciidoc index 16ae50695c1..1a4d1cc869b 100644 --- a/metricbeat/module/docker/cpu/_meta/docs.asciidoc +++ b/metricbeat/module/docker/cpu/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== Docker CPU Metricset +=== Docker cpu metricset The Docker `cpu` metricset collects runtime CPU metrics. diff --git a/metricbeat/module/docker/diskio/_meta/docs.asciidoc b/metricbeat/module/docker/diskio/_meta/docs.asciidoc index 3bd99f6633d..80ae71a0f02 100644 --- a/metricbeat/module/docker/diskio/_meta/docs.asciidoc +++ b/metricbeat/module/docker/diskio/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== Docker Diskio Metricset +=== Docker diskio metricset -The Docker `diskio` metricset collects disk I/O metrics. \ No newline at end of file +The Docker `diskio` metricset collects disk I/O metrics. diff --git a/metricbeat/module/docker/healthcheck/_meta/docs.asciidoc b/metricbeat/module/docker/healthcheck/_meta/docs.asciidoc index bfcf644a106..5aacbf8540d 100644 --- a/metricbeat/module/docker/healthcheck/_meta/docs.asciidoc +++ b/metricbeat/module/docker/healthcheck/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== Docker healthcheck Metricset +=== Docker healthcheck metricset The Docker `healthcheck` metricset collects information and statistics about running Docker containers. diff --git a/metricbeat/module/docker/image/_meta/docs.asciidoc b/metricbeat/module/docker/image/_meta/docs.asciidoc index d78ba7a3d22..d9433b13331 100644 --- a/metricbeat/module/docker/image/_meta/docs.asciidoc +++ b/metricbeat/module/docker/image/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== docker image MetricSet +=== Docker image metricset -This is the image metricset of the module docker. +This is the `image` metricset of the Docker module. diff --git a/metricbeat/module/docker/info/_meta/docs.asciidoc b/metricbeat/module/docker/info/_meta/docs.asciidoc index fc4b8cb81c1..07dba6ee9f8 100644 --- a/metricbeat/module/docker/info/_meta/docs.asciidoc +++ b/metricbeat/module/docker/info/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== Docker Info Metricset +=== Docker info metricset The Docker `info` metricset collects system-wide information based on the -https://docs.docker.com/engine/reference/api/docker_remote_api_v1.24/#/display-system-wide-information[Docker Remote API]. \ No newline at end of file +https://docs.docker.com/engine/reference/api/docker_remote_api_v1.24/#/display-system-wide-information[Docker Remote API]. diff --git a/metricbeat/module/docker/memory/_meta/docs.asciidoc b/metricbeat/module/docker/memory/_meta/docs.asciidoc index 0ee70f95932..2df1d2ff22c 100644 --- a/metricbeat/module/docker/memory/_meta/docs.asciidoc +++ b/metricbeat/module/docker/memory/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== Docker Memory Metricset +=== Docker memory metricset -The Docker `memory` metricset collects memory metrics. \ No newline at end of file +The Docker `memory` metricset collects memory metrics. diff --git a/metricbeat/module/docker/network/_meta/docs.asciidoc b/metricbeat/module/docker/network/_meta/docs.asciidoc index 78bb5abef2a..b303368b525 100644 --- a/metricbeat/module/docker/network/_meta/docs.asciidoc +++ b/metricbeat/module/docker/network/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== Docker Network Metricset +=== Docker network metricset -The Docker `network` metricset collects network metrics. \ No newline at end of file +The Docker `network` metricset collects network metrics. diff --git a/metricbeat/module/dropwizard/_meta/docs.asciidoc b/metricbeat/module/dropwizard/_meta/docs.asciidoc index 21ade09313d..7e475f4c64d 100644 --- a/metricbeat/module/dropwizard/_meta/docs.asciidoc +++ b/metricbeat/module/dropwizard/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -== dropwizard Module +== Dropwizard module -This is the http://dropwizard.io[Dropwizard] Module. +This is the http://dropwizard.io[Dropwizard] module. diff --git a/metricbeat/module/dropwizard/collector/_meta/docs.asciidoc b/metricbeat/module/dropwizard/collector/_meta/docs.asciidoc index c27f157a72f..d650badb1eb 100644 --- a/metricbeat/module/dropwizard/collector/_meta/docs.asciidoc +++ b/metricbeat/module/dropwizard/collector/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== dropwizard collector MetricSet +=== Dropwizard collector metricset -This is the collector metricset of the module dropwizard. +This is the `collector` metricset of the Dropwizard module. diff --git a/metricbeat/module/elasticsearch/_meta/docs.asciidoc b/metricbeat/module/elasticsearch/_meta/docs.asciidoc index e912f0c86eb..bd666f82ac9 100644 --- a/metricbeat/module/elasticsearch/_meta/docs.asciidoc +++ b/metricbeat/module/elasticsearch/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -== Elasticsearch Module +== Elasticsearch module -This is the Elasticsearch Module. The Elasticsearch module contains a minimal set of metrics to enable monitoring of Elasticsearch across multiple versions. To monitor more Elasticsearch metrics, use our {monitoringdoc}/xpack-monitoring.html[X-Pack monitoring] which is available under a free basic license. +The Elasticsearch module contains a minimal set of metrics to enable monitoring of Elasticsearch across multiple versions. To monitor more Elasticsearch metrics, use our {monitoringdoc}/xpack-monitoring.html[X-Pack monitoring] which is available under a free basic license. diff --git a/metricbeat/module/elasticsearch/_meta/fields.yml b/metricbeat/module/elasticsearch/_meta/fields.yml index 1745621c704..9cd0bd9a6c7 100644 --- a/metricbeat/module/elasticsearch/_meta/fields.yml +++ b/metricbeat/module/elasticsearch/_meta/fields.yml @@ -1,9 +1,9 @@ - key: elasticsearch - title: "elasticsearch" + title: "Elasticsearch" description: > []experimental - elasticsearch Module + Elasticsearch module short_config: false fields: - name: elasticsearch diff --git a/metricbeat/module/elasticsearch/node/_meta/docs.asciidoc b/metricbeat/module/elasticsearch/node/_meta/docs.asciidoc index 4cee206ba32..3003d7538fc 100644 --- a/metricbeat/module/elasticsearch/node/_meta/docs.asciidoc +++ b/metricbeat/module/elasticsearch/node/_meta/docs.asciidoc @@ -1,6 +1,6 @@ -=== elasticsearch node MetricSet +=== Elasticsearch node metricset -This is the node metricset of the module elasticsearch. It interrogates the +The `node` metricset interrogates the https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-info.html[Cluster API endpoint] of Elasticsearch to get cluster nodes information. This metricset only fetches the data from the `_local` node so it must run on each Elasticsearch node. diff --git a/metricbeat/module/elasticsearch/node_stats/_meta/docs.asciidoc b/metricbeat/module/elasticsearch/node_stats/_meta/docs.asciidoc index 69b9ea46feb..33bea6ebbd4 100644 --- a/metricbeat/module/elasticsearch/node_stats/_meta/docs.asciidoc +++ b/metricbeat/module/elasticsearch/node_stats/_meta/docs.asciidoc @@ -1,8 +1,8 @@ -=== elasticsearch node_stats MetricSet +=== Elasticsearch node_stats metricset -This is the node_stats metricset of the module elasticsearch. It interrogates +The `node_stats` metricset interrogates the https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-stats.html[Cluster API endpoint] of Elasticsearch to get the cluster nodes statistics. The data received is only for the local node so this Metricbeat has to be run on each Elasticsearch node. -Note: The indices stats are node specific. That means for example the total number of docs reported by all nodes together is not the total number of documents in all indices as there can also be replicas. +NOTE: The indices stats are node-specific. That means for example the total number of docs reported by all nodes together is not the total number of documents in all indices as there can also be replicas. diff --git a/metricbeat/module/golang/_meta/docs.asciidoc b/metricbeat/module/golang/_meta/docs.asciidoc index 9ecd6fd5319..3e951b00b4f 100644 --- a/metricbeat/module/golang/_meta/docs.asciidoc +++ b/metricbeat/module/golang/_meta/docs.asciidoc @@ -1,4 +1,3 @@ -== golang Module +== Golang module -This is the golang Module. Metrics are collected submitting HTTP GET requests to golang-expvar-api. -Reference: https://golang.org/pkg/expvar/ \ No newline at end of file +The golang module collects metrics by submitting HTTP GET requests to https://golang.org/pkg/expvar/[golang-expvar-api]. diff --git a/metricbeat/module/golang/_meta/fields.yml b/metricbeat/module/golang/_meta/fields.yml index 5ad0fa9ff8a..c7cd4cc663f 100644 --- a/metricbeat/module/golang/_meta/fields.yml +++ b/metricbeat/module/golang/_meta/fields.yml @@ -1,7 +1,7 @@ - key: golang - title: "golang" + title: "Golang" description: > - golang Module + Golang module short_config: false fields: - name: golang diff --git a/metricbeat/module/golang/expvar/_meta/docs.asciidoc b/metricbeat/module/golang/expvar/_meta/docs.asciidoc index 1a9454a2000..2e46e32f61a 100644 --- a/metricbeat/module/golang/expvar/_meta/docs.asciidoc +++ b/metricbeat/module/golang/expvar/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== golang expvar MetricSet +=== Golang expvar metricset -This is the expvar metricset of the module golang. -Golang can exposes it's variables by expvar api, with this metricset, user can collect all the expvar exposed variables. \ No newline at end of file +This is the `expvar` metricset of the Golang module. +Golang can expose its variables by the expvar API. With this metricset, you can collect all the expvar-exposed variables. diff --git a/metricbeat/module/golang/heap/_meta/docs.asciidoc b/metricbeat/module/golang/heap/_meta/docs.asciidoc index 6088ad9fb98..2a83c51189e 100644 --- a/metricbeat/module/golang/heap/_meta/docs.asciidoc +++ b/metricbeat/module/golang/heap/_meta/docs.asciidoc @@ -1,4 +1,3 @@ -=== golang heap MetricSet +=== Golang heap metricset -This is the heap metricset of the module golang. -It will collect the memstats information from the expvar api. \ No newline at end of file +The `heap` metricset of the Golang module collects the memstats information from the expvar API. diff --git a/metricbeat/module/haproxy/_meta/docs.asciidoc b/metricbeat/module/haproxy/_meta/docs.asciidoc index f6407ce4072..a502011a6cf 100644 --- a/metricbeat/module/haproxy/_meta/docs.asciidoc +++ b/metricbeat/module/haproxy/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -== HAProxy Module +== HAProxy module This module collects stats from http://www.haproxy.org/[HAProxy]. To configure HAProxy to collect stats, you must enable the stats socket via TCP. For example, diff --git a/metricbeat/module/haproxy/info/_meta/docs.asciidoc b/metricbeat/module/haproxy/info/_meta/docs.asciidoc index abb5442a0dd..277c428b18d 100644 --- a/metricbeat/module/haproxy/info/_meta/docs.asciidoc +++ b/metricbeat/module/haproxy/info/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== HAProxy Info Metricset +=== HAProxy info metricset -The HAProxy `info` metricset collects general information about HAProxy processes. +The HAProxy `info` metricset collects general information about HAProxy processes. diff --git a/metricbeat/module/haproxy/stat/_meta/docs.asciidoc b/metricbeat/module/haproxy/stat/_meta/docs.asciidoc index 63e90104b3c..e3c58908044 100644 --- a/metricbeat/module/haproxy/stat/_meta/docs.asciidoc +++ b/metricbeat/module/haproxy/stat/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== HAProxy Stat Metricset +=== HAProxy stat metricset The HAProxy `stat` metricset collects 'stat' fields from HAProxy processes. diff --git a/metricbeat/module/http/_meta/docs.asciidoc b/metricbeat/module/http/_meta/docs.asciidoc index 1c9db3b9f67..3fd08235c2a 100644 --- a/metricbeat/module/http/_meta/docs.asciidoc +++ b/metricbeat/module/http/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -== HTTP Module +== HTTP module The HTTP module is a Metricbeat module used to call arbitrary HTTP endpoints for which a dedicated Metricbeat module is not available. diff --git a/metricbeat/module/http/_meta/fields.yml b/metricbeat/module/http/_meta/fields.yml index 93d6bd89110..d158a5e6237 100644 --- a/metricbeat/module/http/_meta/fields.yml +++ b/metricbeat/module/http/_meta/fields.yml @@ -1,7 +1,7 @@ - key: http title: "HTTP" description: > - http Module + HTTP module fields: - name: http type: group diff --git a/metricbeat/module/http/json/_meta/docs.asciidoc b/metricbeat/module/http/json/_meta/docs.asciidoc index 033ebb90b8a..bf1311c8001 100644 --- a/metricbeat/module/http/json/_meta/docs.asciidoc +++ b/metricbeat/module/http/json/_meta/docs.asciidoc @@ -1,6 +1,6 @@ -=== http json MetricSet +=== HTTP json metricset -This is the json metricset of the module http. +This is the `json` metricset of the HTTP module. [float] === Features and Configuration diff --git a/metricbeat/module/jolokia/_meta/docs.asciidoc b/metricbeat/module/jolokia/_meta/docs.asciidoc index af59ed28f1c..b41b6d95a7a 100644 --- a/metricbeat/module/jolokia/_meta/docs.asciidoc +++ b/metricbeat/module/jolokia/_meta/docs.asciidoc @@ -1,6 +1,6 @@ -== Jolokia Module +== Jolokia module beta[] -This is the Jolokia Module. +This is the Jolokia module. diff --git a/metricbeat/module/jolokia/_meta/fields.yml b/metricbeat/module/jolokia/_meta/fields.yml index dde458c4980..4e69eef344a 100644 --- a/metricbeat/module/jolokia/_meta/fields.yml +++ b/metricbeat/module/jolokia/_meta/fields.yml @@ -3,7 +3,7 @@ description: > []beta - Jolokia Module + Jolokia module short_config: false fields: - name: jolokia diff --git a/metricbeat/module/jolokia/jmx/_meta/docs.asciidoc b/metricbeat/module/jolokia/jmx/_meta/docs.asciidoc index 0e44cea5735..ada50c96690 100644 --- a/metricbeat/module/jolokia/jmx/_meta/docs.asciidoc +++ b/metricbeat/module/jolokia/jmx/_meta/docs.asciidoc @@ -1,6 +1,6 @@ -=== Jolokia jmx Metricset +=== Jolokia jmx metricset -This is the jmx metricset of the module jolokia. +This is the `jmx` metricset of the Jolokia module. [float] === Features and configuration @@ -45,6 +45,6 @@ All Jolokia requests have canonicalNaming set to false (details see here: https: [float] -=== Exposed fields, Dashboards, Indexes, etc. +=== Exposed fields, dashboards, indexes, etc. Since this is a very general module that can be tailored for any application that exposes its metrics over Jolokia, it comes with no exposed fields description, dashboards or index patterns. diff --git a/metricbeat/module/kafka/_meta/docs.asciidoc b/metricbeat/module/kafka/_meta/docs.asciidoc index f703fbeb18f..49d93d59762 100644 --- a/metricbeat/module/kafka/_meta/docs.asciidoc +++ b/metricbeat/module/kafka/_meta/docs.asciidoc @@ -1,6 +1,6 @@ -== kafka Module +== Kafka module beta[] -This is the kafka Module. +This is the Kafka module. diff --git a/metricbeat/module/kafka/_meta/fields.yml b/metricbeat/module/kafka/_meta/fields.yml index c12923d65f8..61977f1eb9b 100644 --- a/metricbeat/module/kafka/_meta/fields.yml +++ b/metricbeat/module/kafka/_meta/fields.yml @@ -1,7 +1,7 @@ - key: kafka - title: "kafka" + title: "Kafka" description: > - kafka Module + Kafka module beta[] short_config: false diff --git a/metricbeat/module/kafka/consumergroup/_meta/docs.asciidoc b/metricbeat/module/kafka/consumergroup/_meta/docs.asciidoc index fcc5a6d353e..194073538c6 100644 --- a/metricbeat/module/kafka/consumergroup/_meta/docs.asciidoc +++ b/metricbeat/module/kafka/consumergroup/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== kafka consumergroup MetricSet +=== Kafka consumergroup metricset -This is the consumergroup metricset of the module kafka. +This is the `consumergroup` metricset of the Kafka module. diff --git a/metricbeat/module/kafka/partition/_meta/docs.asciidoc b/metricbeat/module/kafka/partition/_meta/docs.asciidoc index 3139b4d61bd..2135af57f86 100644 --- a/metricbeat/module/kafka/partition/_meta/docs.asciidoc +++ b/metricbeat/module/kafka/partition/_meta/docs.asciidoc @@ -1,6 +1,6 @@ -=== kafka partition MetricSet +=== Kafka partition metricset -This is the partition metricset of the module kafka. +This is the partition metricset of the Kafka module. ==== Configuration diff --git a/metricbeat/module/kibana/_meta/docs.asciidoc b/metricbeat/module/kibana/_meta/docs.asciidoc index 829b0ab1beb..7133efcd24f 100644 --- a/metricbeat/module/kibana/_meta/docs.asciidoc +++ b/metricbeat/module/kibana/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -== Kibana Module +== Kibana module -This is the Kibana Module and only tracks the high level metrics. To monitor more Kibana metrics, use our {monitoringdoc}/xpack-monitoring.html[X-Pack monitoring] which is available under a free basic license. +The Kibana module only tracks the high-level metrics. To monitor more Kibana metrics, use our {monitoringdoc}/xpack-monitoring.html[X-Pack monitoring] which is available under a free basic license. diff --git a/metricbeat/module/kibana/_meta/fields.yml b/metricbeat/module/kibana/_meta/fields.yml index b2dbd6f9ee3..40774070ee5 100644 --- a/metricbeat/module/kibana/_meta/fields.yml +++ b/metricbeat/module/kibana/_meta/fields.yml @@ -1,9 +1,9 @@ - key: kibana - title: "kibana" + title: "Kibana" description: > []experimental - kibana Module + Kibana module short_config: false fields: - name: kibana diff --git a/metricbeat/module/kibana/status/_meta/docs.asciidoc b/metricbeat/module/kibana/status/_meta/docs.asciidoc index a38c46b6af7..3c871b8c28f 100644 --- a/metricbeat/module/kibana/status/_meta/docs.asciidoc +++ b/metricbeat/module/kibana/status/_meta/docs.asciidoc @@ -1,7 +1,7 @@ -=== kibana status MetricSet +=== Kibana status metricset -[]experimental +experimental[] -This is the status metricset of the module kibana. This status endpoint is available in 6.0 by default and can be enabled in Kibana >= 5.4 with the config option `status.v6ApiFormat: true`. +This is the `status` metricset of the Kibana module. This status endpoint is available in 6.0 by default and can be enabled in Kibana >= 5.4 with the config option `status.v6ApiFormat: true`. -The indention of this Kibana module is to have a minimal data set that works across Kibana versions. +The intention of the Kibana module is to have a minimal data set that works across Kibana versions. diff --git a/metricbeat/module/kubernetes/_meta/docs.asciidoc b/metricbeat/module/kubernetes/_meta/docs.asciidoc index 419dacd76d9..b10bf62657f 100644 --- a/metricbeat/module/kubernetes/_meta/docs.asciidoc +++ b/metricbeat/module/kubernetes/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -== kubernetes Module +== Kubernetes module beta[] diff --git a/metricbeat/module/kubernetes/_meta/fields.yml b/metricbeat/module/kubernetes/_meta/fields.yml index 7dd514e4183..aee17ef5c01 100644 --- a/metricbeat/module/kubernetes/_meta/fields.yml +++ b/metricbeat/module/kubernetes/_meta/fields.yml @@ -1,9 +1,9 @@ - key: kubernetes - title: "kubernetes" + title: "Kubernetes" description: > beta[] - kubernetes metrics + Kubernetes metrics short_config: false fields: - name: kubernetes diff --git a/metricbeat/module/kubernetes/container/_meta/docs.asciidoc b/metricbeat/module/kubernetes/container/_meta/docs.asciidoc index 91ae69db5ce..06933b477db 100644 --- a/metricbeat/module/kubernetes/container/_meta/docs.asciidoc +++ b/metricbeat/module/kubernetes/container/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== kubernetes container MetricSet +=== Kubernetes container metricset -This is the container metricset of the module kubernetes. +This is the `container` metricset of the Kubernetes module. diff --git a/metricbeat/module/kubernetes/event/_meta/docs.asciidoc b/metricbeat/module/kubernetes/event/_meta/docs.asciidoc index 79634a51855..08563a3087b 100644 --- a/metricbeat/module/kubernetes/event/_meta/docs.asciidoc +++ b/metricbeat/module/kubernetes/event/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== kubernetes event MetricSet +=== Kubernetes event metricset -This is the event metricset of the module kubernetes. +This is the `event` metricset of the Kubernetes module. diff --git a/metricbeat/module/kubernetes/node/_meta/docs.asciidoc b/metricbeat/module/kubernetes/node/_meta/docs.asciidoc index 84cc98e1de7..0acb0fe20c6 100644 --- a/metricbeat/module/kubernetes/node/_meta/docs.asciidoc +++ b/metricbeat/module/kubernetes/node/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== kubernetes node MetricSet +=== Kubernetes node metricset -This is the node metricset of the module kubernetes. +This is the `node` metricset of the Kubernetes module. diff --git a/metricbeat/module/kubernetes/pod/_meta/docs.asciidoc b/metricbeat/module/kubernetes/pod/_meta/docs.asciidoc index 5f28180b741..9e23465f134 100644 --- a/metricbeat/module/kubernetes/pod/_meta/docs.asciidoc +++ b/metricbeat/module/kubernetes/pod/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== kubernetes pod MetricSet +=== Kubernetes pod metricset -This is the pod metricset of the module kubernetes. +This is the `pod` metricset of the Kubernetes module. diff --git a/metricbeat/module/kubernetes/state_container/_meta/docs.asciidoc b/metricbeat/module/kubernetes/state_container/_meta/docs.asciidoc index 300c10f0600..f0a01187cfc 100644 --- a/metricbeat/module/kubernetes/state_container/_meta/docs.asciidoc +++ b/metricbeat/module/kubernetes/state_container/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== kubernetes state_container MetricSet +=== Kubernetes state_container metricset -This is the state_container metricset of the module kubernetes. +This is the `state_container` metricset of the Kubernetes module. diff --git a/metricbeat/module/kubernetes/state_deployment/_meta/docs.asciidoc b/metricbeat/module/kubernetes/state_deployment/_meta/docs.asciidoc index c17160ba76a..7a70986980a 100644 --- a/metricbeat/module/kubernetes/state_deployment/_meta/docs.asciidoc +++ b/metricbeat/module/kubernetes/state_deployment/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== kubernetes state_deployment MetricSet +=== Kubernetes state_deployment metricset -This is the state_deployment metricset of the module kubernetes. +This is the `state_deployment` metricset of the Kubernetes module. diff --git a/metricbeat/module/kubernetes/state_node/_meta/docs.asciidoc b/metricbeat/module/kubernetes/state_node/_meta/docs.asciidoc index a6109ae9f34..eb7ac1772bf 100644 --- a/metricbeat/module/kubernetes/state_node/_meta/docs.asciidoc +++ b/metricbeat/module/kubernetes/state_node/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== kubernetes state_node MetricSet +=== Kubernetes state_node metricset -This is the state_node metricset of the module kubernetes. +This is the `state_node` metricset of the Kubernetes module. diff --git a/metricbeat/module/kubernetes/state_pod/_meta/docs.asciidoc b/metricbeat/module/kubernetes/state_pod/_meta/docs.asciidoc index dc2e89e9447..a21b3a1d36f 100644 --- a/metricbeat/module/kubernetes/state_pod/_meta/docs.asciidoc +++ b/metricbeat/module/kubernetes/state_pod/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== kubernetes state_pod MetricSet +=== Kubernetes state_pod metricset -This is the state_pod metricset of the module kubernetes. +This is the `state_pod` metricset of the Kubernetes module. diff --git a/metricbeat/module/kubernetes/state_replicaset/_meta/docs.asciidoc b/metricbeat/module/kubernetes/state_replicaset/_meta/docs.asciidoc index 5c78069ff83..5587bb980d5 100644 --- a/metricbeat/module/kubernetes/state_replicaset/_meta/docs.asciidoc +++ b/metricbeat/module/kubernetes/state_replicaset/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== kubernetes state_replicaset MetricSet +=== Kubernetes state_replicaset metricset -This is the state_replicaset metricset of the module kubernetes. +This is the `state_replicaset` metricset of the Kubernetes module. diff --git a/metricbeat/module/kubernetes/system/_meta/docs.asciidoc b/metricbeat/module/kubernetes/system/_meta/docs.asciidoc index 32c371221c8..0b899d5cb88 100644 --- a/metricbeat/module/kubernetes/system/_meta/docs.asciidoc +++ b/metricbeat/module/kubernetes/system/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== kubernetes system MetricSet +=== Kubernetes system metricset -This is the system metricset of the module kubernetes. +This is the `system` metricset of the Kubernetes module. diff --git a/metricbeat/module/kubernetes/volume/_meta/docs.asciidoc b/metricbeat/module/kubernetes/volume/_meta/docs.asciidoc index d1bab9673b8..712a5b8e6af 100644 --- a/metricbeat/module/kubernetes/volume/_meta/docs.asciidoc +++ b/metricbeat/module/kubernetes/volume/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== kubernetes volume MetricSet +=== Kubernetes volume metricset -This is the volume metricset of the module kubernetes. +This is the `volume` metricset of the Kubernetes module. diff --git a/metricbeat/module/memcached/_meta/docs.asciidoc b/metricbeat/module/memcached/_meta/docs.asciidoc index 9c69e61f515..30d2718ae4f 100644 --- a/metricbeat/module/memcached/_meta/docs.asciidoc +++ b/metricbeat/module/memcached/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -== memcached Module +== Memcached module -This is the memcached Module. These metricsets were tested with memcached version 1.4.35. +This is the Memcached module. These metricsets were tested with Memcached version 1.4.35. diff --git a/metricbeat/module/memcached/_meta/fields.yml b/metricbeat/module/memcached/_meta/fields.yml index 63ba66b1ec3..6e5aab73367 100644 --- a/metricbeat/module/memcached/_meta/fields.yml +++ b/metricbeat/module/memcached/_meta/fields.yml @@ -1,9 +1,9 @@ - key: memcached - title: "memcached" + title: "Memcached" description: > []beta - memcached Module + Memcached module short_config: false fields: - name: memcached diff --git a/metricbeat/module/memcached/stats/_meta/docs.asciidoc b/metricbeat/module/memcached/stats/_meta/docs.asciidoc index c1cbd71a244..3c50e8fdb73 100644 --- a/metricbeat/module/memcached/stats/_meta/docs.asciidoc +++ b/metricbeat/module/memcached/stats/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== memcached stats MetricSet +=== Memcached stats metricset -This is the stats metricset of the module memcached. +This is the `stats` metricset of the Memcached module. diff --git a/metricbeat/module/mongodb/_meta/docs.asciidoc b/metricbeat/module/mongodb/_meta/docs.asciidoc index 55cb6325b6d..576636b8859 100644 --- a/metricbeat/module/mongodb/_meta/docs.asciidoc +++ b/metricbeat/module/mongodb/_meta/docs.asciidoc @@ -1,10 +1,10 @@ -== MongoDB Module +== MongoDB module This module periodically fetches metrics from https://www.mongodb.com[MongoDB] servers. [float] -=== Module-Specific Configuration Notes +=== Module-specific configuration notes When configuring the `hosts` option, you must use MongoDB URLs of the following format: diff --git a/metricbeat/module/mongodb/dbstats/_meta/docs.asciidoc b/metricbeat/module/mongodb/dbstats/_meta/docs.asciidoc index 514a741ccd9..bc68f4fe5a9 100644 --- a/metricbeat/module/mongodb/dbstats/_meta/docs.asciidoc +++ b/metricbeat/module/mongodb/dbstats/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== mongodb dbstats MetricSet +=== MongoDB dbstats metricset -This is the dbstats metricset of the module mongodb. +This is the `dbstats` metricset of the MongoDB module. diff --git a/metricbeat/module/mongodb/status/_meta/docs.asciidoc b/metricbeat/module/mongodb/status/_meta/docs.asciidoc index 48f2680e5b7..d70c39aba45 100644 --- a/metricbeat/module/mongodb/status/_meta/docs.asciidoc +++ b/metricbeat/module/mongodb/status/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== MongoDB Status Metricset +=== MongoDB status metricset This is the `status` metricset of the MongoDB module. diff --git a/metricbeat/module/mysql/_meta/docs.asciidoc b/metricbeat/module/mysql/_meta/docs.asciidoc index d725e44559e..82336224fc9 100644 --- a/metricbeat/module/mysql/_meta/docs.asciidoc +++ b/metricbeat/module/mysql/_meta/docs.asciidoc @@ -1,10 +1,10 @@ -== MySQL Module +== MySQL module This module periodically fetches metrics from https://www.mysql.com/[MySQL] servers. [float] -=== Module-Specific Configuration Notes +=== Module-specific configuration notes When configuring the `hosts` option, you must use a MySQL Data Source Name (DSN) of the following format: diff --git a/metricbeat/module/mysql/status/_meta/docs.asciidoc b/metricbeat/module/mysql/status/_meta/docs.asciidoc index 231ca3512b6..12d8fe1f4b1 100644 --- a/metricbeat/module/mysql/status/_meta/docs.asciidoc +++ b/metricbeat/module/mysql/status/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== MySQL Status Metricset +=== MySQL status metricset The MySQL `status` metricset collects data from MySQL by running a http://dev.mysql.com/doc/refman/5.7/en/show-status.html[`SHOW GLOBAL STATUS;`] diff --git a/metricbeat/module/nginx/_meta/docs.asciidoc b/metricbeat/module/nginx/_meta/docs.asciidoc index db7aace3aae..5208d5bf07e 100644 --- a/metricbeat/module/nginx/_meta/docs.asciidoc +++ b/metricbeat/module/nginx/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -== Nginx Module +== Nginx module This module periodically fetches metrics from https://nginx.org/[Nginx] servers. diff --git a/metricbeat/module/nginx/stubstatus/_meta/docs.asciidoc b/metricbeat/module/nginx/stubstatus/_meta/docs.asciidoc index b17dea6139c..dfd293fef4b 100644 --- a/metricbeat/module/nginx/stubstatus/_meta/docs.asciidoc +++ b/metricbeat/module/nginx/stubstatus/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== Nginx StubStatus Metricset +=== Nginx stubstatus metricset The Nginx `stubstatus` metricset collects data from the Nginx http://nginx.org/en/docs/http/ngx_http_stub_status_module.html[ngx_http_stub_status] module. It diff --git a/metricbeat/module/php_fpm/_meta/docs.asciidoc b/metricbeat/module/php_fpm/_meta/docs.asciidoc index b296d8ce9fb..6292070038a 100644 --- a/metricbeat/module/php_fpm/_meta/docs.asciidoc +++ b/metricbeat/module/php_fpm/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -== PHP-FPM Module +== PHP-FPM module beta[] @@ -6,14 +6,16 @@ This module periodically fetches metrics from https://php-fpm.org[PHP-FPM] servers. [float] -=== Module-Specific Configuration Notes +=== Module-specific configuration notes You need to enable the PHP-FPM status page by properly configuring `pm.status_path`. Here is a sample nginx configuration to forward requests to the PHP-FPM status page (assuming `pm.status_path` is configured with default value `/status`): -```nginx + +---- +nginx location ~ /status { allow 127.0.0.1; deny all; @@ -21,7 +23,8 @@ location ~ /status { fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass 127.0.0.1:9000; } -``` +---- + [float] === Compatibility diff --git a/metricbeat/module/php_fpm/_meta/fields.yml b/metricbeat/module/php_fpm/_meta/fields.yml index 42f012a060a..769b3b627cd 100644 --- a/metricbeat/module/php_fpm/_meta/fields.yml +++ b/metricbeat/module/php_fpm/_meta/fields.yml @@ -1,5 +1,5 @@ - key: php_fpm - title: "php_fpm" + title: "PHP-FPM" description: > beta[] diff --git a/metricbeat/module/php_fpm/pool/_meta/docs.asciidoc b/metricbeat/module/php_fpm/pool/_meta/docs.asciidoc index 0e158655e08..83fcf358c52 100644 --- a/metricbeat/module/php_fpm/pool/_meta/docs.asciidoc +++ b/metricbeat/module/php_fpm/pool/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== php_fpm pool MetricSet +=== PHP-FPM pool metricset -This is the pool metricset of the module php_fpm. +This is the `pool` metricset of the PHP-FPM module. diff --git a/metricbeat/module/postgresql/_meta/docs.asciidoc b/metricbeat/module/postgresql/_meta/docs.asciidoc index bcc36384070..5becff38406 100644 --- a/metricbeat/module/postgresql/_meta/docs.asciidoc +++ b/metricbeat/module/postgresql/_meta/docs.asciidoc @@ -4,7 +4,7 @@ This module periodically fetches metrics from https://www.postgresql.org/[PostgreSQL] servers. [float] -=== Module-Specific Configuration Notes +=== Module-specific configuration notes When configuring the `hosts` option, you must use Postgres URLs of the following format: diff --git a/metricbeat/module/postgresql/activity/_meta/docs.asciidoc b/metricbeat/module/postgresql/activity/_meta/docs.asciidoc index e0ba63eb36f..8dab02ed0af 100644 --- a/metricbeat/module/postgresql/activity/_meta/docs.asciidoc +++ b/metricbeat/module/postgresql/activity/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== postgresql activity MetricSet +=== PostgreSQL activity metricset -This is the activity metricset of the module postgresql. +This is the `activity` metricset of the PostgreSQL module. diff --git a/metricbeat/module/postgresql/bgwriter/_meta/docs.asciidoc b/metricbeat/module/postgresql/bgwriter/_meta/docs.asciidoc index 5bccc5addae..786f33103ac 100644 --- a/metricbeat/module/postgresql/bgwriter/_meta/docs.asciidoc +++ b/metricbeat/module/postgresql/bgwriter/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== postgresql bgwriter MetricSet +=== PostgreSQL bgwriter metricset -This is the bgwriter metricset of the module postgresql. +This is the `bgwriter` metricset of the PostgreSQL module. diff --git a/metricbeat/module/postgresql/database/_meta/docs.asciidoc b/metricbeat/module/postgresql/database/_meta/docs.asciidoc index d1fa2c9c09a..e6c1eaddfe0 100644 --- a/metricbeat/module/postgresql/database/_meta/docs.asciidoc +++ b/metricbeat/module/postgresql/database/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== postgresql database MetricSet +=== PostgreSQL database metricset -This is the database metricset of the module postgresql. +This is the `database` metricset of the PostgreSQL module. diff --git a/metricbeat/module/prometheus/_meta/docs.asciidoc b/metricbeat/module/prometheus/_meta/docs.asciidoc index c641bcc1f26..f13423376c3 100644 --- a/metricbeat/module/prometheus/_meta/docs.asciidoc +++ b/metricbeat/module/prometheus/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -== Prometheus Module +== Prometheus module beta[] diff --git a/metricbeat/module/prometheus/collector/_meta/docs.asciidoc b/metricbeat/module/prometheus/collector/_meta/docs.asciidoc index 982025ba1f2..10466f109b2 100644 --- a/metricbeat/module/prometheus/collector/_meta/docs.asciidoc +++ b/metricbeat/module/prometheus/collector/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== Prometheus Collector Metricset +=== Prometheus collector metricset The Prometheus `collector` metricset fetches data from https://prometheus.io/docs/instrumenting/exporters/[prometheus exporters]. diff --git a/metricbeat/module/prometheus/stats/_meta/docs.asciidoc b/metricbeat/module/prometheus/stats/_meta/docs.asciidoc index 6da0ba1409f..f8916a8efb8 100644 --- a/metricbeat/module/prometheus/stats/_meta/docs.asciidoc +++ b/metricbeat/module/prometheus/stats/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== Prometheus Stats Metricset +=== Prometheus stats metricset The Prometheus `stats` metricset collects statistics about the Prometheus server. diff --git a/metricbeat/module/rabbitmq/_meta/docs.asciidoc b/metricbeat/module/rabbitmq/_meta/docs.asciidoc index 18d0c8a3837..758e3947b73 100644 --- a/metricbeat/module/rabbitmq/_meta/docs.asciidoc +++ b/metricbeat/module/rabbitmq/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -== rabbitmq Module +== RabbitMQ module -This is the rabbitmq Module. It uses http://www.rabbitmq.com/management.html [HTTP API] created by the management plugin to collect metrics. +The RabbitMQ module uses http://www.rabbitmq.com/management.html[HTTP API] created by the management plugin to collect metrics. diff --git a/metricbeat/module/rabbitmq/_meta/fields.yml b/metricbeat/module/rabbitmq/_meta/fields.yml index a8ba69f2810..2f1dcef1335 100644 --- a/metricbeat/module/rabbitmq/_meta/fields.yml +++ b/metricbeat/module/rabbitmq/_meta/fields.yml @@ -1,9 +1,9 @@ - key: rabbitmq - title: "rabbitmq" + title: "RabbitMQ" description: > []experimental - rabbitmq Module + RabbitMQ module fields: - name: rabbitmq type: group diff --git a/metricbeat/module/rabbitmq/node/_meta/docs.asciidoc b/metricbeat/module/rabbitmq/node/_meta/docs.asciidoc index b6e1d80a53c..d54d59c0e56 100644 --- a/metricbeat/module/rabbitmq/node/_meta/docs.asciidoc +++ b/metricbeat/module/rabbitmq/node/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== rabbitmq node MetricSet +=== RabbitMQ node metricset -This is the node metricset of the module rabbitmq. +This is the `node` metricset of the RabbitMQ module. diff --git a/metricbeat/module/redis/_meta/docs.asciidoc b/metricbeat/module/redis/_meta/docs.asciidoc index 1da255fc893..748cf23c3bf 100644 --- a/metricbeat/module/redis/_meta/docs.asciidoc +++ b/metricbeat/module/redis/_meta/docs.asciidoc @@ -1,9 +1,9 @@ -== Redis Module +== Redis module This module periodically fetches metrics from http://redis.io/[Redis] servers. [float] -=== Module-Specific Configuration Notes +=== Module-specific configuration notes The Redis module has these additional config options: diff --git a/metricbeat/module/redis/info/_meta/docs.asciidoc b/metricbeat/module/redis/info/_meta/docs.asciidoc index 7c263a99772..486bf79ab4a 100644 --- a/metricbeat/module/redis/info/_meta/docs.asciidoc +++ b/metricbeat/module/redis/info/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== Redis Info Metricset +=== Redis info metricset The Redis `info` metricset collects information and statistics from Redis by running the http://redis.io/commands/INFO[`INFO`] command and parsing the returned result. diff --git a/metricbeat/module/redis/keyspace/_meta/docs.asciidoc b/metricbeat/module/redis/keyspace/_meta/docs.asciidoc index e357e6b4e05..bd8d4b1c5cc 100644 --- a/metricbeat/module/redis/keyspace/_meta/docs.asciidoc +++ b/metricbeat/module/redis/keyspace/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== Redis Keyspace Metricset +=== Redis keyspace metricset The Redis `keyspace` metricset collects information about the Redis keyspaces. For each keyspace, an event is sent to Elasticsearch. diff --git a/metricbeat/module/system/_meta/docs.asciidoc b/metricbeat/module/system/_meta/docs.asciidoc index e385a7b520b..2529e86b8d0 100644 --- a/metricbeat/module/system/_meta/docs.asciidoc +++ b/metricbeat/module/system/_meta/docs.asciidoc @@ -1,16 +1,15 @@ -== System Module +== System module The System module allows you to monitor your servers. Because the System module always applies to the local server, the `hosts` config option is not needed. [float] -=== Module-Specific Configuration Notes +=== Module-specific configuration notes The System module has these additional config options: *`processes`*:: When the `process` metricset is enabled, you can use the `processes` option to define a list of -regexp expressions to filter the processes that are reported. For more complex filtering, you should use the -<> configuration option. +regexp expressions to filter the processes that are reported. For more complex filtering, you should use the `processors` configuration option. See <> for more information. + The following example config returns metrics for all processes: + diff --git a/metricbeat/module/system/core/_meta/docs.asciidoc b/metricbeat/module/system/core/_meta/docs.asciidoc index 5b4f2797030..af39d109182 100644 --- a/metricbeat/module/system/core/_meta/docs.asciidoc +++ b/metricbeat/module/system/core/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== System Core Metricset +=== System core metricset The System `core` metricset provides load statistics for each CPU core. diff --git a/metricbeat/module/system/cpu/_meta/docs.asciidoc b/metricbeat/module/system/cpu/_meta/docs.asciidoc index 1a62e46bd01..4d42a6f555f 100644 --- a/metricbeat/module/system/cpu/_meta/docs.asciidoc +++ b/metricbeat/module/system/cpu/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== System CPU Metricset +=== System cpu metricset The System `cpu` metricset provides CPU statistics. diff --git a/metricbeat/module/system/diskio/_meta/docs.asciidoc b/metricbeat/module/system/diskio/_meta/docs.asciidoc index f313e664c02..edcb19e283e 100644 --- a/metricbeat/module/system/diskio/_meta/docs.asciidoc +++ b/metricbeat/module/system/diskio/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== System Diskio Metricset +=== System diskio metricset The System `diskio` metricset provides disk IO metrics collected from the operating system. One event is created for each disk mounted on the system. diff --git a/metricbeat/module/system/filesystem/_meta/docs.asciidoc b/metricbeat/module/system/filesystem/_meta/docs.asciidoc index 04793c4ecda..ee216a01ffd 100644 --- a/metricbeat/module/system/filesystem/_meta/docs.asciidoc +++ b/metricbeat/module/system/filesystem/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== System Filesystem Metricset +=== System filesystem metricset The System `filesystem` metricset provides file system statistics. For each file system, one document is provided. diff --git a/metricbeat/module/system/fsstat/_meta/docs.asciidoc b/metricbeat/module/system/fsstat/_meta/docs.asciidoc index 06ac6e4d07a..16cbe772f05 100644 --- a/metricbeat/module/system/fsstat/_meta/docs.asciidoc +++ b/metricbeat/module/system/fsstat/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== System Fsstat Metricset +=== System fsstat metricset The System `fsstat` metricset provides overall file system statistics. diff --git a/metricbeat/module/system/load/_meta/docs.asciidoc b/metricbeat/module/system/load/_meta/docs.asciidoc index 5dbebca6aca..ac54ecaba62 100644 --- a/metricbeat/module/system/load/_meta/docs.asciidoc +++ b/metricbeat/module/system/load/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== System Load Metricset +=== System load metricset The System `load` metricset provides load statistics. diff --git a/metricbeat/module/system/memory/_meta/docs.asciidoc b/metricbeat/module/system/memory/_meta/docs.asciidoc index c116a45444d..400e83b0a07 100644 --- a/metricbeat/module/system/memory/_meta/docs.asciidoc +++ b/metricbeat/module/system/memory/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== System Memory Metricset +=== System memory metricset The System `memory` metricset provides memory statistics. diff --git a/metricbeat/module/system/network/_meta/docs.asciidoc b/metricbeat/module/system/network/_meta/docs.asciidoc index d68bd51dd59..5da1e75da7e 100644 --- a/metricbeat/module/system/network/_meta/docs.asciidoc +++ b/metricbeat/module/system/network/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== System Network Metricset +=== System network metricset The System `network` metricset provides network IO metrics collected from the operating system. One event is created for each network interface. diff --git a/metricbeat/module/system/process/_meta/docs.asciidoc b/metricbeat/module/system/process/_meta/docs.asciidoc index b2021b669d4..44d0888e435 100644 --- a/metricbeat/module/system/process/_meta/docs.asciidoc +++ b/metricbeat/module/system/process/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== System Process Metricset +=== System process metricset The System `process` metricset provides process statistics. One document is provided for each process. @@ -11,7 +11,7 @@ This metricset is available on: - Windows [float] -=== Cache CmdLine +=== Cache cmdline This metricset caches the command line args for a running process. This means if you alter the command line for a process while this metricset is running, these changes are not detected. @@ -19,14 +19,14 @@ This feature can be disabled by adding `process.cmdline.cache.enabled: false` to the system module configuration. [float] -=== Control Group (cgroup) Metrics +=== Control group (cgroup) metrics On Linux this metricset will collect metrics from any cgroups that the process is a member of. This feature is enabled by default and can be disabled by adding `process.cgroups.enabled: false` to the system module configuration. [float] -=== Process Environment Variables +=== Process environment variables This metricset can collect the environment variables that were used to start the process. This feature is available on Linux, Darwin, and FreeBSD. No environment diff --git a/metricbeat/module/system/process_summary/_meta/docs.asciidoc b/metricbeat/module/system/process_summary/_meta/docs.asciidoc index 1bc646a1c4d..faa96021b7c 100644 --- a/metricbeat/module/system/process_summary/_meta/docs.asciidoc +++ b/metricbeat/module/system/process_summary/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== System Process Summary MetricSet +=== System process summary metricset -This is the `process_summary` metricset of the module system. It collects high -level statistics about the running processes. +The `process_summary` metricset collects high level statistics about the running +processes. diff --git a/metricbeat/module/system/socket/_meta/docs.asciidoc b/metricbeat/module/system/socket/_meta/docs.asciidoc index 77184bc9dd3..23255ba5780 100644 --- a/metricbeat/module/system/socket/_meta/docs.asciidoc +++ b/metricbeat/module/system/socket/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -=== System Socket Metricset +=== System socket metricset beta[] diff --git a/metricbeat/module/vsphere/_meta/docs.asciidoc b/metricbeat/module/vsphere/_meta/docs.asciidoc index d1494db5a70..1014f1e05cc 100644 --- a/metricbeat/module/vsphere/_meta/docs.asciidoc +++ b/metricbeat/module/vsphere/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -== vsphere Module +== vSphere module -This is the vsphere Module that uses the library Govmomi (https://github.com/vmware/govmomi) to collect metrics from any Vmware SDK URL (ESXi/VCenter). This library is built for and tested against ESXi and vCenter 5.5, 6.0 and 6.5. +The vSphere module uses the https://github.com/vmware/govmomi[Govmomi] library to collect metrics from any Vmware SDK URL (ESXi/VCenter). This library is built for and tested against ESXi and vCenter 5.5, 6.0 and 6.5. diff --git a/metricbeat/module/vsphere/_meta/fields.yml b/metricbeat/module/vsphere/_meta/fields.yml index f1888303e84..a2577f4e604 100644 --- a/metricbeat/module/vsphere/_meta/fields.yml +++ b/metricbeat/module/vsphere/_meta/fields.yml @@ -1,7 +1,7 @@ - key: vsphere - title: "vsphere" + title: "vSphere" description: > - vsphere Module + vSphere module fields: - name: vsphere type: group diff --git a/metricbeat/module/vsphere/datastore/_meta/docs.asciidoc b/metricbeat/module/vsphere/datastore/_meta/docs.asciidoc index 3719fed1225..25d2fa3305f 100644 --- a/metricbeat/module/vsphere/datastore/_meta/docs.asciidoc +++ b/metricbeat/module/vsphere/datastore/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== vsphere datastore MetricSet +=== vSphere datastore metricset -This is the datastore metricset of the module vsphere. +This is the `datastore` metricset of the vSphere module. diff --git a/metricbeat/module/vsphere/host/_meta/docs.asciidoc b/metricbeat/module/vsphere/host/_meta/docs.asciidoc index 6b2043878ec..6ab63f563c1 100644 --- a/metricbeat/module/vsphere/host/_meta/docs.asciidoc +++ b/metricbeat/module/vsphere/host/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== vsphere host MetricSet +=== vSphere host metricset -This is the host metricset of the module vsphere. +This is the `host` metricset of the vSphere module. diff --git a/metricbeat/module/vsphere/virtualmachine/_meta/docs.asciidoc b/metricbeat/module/vsphere/virtualmachine/_meta/docs.asciidoc index 69752670241..0b20388be0d 100644 --- a/metricbeat/module/vsphere/virtualmachine/_meta/docs.asciidoc +++ b/metricbeat/module/vsphere/virtualmachine/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== vsphere virtualmachine MetricSet +=== vSphere virtualmachine metricset -This is the virtualmachine metricset of the module vsphere. +This is the `virtualmachine` metricset of the vSphere module. diff --git a/metricbeat/module/windows/_meta/docs.asciidoc b/metricbeat/module/windows/_meta/docs.asciidoc index 1f95a0d2c35..750ab403bcc 100644 --- a/metricbeat/module/windows/_meta/docs.asciidoc +++ b/metricbeat/module/windows/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -== Windows Module +== Windows module This is the Windows module. diff --git a/metricbeat/module/windows/perfmon/_meta/docs.asciidoc b/metricbeat/module/windows/perfmon/_meta/docs.asciidoc index f8b03bc730e..68fcee1c362 100644 --- a/metricbeat/module/windows/perfmon/_meta/docs.asciidoc +++ b/metricbeat/module/windows/perfmon/_meta/docs.asciidoc @@ -1,6 +1,6 @@ -=== Windows Perfmon MetricSet +=== Windows perfmon metricset -This is the perfmon metricset of the Windows module. It reads Windows +The `perfmon` metricset of the Windows module reads Windows performance counters. [float] diff --git a/metricbeat/module/zookeeper/_meta/docs.asciidoc b/metricbeat/module/zookeeper/_meta/docs.asciidoc index c5c363975a8..b493e81c886 100644 --- a/metricbeat/module/zookeeper/_meta/docs.asciidoc +++ b/metricbeat/module/zookeeper/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -== ZooKeeper Module +== ZooKeeper module The ZooKeeper module fetches statistics from the ZooKeeper service. diff --git a/metricbeat/module/zookeeper/mntr/_meta/docs.asciidoc b/metricbeat/module/zookeeper/mntr/_meta/docs.asciidoc index 4de9fb438b6..a54d1d59303 100644 --- a/metricbeat/module/zookeeper/mntr/_meta/docs.asciidoc +++ b/metricbeat/module/zookeeper/mntr/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== ZooKeeper mntr Metricset +=== ZooKeeper mntr metricset The ZooKeeper `mntr` metricset collects ZooKeeper monitoring statistics. diff --git a/metricbeat/scripts/docs_collector.py b/metricbeat/scripts/docs_collector.py index a4a241e839d..aa9456df753 100644 --- a/metricbeat/scripts/docs_collector.py +++ b/metricbeat/scripts/docs_collector.py @@ -54,7 +54,7 @@ def collect(beat_name): module_file += """ [float] -=== Example Configuration +=== Example configuration The """ + title + """ module supports the standard configuration options that are described in <>. Here is an example configuration: diff --git a/packetbeat/docs/capturing.asciidoc b/packetbeat/docs/capturing.asciidoc deleted file mode 100644 index af97b2bc543..00000000000 --- a/packetbeat/docs/capturing.asciidoc +++ /dev/null @@ -1,52 +0,0 @@ -[[capturing-options]] -== Setting Traffic Capturing Options - -There are two main ways of deploying Packetbeat: - -* On dedicated servers, getting the traffic from mirror ports or tap devices. - -* On your existing application servers. - -The first option has the big advantage that there is no overhead of any kind on -your application servers. But it requires dedicated networking gear, which is -generally not available on cloud setups. - -In both cases, the sniffing performance (reading packets passively from the network) -is very important. In the case of a dedicated server, better -sniffing performance means that less hardware is required. When Packetbeat is installed -on an existing application server, better sniffing performance means less overhead. - -Currently Packetbeat has several options for traffic capturing: - - * `pcap`, which uses the libpcap library and works on most platforms, but - it's not the fastest option. - * `af_packet`, which uses memory mapped sniffing. This option is faster than libpcap - and doesn't require a kernel module, but it's Linux-specific. - -The `af_packet` option, also known as "memory-mapped sniffing," makes use of a -Linux-specific -http://lxr.free-electrons.com/source/Documentation/networking/packet_mmap.txt[feature]. -This could be the optimal sniffing mode for both the dedicated server and -when Packetbeat is deployed on an existing application server. - -The way it works is that both the kernel and the user space program map the -same memory zone, and a simple circular buffer is organized in this memory zone. -The kernel writes packets into the circular buffer, and the user space program -reads from it. The poll system call is used for getting a notification for the -first packet available, but the remaining available packets can be simply read -via memory access. - -The `af_packet` sniffer can be further tuned to use more memory in exchange for -better performance. The larger the size of the circular buffer, the fewer -system calls are needed, which means that fewer CPU cycles are consumed. The default size -of the buffer is 30 MB, but you can increase it like this: - -[source,yaml] ------------------------------------------------------------------------------- -packetbeat.interfaces.device: eth0 -packetbeat.interfaces.type: af_packet -packetbeat.interfaces.buffer_size_mb: 100 ------------------------------------------------------------------------------- - -Please see the <> section for more -configuration options. diff --git a/packetbeat/docs/command-line.asciidoc b/packetbeat/docs/command-line.asciidoc index 2bddebfb164..70b289d55d2 100644 --- a/packetbeat/docs/command-line.asciidoc +++ b/packetbeat/docs/command-line.asciidoc @@ -1,12 +1,12 @@ [[command-line-options]] -=== Command Line Options +=== Command line options The following command line options are available for Packetbeat. To use these options, you need to start Packetbeat in the foreground. TIP: Run `./packetbeat -h` to see the full list of options from the command line. -==== Packet-Beat Specific Options +==== Packetbeat-specific options These command line options are specific to Packetbeat: *`-I `*:: @@ -29,7 +29,7 @@ For an infinite loop, use _0_. The `-l` option is useful only for testing Packet *`-t`*:: Read the packets from the pcap file as fast as possible without sleeping. Use this option in combination with the `-I` option. The `-t` option is useful only for testing Packetbeat. -==== Other Options +==== Other options These command line options from libbeat are also available for Packetbeat: diff --git a/packetbeat/docs/configuring-howto.asciidoc b/packetbeat/docs/configuring-howto.asciidoc index 9068788c9eb..eebfef0989b 100644 --- a/packetbeat/docs/configuring-howto.asciidoc +++ b/packetbeat/docs/configuring-howto.asciidoc @@ -3,32 +3,68 @@ [partintro] -- -After following the <> in the -Getting Started, you might want to fine tune the behavior of Packetbeat. This section -describes some common use cases for changing configuration options. +Before modifying configuration settings, make sure you've completed the +<> in the Getting Started. +This section describes some common use cases for changing configuration options. -To configure {beatname_uc}, you edit the configuration file. For rpm and deb, you’ll find the default configuration file at -+/etc/{beatname_lc}/{beatname_lc}.yml+. There's also a full example configuration file at -+/etc/{beatname_lc}/{beatname_lc}.reference.yml+ that shows all non-deprecated options. For mac and win, look in the archive -that you extracted. +To configure {beatname_uc}, you edit the configuration file. For rpm and deb, +you’ll find the configuration file at +/etc/{beatname_lc}/{beatname_lc}.yml+. +There's also a full example configuration file at ++/etc/{beatname_lc}/{beatname_lc}.reference.yml+ that shows all non-deprecated +options. For mac and win, look in the archive that you extracted. -See the -{libbeat}/config-file-format.html[Config File Format] section of the +The {beatname_uc} configuration file uses http://yaml.org/[YAML] for its syntax. +See the {libbeat}/config-file-format.html[Config File Format] section of the _Beats Platform Reference_ for more about the structure of the config file. The following topics describe how to configure Packetbeat: -* <> +* <> +* <> +* <> +* <> +* <> +* <> * <> * <> * <> -* <> +* <> +* <> +* <> +* <> +* <> * <> -* <> -* <> * <> -- -include::reference/configuration.asciidoc[] +include::./packetbeat-options.asciidoc[] + +include::./packetbeat-general-options.asciidoc[] + +:allplatforms: +include::../../libbeat/docs/outputconfig.asciidoc[] + +include::./packetbeat-filtering.asciidoc[] + +include::../../libbeat/docs/shared-config-ingest.asciidoc[] + +include::./packetbeat-geoip.asciidoc[] + +include::../../libbeat/docs/shared-path-config.asciidoc[] + +include::../../libbeat/docs/setup-config.asciidoc[] + +include::../../libbeat/docs/loggingconfig.asciidoc[] + +include::./runconfig.asciidoc[] + +:standalone: +include::../../libbeat/docs/shared-env-vars.asciidoc[] + +:standalone: +:allplatforms: +include::../../libbeat/docs/yaml.asciidoc[] + +include::../../libbeat/docs/reference-yml.asciidoc[] diff --git a/packetbeat/docs/configuring-logstash.asciidoc b/packetbeat/docs/configuring-logstash.asciidoc deleted file mode 100644 index e48b133339c..00000000000 --- a/packetbeat/docs/configuring-logstash.asciidoc +++ /dev/null @@ -1,5 +0,0 @@ -[[config-packetbeat-logstash]] -== Configuring Packetbeat to Use Logstash - -:allplatforms: -include::../../libbeat/docs/shared-logstash-config.asciidoc[] diff --git a/packetbeat/docs/faq.asciidoc b/packetbeat/docs/faq.asciidoc index 24ae6cdc4bb..a6fa5849bad 100644 --- a/packetbeat/docs/faq.asciidoc +++ b/packetbeat/docs/faq.asciidoc @@ -1,5 +1,5 @@ [[faq]] -== Frequently Asked Questions +== Frequently asked questions This section contains frequently asked questions about Packetbeat. Also check out the https://discuss.elastic.co/c/beats/packetbeat[Packetbeat discussion forum]. diff --git a/packetbeat/docs/filtering.asciidoc b/packetbeat/docs/filtering.asciidoc index d2643866313..c7b68c90ccf 100644 --- a/packetbeat/docs/filtering.asciidoc +++ b/packetbeat/docs/filtering.asciidoc @@ -1,10 +1,10 @@ [[kibana-queries-filters]] -== Kibana Queries and Filters +== Kibana queries and filters In Kibana, you can filter transactions either by entering a search query or by clicking on elements within a visualization. [float] -=== Creating Queries +=== Create queries The search field on the *Discover* page provides a way to query a specific subset of transactions from the selected time frame. @@ -17,7 +17,7 @@ you want to find the HTTP redirects, you can search for image:./images/kibana-query-filtering.png[Kibana query] [float] -==== String Queries +==== String queries A query may consist of one or more words or a phrase. A phrase is a group of words surrounded by double quotation marks, such as `"test search"`. @@ -47,7 +47,7 @@ To search for all transactions with the "chunked" encoding: ----------------------------- [float] -==== Field-Based Queries +==== Field-based queries Kibana allows you to search specific fields. @@ -74,7 +74,7 @@ mysql.method: INSERT --------------------- [float] -==== Regexp Queries +==== Regexp queries Kibana supports regular expression for filters and expressions. For example, to search for all HTTP responses with JSON as the returned value type: @@ -89,7 +89,7 @@ http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-regexp- for more details about the syntax. [float] -==== Range Queries +==== Range queries Range queries allow a field to have values between the lower and upper bounds. The interval can include or exclude the bounds depending on the type of @@ -110,7 +110,7 @@ responsetime: {10 TO *} ------------------------- [float] -==== Boolean Queries +==== Boolean queries Boolean operators (AND, OR, NOT) allow combining multiple sub-queries through logic operators. @@ -142,7 +142,7 @@ To search for either INSERT or UPDATE MySQL queries with a response time greater --------------------------------------------------------------------------- [float] -=== Creating Filters +=== Create filters In Kibana, you can also filter transactions by clicking on elements within a visualization. For example, to filter for all the HTTP redirects that are coming from a specific diff --git a/packetbeat/docs/flows.asciidoc b/packetbeat/docs/flows.asciidoc deleted file mode 100644 index 4f7dde72c7e..00000000000 --- a/packetbeat/docs/flows.asciidoc +++ /dev/null @@ -1,80 +0,0 @@ -[[flows]] -== Configuring Flows to Monitor Network Traffic - -You can configure Packetbeat to collect and report statistics on network flows. -A _flow_ is a group of packets sent over the same time period that share -common properties, such as the same source and destination address and protocol. -You can use this feature to analyze network traffic over specific protocols on -your network. - -For each flow, Packetbeat reports the number of packets and the total number of -bytes sent from the source to the destination. Each flow event also contains -information about the source and destination hosts, such as their IP address. -For bi-directional flows, Packetbeat reports statistics for the reverse flow. - -Packetbeat collects and reports statistics up to and including the transport -layer. See <> for more info about the exported -data. - -Here's an example of flow events visualized in the Flows dashboard: - -image:./images/flows.png[] - -To configure flows, use the `flows` option in the +{beatname_lc}.yml+ config file. -Flows are enabled by default. - -[source,yaml] --------------------------------------------------------------------------------- -packetbeat.flows: - timeout: 30s - period: 10s --------------------------------------------------------------------------------- - -See <> for more info about these configuration options. - -Here’s an example of a flow information sent by Packetbeat. See -<> for a description of each field. - -["source","json",subs="attributes"] --------------------------------------------------------------------------------- -{ - "@timestamp": "2017-05-03T19:42:40.003Z", - "beat": { - "hostname": "host.example.com", - "name": "host.example.com", - "version": "{stack-version}" - }, - "connection_id": "AQAAAAAAAAA=", - "dest": { - "ip": "192.0.2.0", - "mac": "fe:ff:20:00:01:00", - "port": 80, - "stats": { - "net_bytes_total": 19236, - "net_packets_total": 16 - } - }, - "final": false, <1> - "flow_id": "EQwA////DP//////FBgBAAEAAAEAAAD+/yAAAQCR/qDtQdDk3ywNUAABAAAAAAAAAA", - "last_time": "2017-05-03T19:42:24.151Z", - "source": { - "ip": "203.0.113.0", - "mac": "00:00:01:00:00:00", - "port": 3372, - "stats": { - "net_bytes_total": 1243, - "net_packets_total": 14 - } - }, - "start_time": "2017-05-03T19:42:24.151Z", - "transport": "tcp", - "type": "flow" -} --------------------------------------------------------------------------------- - -<1> Packetbeat sets the `final` flag to `false` to indicate that the event -contains an intermediate report about a flow that it's tracking. When the flow -completes, Packetbeat sends one last event with `final` set to `true`. If you -want to aggregate sums of traffic, you need to filter on `final:true`, or use -some other technique, so that you get only the latest update from each flow. -You can disable intermediate reports by setting `period: -1s`. diff --git a/packetbeat/docs/gettingstarted.asciidoc b/packetbeat/docs/gettingstarted.asciidoc index 9a2b92ccf20..4ac40e1f80b 100644 --- a/packetbeat/docs/gettingstarted.asciidoc +++ b/packetbeat/docs/gettingstarted.asciidoc @@ -1,5 +1,5 @@ [[packetbeat-getting-started]] -== Getting Started With Packetbeat +== Getting started with Packetbeat The best way to understand the value of a network packet analytics system like Packetbeat is to try it on your own traffic. @@ -23,7 +23,7 @@ After installing the Elastic Stack, read the following topics to learn how to in * <> [[packetbeat-installation]] -=== Step 1: Installing Packetbeat +=== Step 1: Install Packetbeat include::../../libbeat/docs/shared-download-and-install.asciidoc[] @@ -142,10 +142,10 @@ endif::[] Before starting Packetbeat, you should look at the configuration options in the configuration file, for example `C:\Program Files\Packetbeat\packetbeat.yml` or `/etc/packetbeat/packetbeat.yml`. For -more information about these options, see <>. +more information about these options, see <>. [[configuring-packetbeat]] -=== Step 2: Configuring Packetbeat +=== Step 2: Configure Packetbeat include::../../libbeat/docs/shared-configuring.asciidoc[] @@ -236,7 +236,8 @@ output.elasticsearch: hosts: ["192.168.1.42:9200"] ---------------------------------------------------------------------- + -If you are sending output to Logstash, see <> instead. +If you are sending output to Logstash, see +<> instead. TIP: To test your configuration file, change to the directory where the Packetbeat binary is installed, and run Packetbeat in the foreground with the following @@ -248,13 +249,13 @@ test. See {libbeat}/config-file-permissions.html[Config File Ownership and Permi in the _Beats Platform Reference_ for more information. [[packetbeat-template]] -=== Step 3: Loading the Index Template in Elasticsearch +=== Step 3: Load the index template in Elasticsearch :allplatforms: include::../../libbeat/docs/shared-template-load.asciidoc[] [[packetbeat-starting]] -=== Step 4: Starting Packetbeat +=== Step 4: Start Packetbeat Run Packetbeat by issuing the command that is appropriate for your platform. @@ -305,7 +306,7 @@ PS C:\Program Files\Packetbeat> Start-Service packetbeat By default the log files are stored in `C:\ProgramData\packetbeat\Logs`. [float] -=== Testing the Packetbeat Installation +=== Test the Packetbeat installation Packetbeat is now ready to capture data from your network traffic. You can test that it works by creating a simple HTTP request. For example: @@ -326,7 +327,7 @@ Make sure that you replace `localhost:9200` with the address of your Elasticsear instance. The command should return data about the HTTP transaction you just created. [[packetbeat-sample-dashboards]] -=== Step 5: Loading Sample Kibana Dashboards +=== Step 5: Load sample Kibana dashboards To make it easier for you to get application performance insights from packet data, we have created sample Packetbeat dashboards. The dashboards are provided as diff --git a/packetbeat/docs/index.asciidoc b/packetbeat/docs/index.asciidoc index bf301211a30..b28432202b4 100644 --- a/packetbeat/docs/index.asciidoc +++ b/packetbeat/docs/index.asciidoc @@ -38,29 +38,6 @@ include::./upgrading.asciidoc[] include::./configuring-howto.asciidoc[] -include::../../libbeat/docs/shared-env-vars.asciidoc[] - -include::./capturing.asciidoc[] - -include::./packetbeat-filtering.asciidoc[] - -include::../../libbeat/docs/shared-config-ingest.asciidoc[] - -include::./packetbeat-geoip.asciidoc[] - -include::./configuring-logstash.asciidoc[] - -include::./flows.asciidoc[] - -:standalone: -include::../../libbeat/docs/shared-env-vars.asciidoc[] - -include::./thrift.asciidoc[] - -:standalone: -:allplatforms: -include::../../libbeat/docs/yaml.asciidoc[] - include::./fields.asciidoc[] include::./securing-packetbeat.asciidoc[] diff --git a/packetbeat/docs/overview.asciidoc b/packetbeat/docs/overview.asciidoc index 0f2a15891cf..4bc955eb321 100644 --- a/packetbeat/docs/overview.asciidoc +++ b/packetbeat/docs/overview.asciidoc @@ -1,9 +1,13 @@ [[packetbeat-overview]] -== Overview +== Packetbeat overview -Packetbeat is a real-time network packet analyzer that you can use +++++ +Overview +++++ + +Packetbeat is a real-time network packet analyzer that you can use with Elasticsearch to provide an _application monitoring and performance -analytics system_. Packetbeat completes the {libbeat}/index.html[Beats platform] +analytics system_. Packetbeat completes the {libbeat}/index.html[Beats platform] by providing visibility between the servers of your network. Packetbeat works by capturing the network traffic between your application servers, @@ -22,16 +26,16 @@ Currently, Packetbeat supports the following protocols: include::shared-protocol-list.asciidoc[] Packetbeat can insert the correlated transactions directly into Elasticsearch -or into a central queue created with Redis and Logstash. +or into a central queue created with Redis and Logstash. Packetbeat can run on the same servers as your application processes or on its own servers. When running on dedicated servers, Packetbeat can get the traffic from the switch's mirror ports or from tapping devices. In such a deployment, there is zero overhead on the monitored application. See -<> for details. +<> for details. After decoding the Layer 7 messages, Packetbeat correlates the requests with -the responses in what we call _transactions_. For each transaction, Packetbeat +the responses in what we call _transactions_. For each transaction, Packetbeat inserts a JSON document into Elasticsearch. See the <> section for details about which fields are indexed. diff --git a/packetbeat/docs/packetbeat-filtering.asciidoc b/packetbeat/docs/packetbeat-filtering.asciidoc index 7c043b3523b..c30635b6680 100644 --- a/packetbeat/docs/packetbeat-filtering.asciidoc +++ b/packetbeat/docs/packetbeat-filtering.asciidoc @@ -1,5 +1,5 @@ [[filtering-and-enhancing-data]] -== Filtering and Enhancing the Exported Data +== Filter and enhance the exported data include::../../libbeat/docs/processors.asciidoc[] diff --git a/packetbeat/docs/packetbeat-general-options.asciidoc b/packetbeat/docs/packetbeat-general-options.asciidoc new file mode 100644 index 00000000000..0347b3b2dcf --- /dev/null +++ b/packetbeat/docs/packetbeat-general-options.asciidoc @@ -0,0 +1,8 @@ +[[configuration-general-options]] +== Specify general settings + +You can specify settings in the +{beatname_lc}.yml+ config file to control the +general behavior of {beatname_uc}. + +include::../../libbeat/docs/generalconfig.asciidoc[] + diff --git a/packetbeat/docs/packetbeat-geoip.asciidoc b/packetbeat/docs/packetbeat-geoip.asciidoc index 195c205181a..fba9da7b0b0 100644 --- a/packetbeat/docs/packetbeat-geoip.asciidoc +++ b/packetbeat/docs/packetbeat-geoip.asciidoc @@ -1,8 +1,8 @@ [[packetbeat-geoip]] -== Exporting GeoIP Information +== Export GeoIP Information You can use Packetbeat along with the -{plugindoc}/ingest-geoip.html[ingest geoIP processor plugin] in Elasticsearch +{plugindoc}/ingest-geoip.html[ingest geoIP processor plugin] in Elasticsearch to export geographic location information about source IPs for incoming HTTP requests. Then you can use this info to visualize the location of your clients on a map in Kibana. @@ -24,7 +24,7 @@ Logstash. [float] [[packetbeat-configuring-geoip]] -=== Configuring the Ingest GeoIP Processor Plugin +=== Configuring the ingest geoIP processor plugin To configure Packetbeat and the ingest geoIP processor plugin: @@ -46,7 +46,7 @@ PUT _ingest/pipeline/geoip-info "field": "client_ip", "target_field": "client_geoip", "properties": ["location"], - "ignore_failure": true + "ignore_failure": true } } ] @@ -57,15 +57,15 @@ This pipeline adds a `client_geoip.location` field of type `geo_point` to the event. The ID of the pipeline is `geoip-info`. `client_ip` is the output field in Packetbeat that contains the IP address of the client. You set `ignore_failure` to `true` so that the pipeline will continue processing events -when it encounters an event that doesn't have a `client_ip` field. +when it encounters an event that doesn't have a `client_ip` field. + -See +See {plugindoc}/using-ingest-geoip.html[Using the Geoip Processor in a Pipeline] for more options. 3. In the Packetbeat config file, configure the Elasticsearch output to use the pipeline. Specify the pipeline ID in the `pipeline` option under -`output.elasticsearch`. For example: +`output.elasticsearch`. For example: + [source,yaml] ------------------------------------------------------------------------------- @@ -86,12 +86,12 @@ The event that's sent to Elasticsearch should now include a [float] [[packetbeat-visualizing-location]] -=== Visualizing the Location of Your Packetbeat Clients +=== Visualizing the location of your Packetbeat clients To visualize the location of your Packetbeat clients, you can either <> (if you haven't already), or create a new {kibanadoc}/tilemap.html[Tile map] in -Kibana and use the `client_geoip.location` field as the Geohash. +Kibana and use the `client_geoip.location` field as the Geohash. image:./images/kibana-update-map.png[Update Packetbeat client location map in Kibana] diff --git a/packetbeat/docs/reference/configuration/packetbeat-options.asciidoc b/packetbeat/docs/packetbeat-options.asciidoc similarity index 69% rename from packetbeat/docs/reference/configuration/packetbeat-options.asciidoc rename to packetbeat/docs/packetbeat-options.asciidoc index 377292db3b7..bedbffbb87c 100644 --- a/packetbeat/docs/reference/configuration/packetbeat-options.asciidoc +++ b/packetbeat/docs/packetbeat-options.asciidoc @@ -1,21 +1,70 @@ [[configuration-interfaces]] -=== Network Device (Interfaces) +== Set traffic capturing options -The `interfaces` section of the +{beatname_lc}.yml+ config file configures the sniffer. Here is an example configuration: +There are two main ways of deploying Packetbeat: + +* On dedicated servers, getting the traffic from mirror ports or tap devices. + +* On your existing application servers. + +The first option has the big advantage that there is no overhead of any kind on +your application servers. But it requires dedicated networking gear, which is +generally not available on cloud setups. + +In both cases, the sniffing performance (reading packets passively from the network) +is very important. In the case of a dedicated server, better +sniffing performance means that less hardware is required. When Packetbeat is installed +on an existing application server, better sniffing performance means less overhead. + +Currently Packetbeat has several options for traffic capturing: + + * `pcap`, which uses the libpcap library and works on most platforms, but + it's not the fastest option. + * `af_packet`, which uses memory mapped sniffing. This option is faster than libpcap + and doesn't require a kernel module, but it's Linux-specific. + +The `af_packet` option, also known as "memory-mapped sniffing," makes use of a +Linux-specific +http://lxr.free-electrons.com/source/Documentation/networking/packet_mmap.txt[feature]. +This could be the optimal sniffing mode for both the dedicated server and +when Packetbeat is deployed on an existing application server. + +The way it works is that both the kernel and the user space program map the +same memory zone, and a simple circular buffer is organized in this memory zone. +The kernel writes packets into the circular buffer, and the user space program +reads from it. The poll system call is used for getting a notification for the +first packet available, but the remaining available packets can be simply read +via memory access. + +The `af_packet` sniffer can be further tuned to use more memory in exchange for +better performance. The larger the size of the circular buffer, the fewer +system calls are needed, which means that fewer CPU cycles are consumed. The default size +of the buffer is 30 MB, but you can increase it like this: [source,yaml] ------------------------------------------------------------------------------ -packetbeat.interfaces.device: any -packetbeat.interfaces.snaplen: 1514 +packetbeat.interfaces.device: eth0 packetbeat.interfaces.type: af_packet packetbeat.interfaces.buffer_size_mb: 100 ------------------------------------------------------------------------------ -==== Sniffing Options -You can specify the following options in the `interfaces` section of the +{beatname_lc}.yml+ config file: +[float] +=== Sniffing configuration options + +You can specify the following options in the `packetbeat.interfaces` section +of the +{beatname_lc}.yml+ config file. Here is an example configuration: + +[source,yaml] +------------------------------------------------------------------------------ +packetbeat.interfaces.device: any +packetbeat.interfaces.snaplen: 1514 +packetbeat.interfaces.type: af_packet +packetbeat.interfaces.buffer_size_mb: 100 +------------------------------------------------------------------------------ -===== device +[float] +==== `device` The network device to capture traffic from. The specified device is set automatically to promiscuous mode, meaning that Packetbeat can capture traffic from other hosts on the same LAN. @@ -67,7 +116,8 @@ packetbeat.interfaces.device: 0 Specifying the index is especially useful on Windows where device names can be long. -===== snaplen +[float] +==== `snaplen` The maximum size of the packets to capture. The default is 65535, which is large enough for almost all networks and interface @@ -82,7 +132,8 @@ packetbeat.interfaces.device: eth0 packetbeat.interfaces.snaplen: 1514 ------------------------------------------------------------------------------ -===== type +[float] +==== `type` Packetbeat supports three sniffer types: @@ -103,13 +154,13 @@ packetbeat.interfaces.type: af_packet ------------------------------------------------------------------------------ On Linux, if you are trying to optimize the CPU usage of Packetbeat, we -recommend trying the `af_packet` option. Read <> for more -details. +recommend trying the `af_packet` option. If you use the `af_packet` sniffer, you can tune its behaviour by specifying the following options: -===== buffer_size_mb +[float] +==== `buffer_size_mb` The maximum size of the shared memory buffer to use between the kernel and user space. A bigger buffer usually results in lower CPU @@ -125,7 +176,8 @@ packetbeat.interfaces.type: af_packet packetbeat.interfaces.buffer_size_mb: 100 ------------------------------------------------------------------------------ -===== with_vlans +[float] +==== `with_vlans` Packetbeat automatically generates a https://en.wikipedia.org/wiki/Berkeley_Packet_Filter[BPF] for capturing only @@ -138,7 +190,8 @@ tags, the filter that Packetbeat generates is ineffective because the offset is moved by four bytes. To fix this, you can enable the `with_vlans` option, which generates a BPF filter that looks like this: `"port 80 or port 3306 or (vlan and (port 80 or port 3306))"`. -===== bpf_filter +[float] +==== `bpf_filter` Packetbeat automatically generates a https://en.wikipedia.org/wiki/Berkeley_Packet_Filter[BPF] for capturing only @@ -158,7 +211,8 @@ NOTE: This setting disables automatic generation of the BPF filter. If you use this setting, it's your responsibility to keep the BPF filters in sync with the ports defined in the `protocols` section. -===== ignore_outgoing +[float] +==== `ignore_outgoing` If the `ignore_outgoing` option is enabled, Packetbeat ignores all the transactions initiated from the server running Packetbeat. @@ -192,38 +246,107 @@ see the following published transactions (when `ignore_outgoing` is true): [[configuration-flows]] -=== Flows +== Set up flows to monitor network traffic -The `flows` section of the +{beatname_lc}.yml+ config file contains configuration options for bidirectional network -flows. If section is missing from configuration file, network flows are -disabled. +You can configure Packetbeat to collect and report statistics on network flows. +A _flow_ is a group of packets sent over the same time period that share +common properties, such as the same source and destination address and protocol. +You can use this feature to analyze network traffic over specific protocols on +your network. + +For each flow, Packetbeat reports the number of packets and the total number of +bytes sent from the source to the destination. Each flow event also contains +information about the source and destination hosts, such as their IP address. +For bi-directional flows, Packetbeat reports statistics for the reverse flow. + +Packetbeat collects and reports statistics up to and including the transport +layer. See <> for more info about the exported +data. + +Here's an example of flow events visualized in the Flows dashboard: + +image:./images/flows.png[] + +To configure flows, use the `packetbeat.flows` option in the +{beatname_lc}.yml+ +config file. Flows are enabled by default. If this section is missing +from the configuration file, network flows are disabled. [source,yaml] ------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- packetbeat.flows: timeout: 30s period: 10s ------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- -See <> for more information. +Here’s an example of a flow information sent by Packetbeat. See +<> for a description of each field. -==== Options +["source","json",subs="attributes"] +-------------------------------------------------------------------------------- +{ + "@timestamp": "2017-05-03T19:42:40.003Z", + "beat": { + "hostname": "host.example.com", + "name": "host.example.com", + "version": "{stack-version}" + }, + "connection_id": "AQAAAAAAAAA=", + "dest": { + "ip": "192.0.2.0", + "mac": "fe:ff:20:00:01:00", + "port": 80, + "stats": { + "net_bytes_total": 19236, + "net_packets_total": 16 + } + }, + "final": false, <1> + "flow_id": "EQwA////DP//////FBgBAAEAAAEAAAD+/yAAAQCR/qDtQdDk3ywNUAABAAAAAAAAAA", + "last_time": "2017-05-03T19:42:24.151Z", + "source": { + "ip": "203.0.113.0", + "mac": "00:00:01:00:00:00", + "port": 3372, + "stats": { + "net_bytes_total": 1243, + "net_packets_total": 14 + } + }, + "start_time": "2017-05-03T19:42:24.151Z", + "transport": "tcp", + "type": "flow" +} +-------------------------------------------------------------------------------- + +<1> Packetbeat sets the `final` flag to `false` to indicate that the event +contains an intermediate report about a flow that it's tracking. When the flow +completes, Packetbeat sends one last event with `final` set to `true`. If you +want to aggregate sums of traffic, you need to filter on `final:true`, or use +some other technique, so that you get only the latest update from each flow. +You can disable intermediate reports by setting `period: -1s`. -You can specify the following options in the `flows` section of the +{beatname_lc}.yml+ config file: +[float] +=== Configuration options -===== enabled +You can specify the following options in the `packetbeat.flows` section of +the +{beatname_lc}.yml+ config file: + +[float] +==== `enabled` Enables flows support if set to true. Set to false to disable network flows support without having to delete or comment out the flows section. The default value is true. -===== timeout +[float] +==== `timeout` Timeout configures the lifetime of a flow. If no packets have been received for a flow within the timeout time window, the flow is killed and reported. The default value is 30s. -===== period +[float] +==== `period` Configure the reporting interval. All flows are reported at the very same point in time. Periodical reporting can be disabled by setting the value to -1. If @@ -232,14 +355,16 @@ disabled, flows are still reported once being timed out. The default value is [[configuration-protocols]] -=== Transaction Protocols +== Specify which transaction protocols to monitor -The `protocols` section of the +{beatname_lc}.yml+ config file contains configuration options for each supported protocol, -including common options like `enabled`, `ports`, `send_request`, `send_response`, and options that are protocol-specific. +The `packetbeat.protocols` section of the +{beatname_lc}.yml+ config file +contains configuration options for each supported protocol, including common +options like `enabled`, `ports`, `send_request`, `send_response`, and options +that are protocol-specific. Currently, Packetbeat supports the following protocols: -include::../../shared-protocol-list.asciidoc[] +include::./shared-protocol-list.asciidoc[] Example configuration: @@ -280,17 +405,20 @@ packetbeat.protocols: ------------------------------------------------------------------------------ -==== Common Protocol Options +[[common-protocol-options]] +=== Common protocol options The following options are available for all protocols: -===== enabled +[float] +==== `enabled` The enabled setting is a boolean setting to enable or disable protocols without having to comment out configuration sections. If set to false, the protocol is disabled. The default value is true. -===== ports +[float] +==== `ports` Exception: For ICMP the option `enabled` has to be used instead. @@ -301,29 +429,33 @@ If a packet doesn't match the filter, very little CPU is required to discard the packet. Packetbeat also uses the ports specified here to determine which parser to use for each packet. +[float] [[send-request-option]] -===== send_request +==== `send_request` If this option is enabled, the raw message of the request (`request` field) is sent to Elasticsearch. The default is false. This option is useful when you want to index the whole request. Note that for HTTP, the body is not included by default, only the HTTP headers. +[float] [[send-response-option]] -===== send_response +==== `send_response` If this option is enabled, the raw message of the response (`response` field) is sent to Elasticsearch. The default is false. This option is useful when you want to index the whole response. Note that for HTTP, the body is not included by default, only the HTTP headers. +[float] [[transaction-timeout-option]] -===== transaction_timeout +==== `transaction_timeout` The per protocol transaction timeout. Expired transactions will no longer be correlated to incoming responses, but sent to Elasticsearch immediately. +[float] [[packetbeat-configuration-fields]] -===== 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 @@ -343,8 +475,9 @@ packetbeat.protocols: service_id: nginx -------------------------------------------------------------------------------- +[float] [[packetbeat-fields-under-root]] -===== fields_under_root +==== `fields_under_root` If this option is set to true, the custom <> are stored as top-level fields in the output document instead of being grouped @@ -352,17 +485,40 @@ under a `fields` sub-dictionary. If the custom field names conflict with other field names added by Packetbeat, then the custom fields overwrite the other fields. -==== ICMP Configuration Options +[[packetbeat-icmp-options]] +=== Capture ICMP traffic -You can specify the following options in the `icmp` section of the +{beatname_lc}.yml+ config file: +++++ +ICMP +++++ -===== enabled +The `icmp` section of the +{beatname_lc}.yml+ config file specifies options for +the ICMP protocol. Here is a sample configuration section for ICMP: + +[source,yaml] +------------------------------------------------------------------------------ +packetbeat.protocols: + +- type: icmp + enabled: true +------------------------------------------------------------------------------ + +==== Configuration options + +Also see <>. + +===== `enabled` The ICMP protocol can be enabled/disabled via this option. The default is true. If enabled Packetbeat will generate the following BPF filter: `"icmp or icmp6"`. -==== DNS Configuration Options +[[packetbeat-dns-options]] +=== Capture DNS traffic + +++++ +DNS +++++ The `dns` section of the +{beatname_lc}.yml+ config file specifies configuration options for the DNS protocol. The DNS protocol supports processing DNS messages on UDP. Here is a sample configuration section for DNS: @@ -375,17 +531,26 @@ packetbeat.protocols: include_additionals: true ------------------------------------------------------------------------------ -===== include_authorities +==== Configuration options + +Also see <>. + +===== `include_authorities` If this option is enabled, dns.authority fields (authority resource records) are added to DNS events. The default is false. -===== include_additionals +===== `include_additionals` If this option is enabled, dns.additionals fields (additional resource records) are added to DNS events. The default is false. -==== HTTP Configuration Options +[[packetbeat-http-options]] +=== Capture HTTP traffic + +++++ +HTTP +++++ The HTTP protocol has several specific configuration options. Here is a sample configuration for the `http` section of the +{beatname_lc}.yml+ config file: @@ -401,7 +566,11 @@ packetbeat.protocols: real_ip_header: "X-Forwarded-For" ------------------------------------------------------------------------------ -===== hide_keywords +==== Configuration options + +Also see <>. + +===== `hide_keywords` A list of query parameters that Packetbeat will automatically censor in the transactions that it saves. The values associated with these parameters are replaced @@ -419,8 +588,7 @@ you configure Packetbeat to save the raw request and response fields (see the << and the <> options), sensitive data may be present in those fields. - -===== redact_authorization +===== `redact_authorization` When this option is enabled, Packetbeat obscures the value of `Authorization` and `Proxy-Authorization` HTTP headers, and censors @@ -429,17 +597,17 @@ those strings in the response. You should set this option to true for transactions that use Basic Authentication because they may contain the base64 unencrypted username and password. -===== send_headers +===== `send_headers` A list of header names to capture and send to Elasticsearch. These headers are placed under the `headers` dictionary in the resulting JSON. -===== send_all_headers +===== `send_all_headers` Instead of sending a white list of headers to Elasticsearch, you can send all headers by setting this option to true. The default is false. -===== include_body_for +===== `include_body_for` The list of content types for which Packetbeat exports the full HTTP payload. The HTTP body is available under `http.request.body` and `http.response.body` for these Content-Types. @@ -462,7 +630,7 @@ packetbeat.protocols: -===== split_cookie +===== `split_cookie` If the `Cookie` or `Set-Cookie` headers are sent, this option controls whether they are split into individual values. For example, with this option set, an @@ -494,21 +662,25 @@ HTTP response might result in the following JSON: The default is false. -===== real_ip_header +===== `real_ip_header` The header field to extract the real IP from. This setting is useful when you want to capture traffic behind a reverse proxy, but you want to get the geo-location information. If this header is present and contains a valid IP addresses, the information is used for the `real_ip` field. -===== max_message_size +===== `max_message_size` If an individual HTTP message is larger than this setting (in bytes), it will be trimmed to this size. Unless this value is very small (<1.5K), Packetbeat is able to still correctly follow the transaction and create an event for it. The default is 10485760 (10 MB). +[[packetbeat-amqp-options]] +=== Capture AMQP traffic -==== AMQP Configuration Options +++++ +AMQP +++++ The `amqp` section of the +{beatname_lc}.yml+ config file specifies configuration options for the AMQP 0.9.1 protocol. Here is a sample configuration: @@ -524,26 +696,31 @@ packetbeat.protocols: hide_connection_information: true ------------------------------------------------------------------------------ -===== max_body_length + +==== Configuration options + +Also see <>. + +===== `max_body_length` The maximum size in bytes of the message displayed in the request or response fields. Messages that are bigger than the specified size are truncated. Use this option to avoid publishing huge messages when <> or <> is enabled. The default is 1000 bytes. -===== parse_headers +===== `parse_headers` If set to true, Packetbeat parses the additional arguments specified in the headers field of a message. Those arguments are key-value pairs that specify information such as the content type of the message or the message priority. The default is true. -===== parse_arguments +===== `parse_arguments` If set to true, Packetbeat parses the additional arguments specified in AMQP methods. Those arguments are key-value pairs specified by the user and can be of any length. The default is true. -===== hide_connection_information +===== `hide_connection_information` If set to false, the connection layer methods of the protocol are also displayed, such as the opening and closing of connections and channels by clients, @@ -551,7 +728,11 @@ or the quality of service negotiation. The default is true. [[configuration-cassandra]] -==== Cassandra Configuration Options +=== Capture Cassandra traffic + +++++ +Cassandra +++++ The following settings are specific to the Cassandra protocol. Here is a sample configuration for the `cassandra` section of the +{beatname_lc}.yml+ config file: @@ -566,30 +747,38 @@ packetbeat.protocols: ignored_ops: ["SUPPORTED","OPTIONS"] ------------------------------------------------------------------------------ -===== send_request_header +==== Configuration options + +Also see <>. + +===== `send_request_header` If this option is enabled, the raw message of the response (`cassandra_request.request_headers` field) is sent to Elasticsearch. The default is true. enable `send_request` first before enable this option. -===== send_response_header +===== `send_response_header` If this option is enabled, the raw message of the response (`cassandra_response.response_headers` field) is included in published events. The default is true. enable `send_response` first before enable this option. -===== ignored_ops +===== `ignored_ops` This option indicates which Operator/Operators captured will be ignored. currently support: `ERROR` ,`STARTUP` ,`READY` ,`AUTHENTICATE` ,`OPTIONS` ,`SUPPORTED` , `QUERY` ,`RESULT` ,`PREPARE` ,`EXECUTE` ,`REGISTER` ,`EVENT` , `BATCH` ,`AUTH_CHALLENGE`,`AUTH_RESPONSE` ,`AUTH_SUCCESS` . -===== compressor +===== `compressor` Configures the default compression algorithm being used to uncompress compressed frames by name. Currently only `snappy` is can be configured. By default no compressor is configured. +[[packetbeat-memcache-options]] +=== Capture Memcache traffic -==== Memcache Configuration Options +++++ +Memcache +++++ The `memcache` section of the +{beatname_lc}.yml+ config file specifies configuration options for the memcache protocol. Here is a sample configuration section for memcache: @@ -606,13 +795,18 @@ packetbeat.protocols: udptransactiontimeout: 200 ------------------------------------------------------------------------------ -===== parseunknown + +==== Configuration options + +Also see <>. + +===== `parseunknown` When this option is enabled, it forces the memcache text protocol parser to accept unknown commands. NOTE: The unknown commands MUST NOT contain a data part. -===== maxvalues +===== `maxvalues` The maximum number of values to store in the message (multi-get). All values will be base64 encoded. @@ -623,14 +817,14 @@ The possible settings for this option are: * `maxvalue: 0`, which stores no values (default) * `maxvalue: N`, which stores up to N values -===== maxbytespervalue +===== `maxbytespervalue` The maximum number of bytes to be copied for each value element. NOTE: Values will be base64 encoded, so the actual size in the JSON document will be 4 times the value that you specify for `maxbytespervalue`. -===== udptransactiontimeout +===== `udptransactiontimeout` The transaction timeout in milliseconds. The defaults is 10000 milliseconds. @@ -639,27 +833,92 @@ The memcache protocol analyzer will wait for the number of milliseconds specifie `udptransactiontimeout` before publishing quiet messages. Non-quiet messages or quiet requests with an error response are published immediately. +[[packetbeat-mysql-pgsql-options]] +=== Capture MySQL and PgSQL traffic + +++++ +MySQL and PgSQL +++++ + +The `mysql` and `pgsql` sections of the +{beatname_lc}.yml+ config file specify configuration options for the MySQL +and PgSQL protocols. + +[source,yaml] +------------------------------------------------------------------------------ +packetbeat.protocols: + +- type: mysql + ports: [3306] + +- type: pgsql + ports: [5432] +------------------------------------------------------------------------------ -==== MySQL and PgSQL Configuration Options +==== Configuration options -You can specify the following options in the `mysql` or `pgsql` sections of the +{beatname_lc}.yml+ config file: +Also see <>. -===== max_rows +===== `max_rows` The maximum number of rows from the SQL message to publish to Elasticsearch. The default is 10 rows. -===== max_row_length +===== `max_row_length` The maximum length in bytes of a row from the SQL message to publish to Elasticsearch. The default is 1024 bytes. [[configuration-thrift]] -==== Thrift Configuration Options +=== Capture Thrift traffic + +++++ +Thrift +++++ + +https://thrift.apache.org/[Apache Thrift] is a communication protocol and RPC +framework initially created at Facebook. It is sometimes used in +http://martinfowler.com/articles/microservices.html[microservices] +architectures because it provides better performance when compared to the more +obvious HTTP/RESTful API choice, while still supporting a wide range of +programming languages and frameworks. + +Packetbeat works based on a copy of the traffic, which means that you get +performance management features without having to modify your services in +any way and without any latency overhead. Packetbeat captures the transactions from the +network and indexes them in Elasticsearch so that they can be analyzed and +searched. + +Packetbeat indexes the method, parameters, return value, and +exceptions of each Thrift-RPC call. You can search by and create statistics +based on any of these fields. Packetbeat automatically fills in the `status` +column with either `OK` or `Error`, so it's easy to find the problematic RPC calls. +A transaction is put into the `Error` state if it returned an exception. + +Packetbeat also indexes the `responsetime` field so you can get performance +analytics and find the slow RPC calls. + +Here is an example performance dashboard: -The Thrift protocol has several specific configuration options. Here is a -sample configuration for the `thrift` section of the +{beatname_lc}.yml+ config file: +image:./images/thrift-dashboard.png[Thrift-RPC dashboard] + + +Thrift supports multiple http://en.wikipedia.org/wiki/Apache_Thrift[transport +and protocol types]. Currently Packetbeat supports the default `TSocket` +transport as well as the `TFramed` transport. From the protocol point of view, +Packetbeat currently supports only the default `TBinary` protocol. + +Packetbeat also has several configuration options that allow you to get +the right balance between visibility, disk usage, and data protection. You can, +for example, choose to obfuscate all strings or to store the requests but not +the responses, while still capturing the response time for each of the RPC +calls. You can also choose to limit the size of strings and lists to a given +number of elements, so you can fine tune how much data you want to have stored in +Elasticsearch. + +The Thrift protocol has several specific configuration options. Here is an +example configuration section for the Thrift protocol in the ++{beatname_lc}.yml+ config file: [source,yaml] ------------------------------------------------------------------------------ @@ -675,18 +934,28 @@ packetbeat.protocols: drop_after_n_struct_fields: 100 ------------------------------------------------------------------------------ -===== transport_type +Providing the Thrift IDL files to Packetbeat is optional. The binary +Thrift messages include the called method name and enough structural information +to decode the messages without needing the IDL files. However, if you +provide the IDL files, Packetbeat can also resolve the service name, +arguments, and exception names. + +==== Configuration options + +Also see <>. + +===== `transport_type` The Thrift transport type. Currently this option accepts the values `socket` for TSocket, which is the default Thrift transport, and `framed` for the TFramed Thrift transport. The default is `socket`. -===== protocol_type +===== `protocol_type` The Thrift protocol type. Currently the only accepted value is `binary` for the TBinary protocol, which is the default Thrift protocol. -===== idl_files +===== `idl_files` The Thrift interface description language (IDL) files for the service that Packetbeat is monitoring. Providing the IDL files is optional, because the Thrift @@ -694,31 +963,31 @@ messages contain enough information to decode them without having the IDL files. However, providing the IDL enables Packetbeat to include parameter and exception names. -===== string_max_size +===== `string_max_size` The maximum length for strings in parameters or return values. If a string is longer than this value, the string is automatically truncated to this length. Packetbeat adds dots at the end of the string to mark that it was truncated. The default is 200. -===== collection_max_size +===== `collection_max_size` The maximum number of elements in a Thrift list, set, map, or structure. If a collection has more elements than this value, Packetbeat captures only the specified number of elements. Packetbeat adds a fictive last element `...` to the end of the collection to mark that it was truncated. The default is 15. -===== capture_reply +===== `capture_reply` If this option is set to false, Packetbeat decodes the method name from the reply and simply skips the rest of the response message. This setting can be useful for performance, disk usage, or data retention reasons. The default is true. -===== obfuscate_strings +===== `obfuscate_strings` If this option is set to true, Packetbeat replaces all strings found in method parameters, return codes, or exception structures with the `"*"` string. -===== drop_after_n_struct_fields +===== `drop_after_n_struct_fields` The maximum number of fields that a structure can have before Packetbeat ignores the whole transaction. This is a memory protection mechanism (so that @@ -727,7 +996,11 @@ to a relatively high value. The default is 500. [[configuration-mongodb]] -==== MongoDB Configuration Options +=== Capture MongoDB traffic + +++++ +MongoDB +++++ The following settings are specific to the MongoDB protocol. Here is a sample configuration for the `mongodb` section of the +{beatname_lc}.yml+ config file: @@ -742,10 +1015,14 @@ packetbeat.protocols: max_doc_length: 0 ------------------------------------------------------------------------------ -The following two settings are useful for limiting the amount of data -Packetbeat indexes in the `response` fields. +==== Configuration options + +The `max_docs` and `max_doc_length` settings are useful for limiting the amount +of data Packetbeat indexes in the `response` fields. -===== max_docs +Also see <>. + +===== `max_docs` The maximum number of documents from the response to index in the `response` field. The default is 10. You can set this to 0 to index an unlimited number of documents. @@ -753,7 +1030,7 @@ default is 10. You can set this to 0 to index an unlimited number of documents. Packetbeat adds a `[...]` line at the end to signify that there were additional documents that weren't saved because of this setting. -===== max_doc_length +===== `max_doc_length` The maximum number of characters in a single document indexed in the `response` field. The default is 5000. You can set this to 0 to index an unlimited number @@ -765,9 +1042,8 @@ at the end of the document. Note that limiting documents in this way means that they are no longer correctly formatted JSON objects. - [[configuration-processes]] -=== Monitored Processes +== Specify which processes to monitor This section of the +{beatname_lc}.yml+ config file is optional, but configuring the processes enables Packetbeat to show you not only the servers that the @@ -810,18 +1086,21 @@ packetbeat.procs: cmdline_grep: gunicorn ------------------------------------------------------------------------------ -==== Process Monitoring Options +[float] +=== Configuration options You can specify the following process monitoring options in the `monitored` section of the +{beatname_lc}.yml+ config file: -===== process +[float] +==== `process` The name of the process as it will appear in the published transactions. The name doesn't have to match the name of the executable, so feel free to choose something more descriptive (for example, "myapp" instead of "gunicorn"). -===== cmdline_grep +[float] +==== `cmdline_grep` The name used to identify the process at run time. When Packetbeat starts, and then periodically afterwards, it scans the process table for @@ -829,8 +1108,9 @@ processes that match the values specified for this option. The match is done aga process' command line as read from `/proc//cmdline`. +[float] [[shutdown-timeout]] -===== shutdown_timeout +==== `shutdown_timeout` How long Packetbeat waits on shutdown. By default, this option is disabled. Packetbeat will wait for `shutdown_timeout` and then close. It will not track if all events were sent @@ -845,17 +1125,3 @@ packetbeat.shutdown_timeout: 5s -include::../../../../libbeat/docs/generalconfig.asciidoc[] - -include::../../../../libbeat/docs/processors-config.asciidoc[] - -include::../../../../libbeat/docs/outputconfig.asciidoc[] - -include::../../../../libbeat/docs/shared-path-config.asciidoc[] - -include::../../../../libbeat/docs/setup-config.asciidoc[] - -include::../../../../libbeat/docs/loggingconfig.asciidoc[] - -include::./runconfig.asciidoc[] - diff --git a/packetbeat/docs/packetbeat-reference-yml.asciidoc b/packetbeat/docs/packetbeat-reference-yml.asciidoc new file mode 100644 index 00000000000..547b4436009 --- /dev/null +++ b/packetbeat/docs/packetbeat-reference-yml.asciidoc @@ -0,0 +1,11 @@ +[[packetbeat-reference-yml]] +== packetbeat.reference.yml + +The following reference file is available with your Packetbeat installation. It +shows all non-deprecated Packetbeat options. The contents are included here for +your convenience. + +[source,yaml] +-- +include::../packetbeat.reference.yml[] +-- diff --git a/packetbeat/docs/reference/configuration.asciidoc b/packetbeat/docs/reference/configuration.asciidoc deleted file mode 100644 index 5cdaf17c038..00000000000 --- a/packetbeat/docs/reference/configuration.asciidoc +++ /dev/null @@ -1,33 +0,0 @@ - -[[packetbeat-configuration]] -== Configuration Options (Reference) - -Before modifying configuration settings, make sure you've completed the <> in the Getting Started. - -The {beatname_uc} configuration file, +{beatname_lc}.yml+, uses http://yaml.org/[YAML] for its syntax. See the -{libbeat}/config-file-format.html[Config File Format] section of the -_Beats Platform Reference_ for more about the structure of the config file. - -The configuration options are described in the following sections. After changing -configuration settings, you need to restart {beatname_uc} to pick up the changes. - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> - -include::configuration/packetbeat-options.asciidoc[] diff --git a/packetbeat/docs/reference/configuration/runconfig.asciidoc b/packetbeat/docs/runconfig.asciidoc similarity index 87% rename from packetbeat/docs/reference/configuration/runconfig.asciidoc rename to packetbeat/docs/runconfig.asciidoc index 8f1e70e4959..9df3543ed71 100644 --- a/packetbeat/docs/reference/configuration/runconfig.asciidoc +++ b/packetbeat/docs/runconfig.asciidoc @@ -1,11 +1,11 @@ [[configuration-run-options]] -=== Run Options +== Set run options -The Beat can drop privileges after creating the sniffing socket. +Packetbeat can drop privileges after creating the sniffing socket. Root access is required for opening the socket, but everything else requires no privileges. Therefore, it is recommended that you have the Beat switch users after the initialization phase. The `uid` and `gid` settings set the User Id and Group -Id under which the Beat runs. +Id under which {beatname_uc} runs. WARNING: On Linux, Setuid doesn't change the uid of all threads, so the Go garbage collector will continue to run as root. Also note that process diff --git a/packetbeat/docs/running-on-docker.asciidoc b/packetbeat/docs/running-on-docker.asciidoc index fd939cc46f4..090577c58da 100644 --- a/packetbeat/docs/running-on-docker.asciidoc +++ b/packetbeat/docs/running-on-docker.asciidoc @@ -1,6 +1,6 @@ include::../../libbeat/docs/shared-docker.asciidoc[] -=== Required Network Capabilities +=== Required network capabilities Under Docker, Packetbeat runs as a non-root user, but requires some privileged network capabilities to operate correctly. Ensure that the +NET_ADMIN+ @@ -11,7 +11,7 @@ capability is available to the container. docker run --cap-add=NET_ADMIN {dockerimage} ---- -=== Capturing Traffic from the Host System +=== Capture traffic from the host system By default, Docker networking will connect the Packetbeat container to an isolated virtual network, with a limited view of network traffic. You may wish diff --git a/packetbeat/docs/securing-packetbeat.asciidoc b/packetbeat/docs/securing-packetbeat.asciidoc index c40a0483f22..dadc6980383 100644 --- a/packetbeat/docs/securing-packetbeat.asciidoc +++ b/packetbeat/docs/securing-packetbeat.asciidoc @@ -14,11 +14,11 @@ The following topics describe how to secure communication between Packetbeat and -- [[securing-communication-elasticsearch]] -== Securing Communication With Elasticsearch +== Secure communication with Elasticsearch include::../../libbeat/docs/https.asciidoc[] //sets block macro for shared-ssl-logstash-config.asciidoc included in next section [[configuring-ssl-logstash]] -== Securing Communication With Logstash by Using SSL +== Secure communication with Logstash by using SSL include::../../libbeat/docs/shared-ssl-logstash-config.asciidoc[] diff --git a/packetbeat/docs/thrift.asciidoc b/packetbeat/docs/thrift.asciidoc deleted file mode 100644 index acec8ee0aca..00000000000 --- a/packetbeat/docs/thrift.asciidoc +++ /dev/null @@ -1,67 +0,0 @@ -[[thrift-rpc]] -== Configuring Thrift-RPC Support - -https://thrift.apache.org/[Apache Thrift] is a communication protocol and RPC -framework initially created at Facebook. It is sometimes used in -http://martinfowler.com/articles/microservices.html[microservices] -architectures because it provides better performance when compared to the more -obvious HTTP/RESTful API choice, while still supporting a wide range of -programming languages and frameworks. - -Packetbeat works based on a copy of the traffic, which means that you get -performance management features without having to modify your services in -any way and without any latency overhead. Packetbeat captures the transactions from the -network and indexes them in Elasticsearch so that they can be analyzed and -searched. - -Packetbeat indexes the method, parameters, return value, and -exceptions of each Thrift-RPC call. You can search by and create statistics -based on any of these fields. Packetbeat automatically fills in the `status` -column with either `OK` or `Error`, so it's easy to find the problematic RPC calls. -A transaction is put into the `Error` state if it returned an exception. - -Packetbeat also indexes the `responsetime` field so you can get performance -analytics and find the slow RPC calls. - -Here is an example performance dashboard: - -image:./images/thrift-dashboard.png[Thrift-RPC dashboard] - - -Thrift supports multiple http://en.wikipedia.org/wiki/Apache_Thrift[transport -and protocol types]. Currently Packetbeat supports the default `TSocket` -transport as well as the `TFramed` transport. From the protocol point of view, -Packetbeat currently supports only the default `TBinary` protocol. - -Packetbeat also has several configuration options that allow you to get -the right balance between visibility, disk usage, and data protection. You can, -for example, choose to obfuscate all strings or to store the requests but not -the responses, while still capturing the response time for each of the RPC -calls. You can also choose to limit the size of strings and lists to a given -number of elements, so you can fine tune how much data you want to have stored in -Elasticsearch. - -Here is an example configuration section for the Thrift protocol: - -[source,yaml] ------------------------------------------------------------------------------- -packetbeat.protocols: -- type: thrift - transport_type: socket - protocol_type: binary - idl_files: ["tutorial.thrift", "shared.thrift"] - string_max_size: 200 - collection_max_size: 20 - capture_reply: true - obfuscate_strings: true - drop_after_n_struct_fields: 100 ------------------------------------------------------------------------------- - -For more details about the configuration options, see the -<> section. - -Providing the Thrift IDL files to Packetbeat is optional. The binary -Thrift messages include the called method name and enough structural information -to decode the messages without needing the IDL files. However, if you -provide the IDL files, Packetbeat can also resolve the service name, -arguments, and exception names. diff --git a/packetbeat/docs/troubleshooting.asciidoc b/packetbeat/docs/troubleshooting.asciidoc index 132ede8e86d..6c4289097f9 100644 --- a/packetbeat/docs/troubleshooting.asciidoc +++ b/packetbeat/docs/troubleshooting.asciidoc @@ -16,21 +16,21 @@ following tips: -- [[getting-help]] -== Getting Help +== Get help include::../../libbeat/docs/getting-help.asciidoc[] //sets block macro for debugging.asciidoc included in next section [[enable-packetbeat-debugging]] -== Debugging +== Debug include::../../libbeat/docs/debugging.asciidoc[] //sets block macro for recording-trace content included in next section [[recording-trace]] -== Recording a Trace +== Record a trace If you are having an issue, it's often useful to record a full network trace and send it to us. It will help us reproduce the issue, and we can also add it diff --git a/packetbeat/docs/visualizing-data-packetbeat.asciidoc b/packetbeat/docs/visualizing-data-packetbeat.asciidoc index a92e53e2b76..698093b4974 100644 --- a/packetbeat/docs/visualizing-data-packetbeat.asciidoc +++ b/packetbeat/docs/visualizing-data-packetbeat.asciidoc @@ -1,5 +1,5 @@ [[visualizing-data-packetbeat]] -= Visualizing Packetbeat Data in Kibana += Visualizing Packetbeat data in Kibana [partintro] -- @@ -13,7 +13,7 @@ section to learn how to work with Packetbeat data in Kibana: -- [[customizing-discover]] -== Customizing the Discover Page +== Customize the Discover page To make it easier for you to search and discover Packetbeat data in Kibana, the sample dashboards contain predefined searches. @@ -28,7 +28,7 @@ image:./images/discovery-packetbeat-flows.png[Packetbeat Flows Search] These searches are not default views on the *Discover* page. To use these searches, make sure you've <> in Kibana. Then go to the *Discover* page and click -*Open*. +*Open*. You can type `Packetbeat` in the Search field to filter the list of searches. diff --git a/winlogbeat/docs/command-line.asciidoc b/winlogbeat/docs/command-line.asciidoc index a45e37b844d..cef2d72f953 100644 --- a/winlogbeat/docs/command-line.asciidoc +++ b/winlogbeat/docs/command-line.asciidoc @@ -1,5 +1,5 @@ [[command-line-options]] -=== Command Line Options +=== Command line options Winlogbeat does not have any Winlogbeat-specific command line options. Instead, you configure the behavior of Winlogbeat by specifying options in the diff --git a/winlogbeat/docs/configuring-howto.asciidoc b/winlogbeat/docs/configuring-howto.asciidoc index 4df2e62b50b..503dae7a6af 100644 --- a/winlogbeat/docs/configuring-howto.asciidoc +++ b/winlogbeat/docs/configuring-howto.asciidoc @@ -1,29 +1,58 @@ -[[configuring-howto-filebeat]] +[[configuring-howto-winlogbeat]] = Configuring Winlogbeat [partintro] -- -After following the <> in the -Getting Started, you might want to fine tune the behavior of Winlogbeat. This -section describes some common use cases for changing configuration options. +Before modifying configuration settings, make sure you've completed the +<> in the Getting Started. +This section describes some common use cases for changing configuration options. To configure {beatname_uc}, you edit the configuration file. You’ll find the configuration file, +{beatname_lc}.yml+, in the archive that you extracted. There's also a full example configuration file at +/etc/{beatname_lc}/{beatname_lc}.reference.yml+ that shows all non-deprecated options. -See the +The {beatname_uc} configuration file uses http://yaml.org/[YAML] for its syntax. See the {libbeat}/config-file-format.html[Config File Format] section of the _Beats Platform Reference_ for more about the structure of the config file. The following topics describe how to configure Winlogbeat: -* <> +* <> +* <> +* <> * <> * <> +* <> +* <> +* <> +* <> * <> * <> -- -include::reference/configuration.asciidoc[] +include::./winlogbeat-options.asciidoc[] +include::./winlogbeat-general-options.asciidoc[] + +:win: +include::../../libbeat/docs/outputconfig.asciidoc[] + +include::./winlogbeat-filtering.asciidoc[] + +include::../../libbeat/docs/shared-config-ingest.asciidoc[] + +include::../../libbeat/docs/shared-path-config.asciidoc[] + +include::../../libbeat/docs/setup-config.asciidoc[] + +include::../../libbeat/docs/loggingconfig.asciidoc[] + +:standalone: +include::../../libbeat/docs/shared-env-vars.asciidoc[] + +:standalone: +:win: +include::../../libbeat/docs/yaml.asciidoc[] + +include::../../libbeat/docs/reference-yml.asciidoc[] diff --git a/winlogbeat/docs/faq.asciidoc b/winlogbeat/docs/faq.asciidoc index 3fc8013d7a8..4a808765fce 100644 --- a/winlogbeat/docs/faq.asciidoc +++ b/winlogbeat/docs/faq.asciidoc @@ -1,5 +1,5 @@ [[faq]] -== Frequently Asked Questions +== Frequently asked questions This section contains frequently asked questions about Winlogbeat. Also check out the https://discuss.elastic.co/c/beats/winlogbeat[Winlogbeat discussion diff --git a/winlogbeat/docs/getting-started.asciidoc b/winlogbeat/docs/getting-started.asciidoc index fc04d12d6bc..3d7f1648deb 100644 --- a/winlogbeat/docs/getting-started.asciidoc +++ b/winlogbeat/docs/getting-started.asciidoc @@ -23,7 +23,7 @@ After installing the Elastic Stack, read the following topics to learn how to in * <> [[winlogbeat-installation]] -=== Step 1: Installing Winlogbeat +=== Step 1: Install Winlogbeat . Download the Winlogbeat zip file from the https://www.elastic.co/downloads/beats/winlogbeat[downloads page]. @@ -59,10 +59,10 @@ Before starting Winlogbeat, you should look at the configuration options in the configuration file, for example `C:\Program Files\Winlogbeat\winlogbeat.yml`. There’s also a full example configuration file called `winlogbeat.reference.yml` that shows all non-deprecated options. For more information about these options, see -<>. +<>. [[winlogbeat-configuration]] -=== Step 2: Configuring Winlogbeat +=== Step 2: Configure Winlogbeat To configure Winlogbeat, you edit the `winlogbeat.yml` configuration file. See the {libbeat}/config-file-format.html[Config File Format] section of the @@ -124,18 +124,18 @@ PS C:\Program Files\Winlogbeat> .\winlogbeat.exe -c .\winlogbeat.yml -configtest ---------------------------------------------------------------------- [[config-winlogbeat-logstash]] -=== Step 3: Configuring Winlogbeat to Use Logstash +=== Step 3: Configure Winlogbeat to use Logstash :win: include::../../libbeat/docs/shared-logstash-config.asciidoc[] [[winlogbeat-template]] -=== Step 4: Loading the Index Template in Elasticsearch +=== Step 4: Load the index template in Elasticsearch include::../../libbeat/docs/shared-template-load.asciidoc[] [[winlogbeat-starting]] -=== Step 5: Starting Winlogbeat +=== Step 5: Start Winlogbeat Start the Winlogbeat service with the following command: @@ -156,7 +156,7 @@ this command: PS C:\Program Files\Winlogbeat> services.msc ---------------------------------------------------------------------- -==== Stopping Winlogbeat +==== Stop Winlogbeat Stop the Winlogbeat service with the following command: @@ -166,7 +166,7 @@ PS C:\Program Files\Winlogbeat> Stop-Service winlogbeat ---------------------------------------------------------------------- [[winlogbeat-sample-dashboards]] -=== Step 6: Loading Sample Kibana Dashboards +=== Step 6: Load sample Kibana dashboards To make it easier for you to start monitoring your servers in Kibana, we have created sample Winlogbeat dashboards. The dashboards are provided as diff --git a/winlogbeat/docs/index.asciidoc b/winlogbeat/docs/index.asciidoc index 4a61e2f9c9b..d221fb65fa2 100644 --- a/winlogbeat/docs/index.asciidoc +++ b/winlogbeat/docs/index.asciidoc @@ -31,17 +31,6 @@ include::./upgrading.asciidoc[] include::./configuring-howto.asciidoc[] -include::./winlogbeat-filtering.asciidoc[] - -include::../../libbeat/docs/shared-config-ingest.asciidoc[] - -:standalone: -include::../../libbeat/docs/shared-env-vars.asciidoc[] - -:standalone: -:win: -include::../../libbeat/docs/yaml.asciidoc[] - include::./fields.asciidoc[] include::./securing-winlogbeat.asciidoc[] diff --git a/winlogbeat/docs/overview.asciidoc b/winlogbeat/docs/overview.asciidoc index 451afc2544d..1441b1f5df9 100644 --- a/winlogbeat/docs/overview.asciidoc +++ b/winlogbeat/docs/overview.asciidoc @@ -1,4 +1,8 @@ -== Overview +== Winlogbeat Overview + +++++ +Overview +++++ Winlogbeat ships Windows event logs to Elasticsearch or Logstash. You can install it as a Windows service on Windows XP or later. diff --git a/winlogbeat/docs/reference/configuration.asciidoc b/winlogbeat/docs/reference/configuration.asciidoc deleted file mode 100644 index d4f1db33f98..00000000000 --- a/winlogbeat/docs/reference/configuration.asciidoc +++ /dev/null @@ -1,34 +0,0 @@ - -[[winlogbeat-configuration-details]] -== Configuration Options (Reference) - -Before modifying configuration settings, make sure you've completed the -<> in the Getting Started. - -The {beatname_uc} configuration file, +{beatname_lc}.yml+, uses http://yaml.org/[YAML] for its syntax. See the -{libbeat}/config-file-format.html[Config File Format] section of the -_Beats Platform Reference_ for more about the structure of the config file. - -The configuration options are described in the following sections. After changing -configuration settings, you need to restart {beatname_uc} to pick up the changes. - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> - -include::configuration/winlogbeat-options.asciidoc[] - - - - diff --git a/winlogbeat/docs/securing-winlogbeat.asciidoc b/winlogbeat/docs/securing-winlogbeat.asciidoc index 09f2c3f035a..8b1bc8fa635 100644 --- a/winlogbeat/docs/securing-winlogbeat.asciidoc +++ b/winlogbeat/docs/securing-winlogbeat.asciidoc @@ -14,11 +14,11 @@ The following topics describe how to secure communication between Winlogbeat and -- [[securing-communication-elasticsearch]] -== Securing Communication With Elasticsearch +== Secure communication with Elasticsearch include::../../libbeat/docs/https.asciidoc[] //sets block macro for shared-ssl-logstash-config.asciidoc included in next section [[configuring-ssl-logstash]] -== Securing Communication With Logstash by Using SSL +== Secure communication with Logstash by using SSL include::../../libbeat/docs/shared-ssl-logstash-config.asciidoc[] diff --git a/winlogbeat/docs/troubleshooting.asciidoc b/winlogbeat/docs/troubleshooting.asciidoc index 8a08e470924..31dedadade6 100644 --- a/winlogbeat/docs/troubleshooting.asciidoc +++ b/winlogbeat/docs/troubleshooting.asciidoc @@ -14,7 +14,7 @@ If you have issues installing or running Winlogbeat, read the following tips: -- [[getting-help]] -== Getting Help +== Get Help include::../../libbeat/docs/getting-help.asciidoc[] @@ -22,6 +22,6 @@ include::../../libbeat/docs/getting-help.asciidoc[] [[enable-winlogbeat-debugging]] -== Debugging +== Debug include::../../libbeat/docs/debugging.asciidoc[] diff --git a/winlogbeat/docs/winlogbeat-filtering.asciidoc b/winlogbeat/docs/winlogbeat-filtering.asciidoc index d03b7bfcf47..fe26b666c02 100644 --- a/winlogbeat/docs/winlogbeat-filtering.asciidoc +++ b/winlogbeat/docs/winlogbeat-filtering.asciidoc @@ -1,5 +1,5 @@ [[filtering-and-enhancing-data]] -== Filtering and Enhancing the Exported Data +== Filter and Enhance the exported data include::../../libbeat/docs/processors.asciidoc[] diff --git a/winlogbeat/docs/winlogbeat-general-options.asciidoc b/winlogbeat/docs/winlogbeat-general-options.asciidoc new file mode 100644 index 00000000000..8183ec5405e --- /dev/null +++ b/winlogbeat/docs/winlogbeat-general-options.asciidoc @@ -0,0 +1,7 @@ +[[configuration-general-options]] +== Specify general settings + +You can specify settings in the +{beatname_lc}.yml+ config file to control the +general behavior of {beatname_uc}. + +include::../../libbeat/docs/generalconfig.asciidoc[] diff --git a/winlogbeat/docs/reference/configuration/winlogbeat-options.asciidoc b/winlogbeat/docs/winlogbeat-options.asciidoc similarity index 94% rename from winlogbeat/docs/reference/configuration/winlogbeat-options.asciidoc rename to winlogbeat/docs/winlogbeat-options.asciidoc index 6b52d88725c..2bcebc575e9 100644 --- a/winlogbeat/docs/reference/configuration/winlogbeat-options.asciidoc +++ b/winlogbeat/docs/winlogbeat-options.asciidoc @@ -2,7 +2,7 @@ supporting the Windows Event Log API (Microsoft Windows Vista and newer). [[configuration-winlogbeat-options]] -=== Winlogbeat +== Set up Winlogbeat The `winlogbeat` section of the +{beatname_lc}.yml+ config file specifies all options that are specific to Winlogbeat. Most importantly, it contains the list of event logs to monitor. @@ -18,11 +18,13 @@ winlogbeat.event_logs: - name: System -------------------------------------------------------------------------------- -==== Winlogbeat Options +[float] +=== Configuration options You can specify the following options in the `winlogbeat` section of the +{beatname_lc}.yml+ config file: -===== registry_file +[float] +==== `registry_file` The name of the file where Winlogbeat stores information that it uses to resume monitoring after a restart. By default the file is stored as `.winlogbeat.yml` @@ -40,7 +42,8 @@ backslashes (\) for Windows compatibility. You can use either forward or backslashes. Forward slashes are easier to work with in YAML because there is no need to escape them. -===== event_logs +[float] +==== `event_logs` A list of entries (called 'dictionaries' in YAML) that specify which event logs to monitor. Each entry in the list defines an event log to monitor as well as @@ -53,7 +56,8 @@ winlogbeat.event_logs: - name: Application -------------------------------------------------------------------------------- -===== event_logs.batch_read_size +[float] +==== `event_logs.batch_read_size` experimental[] @@ -67,8 +71,9 @@ Windows API, applies any processors to the events, publishes them to the configured outputs, and waits for an acknowledgement from the outputs before reading additional event log records. +[float] [[configuration-winlogbeat-options-event_logs-name]] -===== event_logs.name +==== `event_logs.name` The name of the event log to monitor. Each dictionary under `event_logs` must have a `name` field. You can get a list of available event logs by running @@ -121,7 +126,8 @@ winlogbeat.event_logs: - name: Microsoft-Windows-Windows Firewall With Advanced Security/Firewall -------------------------------------------------------------------------------- -===== event_logs.ignore_older +[float] +==== `event_logs.ignore_older` If this option is specified, Winlogbeat filters events that are older than the specified amount of time. Valid time units are "ns", "us" (or "µs"), "ms", "s", @@ -136,7 +142,8 @@ winlogbeat.event_logs: ignore_older: 168h -------------------------------------------------------------------------------- -===== event_logs.forwarded +[float] +==== `event_logs.forwarded` A boolean flag to indicate that the log contains only events collected from remote hosts using the Windows Event Collector. The value defaults to true for @@ -149,7 +156,8 @@ Collector subscription should be configured to use the "RenderedText" format (this is the default) to ensure that the events are distributed with messages and descriptions. -===== event_logs.event_id +[float] +==== `event_logs.event_id` A whitelist and blacklist of event IDs. The value is a comma-separated list. The accepted values are single event IDs to include (e.g. 4624), a range of event @@ -195,7 +203,8 @@ processors: ======================================= -===== event_logs.level +[float] +==== `event_logs.level` A list of event levels to include. The value is a comma-separated list of levels. *{vista_and_newer}* @@ -228,7 +237,8 @@ winlogbeat.event_logs: level: critical, error, warning -------------------------------------------------------------------------------- -===== event_logs.provider +[float] +==== `event_logs.provider` A list of providers (source names) to include. The value is a YAML list. *{vista_and_newer}* @@ -263,7 +273,8 @@ Microsoft-Windows-Security-Auditing Microsoft-Windows-Eventlog -------------------------------------------------------------------------------- -===== event_logs.include_xml +[float] +==== `event_logs.include_xml` Boolean option that controls if the raw XML representation of an event is included in the data sent by Winlogbeat. The default is false. @@ -282,7 +293,8 @@ winlogbeat.event_logs: include_xml: true -------------------------------------------------------------------------------- -===== event_logs.tags +[float] +==== `event_logs.tags` A list of tags that the Beat includes in the `tags` field of each published event. Tags make it easy to select specific events in Kibana or apply @@ -298,8 +310,9 @@ winlogbeat.event_logs: tags: ["web"] -------------------------------------------------------------------------------- +[float] [[winlogbeat-configuration-fields]] -===== event_logs.fields +==== `event_logs.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 event @@ -318,7 +331,8 @@ winlogbeat.event_logs: customer_id: 51415432 -------------------------------------------------------------------------------- -===== event_logs.fields_under_root +[float] +==== `event_logs.fields_under_root` If this option is set to true, the custom <> are stored as top-level fields in the output document instead of being grouped @@ -326,16 +340,3 @@ under a `fields` sub-dictionary. If the custom field names conflict with other field names added by Winlogbeat, then the custom fields overwrite the other fields. -include::../../../../libbeat/docs/generalconfig.asciidoc[] - -include::../../../../libbeat/docs/processors-config.asciidoc[] - -include::../../../../libbeat/docs/outputconfig.asciidoc[] - -include::../../../../libbeat/docs/shared-path-config.asciidoc[] - -include::../../../../libbeat/docs/setup-config.asciidoc[] - -include::../../../../libbeat/docs/loggingconfig.asciidoc[] - - From ff3ab7bb439acf8d90a2fdd62f2c6000fa9b191a Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Wed, 26 Jul 2017 03:00:05 -0400 Subject: [PATCH 004/139] Update libbeat index-pattern version (#4756) The version embedded in the file needed updating for 7.0. --- libbeat/_meta/kibana/default/index-pattern/libbeat.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbeat/_meta/kibana/default/index-pattern/libbeat.json b/libbeat/_meta/kibana/default/index-pattern/libbeat.json index 62c33ee4a1f..e74e6a98b15 100644 --- a/libbeat/_meta/kibana/default/index-pattern/libbeat.json +++ b/libbeat/_meta/kibana/default/index-pattern/libbeat.json @@ -1,5 +1,5 @@ { - "version": "6.0.0-alpha2", + "version": "7.0.0-alpha1", "objects": [ { "attributes": { From 45fa3c62e53dea92e56d616ef3ddb68bc9c38c4e Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Wed, 26 Jul 2017 10:37:56 +0300 Subject: [PATCH 005/139] Close changelog beta1 (master) (#4754) * Close changelog for beta1 * Added 5.4.2, 5.5.0, and 5.5.1 releases --- CHANGELOG.asciidoc | 175 ++++++++++++++++++++++++++++------ libbeat/docs/release.asciidoc | 4 + 2 files changed, 149 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index f85225fe0b8..83ff4a47015 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -8,7 +8,72 @@ // Template, add newest changes here === Beats version HEAD -https://github.com/elastic/beats/compare/v6.0.0-alpha2...master[Check the HEAD diff] +https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD diff] + +==== Breaking changes + +*Affecting all Beats* + +*Filebeat* + +*Heartbeat* + +*Metricbeat* + +*Packetbeat* + +*Winlogbeat* + +==== Bugfixes + +*Filebeat* + +*Heartbeat* + +*Metricbeat* + +*Packetbeat* + +*Winlogbeat* + +==== Added + +*Affecting all Beats* + +*Filebeat* + +*Heartbeat* + +*Metricbeat* + +*Packetbeat* + +*Winlogbeat* + +*Auditbeat* + +==== Deprecated + +*Affecting all Beats* + +*Filebeat* + +*Heartbeat* + +*Metricbeat* + +*Packetbeat* + +*Winlogbeat* + +==== Known Issue + + +//////////////////////////////////////////////////////////// + +[[release-notes-6.0.0-beta1]] +=== Beats version 6.0.0-beta1 +https://github.com/elastic/beats/compare/v6.0.0-alpha2...v6.0.0-beta1[View commits] ==== Breaking changes @@ -23,13 +88,12 @@ https://github.com/elastic/beats/compare/v6.0.0-alpha2...master[Check the HEAD d - Remove setting `dashboard.snapshot` and `dashboard.snapshot_url`. They are no longer needed because the dashboards are included in the packages by default. {pull}4675[4675] -*Filebeat* - *Heartbeat* - Renamed the heartbeat RPM/DEB name to `heartbeat-elastic`. {pull}4601[4601] *Metricbeat* + - Change all `system.cpu.*.pct` metrics to be scaled by the number of CPU cores. This will make the CPU usage percentages from the system cpu metricset consistent with the system process metricset. The documentation for these metrics already @@ -40,8 +104,6 @@ https://github.com/elastic/beats/compare/v6.0.0-alpha2...master[Check the HEAD d - Remove the already unsupported `pf_ring` sniffer option. {pull}4608[4608] -*Winlogbeat* - ==== Bugfixes *Affecting all Beats* @@ -51,10 +113,6 @@ https://github.com/elastic/beats/compare/v6.0.0-alpha2...master[Check the HEAD d - Normalize all times to UTC to ensure proper index naming. {issue}4569[4569] - Fix issue with loading dashboards to ES 6.0 when .kibana index did not already exist. {issue}4659[4659] -*Filebeat* - -*Heartbeat* - *Metricbeat* - Fix issue affecting Windows services timing out at startup. {pull}4491[4491] @@ -102,6 +160,7 @@ https://github.com/elastic/beats/compare/v6.0.0-alpha2...master[Check the HEAD d - Enabled Cgo which means libc is dynamically compiled. {pull}4546[4546] *Metricbeat* + - Add random startup delay to each metricset to avoid the thundering herd problem. {issue}4010[4010] - Add the ability to configure audit rules to the kernel module. {pull}4482[4482] - Add the ability to configure kernel's audit failure mode. {pull}4516[4516] @@ -110,32 +169,13 @@ https://github.com/elastic/beats/compare/v6.0.0-alpha2...master[Check the HEAD d - Add `test modules` command, to test modules expected output. {pull}4656[4656] - Add `processors` setting to metricbeat modules. {pull}4699[4699] -*Packetbeat* - *Winlogbeat* + - Add the ability to use LevelRaw if Level isn't populated in the event XML. {pull}4257[4257] *Auditbeat* -- Add file integrity metricset to the audit module. {pull}4486[4486] - -==== Deprecated -*Affecting all Beats* - -*Filebeat* - -*Heartbeat* - -*Metricbeat* - -*Packetbeat* - -*Winlogbeat* - -==== Known Issue - - -//////////////////////////////////////////////////////////// +- Add file integrity metricset to the audit module. {pull}4486[4486] [[release-notes-6.0.0-alpha2]] === Beats version 6.0.0-alpha2 @@ -352,6 +392,81 @@ https://github.com/elastic/beats/compare/v5.4.0...v6.0.0-alpha1[View commits] - Prospector reloading only works properly with new files. {pull}3546[3546] +[[release-notes-5.5.1]] +=== Beats version 5.5.1 +https://github.com/elastic/beats/compare/v5.5.0...v5.5.1[View commits] + +==== Bugfixes + +*Affecting all Beats* + +- Normalize all times to UTC to ensure proper index naming. {issue}4569[4569] + +[[release-notes-5.5.0]] +=== Beats version 5.5.0 +https://github.com/elastic/beats/compare/v5.4.2...v5.5.0[View commits] + +==== Breaking changes + +*Affecting all Beats* + +- Usage of field `_type` is now ignored and hardcoded to `doc`. {pull}3757[3757] + +*Metricbeat* +- Change all `system.cpu.*.pct` metrics to be scaled by the number of CPU cores. + This will make the CPU usage percentages from the system cpu metricset consistent + with the system process metricset. The documentation for these metrics already + stated that on multi-core systems the percentages could be greater than 100%. {pull}4544[4544] + +==== Bugfixes + +*Affecting all Beats* + +- Fix console output. {pull}4045[4045] + +*Filebeat* + +- Allow string characters in user agent patch version (NGINX and Apache) {pull}4415[4415] + +*Metricbeat* + +- Fix type of field `haproxy.stat.check.health.last`. {issue}4407[4407] + +*Packetbeat* + +- Fix `packetbeat.interface` options that contain underscores (e.g. `with_vlans` or `bpf_filter`). {pull}4378[4378] +- Enabled /proc/net/tcp6 scanning and fixed ip v6 parsing. {pull}4442[4442] + +==== Deprecated + +*Filebeat* + +- Deprecate `document_type` prospector config option as _type is removed in elasticsearch 6.0. Use fields instead. {pull}4225[4225] + +*Winlogbeat* + +- Deprecated metrics endpoint. It is superseded by a libbeat feature that can serve metrics on an HTTP endpoint. {pull}4145[4145] + +[[release-notes-5.4.2]] +=== Beats version 5.4.2 +https://github.com/elastic/beats/compare/v5.4.1...v5.4.2[View commits] + +==== Bugfixes + +*Affecting all Beats* + +- Removed empty sections from the template files, causing indexing errors for array objects. {pull}4488[4488] + +*Metricbeat* + +- Fix issue affecting Windows services timing out at startup. {pull}4491[4491] +- Add filtering to system filesystem metricset to remove relative mountpoints like those + from Linux network namespaces. {pull}4370[4370] + +*Packetbeat* + +- Clean configured geoip.paths before attempting to open the database. {pull}4306[4306] + [[release-notes-5.4.1]] === Beats version 5.4.1 https://github.com/elastic/beats/compare/v5.4.0...v5.4.1[View commits] diff --git a/libbeat/docs/release.asciidoc b/libbeat/docs/release.asciidoc index eb6fa9521b4..3f52e596aaf 100644 --- a/libbeat/docs/release.asciidoc +++ b/libbeat/docs/release.asciidoc @@ -6,8 +6,12 @@ -- This section summarizes the changes in each release. +* <> * <> * <> +* <> +* <> +* <> * <> * <> * <> From 18474a62fbccbe938d45ce10dca898d259465a05 Mon Sep 17 00:00:00 2001 From: Vijay Samuel Date: Wed, 26 Jul 2017 02:34:48 -0700 Subject: [PATCH 006/139] Adding support to exclude labels from kubernetes pod metadata (#4757) --- CHANGELOG.asciidoc | 2 + .../add_kubernetes_metadata/config.go | 1 + .../add_kubernetes_metadata/indexing.go | 10 +++- .../add_kubernetes_metadata/indexing_test.go | 46 +++++++++++++++++++ .../add_kubernetes_metadata/kubernetes.go | 5 +- 5 files changed, 60 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 83ff4a47015..2f0d578f438 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -46,6 +46,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Metricbeat* +- Add support to exclude labels from kubernetes pod metadata. {pull}4757[4757] + *Packetbeat* *Winlogbeat* diff --git a/libbeat/processors/add_kubernetes_metadata/config.go b/libbeat/processors/add_kubernetes_metadata/config.go index 6d53f63a078..ec18bf58ca6 100644 --- a/libbeat/processors/add_kubernetes_metadata/config.go +++ b/libbeat/processors/add_kubernetes_metadata/config.go @@ -17,6 +17,7 @@ type kubeAnnotatorConfig struct { DefaultMatchers Enabled `config:"default_matchers"` DefaultIndexers Enabled `config:"default_indexers"` IncludeLabels []string `config:"include_labels"` + ExcludeLabels []string `config:"exclude_labels"` IncludeAnnotations []string `config:"include_annotations"` } diff --git a/libbeat/processors/add_kubernetes_metadata/indexing.go b/libbeat/processors/add_kubernetes_metadata/indexing.go index 925ad9bbe24..f4471983e01 100644 --- a/libbeat/processors/add_kubernetes_metadata/indexing.go +++ b/libbeat/processors/add_kubernetes_metadata/indexing.go @@ -172,8 +172,9 @@ func (m *Matchers) MetadataIndex(event common.MapStr) string { } type GenDefaultMeta struct { - annotations []string - labels []string + annotations []string + labels []string + labelsExclude []string } // GenerateMetaData generates default metadata for the given pod taking to account certain filters @@ -189,6 +190,11 @@ func (g *GenDefaultMeta) GenerateMetaData(pod *Pod) common.MapStr { labelMap = generateMapSubset(pod.Metadata.Labels, g.labels) } + // Exclude any labels that are present in the exclude_labels config + for _, label := range g.labelsExclude { + delete(labelMap, label) + } + annotationsMap = generateMapSubset(pod.Metadata.Annotations, g.annotations) meta := common.MapStr{ diff --git a/libbeat/processors/add_kubernetes_metadata/indexing_test.go b/libbeat/processors/add_kubernetes_metadata/indexing_test.go index 674f906b784..5589c31a33c 100644 --- a/libbeat/processors/add_kubernetes_metadata/indexing_test.go +++ b/libbeat/processors/add_kubernetes_metadata/indexing_test.go @@ -209,3 +209,49 @@ func TestFilteredGenMeta(t *testing.T) { ok, _ = annotationsMap.HasKey("a") assert.Equal(t, ok, true) } + +func TestFilteredGenMetaExclusion(t *testing.T) { + var testConfig = common.NewConfig() + + filteredGen := &GenDefaultMeta{ + labelsExclude: []string{"x"}, + } + podIndexer, err := NewPodNameIndexer(*testConfig, filteredGen) + assert.Nil(t, err) + + podName := "testpod" + ns := "testns" + pod := Pod{ + Metadata: ObjectMeta{ + Name: podName, + Namespace: ns, + Labels: map[string]string{ + "foo": "bar", + "x": "y", + }, + Annotations: map[string]string{ + "a": "b", + "c": "d", + }, + }, + Spec: PodSpec{}, + } + + assert.Nil(t, err) + + indexers := podIndexer.GetMetadata(&pod) + assert.Equal(t, len(indexers), 1) + + rawLabels, _ := indexers[0].Data["labels"] + assert.NotNil(t, rawLabels) + + labelMap, ok := rawLabels.(common.MapStr) + assert.Equal(t, ok, true) + assert.Equal(t, len(labelMap), 1) + + ok, _ = labelMap.HasKey("foo") + assert.Equal(t, ok, true) + + ok, _ = labelMap.HasKey("x") + assert.Equal(t, ok, false) +} diff --git a/libbeat/processors/add_kubernetes_metadata/kubernetes.go b/libbeat/processors/add_kubernetes_metadata/kubernetes.go index 40fdd3a5a45..e4c70cd8740 100644 --- a/libbeat/processors/add_kubernetes_metadata/kubernetes.go +++ b/libbeat/processors/add_kubernetes_metadata/kubernetes.go @@ -74,8 +74,9 @@ func newKubernetesAnnotator(cfg *common.Config) (processors.Processor, error) { } metaGen := &GenDefaultMeta{ - labels: config.IncludeLabels, - annotations: config.IncludeAnnotations, + labels: config.IncludeLabels, + annotations: config.IncludeAnnotations, + labelsExclude: config.ExcludeLabels, } indexers := Indexers{ From 30ee5271622ccbde493e397041b819166e22c35a Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Wed, 26 Jul 2017 14:31:19 +0200 Subject: [PATCH 007/139] Improve test and build time by using -i flag (#4758) See https://github.com/elastic/beats/issues/4755 for details. --- libbeat/scripts/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libbeat/scripts/Makefile b/libbeat/scripts/Makefile index ed8c4560324..d7163eed4cb 100755 --- a/libbeat/scripts/Makefile +++ b/libbeat/scripts/Makefile @@ -83,10 +83,11 @@ endif ${BEAT_NAME}: $(GOFILES_ALL) ## @build build the beat application - go build + go build -i # Create test coverage binary ${BEAT_NAME}.test: $(GOFILES_ALL) + @go build -i -o /dev/null @go test $(RACE) -c -coverpkg ${GOPACKAGES_COMMA_SEP} .PHONY: crosscompile @@ -142,15 +143,18 @@ prepare-tests: .PHONY: unit-tests unit-tests: ## @testing Runs the unit tests with coverage. Race is not enabled for unit tests because tests run much slower. unit-tests: prepare-tests + go test -i ${GOPACKAGES} $(COVERAGE_TOOL) $(RACE) -coverprofile=${COVERAGE_DIR}/unit.cov ${GOPACKAGES} .PHONY: unit unit: ## @testing Runs the unit tests without coverage reports. + go test -i ${GOPACKAGES} go test $(RACE) ${GOPACKAGES} .PHONY: integration-tests integration-tests: ## @testing Run integration tests. Unit tests are run as part of the integration tests. integration-tests: prepare-tests + go test -i ${GOPACKAGES} $(COVERAGE_TOOL) -tags=integration $(RACE) -coverprofile=${COVERAGE_DIR}/integration.cov ${GOPACKAGES} # From 5750cc0547303adceb6e434385f9ad8ecedcfb53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20P=C3=A9rez-Aradros=20Herce?= Date: Wed, 26 Jul 2017 18:13:48 +0200 Subject: [PATCH 008/139] Support `npipe` URLs in host parser (#4751) Docker for Windows uses URLs like `npipe://./pipe/docker_engine`. This change makes sure they are supported by our host validators --- CHANGELOG.asciidoc | 4 ++++ metricbeat/mb/parse/url.go | 7 ++++--- metricbeat/mb/parse/url_test.go | 12 ++++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 2f0d578f438..2db0dcd77fa 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -26,12 +26,16 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di ==== Bugfixes +*Affecting all Beats* + *Filebeat* *Heartbeat* *Metricbeat* +- Support `npipe` protocol (Windows) in Docker module. {pull}4751[4751] + *Packetbeat* *Winlogbeat* diff --git a/metricbeat/mb/parse/url.go b/metricbeat/mb/parse/url.go index 6871c1f7d1f..b8f8f9dc40f 100644 --- a/metricbeat/mb/parse/url.go +++ b/metricbeat/mb/parse/url.go @@ -61,7 +61,8 @@ func (b URLHostParserBuilder) Build() mb.HostParser { // NewHostDataFromURL returns a new HostData based on the contents of the URL. // If the URLs scheme is "unix" or end is "unix" (e.g. "http+unix://") then -// the HostData.Host field is set to the URLs path instead of the URLs host. +// the HostData.Host field is set to the URLs path instead of the URLs host, +// the same happens for "npipe". func NewHostDataFromURL(u *url.URL) mb.HostData { var user, pass string if u.User != nil { @@ -70,7 +71,7 @@ func NewHostDataFromURL(u *url.URL) mb.HostData { } host := u.Host - if strings.HasSuffix(u.Scheme, "unix") { + if strings.HasSuffix(u.Scheme, "unix") || strings.HasSuffix(u.Scheme, "npipe") { host = u.Path } @@ -140,7 +141,7 @@ func getURL(rawURL, scheme, username, password, path, query string) (*url.URL, e SetURLUser(u, username, password) - if !strings.HasSuffix(u.Scheme, "unix") { + if !strings.HasSuffix(u.Scheme, "unix") && !strings.HasSuffix(u.Scheme, "npipe") { if u.Host == "" { return nil, fmt.Errorf("error parsing URL: empty host") } diff --git a/metricbeat/mb/parse/url_test.go b/metricbeat/mb/parse/url_test.go index 6571fb889d7..d585c53b8bf 100644 --- a/metricbeat/mb/parse/url_test.go +++ b/metricbeat/mb/parse/url_test.go @@ -41,6 +41,18 @@ func TestParseURL(t *testing.T) { } }) + t.Run("npipe", func(t *testing.T) { + rawURL := "npipe://./pipe/docker_engine" + hostData, err := ParseURL(rawURL, "tcp", "", "", "", "") + if assert.NoError(t, err) { + assert.Equal(t, "npipe://./pipe/docker_engine", hostData.URI) + assert.Equal(t, "npipe://./pipe/docker_engine", hostData.SanitizedURI) + assert.Equal(t, "/pipe/docker_engine", hostData.Host) + assert.Equal(t, "", hostData.User) + assert.Equal(t, "", hostData.Password) + } + }) + t.Run("set default user", func(t *testing.T) { rawURL := "http://:secret@localhost" h, err := ParseURL(rawURL, "https", "root", "passwd", "", "") From 38eb3ebcf227d8b747682db21bdc51306ca3d6d2 Mon Sep 17 00:00:00 2001 From: Vijay Samuel Date: Wed, 26 Jul 2017 17:49:35 -0700 Subject: [PATCH 009/139] Implementing graphite protocol metricbeat module (#4734) * Implementing graphite protocol metricbeat module --- CHANGELOG.asciidoc | 3 + metricbeat/docs/fields.asciidoc | 30 ++++ metricbeat/docs/modules/graphite.asciidoc | 41 +++++ .../docs/modules/graphite/server.asciidoc | 19 ++ metricbeat/docs/modules_list.asciidoc | 2 + metricbeat/helper/server/server.go | 28 +++ metricbeat/helper/server/tcp/config.go | 15 ++ metricbeat/helper/server/tcp/tcp.go | 104 +++++++++++ metricbeat/helper/server/tcp/tcp_test.go | 79 +++++++++ metricbeat/helper/server/udp/config.go | 15 ++ metricbeat/helper/server/udp/udp.go | 98 +++++++++++ metricbeat/helper/server/udp/udp_test.go | 72 ++++++++ metricbeat/include/list.go | 2 + metricbeat/metricbeat.reference.yml | 12 ++ metricbeat/module/graphite/_meta/config.yml | 10 ++ .../module/graphite/_meta/docs.asciidoc | 4 + metricbeat/module/graphite/_meta/fields.yml | 11 ++ metricbeat/module/graphite/doc.go | 4 + .../module/graphite/server/_meta/data.json | 19 ++ .../graphite/server/_meta/docs.asciidoc | 3 + .../module/graphite/server/_meta/fields.yml | 9 + metricbeat/module/graphite/server/config.go | 62 +++++++ metricbeat/module/graphite/server/data.go | 165 ++++++++++++++++++ .../module/graphite/server/data_test.go | 92 ++++++++++ metricbeat/module/graphite/server/server.go | 88 ++++++++++ metricbeat/module/graphite/server/tree.go | 154 ++++++++++++++++ .../module/graphite/server/tree_test.go | 99 +++++++++++ metricbeat/module/kubernetes/event/config.go | 4 - metricbeat/modules.d/graphite.yml.disabled | 10 ++ 29 files changed, 1250 insertions(+), 4 deletions(-) create mode 100644 metricbeat/docs/modules/graphite.asciidoc create mode 100644 metricbeat/docs/modules/graphite/server.asciidoc create mode 100644 metricbeat/helper/server/server.go create mode 100644 metricbeat/helper/server/tcp/config.go create mode 100644 metricbeat/helper/server/tcp/tcp.go create mode 100644 metricbeat/helper/server/tcp/tcp_test.go create mode 100644 metricbeat/helper/server/udp/config.go create mode 100644 metricbeat/helper/server/udp/udp.go create mode 100644 metricbeat/helper/server/udp/udp_test.go create mode 100644 metricbeat/module/graphite/_meta/config.yml create mode 100644 metricbeat/module/graphite/_meta/docs.asciidoc create mode 100644 metricbeat/module/graphite/_meta/fields.yml create mode 100644 metricbeat/module/graphite/doc.go create mode 100644 metricbeat/module/graphite/server/_meta/data.json create mode 100644 metricbeat/module/graphite/server/_meta/docs.asciidoc create mode 100644 metricbeat/module/graphite/server/_meta/fields.yml create mode 100644 metricbeat/module/graphite/server/config.go create mode 100644 metricbeat/module/graphite/server/data.go create mode 100644 metricbeat/module/graphite/server/data_test.go create mode 100644 metricbeat/module/graphite/server/server.go create mode 100644 metricbeat/module/graphite/server/tree.go create mode 100644 metricbeat/module/graphite/server/tree_test.go create mode 100644 metricbeat/modules.d/graphite.yml.disabled diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 2db0dcd77fa..0358220bc32 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -51,6 +51,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Metricbeat* - Add support to exclude labels from kubernetes pod metadata. {pull}4757[4757] +- Add graphite protocol metricbeat module. {pull}4734[4734] *Packetbeat* @@ -175,6 +176,8 @@ https://github.com/elastic/beats/compare/v6.0.0-alpha2...v6.0.0-beta1[View commi - Add `test modules` command, to test modules expected output. {pull}4656[4656] - Add `processors` setting to metricbeat modules. {pull}4699[4699] +*Packetbeat* + *Winlogbeat* - Add the ability to use LevelRaw if Level isn't populated in the event XML. {pull}4257[4257] diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 822daaa6e7d..3f984f0087c 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -24,6 +24,7 @@ grouped in the following categories: * <> * <> * <> +* <> * <> * <> * <> @@ -2788,6 +2789,35 @@ format: bytes Bytes in non-idle span. +[[exported-fields-graphite]] +== graphite Fields + +[]experimental +graphite Module + + + +[float] +== graphite Fields + + + + +[float] +== server Fields + +server + + + +[float] +=== graphite.server.example + +type: keyword + +Example field + + [[exported-fields-haproxy]] == HAProxy Fields diff --git a/metricbeat/docs/modules/graphite.asciidoc b/metricbeat/docs/modules/graphite.asciidoc new file mode 100644 index 00000000000..0a03eb79f80 --- /dev/null +++ b/metricbeat/docs/modules/graphite.asciidoc @@ -0,0 +1,41 @@ +//// +This file is generated! See scripts/docs_collector.py +//// + +[[metricbeat-module-graphite]] +== graphite Module + +This is the graphite Module. + + + +[float] +=== Example configuration + +The graphite module supports the standard configuration options that are described +in <>. Here is an example configuration: + +[source,yaml] +---- +metricbeat.modules: +- module: graphite + metricsets: ["server"] + enabled: true +# protocol: "udp" +# templates: +# - filter: "test.*.bash.*" # This would match metrics like test.localhost.bash.stats +# namespace: "test" +# template: ".host.shell.metric*" # test.localhost.bash.stats would become metric=stats and tags host=localhost,shell=bash +# delimiter: "_" + +---- + +[float] +=== Metricsets + +The following metricsets are available: + +* <> + +include::graphite/server.asciidoc[] + diff --git a/metricbeat/docs/modules/graphite/server.asciidoc b/metricbeat/docs/modules/graphite/server.asciidoc new file mode 100644 index 00000000000..beba3cb5cbe --- /dev/null +++ b/metricbeat/docs/modules/graphite/server.asciidoc @@ -0,0 +1,19 @@ +//// +This file is generated! See scripts/docs_collector.py +//// + +[[metricbeat-metricset-graphite-server]] +include::../../../module/graphite/server/_meta/docs.asciidoc[] + + +==== Fields + +For a description of each field in the metricset, see the +<> section. + +Here is an example document generated by this metricset: + +[source,json] +---- +include::../../../module/graphite/server/_meta/data.json[] +---- diff --git a/metricbeat/docs/modules_list.asciidoc b/metricbeat/docs/modules_list.asciidoc index 9952718e900..61cef2e27ca 100644 --- a/metricbeat/docs/modules_list.asciidoc +++ b/metricbeat/docs/modules_list.asciidoc @@ -10,6 +10,7 @@ This file is generated! See scripts/docs_collector.py * <> * <> * <> + * <> * <> * <> * <> @@ -41,6 +42,7 @@ include::modules/docker.asciidoc[] include::modules/dropwizard.asciidoc[] include::modules/elasticsearch.asciidoc[] include::modules/golang.asciidoc[] +include::modules/graphite.asciidoc[] include::modules/haproxy.asciidoc[] include::modules/http.asciidoc[] include::modules/jolokia.asciidoc[] diff --git a/metricbeat/helper/server/server.go b/metricbeat/helper/server/server.go new file mode 100644 index 00000000000..cac93797589 --- /dev/null +++ b/metricbeat/helper/server/server.go @@ -0,0 +1,28 @@ +package server + +import "github.com/elastic/beats/libbeat/common" + +type Meta common.MapStr + +const ( + EventDataKey = "data" +) + +// Server is an interface that can be used to implement servers which can accept data. +type Server interface { + // Start is used to start the server at a well defined port. + Start() + // Stop the server. + Stop() + // Get a channel of events. + GetEvents() chan Event +} + +// Event is an interface that can be used to get the event and event source related information. +type Event interface { + // Get the raw bytes of the event. + GetEvent() common.MapStr + // Get any metadata associated with the data that was received. Ex: client IP for udp message, + // request/response headers for HTTP call. + GetMeta() Meta +} diff --git a/metricbeat/helper/server/tcp/config.go b/metricbeat/helper/server/tcp/config.go new file mode 100644 index 00000000000..1b240b27842 --- /dev/null +++ b/metricbeat/helper/server/tcp/config.go @@ -0,0 +1,15 @@ +package tcp + +type TcpConfig struct { + Host string `config:"host"` + Port int `config:"port"` + ReceiveBufferSize int `config:"receive_buffer_size"` +} + +func defaultTcpConfig() TcpConfig { + return TcpConfig{ + Host: "localhost", + Port: 2003, + ReceiveBufferSize: 1024, + } +} diff --git a/metricbeat/helper/server/tcp/tcp.go b/metricbeat/helper/server/tcp/tcp.go new file mode 100644 index 00000000000..a2ea7819779 --- /dev/null +++ b/metricbeat/helper/server/tcp/tcp.go @@ -0,0 +1,104 @@ +package tcp + +import ( + "fmt" + "net" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/metricbeat/helper/server" + "github.com/elastic/beats/metricbeat/mb" +) + +type TcpServer struct { + listener *net.TCPListener + receiveBufferSize int + done chan struct{} + eventQueue chan server.Event +} + +type TcpEvent struct { + event common.MapStr +} + +func (m *TcpEvent) GetEvent() common.MapStr { + return m.event +} + +func (m *TcpEvent) GetMeta() server.Meta { + return server.Meta{} +} + +func NewTcpServer(base mb.BaseMetricSet) (server.Server, error) { + config := defaultTcpConfig() + err := base.Module().UnpackConfig(&config) + if err != nil { + return nil, err + } + + addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", config.Host, config.Port)) + + if err != nil { + return nil, err + } + + listener, err := net.ListenTCP("tcp", addr) + if err != nil { + return nil, err + } + + logp.Info("Started listening for TCP on: %s:%d", config.Host, config.Port) + return &TcpServer{ + listener: listener, + receiveBufferSize: config.ReceiveBufferSize, + done: make(chan struct{}), + eventQueue: make(chan server.Event), + }, nil +} + +func (g *TcpServer) Start() { + go g.WatchMetrics() +} + +func (g *TcpServer) WatchMetrics() { + buffer := make([]byte, g.receiveBufferSize) + for { + select { + case <-g.done: + return + default: + } + + conn, err := g.listener.Accept() + if err != nil { + logp.Err("Unable to accept connection due to error: %v", err) + continue + } + defer func() { + if conn != nil { + conn.Close() + } + }() + + length, err := conn.Read(buffer) + if err != nil { + logp.Err("Error reading from buffer: %v", err.Error()) + continue + } + g.eventQueue <- &TcpEvent{ + event: common.MapStr{ + server.EventDataKey: buffer[:length], + }, + } + } +} + +func (g *TcpServer) GetEvents() chan server.Event { + return g.eventQueue +} + +func (g *TcpServer) Stop() { + close(g.done) + g.listener.Close() + close(g.eventQueue) +} diff --git a/metricbeat/helper/server/tcp/tcp_test.go b/metricbeat/helper/server/tcp/tcp_test.go new file mode 100644 index 00000000000..6fd1a55c5a7 --- /dev/null +++ b/metricbeat/helper/server/tcp/tcp_test.go @@ -0,0 +1,79 @@ +// +build !integration + +package tcp + +import ( + "fmt" + "net" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/metricbeat/helper/server" +) + +func GetTestTcpServer(host string, port int) (server.Server, error) { + addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", host, port)) + + if err != nil { + return nil, err + } + + listener, err := net.ListenTCP("tcp", addr) + if err != nil { + return nil, err + } + + logp.Info("Started listening for TCP on: %s:%d", host, port) + return &TcpServer{ + listener: listener, + receiveBufferSize: 1024, + done: make(chan struct{}), + eventQueue: make(chan server.Event), + }, nil +} + +func TestTcpServer(t *testing.T) { + host := "127.0.0.1" + port := 2003 + svc, err := GetTestTcpServer(host, port) + if err != nil { + t.Error(err) + t.FailNow() + } + + svc.Start() + defer svc.Stop() + writeToServer(t, "test1", host, port) + msg := <-svc.GetEvents() + + assert.True(t, msg.GetEvent() != nil) + ok, _ := msg.GetEvent().HasKey("data") + assert.True(t, ok) + bytes, _ := msg.GetEvent()["data"].([]byte) + assert.True(t, string(bytes) == "test1") + +} + +func writeToServer(t *testing.T, message, host string, port int) { + servAddr := fmt.Sprintf("%s:%d", host, port) + tcpAddr, err := net.ResolveTCPAddr("tcp", servAddr) + if err != nil { + t.Error(err) + t.FailNow() + } + + conn, err := net.DialTCP("tcp", nil, tcpAddr) + if err != nil { + t.Error(err) + t.FailNow() + } + + defer conn.Close() + _, err = conn.Write([]byte(message)) + if err != nil { + t.Error(err) + t.FailNow() + } +} diff --git a/metricbeat/helper/server/udp/config.go b/metricbeat/helper/server/udp/config.go new file mode 100644 index 00000000000..fdce2be222a --- /dev/null +++ b/metricbeat/helper/server/udp/config.go @@ -0,0 +1,15 @@ +package udp + +type UdpConfig struct { + Host string `config:"host"` + Port int `config:"port"` + ReceiveBufferSize int `config:"receive_buffer_size"` +} + +func defaultUdpConfig() UdpConfig { + return UdpConfig{ + Host: "localhost", + Port: 2003, + ReceiveBufferSize: 1024, + } +} diff --git a/metricbeat/helper/server/udp/udp.go b/metricbeat/helper/server/udp/udp.go new file mode 100644 index 00000000000..fc476b70207 --- /dev/null +++ b/metricbeat/helper/server/udp/udp.go @@ -0,0 +1,98 @@ +package udp + +import ( + "fmt" + "net" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/metricbeat/helper/server" + "github.com/elastic/beats/metricbeat/mb" +) + +type UdpServer struct { + listener *net.UDPConn + receiveBufferSize int + done chan struct{} + eventQueue chan server.Event +} + +type UdpEvent struct { + event common.MapStr + meta server.Meta +} + +func (u *UdpEvent) GetEvent() common.MapStr { + return u.event +} + +func (u *UdpEvent) GetMeta() server.Meta { + return u.meta +} + +func NewUdpServer(base mb.BaseMetricSet) (server.Server, error) { + config := defaultUdpConfig() + err := base.Module().UnpackConfig(&config) + if err != nil { + return nil, err + } + + addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", config.Host, config.Port)) + + if err != nil { + return nil, err + } + + listener, err := net.ListenUDP("udp", addr) + if err != nil { + return nil, err + } + + logp.Info("Started listening for UDP on: %s:%d", config.Host, config.Port) + return &UdpServer{ + listener: listener, + receiveBufferSize: config.ReceiveBufferSize, + done: make(chan struct{}), + eventQueue: make(chan server.Event), + }, nil +} + +func (g *UdpServer) Start() { + go g.WatchMetrics() +} + +func (g *UdpServer) WatchMetrics() { + buffer := make([]byte, g.receiveBufferSize) + for { + select { + case <-g.done: + return + default: + } + + length, addr, err := g.listener.ReadFromUDP(buffer) + if err != nil { + logp.Err("Error reading from buffer: %v", err.Error()) + continue + } + + g.eventQueue <- &UdpEvent{ + event: common.MapStr{ + server.EventDataKey: buffer[:length], + }, + meta: server.Meta{ + "client_ip": addr.IP.String(), + }, + } + } +} + +func (g *UdpServer) GetEvents() chan server.Event { + return g.eventQueue +} + +func (g *UdpServer) Stop() { + close(g.done) + g.listener.Close() + close(g.eventQueue) +} diff --git a/metricbeat/helper/server/udp/udp_test.go b/metricbeat/helper/server/udp/udp_test.go new file mode 100644 index 00000000000..737f88dd4e5 --- /dev/null +++ b/metricbeat/helper/server/udp/udp_test.go @@ -0,0 +1,72 @@ +// +build !integration + +package udp + +import ( + "fmt" + "net" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/metricbeat/helper/server" +) + +func GetTestUdpServer(host string, port int) (server.Server, error) { + addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", host, port)) + + if err != nil { + return nil, err + } + + listener, err := net.ListenUDP("udp", addr) + if err != nil { + return nil, err + } + + logp.Info("Started listening for UDP on: %s:%d", host, port) + return &UdpServer{ + listener: listener, + receiveBufferSize: 1024, + done: make(chan struct{}), + eventQueue: make(chan server.Event), + }, nil +} + +func TestUdpServer(t *testing.T) { + host := "127.0.0.1" + port := 2003 + svc, err := GetTestUdpServer(host, port) + if err != nil { + t.Error(err) + t.FailNow() + } + + svc.Start() + defer svc.Stop() + writeToServer(t, "test1", host, port) + msg := <-svc.GetEvents() + + assert.True(t, msg.GetEvent() != nil) + ok, _ := msg.GetEvent().HasKey("data") + assert.True(t, ok) + bytes, _ := msg.GetEvent()["data"].([]byte) + assert.True(t, string(bytes) == "test1") +} + +func writeToServer(t *testing.T, message, host string, port int) { + servAddr := fmt.Sprintf("%s:%d", host, port) + conn, err := net.Dial("udp", servAddr) + if err != nil { + t.Error(err) + t.FailNow() + } + + defer conn.Close() + _, err = conn.Write([]byte(message)) + if err != nil { + t.Error(err) + t.FailNow() + } +} diff --git a/metricbeat/include/list.go b/metricbeat/include/list.go index b6973935c42..1d02db49827 100644 --- a/metricbeat/include/list.go +++ b/metricbeat/include/list.go @@ -38,6 +38,8 @@ import ( _ "github.com/elastic/beats/metricbeat/module/golang" _ "github.com/elastic/beats/metricbeat/module/golang/expvar" _ "github.com/elastic/beats/metricbeat/module/golang/heap" + _ "github.com/elastic/beats/metricbeat/module/graphite" + _ "github.com/elastic/beats/metricbeat/module/graphite/server" _ "github.com/elastic/beats/metricbeat/module/haproxy" _ "github.com/elastic/beats/metricbeat/module/haproxy/info" _ "github.com/elastic/beats/metricbeat/module/haproxy/stat" diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index 4638e747573..2061b943aa2 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -155,6 +155,18 @@ metricbeat.modules: namespace: "example" path: "/debug/vars" +#------------------------------ graphite Module ------------------------------ +- module: graphite + metricsets: ["server"] + enabled: true +# protocol: "udp" +# templates: +# - filter: "test.*.bash.*" # This would match metrics like test.localhost.bash.stats +# namespace: "test" +# template: ".host.shell.metric*" # test.localhost.bash.stats would become metric=stats and tags host=localhost,shell=bash +# delimiter: "_" + + #------------------------------- HAProxy Module ------------------------------ - module: haproxy metricsets: ["info", "stat"] diff --git a/metricbeat/module/graphite/_meta/config.yml b/metricbeat/module/graphite/_meta/config.yml new file mode 100644 index 00000000000..b5318ecd7ad --- /dev/null +++ b/metricbeat/module/graphite/_meta/config.yml @@ -0,0 +1,10 @@ +- module: graphite + metricsets: ["server"] + enabled: true +# protocol: "udp" +# templates: +# - filter: "test.*.bash.*" # This would match metrics like test.localhost.bash.stats +# namespace: "test" +# template: ".host.shell.metric*" # test.localhost.bash.stats would become metric=stats and tags host=localhost,shell=bash +# delimiter: "_" + diff --git a/metricbeat/module/graphite/_meta/docs.asciidoc b/metricbeat/module/graphite/_meta/docs.asciidoc new file mode 100644 index 00000000000..a53f5404302 --- /dev/null +++ b/metricbeat/module/graphite/_meta/docs.asciidoc @@ -0,0 +1,4 @@ +== graphite Module + +This is the graphite Module. + diff --git a/metricbeat/module/graphite/_meta/fields.yml b/metricbeat/module/graphite/_meta/fields.yml new file mode 100644 index 00000000000..2f8eb11ae20 --- /dev/null +++ b/metricbeat/module/graphite/_meta/fields.yml @@ -0,0 +1,11 @@ +- key: graphite + title: "graphite" + description: > + []experimental + + graphite Module + fields: + - name: graphite + type: group + description: > + fields: diff --git a/metricbeat/module/graphite/doc.go b/metricbeat/module/graphite/doc.go new file mode 100644 index 00000000000..67de69d767f --- /dev/null +++ b/metricbeat/module/graphite/doc.go @@ -0,0 +1,4 @@ +/* +Package graphite is a Metricbeat module that contains MetricSets. +*/ +package graphite diff --git a/metricbeat/module/graphite/server/_meta/data.json b/metricbeat/module/graphite/server/_meta/data.json new file mode 100644 index 00000000000..3c7e4f4fbcc --- /dev/null +++ b/metricbeat/module/graphite/server/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"graphite", + "name":"server", + "rtt":44269 + }, + "graphite":{ + "collector":{ + "example": "collector" + } + }, + "type":"metricsets" +} diff --git a/metricbeat/module/graphite/server/_meta/docs.asciidoc b/metricbeat/module/graphite/server/_meta/docs.asciidoc new file mode 100644 index 00000000000..8b3f4138661 --- /dev/null +++ b/metricbeat/module/graphite/server/_meta/docs.asciidoc @@ -0,0 +1,3 @@ +=== graphite server MetricSet + +This is the server metricset of the module graphite. diff --git a/metricbeat/module/graphite/server/_meta/fields.yml b/metricbeat/module/graphite/server/_meta/fields.yml new file mode 100644 index 00000000000..9dadb8340ce --- /dev/null +++ b/metricbeat/module/graphite/server/_meta/fields.yml @@ -0,0 +1,9 @@ +- name: server + type: group + description: > + server + fields: + - name: example + type: keyword + description: > + Example field diff --git a/metricbeat/module/graphite/server/config.go b/metricbeat/module/graphite/server/config.go new file mode 100644 index 00000000000..c1419e87a35 --- /dev/null +++ b/metricbeat/module/graphite/server/config.go @@ -0,0 +1,62 @@ +package server + +import ( + "errors" +) + +const ( + defaultDelimiter = "." +) + +type graphiteCollectorConfig struct { + Protocol string `config:"protocol"` + Templates []templateConfig `config:"templates"` + DefaultTemplate templateConfig `config:"default_template"` +} + +type templateConfig struct { + Filter string `config:"filter"` + Template string `config:"template"` + Namespace string `config:"namespace"` + Delimiter string `config:"delimiter"` + Tags map[string]string `config:"tags"` +} + +func defaultGraphiteCollectorConfig() graphiteCollectorConfig { + return graphiteCollectorConfig{ + Protocol: "udp", + DefaultTemplate: templateConfig{ + Filter: "*", + Template: "metric*", + Namespace: "graphite", + Delimiter: ".", + }, + } +} + +func (c graphiteCollectorConfig) Validate() error { + if c.Protocol != "tcp" && c.Protocol != "udp" { + return errors.New("`protocol` can only be tcp or udp") + } + return nil +} + +func (t *templateConfig) Validate() error { + if t.Namespace == "" { + return errors.New("`namespace` can not be empty in template configuration") + } + + if t.Filter == "" { + return errors.New("`filter` can not be empty in template configuration") + } + + if t.Template == "" { + return errors.New("`template` can not be empty in template configuration") + } + + if t.Delimiter == "" { + t.Delimiter = defaultDelimiter + } + + return nil +} diff --git a/metricbeat/module/graphite/server/data.go b/metricbeat/module/graphite/server/data.go new file mode 100644 index 00000000000..2e6a8b6ae27 --- /dev/null +++ b/metricbeat/module/graphite/server/data.go @@ -0,0 +1,165 @@ +package server + +import ( + "errors" + "math" + "strconv" + "strings" + "sync" + "time" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/metricbeat/mb" +) + +type template struct { + Namespace string + Delimiter string + Parts []string + Tags map[string]string +} + +type metricProcessor struct { + templates *tree + defaultTemplate template + sync.RWMutex +} + +func NewMetricProcessor(templates []templateConfig, defaultTemplate templateConfig) *metricProcessor { + templateTree := NewTree(getTemplateFromConfig(defaultTemplate)) + for _, t := range templates { + templateTree.Insert(t.Filter, getTemplateFromConfig(t)) + } + + return &metricProcessor{ + templates: templateTree, + defaultTemplate: getTemplateFromConfig(defaultTemplate), + } +} + +func getTemplateFromConfig(config templateConfig) template { + return template{ + Namespace: config.Namespace, + Tags: config.Tags, + Delimiter: config.Delimiter, + Parts: strings.Split(config.Template, "."), + } +} + +func (m *metricProcessor) AddTemplate(t templateConfig) { + m.Lock() + template := getTemplateFromConfig(t) + m.templates.Insert(t.Filter, template) + m.Unlock() +} + +func (m *metricProcessor) RemoveTemplate(template templateConfig) { + m.Lock() + m.templates.Delete(template.Filter) + m.Unlock() +} + +func (m *metricProcessor) Process(message string) (common.MapStr, error) { + metric, timestamp, value, err := m.splitMetric(message) + if err != nil { + return nil, err + } + + parts := strings.Split(metric, ".") + t := m.FindTemplate(parts) + + var name, namespace string + var tags common.MapStr + if t == nil { + name, tags = m.defaultTemplate.Apply(parts) + namespace = m.defaultTemplate.Namespace + } else { + name, tags = t.Apply(parts) + namespace = t.Namespace + } + + event := common.MapStr{ + "@timestamp": timestamp, + name: value, + mb.NamespaceKey: namespace, + } + if len(tags) != 0 { + event["tag"] = tags + } + return event, nil +} + +func (m *metricProcessor) FindTemplate(metric []string) *template { + return m.templates.Search(metric) +} + +func (m *metricProcessor) splitMetric(metric string) (string, common.Time, float64, error) { + var metricName string + var timestamp common.Time + var value float64 + + parts := strings.Fields(metric) + currentTime := common.Time(time.Now()) + if len(parts) < 2 { + return "", currentTime, 0, errors.New("Message not in expected format") + } else { + metricName = parts[0] + val, err := strconv.ParseFloat(parts[1], 64) + if err != nil { + return "", currentTime, 0, errors.New("Unable to parse metric value") + } else { + value = val + } + } + + if len(parts) == 3 { + if parts[2] == "N" { + timestamp = currentTime + } + ts, err := strconv.ParseFloat(parts[2], 64) + if err != nil { + return "", currentTime, 0, errors.New("Unable to parse timestamp") + } + + if ts != -1 { + timestamp = common.Time(time.Unix(int64(ts), int64((ts-math.Floor(ts))*float64(time.Second)))) + } else { + timestamp = currentTime + } + + } else { + timestamp = currentTime + } + + return metricName, timestamp, value, nil +} + +func (t *template) Apply(parts []string) (string, common.MapStr) { + tags := make(common.MapStr) + + metric := make([]string, 0) + for tagKey, tagVal := range t.Tags { + tags[tagKey] = tagVal + } + + tagsMap := make(map[string][]string) + for i := 0; i < len(t.Parts); i++ { + if t.Parts[i] == "metric" { + metric = append(metric, parts[i]) + } else if t.Parts[i] == "metric*" { + metric = append(metric, parts[i:]...) + } else if t.Parts[i] != "" { + tagsMap[t.Parts[i]] = append(tagsMap[t.Parts[i]], parts[i]) + } + } + + for key, value := range tagsMap { + tags[key] = strings.Join(value, t.Delimiter) + } + + if len(metric) == 0 { + return "", tags + } else { + return strings.Join(metric, t.Delimiter), tags + } +} diff --git a/metricbeat/module/graphite/server/data_test.go b/metricbeat/module/graphite/server/data_test.go new file mode 100644 index 00000000000..cb93978e056 --- /dev/null +++ b/metricbeat/module/graphite/server/data_test.go @@ -0,0 +1,92 @@ +// +build !integration + +package server + +import ( + "math" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/libbeat/common" +) + +func GetMetricProcessor() *metricProcessor { + templates := []templateConfig{ + { + Namespace: "foo", + Filter: "test.localhost.*", + Template: ".host.shell.metric", + Delimiter: ".", + }, + { + Namespace: "foo", + Filter: "test.xyz.*", + Template: ".host.metric*", + Delimiter: "_", + Tags: map[string]string{ + "a": "b", + }, + }, + } + + defaultTemplate := defaultGraphiteCollectorConfig().DefaultTemplate + return NewMetricProcessor(templates, defaultTemplate) +} + +func TestMetricProcessorAddTemplate(t *testing.T) { + processor := GetMetricProcessor() + temp := templateConfig{ + Namespace: "xyz", + Filter: "a.b.*", + Template: ".host.shell.metric", + Delimiter: ".", + } + processor.AddTemplate(temp) + out := processor.templates.Search([]string{"a", "b", "c"}) + assert.NotNil(t, out) + assert.Equal(t, out.Namespace, temp.Namespace) +} + +func TestMetricProcessorDeleteTemplate(t *testing.T) { + processor := GetMetricProcessor() + temp := templateConfig{ + Namespace: "xyz", + Filter: "a.b.*", + Template: ".host.shell.metric", + Delimiter: ".", + } + processor.AddTemplate(temp) + processor.RemoveTemplate(temp) + out := processor.templates.Search([]string{"a", "b", "c"}) + assert.Nil(t, out) + +} + +func TestMetricProcessorProcess(t *testing.T) { + processor := GetMetricProcessor() + event, err := processor.Process("test.localhost.bash.stats 42 1500934723") + assert.Nil(t, err) + assert.NotNil(t, event) + + tag := event["tag"].(common.MapStr) + assert.Equal(t, len(tag), 2) + assert.Equal(t, tag["host"], "localhost") + assert.Equal(t, tag["shell"], "bash") + + assert.NotNil(t, event["stats"]) + assert.Equal(t, event["stats"], float64(42)) + + ts := float64(1500934723) + timestamp := common.Time(time.Unix(int64(ts), int64((ts-math.Floor(ts))*float64(time.Second)))) + + assert.Equal(t, event["@timestamp"], timestamp) + + event, err = processor.Process("test.localhost.bash.stats 42") + assert.Nil(t, err) + assert.NotNil(t, event) + + assert.NotNil(t, event["stats"]) + assert.Equal(t, event["stats"], float64(42)) +} diff --git a/metricbeat/module/graphite/server/server.go b/metricbeat/module/graphite/server/server.go new file mode 100644 index 00000000000..37e01fbd2dc --- /dev/null +++ b/metricbeat/module/graphite/server/server.go @@ -0,0 +1,88 @@ +package server + +import ( + "github.com/elastic/beats/libbeat/common/cfgwarn" + serverhelper "github.com/elastic/beats/metricbeat/helper/server" + "github.com/elastic/beats/metricbeat/helper/server/tcp" + "github.com/elastic/beats/metricbeat/helper/server/udp" + "github.com/elastic/beats/metricbeat/mb" +) + +// init registers the MetricSet with the central registry. +// The New method will be called after the setup of the module and before starting to fetch data +func init() { + if err := mb.Registry.AddMetricSet("graphite", "server", New); err != nil { + panic(err) + } +} + +// MetricSet type defines all fields of the MetricSet +// As a minimum it must inherit the mb.BaseMetricSet fields, but can be extended with +// additional entries. These variables can be used to persist data or configuration between +// multiple fetch calls. +type MetricSet struct { + mb.BaseMetricSet + server serverhelper.Server + processor *metricProcessor +} + +// New create a new instance of the MetricSet +// Part of new is also setting up the configuration by processing additional +// configuration entries if needed. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Experimental("The graphite server metricset is experimental") + + config := defaultGraphiteCollectorConfig() + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + + var s serverhelper.Server + var err error + if config.Protocol == "tcp" { + s, err = tcp.NewTcpServer(base) + } else { + s, err = udp.NewUdpServer(base) + } + + if err != nil { + return nil, err + } + + processor := NewMetricProcessor(config.Templates, config.DefaultTemplate) + + return &MetricSet{ + BaseMetricSet: base, + server: s, + processor: processor, + }, nil +} + +// Run method provides the Graphite server with a reporter with which events can be reported. +func (m *MetricSet) Run(reporter mb.PushReporter) { + // Start event watcher + m.server.Start() + + for { + select { + case <-reporter.Done(): + m.server.Stop() + return + case msg := <-m.server.GetEvents(): + input := msg.GetEvent() + bytesRaw, ok := input[serverhelper.EventDataKey] + if ok { + bytes, ok := bytesRaw.([]byte) + if ok && len(bytes) != 0 { + event, err := m.processor.Process(string(bytes)) + if err != nil { + reporter.Error(err) + } else { + reporter.Event(event) + } + } + } + + } + } +} diff --git a/metricbeat/module/graphite/server/tree.go b/metricbeat/module/graphite/server/tree.go new file mode 100644 index 00000000000..cd84b4db752 --- /dev/null +++ b/metricbeat/module/graphite/server/tree.go @@ -0,0 +1,154 @@ +package server + +import ( + "strings" +) + +type tree struct { + root *node // Root node +} + +// node is a single element within the tree +type node struct { + parent *node + entry *entry // entry + children map[string]*node // Children nodes +} + +// entry represents the key-value pair contained within nodes +type entry struct { + key string + value *template +} + +func (n *node) FindChild(key string) *node { + child, ok := n.children[key] + if ok { + return child + } + return nil +} + +func (n *node) AddChild(key string) *node { + temp := &node{ + parent: n, + children: make(map[string]*node), + } + + n.children[key] = temp + return temp +} + +func (n *node) GetTemplate() *template { + if n.entry != nil { + return n.entry.value + } + + return nil +} + +func (n *node) Search(parts []string) *template { + if len(parts) == 0 || len(n.children) == 0 { + return n.GetTemplate() + } + child := n.FindChild(parts[0]) + if child == nil { + child = n.FindChild("*") + } + + if child != nil { + return child.Search(parts[1:]) + } + + return n.GetTemplate() +} + +func (t *tree) Insert(filter string, template template) { + cur := t.root + parts := strings.Split(filter, ".") + for _, part := range parts { + child := cur.FindChild(part) + if child == nil { + child = cur.AddChild(part) + if child != nil && part == "*" { + child.entry = cur.entry + } + } + cur = child + } + + if cur != nil { + cur.entry = &entry{ + key: parts[len(parts)-1], + value: &template, + } + } +} + +func (t *tree) Search(parts []string) *template { + return t.root.Search(parts) +} + +func (t *tree) Delete(filter string) { + parts := strings.Split(filter, ".") + cur := t.root + for _, part := range parts { + child := cur.FindChild(part) + if child == nil { + // entry does not exist + return + } + cur = child + } + + // we are in the last element at this point + if cur != nil { + // There are more entries, so just make the template nil and make all subsequent '*' templates nil + if len(cur.children) != 0 { + cur.entry = nil + doBreak := false + temp := cur + for doBreak == false { + child := temp.FindChild("*") + if child != nil { + child.entry = nil + temp = child + } else { + doBreak = true + } + } + } else { + // Keep removing parts till there is no more childless entry + temp := cur + length := len(parts) + for temp != t.root { + parent := temp.parent + // Remove only if there is only one child for the parent + if len(parent.children) == 1 { + delete(parent.children, parts[length-1]) + temp = parent + length = length - 1 + } else { + break + } + + } + + } + } +} + +func NewTree(defaultTemplate template) *tree { + root := &node{ + entry: &entry{ + key: "*", + value: &defaultTemplate, + }, + children: make(map[string]*node), + parent: nil, + } + + return &tree{ + root: root, + } +} diff --git a/metricbeat/module/graphite/server/tree_test.go b/metricbeat/module/graphite/server/tree_test.go new file mode 100644 index 00000000000..ea2a87ba687 --- /dev/null +++ b/metricbeat/module/graphite/server/tree_test.go @@ -0,0 +1,99 @@ +// +build !integration + +package server + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func NewTestTree() *tree { + defaultTemplate := template{ + Parts: []string{"metric*"}, + Namespace: "foo", + Delimiter: ".", + } + + return NewTree(defaultTemplate) +} +func TestTreeInsert(t *testing.T) { + test := NewTestTree() + temp := template{ + Delimiter: "_", + Namespace: "foo", + Parts: []string{"", "host", "metric*"}, + } + test.Insert("test.localhost.*", temp) + + assert.Equal(t, len(test.root.children), 1) + child := test.root.children["test"] + assert.NotNil(t, child) + assert.Nil(t, child.GetTemplate()) + + cur := child + assert.Equal(t, len(cur.children), 1) + child = cur.children["localhost"] + assert.NotNil(t, child) + assert.Nil(t, child.GetTemplate()) + + cur = child + assert.Equal(t, len(cur.children), 1) + child = cur.children["*"] + assert.NotNil(t, child) + assert.NotNil(t, child.GetTemplate()) + assert.Equal(t, &temp, child.GetTemplate()) + + cur = child + assert.Equal(t, len(cur.children), 0) + test.Insert("test.localhost.*.foo", temp) + assert.Equal(t, len(cur.children), 1) + + test.Insert("a.b.c.d", temp) + assert.Equal(t, len(test.root.children), 2) +} + +func TestTreeSearch(t *testing.T) { + test := NewTestTree() + temp := template{ + Delimiter: "_", + Namespace: "foo", + Parts: []string{"", "host", "metric*"}, + } + test.Insert("test.localhost.*", temp) + + // Search for a valid scenario + outTemp := test.Search([]string{"test", "localhost", "bash", "stats"}) + assert.NotNil(t, outTemp) + assert.Equal(t, outTemp, &temp) + + // Search for a case where only half the tree is traversed and there is no entry + outTemp = test.Search([]string{"test"}) + assert.Nil(t, outTemp) + + // Search for a default case where root data is returned + outTemp = test.Search([]string{"a.b.c.d"}) + assert.NotNil(t, outTemp) + assert.Equal(t, outTemp, test.root.entry.value) +} + +func TestTreeDelete(t *testing.T) { + test := NewTestTree() + temp := template{ + Delimiter: "_", + Namespace: "foo", + Parts: []string{"", "host", "metric*"}, + } + test.Insert("test.localhost.*", temp) + test.Delete("test.localhost.*") + + assert.Equal(t, len(test.root.children), 0) + + test.Insert("test.localhost.*", temp) + test.Insert("test.*", temp) + test.Delete("test.*") + + assert.Equal(t, len(test.root.children), 1) + assert.NotNil(t, test.root.FindChild("test")) + +} diff --git a/metricbeat/module/kubernetes/event/config.go b/metricbeat/module/kubernetes/event/config.go index 551976fd5e2..5c65f2e2089 100644 --- a/metricbeat/module/kubernetes/event/config.go +++ b/metricbeat/module/kubernetes/event/config.go @@ -3,8 +3,6 @@ package event import ( "errors" "time" - - "github.com/elastic/beats/libbeat/common" ) type kubeEventsConfig struct { @@ -18,8 +16,6 @@ type Enabled struct { Enabled bool `config:"enabled"` } -type PluginConfig []map[string]common.Config - func defaultKuberentesEventsConfig() kubeEventsConfig { return kubeEventsConfig{ InCluster: true, diff --git a/metricbeat/modules.d/graphite.yml.disabled b/metricbeat/modules.d/graphite.yml.disabled new file mode 100644 index 00000000000..b5318ecd7ad --- /dev/null +++ b/metricbeat/modules.d/graphite.yml.disabled @@ -0,0 +1,10 @@ +- module: graphite + metricsets: ["server"] + enabled: true +# protocol: "udp" +# templates: +# - filter: "test.*.bash.*" # This would match metrics like test.localhost.bash.stats +# namespace: "test" +# template: ".host.shell.metric*" # test.localhost.bash.stats would become metric=stats and tags host=localhost,shell=bash +# delimiter: "_" + From 47d3db437b41a575a2790297959f3762d96cd306 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Thu, 27 Jul 2017 09:18:45 -0400 Subject: [PATCH 010/139] Use ProgramData for Windows service logs (#4765) The logs for Beats that are running as Windows services are currently written to `C:\Program Files\[beatname]\logs` (or the extract path which is `path.home`). Our Getting Started guides say that the logs go to `C:\ProgramData\[beatname]\Logs`. This PR sets `path.log` for the Windows service to `C:\ProgramData\[beatname]\logs`. See #4764 --- CHANGELOG.asciidoc | 2 ++ dev-tools/packer/platforms/windows/install-service.ps1.j2 | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 0358220bc32..5feb82d68a0 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -14,6 +14,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Affecting all Beats* +- The log directory (`path.log`) for Windows services is now set to `C:\ProgramData\[beatname]\logs`. {issue}4764[4764] + *Filebeat* *Heartbeat* diff --git a/dev-tools/packer/platforms/windows/install-service.ps1.j2 b/dev-tools/packer/platforms/windows/install-service.ps1.j2 index 9ba8db5b329..556d7a4e0bf 100644 --- a/dev-tools/packer/platforms/windows/install-service.ps1.j2 +++ b/dev-tools/packer/platforms/windows/install-service.ps1.j2 @@ -11,4 +11,4 @@ $workdir = Split-Path $MyInvocation.MyCommand.Path # create new service New-Service -name {{.beat_name}} ` -displayName {{.beat_name}} ` - -binaryPathName "`"$workdir\\{{.beat_name}}.exe`" -c `"$workdir\\{{.beat_name}}.yml`" -path.home `"$workdir`" -path.data `"C:\\ProgramData\\{{.beat_name}}`"" + -binaryPathName "`"$workdir\\{{.beat_name}}.exe`" -c `"$workdir\\{{.beat_name}}.yml`" -path.home `"$workdir`" -path.data `"C:\\ProgramData\\{{.beat_name}}`" -path.logs `"C:\\ProgramData\\{{.beat_name}}\logs`"" From 4b7f09790a315e09125bcd6b0096da5ab210013f Mon Sep 17 00:00:00 2001 From: Steffen Siering Date: Thu, 27 Jul 2017 21:01:36 +0200 Subject: [PATCH 011/139] Update docs (#4753) - remove removed settings in libbeat/filebeat docs - add tags/fields/fields_under_root/processor settings to every beat --- .../docs/filebeat-general-options.asciidoc | 39 +-------------- filebeat/docs/filebeat-options.asciidoc | 9 +++- filebeat/docs/load-balancing.asciidoc | 35 -------------- filebeat/docs/migration.asciidoc | 6 +-- filebeat/docs/overview.asciidoc | 2 +- heartbeat/docs/heartbeat-options.asciidoc | 38 +++++++++++++++ libbeat/docs/generalconfig.asciidoc | 11 ++--- metricbeat/docs/metricbeat-options.asciidoc | 9 ++-- packetbeat/docs/packetbeat-options.asciidoc | 48 +++++++++++++++++++ winlogbeat/docs/winlogbeat-options.asciidoc | 17 +++++-- 10 files changed, 121 insertions(+), 93 deletions(-) diff --git a/filebeat/docs/filebeat-general-options.asciidoc b/filebeat/docs/filebeat-general-options.asciidoc index 704c85e589c..80076d8124c 100644 --- a/filebeat/docs/filebeat-general-options.asciidoc +++ b/filebeat/docs/filebeat-general-options.asciidoc @@ -16,43 +16,6 @@ Beats. These options are in the `filebeat` namespace. -[float] -==== `spool_size` - -The event count spool threshold. This setting forces a network flush if the number of events in the spooler exceeds -the specified value. - -[source,yaml] -------------------------------------------------------------------------------------- -filebeat.spool_size: 2048 -------------------------------------------------------------------------------------- - -See <> for more information about how this setting affects load balancing. - -[float] -==== `publish_async` - -experimental[] -deprecated[5.3.0] - -If enabled, the publisher pipeline in Filebeat operates in async mode preparing -a new batch of lines while waiting for ACK. This option can improve load-balancing -throughput at the cost of increased memory usage. The default value is false. - -See <> for more information about how this setting affects load balancing. - -[float] -==== `idle_timeout` - -A duration string that specifies how often the spooler is flushed. After the -`idle_timeout` is reached, the spooler is flushed even if the `spool_size` has not been reached. - -[source,yaml] -------------------------------------------------------------------------------------- -filebeat.idle_timeout: 5s -------------------------------------------------------------------------------------- - - [float] ==== `registry_file` @@ -76,7 +39,7 @@ That means in case there are some states where the TTL expired, these are only r The full path to the directory that contains additional prospector configuration files. Each configuration file must end with `.yml`. Each config file must also specify the full Filebeat config hierarchy even though only the prospector part of the file is processed. All global -options, such as `spool_size`, are ignored. +options, such as `registry_file`, are ignored. The `config_dir` option MUST point to a directory other than the directory where the main Filebeat config file resides. diff --git a/filebeat/docs/filebeat-options.asciidoc b/filebeat/docs/filebeat-options.asciidoc index 7e72e9e8caf..8458096de10 100644 --- a/filebeat/docs/filebeat-options.asciidoc +++ b/filebeat/docs/filebeat-options.asciidoc @@ -191,6 +191,14 @@ 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 Filebeat, then the custom fields overwrite the other fields. +[float] +==== `processors` + +A list of processors to apply to the data generated by the prospector. + +See <> for information about specifying +processors in your config. + [float] [[ignore-older]] ==== `ignore_older` @@ -484,4 +492,3 @@ by assigning a higher limit of harvesters. The `enabled` option can be used with each prospector to define if a prospector is enabled or not. By default, enabled is set to true. - diff --git a/filebeat/docs/load-balancing.asciidoc b/filebeat/docs/load-balancing.asciidoc index 7b091a12d84..330db6d8295 100644 --- a/filebeat/docs/load-balancing.asciidoc +++ b/filebeat/docs/load-balancing.asciidoc @@ -17,16 +17,6 @@ output.logstash: The `loadbalance` option is available for Redis, Logstash, and Elasticsearch outputs. The Kafka output handles load balancing internally. -Filebeat can send events in a few different modes: - -* **Send events to one host after another:** -+ -By default, when you configure Filebeat to send events to multiple hosts -(`loadbalance: true`), Filebeat will send the events to one host after -another. This mode requires the least memory and CPU usage. This is not -true load balancing in the sense that Filebeat doesn't account for the load -being processed by each host. -+ The load balancer also supports multiple workers per host. The default is `worker: 1`. If you increase the number of workers, additional network connections will be used. The total number of workers participating @@ -47,28 +37,3 @@ output.logstash: ------------------------------------------------------------------------------- + In this example, there are 4 workers participating in load balancing. - -* **Send events to `N` hosts in lock-step:** -+ -You can configure Filebeat to send events to `N` hosts in lock-step by setting -`spool_size = N * bulk_max_size`. In lock-step mode, the batch collected by the -spooler is split up into smaller batches of size `bulk_max_size`. These smaller -batches are load balanced between available connections. Filebeat waits for all -sub-batches to be published before it retrieves another batch from the spooler. -+ -This mode requires more memory and CPU usage than the previous mode. -+ -Example: -+ -[source,yaml] -------------------------------------------------------------------------------- -filebeat.prospectors: -- type: log - paths: - - /var/log/*.log -filebeat.spool_size: 4096 -output.logstash: - hosts: ["localhost:5044", "localhost:5045"] - loadbalance: true - bulk_max_size: 2048 -------------------------------------------------------------------------------- diff --git a/filebeat/docs/migration.asciidoc b/filebeat/docs/migration.asciidoc index 328e8c5ec1e..06f10932c8d 100644 --- a/filebeat/docs/migration.asciidoc +++ b/filebeat/docs/migration.asciidoc @@ -321,11 +321,11 @@ replaced by options specified in libbeat. The `config_dir` option specifies the path to the directory that contains additional configuration files. This option MUST point to a directory other than the directory where the main Filebeat config file resides. |`-idle-timeout` -|`idle_timeout` -|`idle_timeout` was moved to the config file and removed as a flag. +| +|`idle_timeout` was removed. Libbeat is used for publishing logs. |`-spool-size` -|`spool_size` +|`queue.mem.events` |`spool_size` was moved to the config file and removed as a flag. |`-harvester-buff-size` diff --git a/filebeat/docs/overview.asciidoc b/filebeat/docs/overview.asciidoc index 8db37a4cc87..37e98845f6b 100644 --- a/filebeat/docs/overview.asciidoc +++ b/filebeat/docs/overview.asciidoc @@ -8,7 +8,7 @@ Filebeat is a log data shipper for local files. Installed as an agent on your servers, Filebeat monitors the log directories or specific log files, tails the files, and forwards them either to https://www.elastic.co/products/elasticsearch[Elasticsearch] or https://www.elastic.co/products/logstash[Logstash] for indexing. -Here's how Filebeat works: When you start Filebeat, it starts one or more prospectors that look in the local paths you've specified for log files. For each log file that the prospector locates, Filebeat starts a harvester. Each harvester reads a single log file for new content and sends the new log data to the spooler, which aggregates the events and sends the aggregated data to the output that you've configured for Filebeat. +Here's how Filebeat works: When you start Filebeat, it starts one or more prospectors that look in the local paths you've specified for log files. For each log file that the prospector locates, Filebeat starts a harvester. Each harvester reads a single log file for new content and sends the new log data to libbeat, which aggregates the events and sends the aggregated data to the output that you've configured for Filebeat. image:./images/filebeat.png[Beats design] diff --git a/heartbeat/docs/heartbeat-options.asciidoc b/heartbeat/docs/heartbeat-options.asciidoc index 785ef4042bb..aab178bbf22 100644 --- a/heartbeat/docs/heartbeat-options.asciidoc +++ b/heartbeat/docs/heartbeat-options.asciidoc @@ -122,6 +122,44 @@ If the timeout is exceeded, Heartbeat 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 <> +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 Heartbeat, 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 <> for information about specifying +processors in your config. + [float] [[monitor-watch-poll-file]] ==== `watch.poll_file` diff --git a/libbeat/docs/generalconfig.asciidoc b/libbeat/docs/generalconfig.asciidoc index db07e820cf1..a3f7426160a 100644 --- a/libbeat/docs/generalconfig.asciidoc +++ b/libbeat/docs/generalconfig.asciidoc @@ -91,15 +91,12 @@ fields: ------------------------------------------------------------------------------ [float] -==== `queue_size` +==== `processors` -The internal queue size for single events in the processing pipeline. The default -value is 1000. +A list of processors to apply to the data generated by the beat. -[float] -==== `bulk_queue_size` - -(DO NOT TOUCH) The internal queue size for bulk events in the processing pipeline. The default value is 0. +See <> for information about specifying +processors in your config. [float] ==== `max_procs` diff --git a/metricbeat/docs/metricbeat-options.asciidoc b/metricbeat/docs/metricbeat-options.asciidoc index 97ba20c2acd..3e4bc4272d0 100644 --- a/metricbeat/docs/metricbeat-options.asciidoc +++ b/metricbeat/docs/metricbeat-options.asciidoc @@ -19,7 +19,7 @@ metricbeat: fields: dc: west tags: ["tag"] - filters: + processors: .... ---- @@ -131,9 +131,10 @@ A dictionary of fields that will be sent with the metricset event. This setting A list of tags that will be sent with the metricset event. This setting is optional. [float] -==== `filters` +==== `processors` -deprecated[5.1,This option will be renamed and changed in a future release] +A list of processors to apply to the data generated by the metricset. -A list of filters to apply to the data generated by the module. +See <> for information about specifying +processors in your config. diff --git a/packetbeat/docs/packetbeat-options.asciidoc b/packetbeat/docs/packetbeat-options.asciidoc index bedbffbb87c..c5565e7ee9d 100644 --- a/packetbeat/docs/packetbeat-options.asciidoc +++ b/packetbeat/docs/packetbeat-options.asciidoc @@ -353,6 +353,41 @@ in time. Periodical reporting can be disabled by setting the value to -1. If disabled, flows are still reported once being timed out. The default value is 10s. +[float] +[[packetbeat-configuration-flows-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] +==== `fields_under_root` + +If this option is set to true, the custom <> +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 Packetbeat, then the custom fields overwrite the other +fields. + +[float] +==== `tags` + +A list of tags that will be sent with the protocol event. This setting is optional. + +[float] +==== `processors` + +A list of processors to apply to the data generated by the protocol. + +See <> for information about specifying +processors in your config. + [[configuration-protocols]] == Specify which transaction protocols to monitor @@ -485,6 +520,19 @@ under a `fields` sub-dictionary. If the custom field names conflict with other field names added by Packetbeat, then the custom fields overwrite the other fields. +[float] +==== `tags` + +A list of tags that will be sent with the transaction event. This setting is optional. + +[float] +==== `processors` + +A list of processors to apply to the data generated by the protocol. + +See <> for information about specifying +processors in your config. + [[packetbeat-icmp-options]] === Capture ICMP traffic diff --git a/winlogbeat/docs/winlogbeat-options.asciidoc b/winlogbeat/docs/winlogbeat-options.asciidoc index 2bcebc575e9..406d5adca54 100644 --- a/winlogbeat/docs/winlogbeat-options.asciidoc +++ b/winlogbeat/docs/winlogbeat-options.asciidoc @@ -191,10 +191,11 @@ event IDs. [source,yaml] -------------------------------------------------------------------------------- -processors: -- drop_event.when.and: - - equals.log_name: Security - - not.or: +winlogbeat.event_logs: + - name: Security + event_id: ... + processors: + - drop_event.when.not.or: - equals.event_id: 903 - equals.event_id: 1024 - equals.event_id: 4624 @@ -340,3 +341,11 @@ under a `fields` sub-dictionary. If the custom field names conflict with other field names added by Winlogbeat, then the custom fields overwrite the other fields. +[float] +==== `event_logs.processors` + +A list of processors to apply to the data generated by the event log. + +See <> for information about specifying +processors in your config. + From ce2690e6818b20970210f9ec83fed050ef0d7930 Mon Sep 17 00:00:00 2001 From: Steffen Siering Date: Thu, 27 Jul 2017 21:55:45 +0200 Subject: [PATCH 012/139] Fix batch being ACKed on failure in ES monitoring reporter (#4773) --- libbeat/monitoring/report/elasticsearch/client.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libbeat/monitoring/report/elasticsearch/client.go b/libbeat/monitoring/report/elasticsearch/client.go index 8fdef93e477..1641703d7cc 100644 --- a/libbeat/monitoring/report/elasticsearch/client.go +++ b/libbeat/monitoring/report/elasticsearch/client.go @@ -91,9 +91,11 @@ func (c *publishClient) Publish(batch publisher.Batch) error { _, err := c.es.BulkWith("_xpack", "monitoring", c.params, nil, bulk) if err != nil { batch.Retry() + return err } + batch.ACK() - return err + return nil } func (c *publishClient) Test(d testing.Driver) { From c4af03c51373c1de7daaca660f5d21b3f602771c Mon Sep 17 00:00:00 2001 From: DeDe Morton Date: Thu, 27 Jul 2017 16:48:06 -0700 Subject: [PATCH 013/139] Clean up exported fields titles (#4768) Change PHP-FPM to PHP_FPM when referring to the module --- auditbeat/docs/fields.asciidoc | 666 ++--- filebeat/_meta/fields.common.yml | 2 +- filebeat/docs/fields.asciidoc | 442 +-- heartbeat/_meta/fields.common.yml | 4 +- heartbeat/docs/fields.asciidoc | 178 +- .../active/dialchain/_meta/fields.yml | 4 +- .../monitors/active/http/_meta/fields.yml | 2 +- .../monitors/active/tcp/_meta/fields.yml | 2 +- .../add_cloud_metadata/_meta/fields.yml | 2 +- .../add_docker_metadata/_meta/fields.yml | 2 +- .../add_kubernetes_metadata/_meta/fields.yml | 2 +- libbeat/scripts/generate_fields_docs.py | 6 +- metricbeat/docs/fields.asciidoc | 2610 ++++++++--------- metricbeat/docs/modules/php_fpm.asciidoc | 6 +- metricbeat/docs/modules_list.asciidoc | 2 +- metricbeat/metricbeat.reference.yml | 2 +- metricbeat/module/aerospike/_meta/fields.yml | 2 +- .../module/elasticsearch/_meta/fields.yml | 2 +- metricbeat/module/jolokia/_meta/fields.yml | 2 +- metricbeat/module/kibana/_meta/fields.yml | 2 +- metricbeat/module/memcached/_meta/fields.yml | 2 +- metricbeat/module/php_fpm/_meta/docs.asciidoc | 4 +- metricbeat/module/php_fpm/_meta/fields.yml | 2 +- .../module/php_fpm/pool/_meta/docs.asciidoc | 4 +- metricbeat/module/rabbitmq/_meta/fields.yml | 2 +- metricbeat/module/windows/_meta/fields.yml | 2 +- metricbeat/scripts/module/docs.asciidoc | 4 +- metricbeat/scripts/module/fields.yml | 4 +- packetbeat/docs/fields.asciidoc | 782 ++--- winlogbeat/_meta/fields.yml | 2 +- winlogbeat/docs/fields.asciidoc | 120 +- 31 files changed, 2434 insertions(+), 2434 deletions(-) diff --git a/auditbeat/docs/fields.asciidoc b/auditbeat/docs/fields.asciidoc index 2bb7be32d46..4f8efacf929 100644 --- a/auditbeat/docs/fields.asciidoc +++ b/auditbeat/docs/fields.asciidoc @@ -4,7 +4,7 @@ This file is generated! See _meta/fields.yml and scripts/generate_field_docs.py //// [[exported-fields]] -= Exported Fields += Exported fields [partintro] @@ -21,41 +21,41 @@ grouped in the following categories: -- [[exported-fields-audit]] -== Audit Fields +== Audit fields The `audit` module reports security-relevant information based on data captured from the operating system (OS) or services running on the OS. [float] -== audit Fields +== audit fields [float] -== file Fields +== file fields The file metricset generates events when a file changes on disk. [float] -=== audit.file.path +=== `audit.file.path` type: keyword The path to the file. [float] -=== audit.file.target_path +=== `audit.file.target_path` type: keyword The target path for symlinks. [float] -=== audit.file.action +=== `audit.file.action` type: keyword @@ -65,56 +65,56 @@ Action describes the change to the file. The possible values are: attributes_mod [float] -=== audit.file.type +=== `audit.file.type` type: keyword The file type (file, dir, or symlink). [float] -=== audit.file.inode +=== `audit.file.inode` type: keyword The inode representing the file in the filesystem. [float] -=== audit.file.uid +=== `audit.file.uid` type: keyword The user ID (UID) of the file owner. [float] -=== audit.file.owner +=== `audit.file.owner` type: keyword The file owner's username. [float] -=== audit.file.gid +=== `audit.file.gid` type: keyword The primary group ID (GID) of the file. [float] -=== audit.file.group +=== `audit.file.group` type: keyword The primary group name of the file. [float] -=== audit.file.sid +=== `audit.file.sid` type: keyword The security identifier (SID) of the file owner (Windows only). [float] -=== audit.file.mode +=== `audit.file.mode` type: keyword @@ -123,35 +123,35 @@ example: 416 The mode of the file in octal representation. [float] -=== audit.file.size +=== `audit.file.size` type: long The file size in bytes. [float] -=== audit.file.atime +=== `audit.file.atime` type: date The last access time of the file. [float] -=== audit.file.mtime +=== `audit.file.mtime` type: date The last modified time of the file. [float] -=== audit.file.ctime +=== `audit.file.ctime` type: date The creation time of the file. [float] -=== audit.file.hashed +=== `audit.file.hashed` type: boolean @@ -159,35 +159,35 @@ Boolean indicating if the event includes file hashes. If true the md5, sha1, and [float] -=== audit.file.md5 +=== `audit.file.md5` type: keyword MD5 hash of the file. [float] -=== audit.file.sha1 +=== `audit.file.sha1` type: keyword SHA1 hash of the file. [float] -=== audit.file.sha256 +=== `audit.file.sha256` type: keyword SHA256 hash of the file. [float] -== kernel Fields +== kernel fields The kernel metricset distributes audit events received from the Linux Audit Framework that is a part of the Linux kernel. [float] -=== audit.kernel.action +=== `audit.kernel.action` type: keyword @@ -196,82 +196,82 @@ example: logged-in A description of the action taken by the user. [float] -== actor Fields +== actor fields The actor is the user that triggered the audit event. [float] -== attrs Fields +== attrs fields Attributes of the actor. [float] -=== audit.kernel.actor.attrs.auid +=== `audit.kernel.actor.attrs.auid` type: keyword login user ID [float] -=== audit.kernel.actor.attrs.uid +=== `audit.kernel.actor.attrs.uid` type: keyword user ID [float] -=== audit.kernel.actor.attrs.euid +=== `audit.kernel.actor.attrs.euid` type: keyword effective user ID [float] -=== audit.kernel.actor.attrs.fsuid +=== `audit.kernel.actor.attrs.fsuid` type: keyword file system user ID [float] -=== audit.kernel.actor.attrs.suid +=== `audit.kernel.actor.attrs.suid` type: keyword sent user ID [float] -=== audit.kernel.actor.attrs.gid +=== `audit.kernel.actor.attrs.gid` type: keyword group ID [float] -=== audit.kernel.actor.attrs.egid +=== `audit.kernel.actor.attrs.egid` type: keyword effective group ID [float] -=== audit.kernel.actor.attrs.sgid +=== `audit.kernel.actor.attrs.sgid` type: keyword set group ID [float] -=== audit.kernel.actor.attrs.fsgid +=== `audit.kernel.actor.attrs.fsgid` type: keyword file system group ID [float] -=== audit.kernel.actor.primary +=== `audit.kernel.actor.primary` type: keyword @@ -279,41 +279,41 @@ The primary identity of the actor. This is the actor's original login ID. It wil [float] -=== audit.kernel.actor.secondary +=== `audit.kernel.actor.secondary` type: keyword The secondary identity of the actor. This is typically the same as the primary, except for when the user has used `su`. [float] -== selinux Fields +== selinux fields The SELinux identity of the actor. [float] -=== audit.kernel.actor.selinux.user +=== `audit.kernel.actor.selinux.user` type: keyword account submitted for authentication [float] -=== audit.kernel.actor.selinux.role +=== `audit.kernel.actor.selinux.role` type: keyword user's SELinux role [float] -=== audit.kernel.actor.selinux.domain +=== `audit.kernel.actor.selinux.domain` type: keyword The actor's SELinux domain or type. [float] -=== audit.kernel.actor.selinux.level +=== `audit.kernel.actor.selinux.level` type: keyword @@ -322,14 +322,14 @@ example: s0 The actor's SELinux level. [float] -=== audit.kernel.actor.selinux.category +=== `audit.kernel.actor.selinux.category` type: keyword The actor's SELinux category or compartments. [float] -=== audit.kernel.category +=== `audit.kernel.category` type: keyword @@ -339,7 +339,7 @@ The event's category is a value derived from the `record_type`. [float] -=== audit.kernel.sequence +=== `audit.kernel.sequence` type: long @@ -347,7 +347,7 @@ The sequence number of the event as assigned by the kernel. Sequence numbers are [float] -=== audit.kernel.session +=== `audit.kernel.session` type: keyword @@ -355,145 +355,145 @@ The session ID assigned to a login. All events related to a login session will h [float] -== paths Fields +== paths fields List of paths associated with the event. [float] -=== audit.kernel.paths.inode +=== `audit.kernel.paths.inode` type: keyword inode number [float] -=== audit.kernel.paths.dev +=== `audit.kernel.paths.dev` type: keyword device name as found in /dev [float] -=== audit.kernel.paths.obj_user +=== `audit.kernel.paths.obj_user` type: keyword [float] -=== audit.kernel.paths.obj_role +=== `audit.kernel.paths.obj_role` type: keyword [float] -=== audit.kernel.paths.obj_domain +=== `audit.kernel.paths.obj_domain` type: keyword [float] -=== audit.kernel.paths.obj_level +=== `audit.kernel.paths.obj_level` type: keyword [float] -=== audit.kernel.paths.objtype +=== `audit.kernel.paths.objtype` type: keyword [float] -=== audit.kernel.paths.ouid +=== `audit.kernel.paths.ouid` type: keyword file owner user ID [float] -=== audit.kernel.paths.rdev +=== `audit.kernel.paths.rdev` type: keyword the device identifier (special files only) [float] -=== audit.kernel.paths.nametype +=== `audit.kernel.paths.nametype` type: keyword kind of file operation being referenced [float] -=== audit.kernel.paths.ogid +=== `audit.kernel.paths.ogid` type: keyword file owner group ID [float] -=== audit.kernel.paths.item +=== `audit.kernel.paths.item` type: keyword which item is being recorded [float] -=== audit.kernel.paths.mode +=== `audit.kernel.paths.mode` type: keyword mode flags on a file [float] -=== audit.kernel.paths.name +=== `audit.kernel.paths.name` type: keyword file name in avcs [float] -=== audit.kernel.record_type +=== `audit.kernel.record_type` type: keyword The audit record's type. [float] -== socket Fields +== socket fields Socket data from sockaddr messages. [float] -=== audit.kernel.socket.port +=== `audit.kernel.socket.port` type: keyword The port number. [float] -=== audit.kernel.socket.saddr +=== `audit.kernel.socket.saddr` type: keyword The raw socket address structure. [float] -=== audit.kernel.socket.addr +=== `audit.kernel.socket.addr` type: keyword The remote address. [float] -=== audit.kernel.socket.family +=== `audit.kernel.socket.family` type: keyword @@ -502,21 +502,21 @@ example: unix The socket family (unix, ipv4, ipv6, netlink). [float] -=== audit.kernel.socket.path +=== `audit.kernel.socket.path` type: keyword This is the path associated with a unix socket. [float] -== thing Fields +== thing fields This is the thing or object being acted upon in the event. [float] -=== audit.kernel.thing.what +=== `audit.kernel.thing.what` type: keyword @@ -524,48 +524,48 @@ A description of the what the "thing" is (e.g. file, socket, user-session). [float] -=== audit.kernel.thing.primary +=== `audit.kernel.thing.primary` type: keyword [float] -=== audit.kernel.thing.secondary +=== `audit.kernel.thing.secondary` type: keyword [float] -== selinux Fields +== selinux fields The SELinux identity of the object. [float] -=== audit.kernel.thing.selinux.user +=== `audit.kernel.thing.selinux.user` type: keyword The owner of the object. [float] -=== audit.kernel.thing.selinux.role +=== `audit.kernel.thing.selinux.role` type: keyword The object's SELinux role. [float] -=== audit.kernel.thing.selinux.domain +=== `audit.kernel.thing.selinux.domain` type: keyword The object's SELinux domain or type. [float] -=== audit.kernel.thing.selinux.level +=== `audit.kernel.thing.selinux.level` type: keyword @@ -574,7 +574,7 @@ example: s0 The object's SELinux level. [float] -=== audit.kernel.how +=== `audit.kernel.how` type: keyword @@ -582,14 +582,14 @@ This describes how the action was performed. Usually this is the exe or command [float] -=== audit.kernel.key +=== `audit.kernel.key` type: keyword The key assigned to the audit rule that triggered the event. [float] -=== audit.kernel.result +=== `audit.kernel.result` type: keyword @@ -598,1441 +598,1441 @@ example: success or fail The result of the audited operation (success/fail). [float] -== data Fields +== data fields The data from the audit messages. [float] -=== audit.kernel.data.action +=== `audit.kernel.data.action` type: keyword netfilter packet disposition [float] -=== audit.kernel.data.minor +=== `audit.kernel.data.minor` type: keyword device minor number [float] -=== audit.kernel.data.acct +=== `audit.kernel.data.acct` type: keyword a user's account name [float] -=== audit.kernel.data.addr +=== `audit.kernel.data.addr` type: keyword the remote address that the user is connecting from [float] -=== audit.kernel.data.cipher +=== `audit.kernel.data.cipher` type: keyword name of crypto cipher selected [float] -=== audit.kernel.data.id +=== `audit.kernel.data.id` type: keyword during account changes [float] -=== audit.kernel.data.entries +=== `audit.kernel.data.entries` type: keyword number of entries in the netfilter table [float] -=== audit.kernel.data.kind +=== `audit.kernel.data.kind` type: keyword server or client in crypto operation [float] -=== audit.kernel.data.ksize +=== `audit.kernel.data.ksize` type: keyword key size for crypto operation [float] -=== audit.kernel.data.spid +=== `audit.kernel.data.spid` type: keyword sent process ID [float] -=== audit.kernel.data.arch +=== `audit.kernel.data.arch` type: keyword the elf architecture flags [float] -=== audit.kernel.data.argc +=== `audit.kernel.data.argc` type: keyword the number of arguments to an execve syscall [float] -=== audit.kernel.data.major +=== `audit.kernel.data.major` type: keyword device major number [float] -=== audit.kernel.data.unit +=== `audit.kernel.data.unit` type: keyword systemd unit [float] -=== audit.kernel.data.table +=== `audit.kernel.data.table` type: keyword netfilter table name [float] -=== audit.kernel.data.terminal +=== `audit.kernel.data.terminal` type: keyword terminal name the user is running programs on [float] -=== audit.kernel.data.comm +=== `audit.kernel.data.comm` type: keyword command line program name [float] -=== audit.kernel.data.exe +=== `audit.kernel.data.exe` type: keyword executable name [float] -=== audit.kernel.data.grantors +=== `audit.kernel.data.grantors` type: keyword pam modules approving the action [float] -=== audit.kernel.data.pid +=== `audit.kernel.data.pid` type: keyword process ID [float] -=== audit.kernel.data.direction +=== `audit.kernel.data.direction` type: keyword direction of crypto operation [float] -=== audit.kernel.data.op +=== `audit.kernel.data.op` type: keyword the operation being performed that is audited [float] -=== audit.kernel.data.tty +=== `audit.kernel.data.tty` type: keyword tty udevice the user is running programs on [float] -=== audit.kernel.data.proctitle +=== `audit.kernel.data.proctitle` type: keyword process title and command line parameters [float] -=== audit.kernel.data.syscall +=== `audit.kernel.data.syscall` type: keyword syscall number in effect when the event occurred [float] -=== audit.kernel.data.data +=== `audit.kernel.data.data` type: keyword TTY text [float] -=== audit.kernel.data.family +=== `audit.kernel.data.family` type: keyword netfilter protocol [float] -=== audit.kernel.data.mac +=== `audit.kernel.data.mac` type: keyword crypto MAC algorithm selected [float] -=== audit.kernel.data.pfs +=== `audit.kernel.data.pfs` type: keyword perfect forward secrecy method [float] -=== audit.kernel.data.items +=== `audit.kernel.data.items` type: keyword the number of path records in the event [float] -=== audit.kernel.data.a0 +=== `audit.kernel.data.a0` type: keyword [float] -=== audit.kernel.data.a1 +=== `audit.kernel.data.a1` type: keyword [float] -=== audit.kernel.data.a2 +=== `audit.kernel.data.a2` type: keyword [float] -=== audit.kernel.data.a3 +=== `audit.kernel.data.a3` type: keyword [float] -=== audit.kernel.data.cwd +=== `audit.kernel.data.cwd` type: keyword the current working directory [float] -=== audit.kernel.data.hostname +=== `audit.kernel.data.hostname` type: keyword the hostname that the user is connecting from [float] -=== audit.kernel.data.lport +=== `audit.kernel.data.lport` type: keyword local network port [float] -=== audit.kernel.data.ppid +=== `audit.kernel.data.ppid` type: keyword parent process ID [float] -=== audit.kernel.data.rport +=== `audit.kernel.data.rport` type: keyword remote port number [float] -=== audit.kernel.data.cmdline +=== `audit.kernel.data.cmdline` type: keyword The full command line from the execve message. [float] -=== audit.kernel.data.exit +=== `audit.kernel.data.exit` type: keyword syscall exit code [float] -=== audit.kernel.data.fp +=== `audit.kernel.data.fp` type: keyword crypto key finger print [float] -=== audit.kernel.data.laddr +=== `audit.kernel.data.laddr` type: keyword local network address [float] -=== audit.kernel.data.sport +=== `audit.kernel.data.sport` type: keyword local port number [float] -=== audit.kernel.data.capability +=== `audit.kernel.data.capability` type: keyword posix capabilities [float] -=== audit.kernel.data.nargs +=== `audit.kernel.data.nargs` type: keyword the number of arguments to a socket call [float] -=== audit.kernel.data.new-enabled +=== `audit.kernel.data.new-enabled` type: keyword new TTY audit enabled setting [float] -=== audit.kernel.data.audit_backlog_limit +=== `audit.kernel.data.audit_backlog_limit` type: keyword audit system's backlog queue size [float] -=== audit.kernel.data.dir +=== `audit.kernel.data.dir` type: keyword directory name [float] -=== audit.kernel.data.cap_pe +=== `audit.kernel.data.cap_pe` type: keyword process effective capability map [float] -=== audit.kernel.data.model +=== `audit.kernel.data.model` type: keyword security model being used for virt [float] -=== audit.kernel.data.new_pp +=== `audit.kernel.data.new_pp` type: keyword new process permitted capability map [float] -=== audit.kernel.data.old-enabled +=== `audit.kernel.data.old-enabled` type: keyword present TTY audit enabled setting [float] -=== audit.kernel.data.oauid +=== `audit.kernel.data.oauid` type: keyword object's login user ID [float] -=== audit.kernel.data.old +=== `audit.kernel.data.old` type: keyword old value [float] -=== audit.kernel.data.banners +=== `audit.kernel.data.banners` type: keyword banners used on printed page [float] -=== audit.kernel.data.feature +=== `audit.kernel.data.feature` type: keyword kernel feature being changed [float] -=== audit.kernel.data.vm-ctx +=== `audit.kernel.data.vm-ctx` type: keyword the vm's context string [float] -=== audit.kernel.data.opid +=== `audit.kernel.data.opid` type: keyword object's process ID [float] -=== audit.kernel.data.seperms +=== `audit.kernel.data.seperms` type: keyword SELinux permissions being used [float] -=== audit.kernel.data.seresult +=== `audit.kernel.data.seresult` type: keyword SELinux AVC decision granted/denied [float] -=== audit.kernel.data.new-rng +=== `audit.kernel.data.new-rng` type: keyword device name of rng being added from a vm [float] -=== audit.kernel.data.old-net +=== `audit.kernel.data.old-net` type: keyword present MAC address assigned to vm [float] -=== audit.kernel.data.sigev_signo +=== `audit.kernel.data.sigev_signo` type: keyword signal number [float] -=== audit.kernel.data.ino +=== `audit.kernel.data.ino` type: keyword inode number [float] -=== audit.kernel.data.old_enforcing +=== `audit.kernel.data.old_enforcing` type: keyword old MAC enforcement status [float] -=== audit.kernel.data.old-vcpu +=== `audit.kernel.data.old-vcpu` type: keyword present number of CPU cores [float] -=== audit.kernel.data.range +=== `audit.kernel.data.range` type: keyword user's SE Linux range [float] -=== audit.kernel.data.res +=== `audit.kernel.data.res` type: keyword result of the audited operation(success/fail) [float] -=== audit.kernel.data.added +=== `audit.kernel.data.added` type: keyword number of new files detected [float] -=== audit.kernel.data.fam +=== `audit.kernel.data.fam` type: keyword socket address family [float] -=== audit.kernel.data.nlnk-pid +=== `audit.kernel.data.nlnk-pid` type: keyword pid of netlink packet sender [float] -=== audit.kernel.data.subj +=== `audit.kernel.data.subj` type: keyword lspp subject's context string [float] -=== audit.kernel.data.a[0-3] +=== `audit.kernel.data.a[0-3]` type: keyword the arguments to a syscall [float] -=== audit.kernel.data.cgroup +=== `audit.kernel.data.cgroup` type: keyword path to cgroup in sysfs [float] -=== audit.kernel.data.kernel +=== `audit.kernel.data.kernel` type: keyword kernel's version number [float] -=== audit.kernel.data.ocomm +=== `audit.kernel.data.ocomm` type: keyword object's command line name [float] -=== audit.kernel.data.new-net +=== `audit.kernel.data.new-net` type: keyword MAC address being assigned to vm [float] -=== audit.kernel.data.permissive +=== `audit.kernel.data.permissive` type: keyword SELinux is in permissive mode [float] -=== audit.kernel.data.class +=== `audit.kernel.data.class` type: keyword resource class assigned to vm [float] -=== audit.kernel.data.compat +=== `audit.kernel.data.compat` type: keyword is_compat_task result [float] -=== audit.kernel.data.fi +=== `audit.kernel.data.fi` type: keyword file assigned inherited capability map [float] -=== audit.kernel.data.changed +=== `audit.kernel.data.changed` type: keyword number of changed files [float] -=== audit.kernel.data.msg +=== `audit.kernel.data.msg` type: keyword the payload of the audit record [float] -=== audit.kernel.data.dport +=== `audit.kernel.data.dport` type: keyword remote port number [float] -=== audit.kernel.data.new-seuser +=== `audit.kernel.data.new-seuser` type: keyword new SELinux user [float] -=== audit.kernel.data.invalid_context +=== `audit.kernel.data.invalid_context` type: keyword SELinux context [float] -=== audit.kernel.data.dmac +=== `audit.kernel.data.dmac` type: keyword remote MAC address [float] -=== audit.kernel.data.ipx-net +=== `audit.kernel.data.ipx-net` type: keyword IPX network number [float] -=== audit.kernel.data.iuid +=== `audit.kernel.data.iuid` type: keyword ipc object's user ID [float] -=== audit.kernel.data.macproto +=== `audit.kernel.data.macproto` type: keyword ethernet packet type ID field [float] -=== audit.kernel.data.obj +=== `audit.kernel.data.obj` type: keyword lspp object context string [float] -=== audit.kernel.data.a[[:digit:]+]\[.*\] +=== `audit.kernel.data.a[[:digit:]+]\[.*\]` type: keyword the arguments to the execve syscall [float] -=== audit.kernel.data.ipid +=== `audit.kernel.data.ipid` type: keyword IP datagram fragment identifier [float] -=== audit.kernel.data.new-fs +=== `audit.kernel.data.new-fs` type: keyword file system being added to vm [float] -=== audit.kernel.data.vm-pid +=== `audit.kernel.data.vm-pid` type: keyword vm's process ID [float] -=== audit.kernel.data.cap_pi +=== `audit.kernel.data.cap_pi` type: keyword process inherited capability map [float] -=== audit.kernel.data.old-auid +=== `audit.kernel.data.old-auid` type: keyword previous auid value [float] -=== audit.kernel.data.oses +=== `audit.kernel.data.oses` type: keyword object's session ID [float] -=== audit.kernel.data.fd +=== `audit.kernel.data.fd` type: keyword file descriptor number [float] -=== audit.kernel.data.igid +=== `audit.kernel.data.igid` type: keyword ipc object's group ID [float] -=== audit.kernel.data.new-disk +=== `audit.kernel.data.new-disk` type: keyword disk being added to vm [float] -=== audit.kernel.data.parent +=== `audit.kernel.data.parent` type: keyword the inode number of the parent file [float] -=== audit.kernel.data.len +=== `audit.kernel.data.len` type: keyword length [float] -=== audit.kernel.data.oflag +=== `audit.kernel.data.oflag` type: keyword open syscall flags [float] -=== audit.kernel.data.uuid +=== `audit.kernel.data.uuid` type: keyword a UUID [float] -=== audit.kernel.data.code +=== `audit.kernel.data.code` type: keyword seccomp action code [float] -=== audit.kernel.data.nlnk-grp +=== `audit.kernel.data.nlnk-grp` type: keyword netlink group number [float] -=== audit.kernel.data.cap_fp +=== `audit.kernel.data.cap_fp` type: keyword file permitted capability map [float] -=== audit.kernel.data.new-mem +=== `audit.kernel.data.new-mem` type: keyword new amount of memory in KB [float] -=== audit.kernel.data.seperm +=== `audit.kernel.data.seperm` type: keyword SELinux permission being decided on [float] -=== audit.kernel.data.enforcing +=== `audit.kernel.data.enforcing` type: keyword new MAC enforcement status [float] -=== audit.kernel.data.new-chardev +=== `audit.kernel.data.new-chardev` type: keyword new character device being assigned to vm [float] -=== audit.kernel.data.old-rng +=== `audit.kernel.data.old-rng` type: keyword device name of rng being removed from a vm [float] -=== audit.kernel.data.outif +=== `audit.kernel.data.outif` type: keyword out interface number [float] -=== audit.kernel.data.cmd +=== `audit.kernel.data.cmd` type: keyword command being executed [float] -=== audit.kernel.data.hook +=== `audit.kernel.data.hook` type: keyword netfilter hook that packet came from [float] -=== audit.kernel.data.new-level +=== `audit.kernel.data.new-level` type: keyword new run level [float] -=== audit.kernel.data.sauid +=== `audit.kernel.data.sauid` type: keyword sent login user ID [float] -=== audit.kernel.data.sig +=== `audit.kernel.data.sig` type: keyword signal number [float] -=== audit.kernel.data.audit_backlog_wait_time +=== `audit.kernel.data.audit_backlog_wait_time` type: keyword audit system's backlog wait time [float] -=== audit.kernel.data.printer +=== `audit.kernel.data.printer` type: keyword printer name [float] -=== audit.kernel.data.old-mem +=== `audit.kernel.data.old-mem` type: keyword present amount of memory in KB [float] -=== audit.kernel.data.perm +=== `audit.kernel.data.perm` type: keyword the file permission being used [float] -=== audit.kernel.data.old_pi +=== `audit.kernel.data.old_pi` type: keyword old process inherited capability map [float] -=== audit.kernel.data.state +=== `audit.kernel.data.state` type: keyword audit daemon configuration resulting state [float] -=== audit.kernel.data.format +=== `audit.kernel.data.format` type: keyword audit log's format [float] -=== audit.kernel.data.new_gid +=== `audit.kernel.data.new_gid` type: keyword new group ID being assigned [float] -=== audit.kernel.data.tcontext +=== `audit.kernel.data.tcontext` type: keyword the target's or object's context string [float] -=== audit.kernel.data.maj +=== `audit.kernel.data.maj` type: keyword device major number [float] -=== audit.kernel.data.watch +=== `audit.kernel.data.watch` type: keyword file name in a watch record [float] -=== audit.kernel.data.device +=== `audit.kernel.data.device` type: keyword device name [float] -=== audit.kernel.data.grp +=== `audit.kernel.data.grp` type: keyword group name [float] -=== audit.kernel.data.bool +=== `audit.kernel.data.bool` type: keyword name of SELinux boolean [float] -=== audit.kernel.data.icmp_type +=== `audit.kernel.data.icmp_type` type: keyword type of icmp message [float] -=== audit.kernel.data.new_lock +=== `audit.kernel.data.new_lock` type: keyword new value of feature lock [float] -=== audit.kernel.data.old_prom +=== `audit.kernel.data.old_prom` type: keyword network promiscuity flag [float] -=== audit.kernel.data.acl +=== `audit.kernel.data.acl` type: keyword access mode of resource assigned to vm [float] -=== audit.kernel.data.ip +=== `audit.kernel.data.ip` type: keyword network address of a printer [float] -=== audit.kernel.data.new_pi +=== `audit.kernel.data.new_pi` type: keyword new process inherited capability map [float] -=== audit.kernel.data.default-context +=== `audit.kernel.data.default-context` type: keyword default MAC context [float] -=== audit.kernel.data.inode_gid +=== `audit.kernel.data.inode_gid` type: keyword group ID of the inode's owner [float] -=== audit.kernel.data.new-log_passwd +=== `audit.kernel.data.new-log_passwd` type: keyword new value for TTY password logging [float] -=== audit.kernel.data.new_pe +=== `audit.kernel.data.new_pe` type: keyword new process effective capability map [float] -=== audit.kernel.data.selected-context +=== `audit.kernel.data.selected-context` type: keyword new MAC context assigned to session [float] -=== audit.kernel.data.cap_fver +=== `audit.kernel.data.cap_fver` type: keyword file system capabilities version number [float] -=== audit.kernel.data.file +=== `audit.kernel.data.file` type: keyword file name [float] -=== audit.kernel.data.net +=== `audit.kernel.data.net` type: keyword network MAC address [float] -=== audit.kernel.data.virt +=== `audit.kernel.data.virt` type: keyword kind of virtualization being referenced [float] -=== audit.kernel.data.cap_pp +=== `audit.kernel.data.cap_pp` type: keyword process permitted capability map [float] -=== audit.kernel.data.old-range +=== `audit.kernel.data.old-range` type: keyword present SELinux range [float] -=== audit.kernel.data.resrc +=== `audit.kernel.data.resrc` type: keyword resource being assigned [float] -=== audit.kernel.data.new-range +=== `audit.kernel.data.new-range` type: keyword new SELinux range [float] -=== audit.kernel.data.obj_gid +=== `audit.kernel.data.obj_gid` type: keyword group ID of object [float] -=== audit.kernel.data.proto +=== `audit.kernel.data.proto` type: keyword network protocol [float] -=== audit.kernel.data.old-disk +=== `audit.kernel.data.old-disk` type: keyword disk being removed from vm [float] -=== audit.kernel.data.audit_failure +=== `audit.kernel.data.audit_failure` type: keyword audit system's failure mode [float] -=== audit.kernel.data.inif +=== `audit.kernel.data.inif` type: keyword in interface number [float] -=== audit.kernel.data.vm +=== `audit.kernel.data.vm` type: keyword virtual machine name [float] -=== audit.kernel.data.flags +=== `audit.kernel.data.flags` type: keyword mmap syscall flags [float] -=== audit.kernel.data.nlnk-fam +=== `audit.kernel.data.nlnk-fam` type: keyword netlink protocol number [float] -=== audit.kernel.data.old-fs +=== `audit.kernel.data.old-fs` type: keyword file system being removed from vm [float] -=== audit.kernel.data.old-ses +=== `audit.kernel.data.old-ses` type: keyword previous ses value [float] -=== audit.kernel.data.seqno +=== `audit.kernel.data.seqno` type: keyword sequence number [float] -=== audit.kernel.data.fver +=== `audit.kernel.data.fver` type: keyword file system capabilities version number [float] -=== audit.kernel.data.qbytes +=== `audit.kernel.data.qbytes` type: keyword ipc objects quantity of bytes [float] -=== audit.kernel.data.seuser +=== `audit.kernel.data.seuser` type: keyword user's SE Linux user acct [float] -=== audit.kernel.data.cap_fe +=== `audit.kernel.data.cap_fe` type: keyword file assigned effective capability map [float] -=== audit.kernel.data.new-vcpu +=== `audit.kernel.data.new-vcpu` type: keyword new number of CPU cores [float] -=== audit.kernel.data.old-level +=== `audit.kernel.data.old-level` type: keyword old run level [float] -=== audit.kernel.data.old_pp +=== `audit.kernel.data.old_pp` type: keyword old process permitted capability map [float] -=== audit.kernel.data.daddr +=== `audit.kernel.data.daddr` type: keyword remote IP address [float] -=== audit.kernel.data.old-role +=== `audit.kernel.data.old-role` type: keyword present SELinux role [float] -=== audit.kernel.data.ioctlcmd +=== `audit.kernel.data.ioctlcmd` type: keyword The request argument to the ioctl syscall [float] -=== audit.kernel.data.smac +=== `audit.kernel.data.smac` type: keyword local MAC address [float] -=== audit.kernel.data.apparmor +=== `audit.kernel.data.apparmor` type: keyword apparmor event information [float] -=== audit.kernel.data.fe +=== `audit.kernel.data.fe` type: keyword file assigned effective capability map [float] -=== audit.kernel.data.perm_mask +=== `audit.kernel.data.perm_mask` type: keyword file permission mask that triggered a watch event [float] -=== audit.kernel.data.ses +=== `audit.kernel.data.ses` type: keyword login session ID [float] -=== audit.kernel.data.cap_fi +=== `audit.kernel.data.cap_fi` type: keyword file inherited capability map [float] -=== audit.kernel.data.obj_uid +=== `audit.kernel.data.obj_uid` type: keyword user ID of object [float] -=== audit.kernel.data.reason +=== `audit.kernel.data.reason` type: keyword text string denoting a reason for the action [float] -=== audit.kernel.data.list +=== `audit.kernel.data.list` type: keyword the audit system's filter list number [float] -=== audit.kernel.data.old_lock +=== `audit.kernel.data.old_lock` type: keyword present value of feature lock [float] -=== audit.kernel.data.bus +=== `audit.kernel.data.bus` type: keyword name of subsystem bus a vm resource belongs to [float] -=== audit.kernel.data.old_pe +=== `audit.kernel.data.old_pe` type: keyword old process effective capability map [float] -=== audit.kernel.data.new-role +=== `audit.kernel.data.new-role` type: keyword new SELinux role [float] -=== audit.kernel.data.prom +=== `audit.kernel.data.prom` type: keyword network promiscuity flag [float] -=== audit.kernel.data.uri +=== `audit.kernel.data.uri` type: keyword URI pointing to a printer [float] -=== audit.kernel.data.audit_enabled +=== `audit.kernel.data.audit_enabled` type: keyword audit systems's enable/disable status [float] -=== audit.kernel.data.old-log_passwd +=== `audit.kernel.data.old-log_passwd` type: keyword present value for TTY password logging [float] -=== audit.kernel.data.old-seuser +=== `audit.kernel.data.old-seuser` type: keyword present SELinux user [float] -=== audit.kernel.data.per +=== `audit.kernel.data.per` type: keyword linux personality [float] -=== audit.kernel.data.scontext +=== `audit.kernel.data.scontext` type: keyword the subject's context string [float] -=== audit.kernel.data.tclass +=== `audit.kernel.data.tclass` type: keyword target's object classification [float] -=== audit.kernel.data.ver +=== `audit.kernel.data.ver` type: keyword audit daemon's version number [float] -=== audit.kernel.data.new +=== `audit.kernel.data.new` type: keyword value being set in feature [float] -=== audit.kernel.data.val +=== `audit.kernel.data.val` type: keyword generic value associated with the operation [float] -=== audit.kernel.data.img-ctx +=== `audit.kernel.data.img-ctx` type: keyword the vm's disk image context string [float] -=== audit.kernel.data.old-chardev +=== `audit.kernel.data.old-chardev` type: keyword present character device assigned to vm [float] -=== audit.kernel.data.old_val +=== `audit.kernel.data.old_val` type: keyword current value of SELinux boolean [float] -=== audit.kernel.data.success +=== `audit.kernel.data.success` type: keyword whether the syscall was successful or not [float] -=== audit.kernel.data.inode_uid +=== `audit.kernel.data.inode_uid` type: keyword user ID of the inode's owner [float] -=== audit.kernel.data.removed +=== `audit.kernel.data.removed` type: keyword number of deleted files [float] -=== audit.kernel.messages +=== `audit.kernel.messages` type: text @@ -2040,7 +2040,7 @@ An ordered list of the raw messages received from the kernel that were used to c [float] -=== audit.kernel.warnings +=== `audit.kernel.warnings` type: keyword @@ -2048,14 +2048,14 @@ The warnings generated by the Beat during the construction of the event. These a [float] -== geoip Fields +== geoip fields Contains GeoIP information gathered based on the `os_events.audit.addr` field. Only present if the GeoIP Elasticsearch plugin is available and used. [float] -=== audit.kernel.geoip.continent_name +=== `audit.kernel.geoip.continent_name` type: keyword @@ -2063,7 +2063,7 @@ The name of the continent. [float] -=== audit.kernel.geoip.city_name +=== `audit.kernel.geoip.city_name` type: keyword @@ -2071,7 +2071,7 @@ The name of the city. [float] -=== audit.kernel.geoip.region_name +=== `audit.kernel.geoip.region_name` type: keyword @@ -2079,7 +2079,7 @@ The name of the region. [float] -=== audit.kernel.geoip.country_iso_code +=== `audit.kernel.geoip.country_iso_code` type: keyword @@ -2087,7 +2087,7 @@ Country ISO code. [float] -=== audit.kernel.geoip.location +=== `audit.kernel.geoip.location` type: geo_point @@ -2095,38 +2095,38 @@ The longitude and latitude. [[exported-fields-beat]] -== Beat Fields +== Beat fields Contains common beat fields available in all event types. [float] -=== beat.name +=== `beat.name` The name of the Beat sending the log messages. If the Beat name is set in the configuration file, then that value is used. If it is not set, the hostname is used. To set the Beat name, use the `name` option in the configuration file. [float] -=== beat.hostname +=== `beat.hostname` The hostname as returned by the operating system on which the Beat is running. [float] -=== beat.timezone +=== `beat.timezone` The timezone as returned by the operating system on which the Beat is running. [float] -=== beat.version +=== `beat.version` The version of the beat that generated this event. [float] -=== @timestamp +=== `@timestamp` type: date @@ -2140,13 +2140,13 @@ The timestamp when the event log record was generated. [float] -=== tags +=== `tags` Arbitrary tags that can be set per Beat and per transaction type. [float] -=== fields +=== `fields` type: object @@ -2154,14 +2154,14 @@ Contains user configurable fields. [float] -== error Fields +== error fields Error fields containing additional info in case of errors. [float] -=== error.message +=== `error.message` type: text @@ -2169,7 +2169,7 @@ Error message. [float] -=== error.code +=== `error.code` type: long @@ -2177,7 +2177,7 @@ Error code. [float] -=== error.type +=== `error.type` type: keyword @@ -2185,14 +2185,14 @@ Error type. [[exported-fields-cloud]] -== Cloud Provider Metadata Fields +== Cloud provider metadata fields Metadata from cloud providers added by the add_cloud_metadata processor. [float] -=== meta.cloud.provider +=== `meta.cloud.provider` example: ec2 @@ -2200,19 +2200,19 @@ Name of the cloud provider. Possible values are ec2, gce, or digitalocean. [float] -=== meta.cloud.instance_id +=== `meta.cloud.instance_id` Instance ID of the host machine. [float] -=== meta.cloud.instance_name +=== `meta.cloud.instance_name` Instance name of the host machine. [float] -=== meta.cloud.machine_type +=== `meta.cloud.machine_type` example: t2.medium @@ -2220,7 +2220,7 @@ Machine type of the host machine. [float] -=== meta.cloud.availability_zone +=== `meta.cloud.availability_zone` example: us-east-1c @@ -2228,7 +2228,7 @@ Availability zone in which this host is running. [float] -=== meta.cloud.project_id +=== `meta.cloud.project_id` example: project-x @@ -2236,38 +2236,38 @@ Name of the project in Google Cloud. [float] -=== meta.cloud.region +=== `meta.cloud.region` Region in which this host is running. [[exported-fields-common]] -== Common Fields +== Common fields Contains common fields available in all event types. [float] -=== metricset.module +=== `metricset.module` The name of the module that generated the event. [float] -=== metricset.name +=== `metricset.name` The name of the metricset that generated the event. [float] -=== metricset.host +=== `metricset.host` Hostname of the machine from which the metricset was collected. This field may not be present when the data was collected locally. [float] -=== metricset.rtt +=== `metricset.rtt` type: long @@ -2277,7 +2277,7 @@ Event round trip time in microseconds. [float] -=== metricset.namespace +=== `metricset.namespace` type: keyword @@ -2285,7 +2285,7 @@ Namespace of dynamic metricsets. [float] -=== type +=== `type` example: metricsets @@ -2295,7 +2295,7 @@ The document type. Always set to "metricsets". [[exported-fields-docker-processor]] -== docker Fields +== Docker fields beta[] Docker stats collected from Docker. @@ -2304,7 +2304,7 @@ Docker stats collected from Docker. [float] -=== docker.container.id +=== `docker.container.id` type: keyword @@ -2312,7 +2312,7 @@ Unique container id. [float] -=== docker.container.image +=== `docker.container.image` type: keyword @@ -2320,7 +2320,7 @@ Name of the image the container was built on. [float] -=== docker.container.name +=== `docker.container.name` type: keyword @@ -2328,7 +2328,7 @@ Container name. [float] -=== docker.container.labels +=== `docker.container.labels` type: object @@ -2336,7 +2336,7 @@ Image labels. [[exported-fields-kubernetes-processor]] -== kubernetes Fields +== Kubernetes fields beta[] Kubernetes metadata added by the kubernetes processor @@ -2345,7 +2345,7 @@ Kubernetes metadata added by the kubernetes processor [float] -=== kubernetes.pod.name +=== `kubernetes.pod.name` type: keyword @@ -2353,7 +2353,7 @@ Kubernetes pod name [float] -=== kubernetes.namespace +=== `kubernetes.namespace` type: keyword @@ -2361,7 +2361,7 @@ Kubernetes namespace [float] -=== kubernetes.labels +=== `kubernetes.labels` type: object @@ -2369,7 +2369,7 @@ Kubernetes labels map [float] -=== kubernetes.annotations +=== `kubernetes.annotations` type: object @@ -2377,7 +2377,7 @@ Kubernetes annotations map [float] -=== kubernetes.container.name +=== `kubernetes.container.name` type: keyword @@ -2385,7 +2385,7 @@ Kubernetes container name [float] -=== kubernetes.container.image +=== `kubernetes.container.image` type: keyword diff --git a/filebeat/_meta/fields.common.yml b/filebeat/_meta/fields.common.yml index 14258c62149..f153ed4062f 100644 --- a/filebeat/_meta/fields.common.yml +++ b/filebeat/_meta/fields.common.yml @@ -1,5 +1,5 @@ - key: log - title: Log File Content + title: Log file content description: > Contains log file lines. fields: diff --git a/filebeat/docs/fields.asciidoc b/filebeat/docs/fields.asciidoc index 3053e282ad6..54ef5bc482d 100644 --- a/filebeat/docs/fields.asciidoc +++ b/filebeat/docs/fields.asciidoc @@ -4,7 +4,7 @@ This file is generated! See _meta/fields.yml and scripts/generate_field_docs.py //// [[exported-fields]] -= Exported Fields += Exported fields [partintro] @@ -27,28 +27,28 @@ grouped in the following categories: -- [[exported-fields-apache2]] -== Apache2 Fields +== Apache2 fields Apache2 Module [float] -== apache2 Fields +== apache2 fields Apache2 fields. [float] -== access Fields +== access fields Contains fields for the Apache2 HTTPD access logs. [float] -=== apache2.access.remote_ip +=== `apache2.access.remote_ip` type: keyword @@ -56,7 +56,7 @@ Client IP address. [float] -=== apache2.access.user_name +=== `apache2.access.user_name` type: keyword @@ -64,7 +64,7 @@ The user name used when basic authentication is used. [float] -=== apache2.access.method +=== `apache2.access.method` type: keyword @@ -74,7 +74,7 @@ The request HTTP method. [float] -=== apache2.access.url +=== `apache2.access.url` type: keyword @@ -82,7 +82,7 @@ The request HTTP URL. [float] -=== apache2.access.http_version +=== `apache2.access.http_version` type: keyword @@ -90,7 +90,7 @@ The HTTP version. [float] -=== apache2.access.response_code +=== `apache2.access.response_code` type: long @@ -98,7 +98,7 @@ The HTTP response code. [float] -=== apache2.access.body_sent.bytes +=== `apache2.access.body_sent.bytes` type: long @@ -108,7 +108,7 @@ The number of bytes of the server response body. [float] -=== apache2.access.referrer +=== `apache2.access.referrer` type: keyword @@ -116,7 +116,7 @@ The HTTP referrer. [float] -=== apache2.access.agent +=== `apache2.access.agent` type: text @@ -124,14 +124,14 @@ Contains the un-parsed user agent string. Only present if the user agent Elastic [float] -== user_agent Fields +== user_agent fields Contains the parsed User agent field. Only present if the user agent Elasticsearch plugin is available and used. [float] -=== apache2.access.user_agent.device +=== `apache2.access.user_agent.device` type: keyword @@ -139,7 +139,7 @@ The name of the physical device. [float] -=== apache2.access.user_agent.major +=== `apache2.access.user_agent.major` type: long @@ -147,7 +147,7 @@ The major version of the user agent. [float] -=== apache2.access.user_agent.minor +=== `apache2.access.user_agent.minor` type: long @@ -155,7 +155,7 @@ The minor version of the user agent. [float] -=== apache2.access.user_agent.patch +=== `apache2.access.user_agent.patch` type: keyword @@ -163,7 +163,7 @@ The patch version of the user agent. [float] -=== apache2.access.user_agent.name +=== `apache2.access.user_agent.name` type: keyword @@ -173,7 +173,7 @@ The name of the user agent. [float] -=== apache2.access.user_agent.os +=== `apache2.access.user_agent.os` type: keyword @@ -181,7 +181,7 @@ The name of the operating system. [float] -=== apache2.access.user_agent.os_major +=== `apache2.access.user_agent.os_major` type: long @@ -189,7 +189,7 @@ The major version of the operating system. [float] -=== apache2.access.user_agent.os_minor +=== `apache2.access.user_agent.os_minor` type: long @@ -197,7 +197,7 @@ The minor version of the operating system. [float] -=== apache2.access.user_agent.os_name +=== `apache2.access.user_agent.os_name` type: keyword @@ -205,14 +205,14 @@ The name of the operating system. [float] -== geoip Fields +== geoip fields Contains GeoIP information gathered based on the remote_ip field. Only present if the GeoIP Elasticsearch plugin is available and used. [float] -=== apache2.access.geoip.continent_name +=== `apache2.access.geoip.continent_name` type: keyword @@ -220,7 +220,7 @@ The name of the continent. [float] -=== apache2.access.geoip.country_iso_code +=== `apache2.access.geoip.country_iso_code` type: keyword @@ -228,7 +228,7 @@ Country ISO code. [float] -=== apache2.access.geoip.location +=== `apache2.access.geoip.location` type: geo_point @@ -236,7 +236,7 @@ The longitude and latitude. [float] -=== apache2.access.geoip.region_name +=== `apache2.access.geoip.region_name` type: keyword @@ -244,7 +244,7 @@ The region name. [float] -=== apache2.access.geoip.city_name +=== `apache2.access.geoip.city_name` type: keyword @@ -252,14 +252,14 @@ The city name. [float] -== error Fields +== error fields Fields from the Apache error logs. [float] -=== apache2.error.level +=== `apache2.error.level` type: keyword @@ -267,7 +267,7 @@ The severity level of the message. [float] -=== apache2.error.client +=== `apache2.error.client` type: keyword @@ -275,7 +275,7 @@ The IP address of the client that generated the error. [float] -=== apache2.error.message +=== `apache2.error.message` type: text @@ -283,7 +283,7 @@ The logged message. [float] -=== apache2.error.pid +=== `apache2.error.pid` type: long @@ -291,7 +291,7 @@ The process ID. [float] -=== apache2.error.tid +=== `apache2.error.tid` type: long @@ -299,7 +299,7 @@ The thread ID. [float] -=== apache2.error.module +=== `apache2.error.module` type: keyword @@ -307,58 +307,58 @@ The module producing the logged message. [[exported-fields-auditd]] -== Auditd Fields +== Auditd fields Module for parsing auditd logs. [float] -== auditd Fields +== auditd fields Fields from the auditd logs. [float] -== log Fields +== log fields Fields from the Linux audit log. Not all fields are documented here because they are dynamic and vary by audit event type. [float] -=== auditd.log.record_type +=== `auditd.log.record_type` The audit event type. [float] -=== auditd.log.old_auid +=== `auditd.log.old_auid` For login events this is the old audit ID used for the user prior to this login. [float] -=== auditd.log.new_auid +=== `auditd.log.new_auid` For login events this is the new audit ID. The audit ID can be used to trace future events to the user even if their identity changes (like becoming root). [float] -=== auditd.log.old_ses +=== `auditd.log.old_ses` For login events this is the old session ID used for the user prior to this login. [float] -=== auditd.log.new_ses +=== `auditd.log.new_ses` For login events this is the new session ID. It can be used to tie a user to future events by session ID. [float] -=== auditd.log.sequence +=== `auditd.log.sequence` type: long @@ -366,56 +366,56 @@ The audit event sequence number. [float] -=== auditd.log.acct +=== `auditd.log.acct` The user account name associated with the event. [float] -=== auditd.log.pid +=== `auditd.log.pid` The ID of the process. [float] -=== auditd.log.ppid +=== `auditd.log.ppid` The ID of the process. [float] -=== auditd.log.items +=== `auditd.log.items` The number of items in an event. [float] -=== auditd.log.item +=== `auditd.log.item` The item field indicates which item out of the total number of items. This number is zero-based; a value of 0 means it is the first item. [float] -=== auditd.log.a0 +=== `auditd.log.a0` The first argument to the system call. [float] -=== auditd.log.res +=== `auditd.log.res` The result of the system call (success or failure). [float] -== geoip Fields +== geoip fields Contains GeoIP information gathered based on the `auditd.log.addr` field. Only present if the GeoIP Elasticsearch plugin is available and used. [float] -=== auditd.log.geoip.continent_name +=== `auditd.log.geoip.continent_name` type: keyword @@ -423,7 +423,7 @@ The name of the continent. [float] -=== auditd.log.geoip.city_name +=== `auditd.log.geoip.city_name` type: keyword @@ -431,7 +431,7 @@ The name of the city. [float] -=== auditd.log.geoip.region_name +=== `auditd.log.geoip.region_name` type: keyword @@ -439,7 +439,7 @@ The name of the region. [float] -=== auditd.log.geoip.country_iso_code +=== `auditd.log.geoip.country_iso_code` type: keyword @@ -447,7 +447,7 @@ Country ISO code. [float] -=== auditd.log.geoip.location +=== `auditd.log.geoip.location` type: geo_point @@ -455,38 +455,38 @@ The longitude and latitude. [[exported-fields-beat]] -== Beat Fields +== Beat fields Contains common beat fields available in all event types. [float] -=== beat.name +=== `beat.name` The name of the Beat sending the log messages. If the Beat name is set in the configuration file, then that value is used. If it is not set, the hostname is used. To set the Beat name, use the `name` option in the configuration file. [float] -=== beat.hostname +=== `beat.hostname` The hostname as returned by the operating system on which the Beat is running. [float] -=== beat.timezone +=== `beat.timezone` The timezone as returned by the operating system on which the Beat is running. [float] -=== beat.version +=== `beat.version` The version of the beat that generated this event. [float] -=== @timestamp +=== `@timestamp` type: date @@ -500,13 +500,13 @@ The timestamp when the event log record was generated. [float] -=== tags +=== `tags` Arbitrary tags that can be set per Beat and per transaction type. [float] -=== fields +=== `fields` type: object @@ -514,14 +514,14 @@ Contains user configurable fields. [float] -== error Fields +== error fields Error fields containing additional info in case of errors. [float] -=== error.message +=== `error.message` type: text @@ -529,7 +529,7 @@ Error message. [float] -=== error.code +=== `error.code` type: long @@ -537,7 +537,7 @@ Error code. [float] -=== error.type +=== `error.type` type: keyword @@ -545,14 +545,14 @@ Error type. [[exported-fields-cloud]] -== Cloud Provider Metadata Fields +== Cloud provider metadata fields Metadata from cloud providers added by the add_cloud_metadata processor. [float] -=== meta.cloud.provider +=== `meta.cloud.provider` example: ec2 @@ -560,19 +560,19 @@ Name of the cloud provider. Possible values are ec2, gce, or digitalocean. [float] -=== meta.cloud.instance_id +=== `meta.cloud.instance_id` Instance ID of the host machine. [float] -=== meta.cloud.instance_name +=== `meta.cloud.instance_name` Instance name of the host machine. [float] -=== meta.cloud.machine_type +=== `meta.cloud.machine_type` example: t2.medium @@ -580,7 +580,7 @@ Machine type of the host machine. [float] -=== meta.cloud.availability_zone +=== `meta.cloud.availability_zone` example: us-east-1c @@ -588,7 +588,7 @@ Availability zone in which this host is running. [float] -=== meta.cloud.project_id +=== `meta.cloud.project_id` example: project-x @@ -596,13 +596,13 @@ Name of the project in Google Cloud. [float] -=== meta.cloud.region +=== `meta.cloud.region` Region in which this host is running. [[exported-fields-docker-processor]] -== docker Fields +== Docker fields beta[] Docker stats collected from Docker. @@ -611,7 +611,7 @@ Docker stats collected from Docker. [float] -=== docker.container.id +=== `docker.container.id` type: keyword @@ -619,7 +619,7 @@ Unique container id. [float] -=== docker.container.image +=== `docker.container.image` type: keyword @@ -627,7 +627,7 @@ Name of the image the container was built on. [float] -=== docker.container.name +=== `docker.container.name` type: keyword @@ -635,7 +635,7 @@ Container name. [float] -=== docker.container.labels +=== `docker.container.labels` type: object @@ -643,27 +643,27 @@ Image labels. [[exported-fields-icinga]] -== Icinga Fields +== Icinga fields Icinga Module [float] -== icinga Fields +== icinga fields [float] -== debug Fields +== debug fields Contains fields for the Icinga debug logs. [float] -=== icinga.debug.facility +=== `icinga.debug.facility` type: keyword @@ -671,7 +671,7 @@ Specifies what component of Icinga logged the message. [float] -=== icinga.debug.severity +=== `icinga.debug.severity` type: keyword @@ -679,7 +679,7 @@ Possible values are "debug", "notice", "information", "warning" or "critical". [float] -=== icinga.debug.message +=== `icinga.debug.message` type: text @@ -687,14 +687,14 @@ The logged message. [float] -== main Fields +== main fields Contains fields for the Icinga main logs. [float] -=== icinga.main.facility +=== `icinga.main.facility` type: keyword @@ -702,7 +702,7 @@ Specifies what component of Icinga logged the message. [float] -=== icinga.main.severity +=== `icinga.main.severity` type: keyword @@ -710,7 +710,7 @@ Possible values are "debug", "notice", "information", "warning" or "critical". [float] -=== icinga.main.message +=== `icinga.main.message` type: text @@ -718,14 +718,14 @@ The logged message. [float] -== startup Fields +== startup fields Contains fields for the Icinga startup logs. [float] -=== icinga.startup.facility +=== `icinga.startup.facility` type: keyword @@ -733,7 +733,7 @@ Specifies what component of Icinga logged the message. [float] -=== icinga.startup.severity +=== `icinga.startup.severity` type: keyword @@ -741,7 +741,7 @@ Possible values are "debug", "notice", "information", "warning" or "critical". [float] -=== icinga.startup.message +=== `icinga.startup.message` type: text @@ -749,7 +749,7 @@ The logged message. [[exported-fields-kubernetes-processor]] -== kubernetes Fields +== Kubernetes fields beta[] Kubernetes metadata added by the kubernetes processor @@ -758,7 +758,7 @@ Kubernetes metadata added by the kubernetes processor [float] -=== kubernetes.pod.name +=== `kubernetes.pod.name` type: keyword @@ -766,7 +766,7 @@ Kubernetes pod name [float] -=== kubernetes.namespace +=== `kubernetes.namespace` type: keyword @@ -774,7 +774,7 @@ Kubernetes namespace [float] -=== kubernetes.labels +=== `kubernetes.labels` type: object @@ -782,7 +782,7 @@ Kubernetes labels map [float] -=== kubernetes.annotations +=== `kubernetes.annotations` type: object @@ -790,7 +790,7 @@ Kubernetes annotations map [float] -=== kubernetes.container.name +=== `kubernetes.container.name` type: keyword @@ -798,7 +798,7 @@ Kubernetes container name [float] -=== kubernetes.container.image +=== `kubernetes.container.image` type: keyword @@ -806,14 +806,14 @@ Kubernetes container image [[exported-fields-log]] -== Log File Content Fields +== Log file content fields Contains log file lines. [float] -=== source +=== `source` type: keyword @@ -823,7 +823,7 @@ The file from which the line was read. This field contains the absolute path to [float] -=== offset +=== `offset` type: long @@ -833,7 +833,7 @@ The file offset the reported line starts at. [float] -=== message +=== `message` type: text @@ -843,7 +843,7 @@ The content of the line read from the log file. [float] -=== prospector.type +=== `prospector.type` required: True @@ -851,52 +851,52 @@ The prospector type from which the event was generated. This field is set to the [float] -=== read_timestamp +=== `read_timestamp` In case the ingest pipeline parses the timestamp from the log contents, it stores the original `@timestamp` (representing the time when the log line was read) in this field. [float] -=== fileset.module +=== `fileset.module` The Filebeat module that generated this event. [float] -=== fileset.name +=== `fileset.name` The Filebeat fileset that generated this event. [[exported-fields-mysql]] -== MySQL Fields +== MySQL fields Module for parsing the MySQL log files. [float] -== mysql Fields +== mysql fields Fields from the MySQL log files. [float] -== error Fields +== error fields Contains fields from the MySQL error logs. [float] -=== mysql.error.timestamp +=== `mysql.error.timestamp` The timestamp from the log line. [float] -=== mysql.error.thread_id +=== `mysql.error.thread_id` type: long @@ -904,14 +904,14 @@ As of MySQL 5.7.2, this is the thread id. For MySQL versions prior to 5.7.2, thi [float] -=== mysql.error.level +=== `mysql.error.level` example: Warning The log level. [float] -=== mysql.error.message +=== `mysql.error.message` type: text @@ -919,32 +919,32 @@ The logged message. [float] -== slowlog Fields +== slowlog fields Contains fields from the MySQL slow logs. [float] -=== mysql.slowlog.user +=== `mysql.slowlog.user` The MySQL user that created the query. [float] -=== mysql.slowlog.host +=== `mysql.slowlog.host` The host from where the user that created the query logged in. [float] -=== mysql.slowlog.ip +=== `mysql.slowlog.ip` The IP address from where the user that created the query logged in. [float] -=== mysql.slowlog.query_time.sec +=== `mysql.slowlog.query_time.sec` type: float @@ -952,7 +952,7 @@ The total time the query took, in seconds, as a floating point number. [float] -=== mysql.slowlog.lock_time.sec +=== `mysql.slowlog.lock_time.sec` type: float @@ -960,7 +960,7 @@ The amount of time the query waited for the lock to be available. The value is i [float] -=== mysql.slowlog.rows_sent +=== `mysql.slowlog.rows_sent` type: long @@ -968,7 +968,7 @@ The number of rows returned by the query. [float] -=== mysql.slowlog.rows_examined +=== `mysql.slowlog.rows_examined` type: long @@ -976,7 +976,7 @@ The number of rows scanned by the query. [float] -=== mysql.slowlog.timestamp +=== `mysql.slowlog.timestamp` type: long @@ -984,13 +984,13 @@ The unix timestamp taken from the `SET timestamp` query. [float] -=== mysql.slowlog.query +=== `mysql.slowlog.query` The slow query. [float] -=== mysql.slowlog.id +=== `mysql.slowlog.id` type: long @@ -998,28 +998,28 @@ The connection ID for the query. [[exported-fields-nginx]] -== Nginx Fields +== Nginx fields Module for parsing the Nginx log files. [float] -== nginx Fields +== nginx fields Fields from the Nginx log files. [float] -== access Fields +== access fields Contains fields for the Nginx access logs. [float] -=== nginx.access.remote_ip_list +=== `nginx.access.remote_ip_list` type: array @@ -1027,7 +1027,7 @@ An array of remote IP addresses. It is a list because it is common to include, b [float] -=== nginx.access.remote_ip +=== `nginx.access.remote_ip` type: keyword @@ -1035,7 +1035,7 @@ Client IP address. The first public IP address from the `remote_ip_list` array. [float] -=== nginx.access.user_name +=== `nginx.access.user_name` type: keyword @@ -1043,7 +1043,7 @@ The user name used when basic authentication is used. [float] -=== nginx.access.method +=== `nginx.access.method` type: keyword @@ -1053,7 +1053,7 @@ The request HTTP method. [float] -=== nginx.access.url +=== `nginx.access.url` type: keyword @@ -1061,7 +1061,7 @@ The request HTTP URL. [float] -=== nginx.access.http_version +=== `nginx.access.http_version` type: keyword @@ -1069,7 +1069,7 @@ The HTTP version. [float] -=== nginx.access.response_code +=== `nginx.access.response_code` type: long @@ -1077,7 +1077,7 @@ The HTTP response code. [float] -=== nginx.access.body_sent.bytes +=== `nginx.access.body_sent.bytes` type: long @@ -1087,7 +1087,7 @@ The number of bytes of the server response body. [float] -=== nginx.access.referrer +=== `nginx.access.referrer` type: keyword @@ -1095,7 +1095,7 @@ The HTTP referrer. [float] -=== nginx.access.agent +=== `nginx.access.agent` type: text @@ -1103,14 +1103,14 @@ Contains the un-parsed user agent string. Only present if the user agent Elastic [float] -== user_agent Fields +== user_agent fields Contains the parsed User agent field. Only present if the user agent Elasticsearch plugin is available and used. [float] -=== nginx.access.user_agent.device +=== `nginx.access.user_agent.device` type: keyword @@ -1118,7 +1118,7 @@ The name of the physical device. [float] -=== nginx.access.user_agent.major +=== `nginx.access.user_agent.major` type: long @@ -1126,7 +1126,7 @@ The major version of the user agent. [float] -=== nginx.access.user_agent.minor +=== `nginx.access.user_agent.minor` type: long @@ -1134,7 +1134,7 @@ The minor version of the user agent. [float] -=== nginx.access.user_agent.patch +=== `nginx.access.user_agent.patch` type: keyword @@ -1142,7 +1142,7 @@ The patch version of the user agent. [float] -=== nginx.access.user_agent.name +=== `nginx.access.user_agent.name` type: keyword @@ -1152,7 +1152,7 @@ The name of the user agent. [float] -=== nginx.access.user_agent.os +=== `nginx.access.user_agent.os` type: keyword @@ -1160,7 +1160,7 @@ The name of the operating system. [float] -=== nginx.access.user_agent.os_major +=== `nginx.access.user_agent.os_major` type: long @@ -1168,7 +1168,7 @@ The major version of the operating system. [float] -=== nginx.access.user_agent.os_minor +=== `nginx.access.user_agent.os_minor` type: long @@ -1176,7 +1176,7 @@ The minor version of the operating system. [float] -=== nginx.access.user_agent.os_name +=== `nginx.access.user_agent.os_name` type: keyword @@ -1184,14 +1184,14 @@ The name of the operating system. [float] -== geoip Fields +== geoip fields Contains GeoIP information gathered based on the remote_ip field. Only present if the GeoIP Elasticsearch plugin is available and used. [float] -=== nginx.access.geoip.continent_name +=== `nginx.access.geoip.continent_name` type: keyword @@ -1199,7 +1199,7 @@ The name of the continent. [float] -=== nginx.access.geoip.country_iso_code +=== `nginx.access.geoip.country_iso_code` type: keyword @@ -1207,7 +1207,7 @@ Country ISO code. [float] -=== nginx.access.geoip.location +=== `nginx.access.geoip.location` type: geo_point @@ -1215,7 +1215,7 @@ The longitude and latitude. [float] -=== nginx.access.geoip.region_name +=== `nginx.access.geoip.region_name` type: keyword @@ -1223,7 +1223,7 @@ The region name. [float] -=== nginx.access.geoip.city_name +=== `nginx.access.geoip.city_name` type: keyword @@ -1231,14 +1231,14 @@ The city name. [float] -== error Fields +== error fields Contains fields for the Nginx error logs. [float] -=== nginx.error.level +=== `nginx.error.level` type: keyword @@ -1246,7 +1246,7 @@ Error level (e.g. error, critical). [float] -=== nginx.error.pid +=== `nginx.error.pid` type: long @@ -1254,7 +1254,7 @@ Process identifier (PID). [float] -=== nginx.error.tid +=== `nginx.error.tid` type: long @@ -1262,7 +1262,7 @@ Thread identifier. [float] -=== nginx.error.connection_id +=== `nginx.error.connection_id` type: long @@ -1270,7 +1270,7 @@ Connection identifier. [float] -=== nginx.error.message +=== `nginx.error.message` type: text @@ -1278,27 +1278,27 @@ The error message [[exported-fields-redis]] -== Redis Fields +== Redis fields Redis Module [float] -== redis Fields +== redis fields [float] -== log Fields +== log fields Redis log files [float] -=== redis.log.pid +=== `redis.log.pid` type: long @@ -1306,7 +1306,7 @@ The process ID of the Redis server. [float] -=== redis.log.role +=== `redis.log.role` type: keyword @@ -1314,7 +1314,7 @@ The role of the Redis instance. Can be one of `master`, `slave`, `child` (for RD [float] -=== redis.log.level +=== `redis.log.level` type: keyword @@ -1322,7 +1322,7 @@ The log level. Can be one of `debug`, `verbose`, `notice`, or `warning`. [float] -=== redis.log.message +=== `redis.log.message` type: text @@ -1330,14 +1330,14 @@ The log message [float] -== slowlog Fields +== slowlog fields Slow logs are retrieved from Redis via a network connection. [float] -=== redis.slowlog.cmd +=== `redis.slowlog.cmd` type: keyword @@ -1345,7 +1345,7 @@ The command executed. [float] -=== redis.slowlog.duration.us +=== `redis.slowlog.duration.us` type: long @@ -1353,7 +1353,7 @@ How long it took to execute the command in microseconds. [float] -=== redis.slowlog.id +=== `redis.slowlog.id` type: long @@ -1361,7 +1361,7 @@ The ID of the query. [float] -=== redis.slowlog.key +=== `redis.slowlog.key` type: keyword @@ -1369,7 +1369,7 @@ The key on which the command was executed. [float] -=== redis.slowlog.args +=== `redis.slowlog.args` type: keyword @@ -1377,46 +1377,46 @@ The arguments with which the command was called. [[exported-fields-system]] -== System Fields +== System fields Module for parsing system log files. [float] -== system Fields +== system fields Fields from the system log files. [float] -== auth Fields +== auth fields Fields from the Linux authorization logs. [float] -=== system.auth.timestamp +=== `system.auth.timestamp` The timestamp as read from the auth message. [float] -=== system.auth.hostname +=== `system.auth.hostname` The hostname as read from the auth message. [float] -=== system.auth.program +=== `system.auth.program` The process name as read from the auth message. [float] -=== system.auth.pid +=== `system.auth.pid` type: long @@ -1424,38 +1424,38 @@ The PID of the process that sent the auth message. [float] -=== system.auth.message +=== `system.auth.message` The message in the log line. [float] -=== system.auth.user +=== `system.auth.user` The Unix user that this event refers to. [float] -== ssh Fields +== ssh fields Fields specific to SSH login events. [float] -=== system.auth.ssh.event +=== `system.auth.ssh.event` The SSH login event. Can be one of "Accepted", "Failed", or "Invalid". "Accepted" means a successful login. "Invalid" means that the user is not configured on the system. "Failed" means that the SSH login attempt has failed. [float] -=== system.auth.ssh.method +=== `system.auth.ssh.method` The SSH authentication method. Can be one of "password" or "publickey". [float] -=== system.auth.ssh.ip +=== `system.auth.ssh.ip` type: ip @@ -1463,7 +1463,7 @@ The client IP from where the login attempt was made. [float] -=== system.auth.ssh.dropped_ip +=== `system.auth.ssh.dropped_ip` type: ip @@ -1471,7 +1471,7 @@ The client IP from SSH connections that are open and immediately dropped. [float] -=== system.auth.ssh.port +=== `system.auth.ssh.port` type: long @@ -1479,20 +1479,20 @@ The client port from where the login attempt was made. [float] -=== system.auth.ssh.signature +=== `system.auth.ssh.signature` The signature of the client public key. [float] -== geoip Fields +== geoip fields Contains GeoIP information gathered based on the `system.auth.ip` field. Only present if the GeoIP Elasticsearch plugin is available and used. [float] -=== system.auth.ssh.geoip.continent_name +=== `system.auth.ssh.geoip.continent_name` type: keyword @@ -1500,7 +1500,7 @@ The name of the continent. [float] -=== system.auth.ssh.geoip.city_name +=== `system.auth.ssh.geoip.city_name` type: keyword @@ -1508,7 +1508,7 @@ The name of the city. [float] -=== system.auth.ssh.geoip.region_name +=== `system.auth.ssh.geoip.region_name` type: keyword @@ -1516,7 +1516,7 @@ The name of the region. [float] -=== system.auth.ssh.geoip.country_iso_code +=== `system.auth.ssh.geoip.country_iso_code` type: keyword @@ -1524,7 +1524,7 @@ Country ISO code. [float] -=== system.auth.ssh.geoip.location +=== `system.auth.ssh.geoip.location` type: geo_point @@ -1532,14 +1532,14 @@ The longitude and latitude. [float] -== sudo Fields +== sudo fields Fields specific to events created by the `sudo` command. [float] -=== system.auth.sudo.error +=== `system.auth.sudo.error` example: user NOT in sudoers @@ -1547,19 +1547,19 @@ The error message in case the sudo command failed. [float] -=== system.auth.sudo.tty +=== `system.auth.sudo.tty` The TTY where the sudo command is executed. [float] -=== system.auth.sudo.pwd +=== `system.auth.sudo.pwd` The current directory where the sudo command is executed. [float] -=== system.auth.sudo.user +=== `system.auth.sudo.user` example: root @@ -1567,63 +1567,63 @@ The target user to which the sudo command is switching. [float] -=== system.auth.sudo.command +=== `system.auth.sudo.command` The command executed via sudo. [float] -== useradd Fields +== useradd fields Fields specific to events created by the `useradd` command. [float] -=== system.auth.useradd.name +=== `system.auth.useradd.name` The user name being added. [float] -=== system.auth.useradd.uid +=== `system.auth.useradd.uid` type: long The user ID. [float] -=== system.auth.useradd.gid +=== `system.auth.useradd.gid` type: long The group ID. [float] -=== system.auth.useradd.home +=== `system.auth.useradd.home` The home folder for the new user. [float] -=== system.auth.useradd.shell +=== `system.auth.useradd.shell` The default shell for the new user. [float] -== groupadd Fields +== groupadd fields Fields specific to events created by the `groupadd` command. [float] -=== system.auth.groupadd.name +=== `system.auth.groupadd.name` The name of the new group. [float] -=== system.auth.groupadd.gid +=== `system.auth.groupadd.gid` type: long @@ -1631,38 +1631,38 @@ The ID of the new group. [float] -== syslog Fields +== syslog fields Contains fields from the syslog system logs. [float] -=== system.syslog.timestamp +=== `system.syslog.timestamp` The timestamp as read from the syslog message. [float] -=== system.syslog.hostname +=== `system.syslog.hostname` The hostname as read from the syslog message. [float] -=== system.syslog.program +=== `system.syslog.program` The process name as read from the syslog message. [float] -=== system.syslog.pid +=== `system.syslog.pid` The PID of the process that sent the syslog message. [float] -=== system.syslog.message +=== `system.syslog.message` The message in the log line. diff --git a/heartbeat/_meta/fields.common.yml b/heartbeat/_meta/fields.common.yml index c44d387158d..c4d38695b08 100644 --- a/heartbeat/_meta/fields.common.yml +++ b/heartbeat/_meta/fields.common.yml @@ -1,5 +1,5 @@ - key: common - title: "Common Heartbeat Monitor" + title: "Common heartbeat monitor" description: fields: - name: monitor @@ -55,7 +55,7 @@ Indicator if monitor could validate the service to be available. - key: resolve - title: "Host Lookup" + title: "Host lookup" description: fields: - name: resolve diff --git a/heartbeat/docs/fields.asciidoc b/heartbeat/docs/fields.asciidoc index e948ad3745d..5ac4d01ccb8 100644 --- a/heartbeat/docs/fields.asciidoc +++ b/heartbeat/docs/fields.asciidoc @@ -4,7 +4,7 @@ This file is generated! See _meta/fields.yml and scripts/generate_field_docs.py //// [[exported-fields]] -= Exported Fields += Exported fields [partintro] @@ -26,38 +26,38 @@ grouped in the following categories: -- [[exported-fields-beat]] -== Beat Fields +== Beat fields Contains common beat fields available in all event types. [float] -=== beat.name +=== `beat.name` The name of the Beat sending the log messages. If the Beat name is set in the configuration file, then that value is used. If it is not set, the hostname is used. To set the Beat name, use the `name` option in the configuration file. [float] -=== beat.hostname +=== `beat.hostname` The hostname as returned by the operating system on which the Beat is running. [float] -=== beat.timezone +=== `beat.timezone` The timezone as returned by the operating system on which the Beat is running. [float] -=== beat.version +=== `beat.version` The version of the beat that generated this event. [float] -=== @timestamp +=== `@timestamp` type: date @@ -71,13 +71,13 @@ The timestamp when the event log record was generated. [float] -=== tags +=== `tags` Arbitrary tags that can be set per Beat and per transaction type. [float] -=== fields +=== `fields` type: object @@ -85,14 +85,14 @@ Contains user configurable fields. [float] -== error Fields +== error fields Error fields containing additional info in case of errors. [float] -=== error.message +=== `error.message` type: text @@ -100,7 +100,7 @@ Error message. [float] -=== error.code +=== `error.code` type: long @@ -108,7 +108,7 @@ Error code. [float] -=== error.type +=== `error.type` type: keyword @@ -116,14 +116,14 @@ Error type. [[exported-fields-cloud]] -== Cloud Provider Metadata Fields +== Cloud provider metadata fields Metadata from cloud providers added by the add_cloud_metadata processor. [float] -=== meta.cloud.provider +=== `meta.cloud.provider` example: ec2 @@ -131,19 +131,19 @@ Name of the cloud provider. Possible values are ec2, gce, or digitalocean. [float] -=== meta.cloud.instance_id +=== `meta.cloud.instance_id` Instance ID of the host machine. [float] -=== meta.cloud.instance_name +=== `meta.cloud.instance_name` Instance name of the host machine. [float] -=== meta.cloud.machine_type +=== `meta.cloud.machine_type` example: t2.medium @@ -151,7 +151,7 @@ Machine type of the host machine. [float] -=== meta.cloud.availability_zone +=== `meta.cloud.availability_zone` example: us-east-1c @@ -159,7 +159,7 @@ Availability zone in which this host is running. [float] -=== meta.cloud.project_id +=== `meta.cloud.project_id` example: project-x @@ -167,26 +167,26 @@ Name of the project in Google Cloud. [float] -=== meta.cloud.region +=== `meta.cloud.region` Region in which this host is running. [[exported-fields-common]] -== Common Heartbeat Monitor Fields +== Common heartbeat monitor fields None [float] -== monitor Fields +== monitor fields Common monitor fields. [float] -=== monitor.type +=== `monitor.type` type: keyword @@ -194,7 +194,7 @@ The monitor type. [float] -=== monitor.name +=== `monitor.name` type: keyword @@ -202,7 +202,7 @@ The monitors configured name [float] -=== monitor.id +=== `monitor.id` type: keyword @@ -210,20 +210,20 @@ The monitors full job ID as used by heartbeat. [float] -== duration Fields +== duration fields total monitoring test duration [float] -=== monitor.duration.us +=== `monitor.duration.us` type: long Duration in microseconds [float] -=== monitor.scheme +=== `monitor.scheme` type: keyword @@ -231,7 +231,7 @@ Address url scheme. For example `tcp`, `tls`, `http`, and `https`. [float] -=== monitor.host +=== `monitor.host` type: keyword @@ -239,7 +239,7 @@ Hostname of service being monitored. Can be missing, if service is monitored by [float] -=== monitor.ip +=== `monitor.ip` type: ip @@ -247,7 +247,7 @@ IP of service being monitored. If service is monitored by hostname, the `ip` fie [float] -=== monitor.status +=== `monitor.status` type: keyword @@ -257,7 +257,7 @@ Indicator if monitor could validate the service to be available. [[exported-fields-docker-processor]] -== docker Fields +== Docker fields beta[] Docker stats collected from Docker. @@ -266,7 +266,7 @@ Docker stats collected from Docker. [float] -=== docker.container.id +=== `docker.container.id` type: keyword @@ -274,7 +274,7 @@ Unique container id. [float] -=== docker.container.image +=== `docker.container.image` type: keyword @@ -282,7 +282,7 @@ Name of the image the container was built on. [float] -=== docker.container.name +=== `docker.container.name` type: keyword @@ -290,7 +290,7 @@ Container name. [float] -=== docker.container.labels +=== `docker.container.labels` type: object @@ -298,20 +298,20 @@ Image labels. [[exported-fields-http]] -== HTTP Monitor Fields +== HTTP monitor fields None [float] -== http Fields +== http fields HTTP related fields. [float] -=== http.url +=== `http.url` type: text @@ -319,14 +319,14 @@ Service url used by monitor. [float] -== response Fields +== response fields Service response parameters. [float] -=== http.response.status +=== `http.response.status` type: integer @@ -334,14 +334,14 @@ Response status code. [float] -== rtt Fields +== rtt fields HTTP layer round trip times. [float] -== validate Fields +== validate fields Duration between first byte of HTTP request being written and response being processed by validator. Duration based on already @@ -354,14 +354,14 @@ Note: if validator is not reading body or only a prefix, this [float] -=== http.rtt.validate.us +=== `http.rtt.validate.us` type: long Duration in microseconds [float] -== validate_body Fields +== validate_body fields Duration of validator required to read and validate the response body. @@ -373,40 +373,40 @@ Note: if validator is not reading body or only a prefix, this [float] -=== http.rtt.validate_body.us +=== `http.rtt.validate_body.us` type: long Duration in microseconds [float] -== write_request Fields +== write_request fields Duration of sending the complete HTTP request. Duration based on already available network connection. [float] -=== http.rtt.write_request.us +=== `http.rtt.write_request.us` type: long Duration in microseconds [float] -== response_header Fields +== response_header fields Time required between sending the start of sending the HTTP request and first by from HTTP response being read. Duration based on already available network connection. [float] -=== http.rtt.response_header.us +=== `http.rtt.response_header.us` type: long Duration in microseconds [float] -== total Fields +== total fields Duration required to process the HTTP transaction. Starts with the initial TCP connection attempt. Ends with after validator @@ -418,27 +418,27 @@ Note: if validator is not reading body or only a prefix, this [float] -=== http.rtt.total.us +=== `http.rtt.total.us` type: long Duration in microseconds [[exported-fields-icmp]] -== ICMP Fields +== ICMP fields None [float] -== icmp Fields +== icmp fields IP ping fields. [float] -=== icmp.requests +=== `icmp.requests` type: integer @@ -446,20 +446,20 @@ Number if ICMP EchoRequests send. [float] -== rtt Fields +== rtt fields ICMP Echo Request and Reply round trip time [float] -=== icmp.rtt.us +=== `icmp.rtt.us` type: long Duration in microseconds [[exported-fields-kubernetes-processor]] -== kubernetes Fields +== Kubernetes fields beta[] Kubernetes metadata added by the kubernetes processor @@ -468,7 +468,7 @@ Kubernetes metadata added by the kubernetes processor [float] -=== kubernetes.pod.name +=== `kubernetes.pod.name` type: keyword @@ -476,7 +476,7 @@ Kubernetes pod name [float] -=== kubernetes.namespace +=== `kubernetes.namespace` type: keyword @@ -484,7 +484,7 @@ Kubernetes namespace [float] -=== kubernetes.labels +=== `kubernetes.labels` type: object @@ -492,7 +492,7 @@ Kubernetes labels map [float] -=== kubernetes.annotations +=== `kubernetes.annotations` type: object @@ -500,7 +500,7 @@ Kubernetes annotations map [float] -=== kubernetes.container.name +=== `kubernetes.container.name` type: keyword @@ -508,7 +508,7 @@ Kubernetes container name [float] -=== kubernetes.container.image +=== `kubernetes.container.image` type: keyword @@ -516,20 +516,20 @@ Kubernetes container image [[exported-fields-resolve]] -== Host Lookup Fields +== Host lookup fields None [float] -== resolve Fields +== resolve fields Host lookup fields. [float] -=== resolve.host +=== `resolve.host` type: keyword @@ -537,7 +537,7 @@ Hostname of service being monitored. [float] -=== resolve.ip +=== `resolve.ip` type: ip @@ -545,67 +545,67 @@ IP address found for the given host. [float] -== rtt Fields +== rtt fields Duration required to resolve an IP from hostname. [float] -=== resolve.rtt.us +=== `resolve.rtt.us` type: long Duration in microseconds [[exported-fields-socks5]] -== SOCKS5 Proxy Fields +== SOCKS5 proxy fields None [float] -== socks5 Fields +== socks5 fields SOCKS5 proxy related fields: [float] -== rtt Fields +== rtt fields TLS layer round trip times. [float] -== connect Fields +== connect fields Time required to establish a connection via SOCKS5 to endpoint based on available connection to SOCKS5 proxy. [float] -=== socks5.rtt.connect.us +=== `socks5.rtt.connect.us` type: long Duration in microseconds [[exported-fields-tcp]] -== TCP Layer Fields +== TCP layer fields None [float] -== tcp Fields +== tcp fields TCP network layer related fields. [float] -=== tcp.port +=== `tcp.port` type: integer @@ -613,69 +613,69 @@ Service port number. [float] -== rtt Fields +== rtt fields TCP layer round trip times. [float] -== connect Fields +== connect fields Duration required to establish a TCP connection based on already available IP address. [float] -=== tcp.rtt.connect.us +=== `tcp.rtt.connect.us` type: long Duration in microseconds [float] -== validate Fields +== validate fields Duration of validation step based on existing TCP connection. [float] -=== tcp.rtt.validate.us +=== `tcp.rtt.validate.us` type: long Duration in microseconds [[exported-fields-tls]] -== TLS Encryption Layer Fields +== TLS encryption layer fields None [float] -== tls Fields +== tls fields TLS layer related fields. [float] -== rtt Fields +== rtt fields TLS layer round trip times. [float] -== handshake Fields +== handshake fields Time required to finish TLS handshake based on already available network connection. [float] -=== tls.rtt.handshake.us +=== `tls.rtt.handshake.us` type: long diff --git a/heartbeat/monitors/active/dialchain/_meta/fields.yml b/heartbeat/monitors/active/dialchain/_meta/fields.yml index 913a95a9c63..f0e0a869c17 100644 --- a/heartbeat/monitors/active/dialchain/_meta/fields.yml +++ b/heartbeat/monitors/active/dialchain/_meta/fields.yml @@ -1,5 +1,5 @@ - key: socks5 - title: "SOCKS5 Proxy" + title: "SOCKS5 proxy" description: fields: - name: socks5 @@ -24,7 +24,7 @@ - key: tls - title: "TLS Encryption Layer" + title: "TLS encryption layer" description: fields: - name: tls diff --git a/heartbeat/monitors/active/http/_meta/fields.yml b/heartbeat/monitors/active/http/_meta/fields.yml index 5ce12f3bd7c..c67f29e2681 100644 --- a/heartbeat/monitors/active/http/_meta/fields.yml +++ b/heartbeat/monitors/active/http/_meta/fields.yml @@ -1,5 +1,5 @@ - key: http - title: "HTTP Monitor" + title: "HTTP monitor" description: fields: - name: http diff --git a/heartbeat/monitors/active/tcp/_meta/fields.yml b/heartbeat/monitors/active/tcp/_meta/fields.yml index 5f7d03e375e..98aaa92149f 100644 --- a/heartbeat/monitors/active/tcp/_meta/fields.yml +++ b/heartbeat/monitors/active/tcp/_meta/fields.yml @@ -1,5 +1,5 @@ - key: tcp - title: "TCP Layer" + title: "TCP layer" description: fields: - name: tcp diff --git a/libbeat/processors/add_cloud_metadata/_meta/fields.yml b/libbeat/processors/add_cloud_metadata/_meta/fields.yml index 1347d04de00..5049185ead8 100644 --- a/libbeat/processors/add_cloud_metadata/_meta/fields.yml +++ b/libbeat/processors/add_cloud_metadata/_meta/fields.yml @@ -1,5 +1,5 @@ - key: cloud - title: Cloud Provider Metadata + title: Cloud provider metadata description: > Metadata from cloud providers added by the add_cloud_metadata processor. fields: diff --git a/libbeat/processors/add_docker_metadata/_meta/fields.yml b/libbeat/processors/add_docker_metadata/_meta/fields.yml index 518041a34df..d3804523678 100644 --- a/libbeat/processors/add_docker_metadata/_meta/fields.yml +++ b/libbeat/processors/add_docker_metadata/_meta/fields.yml @@ -1,5 +1,5 @@ - key: docker - title: docker + title: Docker description: > beta[] diff --git a/libbeat/processors/add_kubernetes_metadata/_meta/fields.yml b/libbeat/processors/add_kubernetes_metadata/_meta/fields.yml index c3a9113b485..9394e1a9248 100644 --- a/libbeat/processors/add_kubernetes_metadata/_meta/fields.yml +++ b/libbeat/processors/add_kubernetes_metadata/_meta/fields.yml @@ -1,5 +1,5 @@ - key: kubernetes - title: kubernetes + title: Kubernetes description: > beta[] diff --git a/libbeat/scripts/generate_fields_docs.py b/libbeat/scripts/generate_fields_docs.py index e8fef273587..8745734bd39 100644 --- a/libbeat/scripts/generate_fields_docs.py +++ b/libbeat/scripts/generate_fields_docs.py @@ -15,7 +15,7 @@ def document_fields(output, section, sections, path): output.write("[float]\n") if "description" in section: - output.write("== {} Fields\n\n".format(section["name"])) + output.write("== {} fields\n\n".format(section["name"])) output.write("{}\n\n".format(section["description"])) if "fields" not in section or not section["fields"]: @@ -40,7 +40,7 @@ def document_field(output, field, path): if "path" not in field: field["path"] = path - output.write("[float]\n=== {}\n\n".format(field["path"])) + output.write("[float]\n=== `{}`\n\n".format(field["path"])) if "type" in field: output.write("type: {}\n\n".format(field["type"])) @@ -65,7 +65,7 @@ def fields_to_asciidoc(input, output, beat): //// [[exported-fields]] -= Exported Fields += Exported fields [partintro] diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 3f984f0087c..94fc717a31a 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -4,7 +4,7 @@ This file is generated! See _meta/fields.yml and scripts/generate_field_docs.py //// [[exported-fields]] -= Exported Fields += Exported fields [partintro] @@ -48,42 +48,42 @@ grouped in the following categories: -- [[exported-fields-aerospike]] -== Aerospike Fields +== Aerospike fields -[]experimental +experimental[] Aerospike module [float] -== aerospike Fields +== aerospike fields [float] -== namespace Fields +== namespace fields namespace [float] -== client Fields +== client fields Client stats. [float] -== delete Fields +== delete fields Client delete transactions stats. [float] -=== aerospike.namespace.client.delete.error +=== `aerospike.namespace.client.delete.error` type: long @@ -91,7 +91,7 @@ Number of client delete transactions that failed with an error. [float] -=== aerospike.namespace.client.delete.not_found +=== `aerospike.namespace.client.delete.not_found` type: long @@ -99,7 +99,7 @@ Number of client delete transactions that resulted in a not found. [float] -=== aerospike.namespace.client.delete.success +=== `aerospike.namespace.client.delete.success` type: long @@ -107,7 +107,7 @@ Number of successful client delete transactions. [float] -=== aerospike.namespace.client.delete.timeout +=== `aerospike.namespace.client.delete.timeout` type: long @@ -115,14 +115,14 @@ Number of client delete transactions that timed out. [float] -== read Fields +== read fields Client read transactions stats. [float] -=== aerospike.namespace.client.read.error +=== `aerospike.namespace.client.read.error` type: long @@ -130,7 +130,7 @@ Number of client read transaction errors. [float] -=== aerospike.namespace.client.read.not_found +=== `aerospike.namespace.client.read.not_found` type: long @@ -138,7 +138,7 @@ Number of client read transaction that resulted in not found. [float] -=== aerospike.namespace.client.read.success +=== `aerospike.namespace.client.read.success` type: long @@ -146,7 +146,7 @@ Number of successful client read transactions. [float] -=== aerospike.namespace.client.read.timeout +=== `aerospike.namespace.client.read.timeout` type: long @@ -154,14 +154,14 @@ Number of client read transaction that timed out. [float] -== write Fields +== write fields Client write transactions stats. [float] -=== aerospike.namespace.client.write.error +=== `aerospike.namespace.client.write.error` type: long @@ -169,7 +169,7 @@ Number of client write transactions that failed with an error. [float] -=== aerospike.namespace.client.write.success +=== `aerospike.namespace.client.write.success` type: long @@ -177,7 +177,7 @@ Number of successful client write transactions. [float] -=== aerospike.namespace.client.write.timeout +=== `aerospike.namespace.client.write.timeout` type: long @@ -185,14 +185,14 @@ Number of client write transactions that timed out. [float] -== device Fields +== device fields Disk storage stats [float] -=== aerospike.namespace.device.available.pct +=== `aerospike.namespace.device.available.pct` type: scaled_float @@ -202,7 +202,7 @@ Measures the minimum contiguous disk space across all disks in a namespace. [float] -=== aerospike.namespace.device.free.pct +=== `aerospike.namespace.device.free.pct` type: scaled_float @@ -212,7 +212,7 @@ Percentage of disk capacity free for this namespace. [float] -=== aerospike.namespace.device.total.bytes +=== `aerospike.namespace.device.total.bytes` type: long @@ -222,7 +222,7 @@ Total bytes of disk space allocated to this namespace on this node. [float] -=== aerospike.namespace.device.used.bytes +=== `aerospike.namespace.device.used.bytes` type: long @@ -232,7 +232,7 @@ Total bytes of disk space used by this namespace on this node. [float] -=== aerospike.namespace.hwm_breached +=== `aerospike.namespace.hwm_breached` type: boolean @@ -240,14 +240,14 @@ If true, Aerospike has breached 'high-water-[disk|memory]-pct' for this namespac [float] -== memory Fields +== memory fields Memory storage stats. [float] -=== aerospike.namespace.memory.free.pct +=== `aerospike.namespace.memory.free.pct` type: scaled_float @@ -257,7 +257,7 @@ Percentage of memory capacity free for this namespace on this node. [float] -=== aerospike.namespace.memory.used.data.bytes +=== `aerospike.namespace.memory.used.data.bytes` type: long @@ -267,7 +267,7 @@ Amount of memory occupied by data for this namespace on this node. [float] -=== aerospike.namespace.memory.used.index.bytes +=== `aerospike.namespace.memory.used.index.bytes` type: long @@ -277,7 +277,7 @@ Amount of memory occupied by the index for this namespace on this node. [float] -=== aerospike.namespace.memory.used.sindex.bytes +=== `aerospike.namespace.memory.used.sindex.bytes` type: long @@ -287,7 +287,7 @@ Amount of memory occupied by secondary indexes for this namespace on this node. [float] -=== aerospike.namespace.memory.used.total.bytes +=== `aerospike.namespace.memory.used.total.bytes` type: long @@ -297,7 +297,7 @@ Total bytes of memory used by this namespace on this node. [float] -=== aerospike.namespace.name +=== `aerospike.namespace.name` type: keyword @@ -305,12 +305,12 @@ Namespace name [float] -=== aerospike.namespace.node.host +=== `aerospike.namespace.node.host` type: keyword [float] -=== aerospike.namespace.node.name +=== `aerospike.namespace.node.name` type: keyword @@ -318,14 +318,14 @@ Node name [float] -== objects Fields +== objects fields Records stats. [float] -=== aerospike.namespace.objects.master +=== `aerospike.namespace.objects.master` type: long @@ -333,7 +333,7 @@ Number of records on this node which are active masters. [float] -=== aerospike.namespace.objects.total +=== `aerospike.namespace.objects.total` type: long @@ -341,7 +341,7 @@ Number of records in this namespace for this node. [float] -=== aerospike.namespace.stop_writes +=== `aerospike.namespace.stop_writes` type: boolean @@ -349,28 +349,28 @@ If true this namespace is currently not allowing writes. [[exported-fields-apache]] -== Apache Fields +== Apache fields Apache HTTPD server metricsets collected from the Apache web server. [float] -== apache Fields +== apache fields `apache` contains the metrics that were scraped from Apache. [float] -== status Fields +== status fields `status` contains the metrics that were scraped from the Apache status page. [float] -=== apache.status.hostname +=== `apache.status.hostname` type: keyword @@ -378,7 +378,7 @@ Apache hostname. [float] -=== apache.status.total_accesses +=== `apache.status.total_accesses` type: long @@ -386,7 +386,7 @@ Total number of access requests. [float] -=== apache.status.total_kbytes +=== `apache.status.total_kbytes` type: long @@ -394,7 +394,7 @@ Total number of kilobytes served. [float] -=== apache.status.requests_per_sec +=== `apache.status.requests_per_sec` type: scaled_float @@ -402,7 +402,7 @@ Requests per second. [float] -=== apache.status.bytes_per_sec +=== `apache.status.bytes_per_sec` type: scaled_float @@ -410,7 +410,7 @@ Bytes per second. [float] -=== apache.status.bytes_per_request +=== `apache.status.bytes_per_request` type: scaled_float @@ -418,7 +418,7 @@ Bytes per request. [float] -=== apache.status.workers.busy +=== `apache.status.workers.busy` type: long @@ -426,7 +426,7 @@ Number of busy workers. [float] -=== apache.status.workers.idle +=== `apache.status.workers.idle` type: long @@ -434,14 +434,14 @@ Number of idle workers. [float] -== uptime Fields +== uptime fields Uptime stats. [float] -=== apache.status.uptime.server_uptime +=== `apache.status.uptime.server_uptime` type: long @@ -449,7 +449,7 @@ Server uptime in seconds. [float] -=== apache.status.uptime.uptime +=== `apache.status.uptime.uptime` type: long @@ -457,14 +457,14 @@ Server uptime. [float] -== cpu Fields +== cpu fields CPU stats. [float] -=== apache.status.cpu.load +=== `apache.status.cpu.load` type: scaled_float @@ -472,7 +472,7 @@ CPU Load. [float] -=== apache.status.cpu.user +=== `apache.status.cpu.user` type: scaled_float @@ -480,7 +480,7 @@ CPU user load. [float] -=== apache.status.cpu.system +=== `apache.status.cpu.system` type: scaled_float @@ -488,7 +488,7 @@ System cpu. [float] -=== apache.status.cpu.children_user +=== `apache.status.cpu.children_user` type: scaled_float @@ -496,7 +496,7 @@ CPU of children user. [float] -=== apache.status.cpu.children_system +=== `apache.status.cpu.children_system` type: scaled_float @@ -504,14 +504,14 @@ CPU of children system. [float] -== connections Fields +== connections fields Connection stats. [float] -=== apache.status.connections.total +=== `apache.status.connections.total` type: long @@ -519,7 +519,7 @@ Total connections. [float] -=== apache.status.connections.async.writing +=== `apache.status.connections.async.writing` type: long @@ -527,7 +527,7 @@ Async connection writing. [float] -=== apache.status.connections.async.keep_alive +=== `apache.status.connections.async.keep_alive` type: long @@ -535,7 +535,7 @@ Async keeped alive connections. [float] -=== apache.status.connections.async.closing +=== `apache.status.connections.async.closing` type: long @@ -543,14 +543,14 @@ Async closed connections. [float] -== load Fields +== load fields Load averages. [float] -=== apache.status.load.1 +=== `apache.status.load.1` type: scaled_float @@ -558,7 +558,7 @@ Load average for the last minute. [float] -=== apache.status.load.5 +=== `apache.status.load.5` type: scaled_float @@ -566,7 +566,7 @@ Load average for the last 5 minutes. [float] -=== apache.status.load.15 +=== `apache.status.load.15` type: scaled_float @@ -574,14 +574,14 @@ Load average for the last 15 minutes. [float] -== scoreboard Fields +== scoreboard fields Scoreboard metrics. [float] -=== apache.status.scoreboard.starting_up +=== `apache.status.scoreboard.starting_up` type: long @@ -589,7 +589,7 @@ Starting up. [float] -=== apache.status.scoreboard.reading_request +=== `apache.status.scoreboard.reading_request` type: long @@ -597,7 +597,7 @@ Reading requests. [float] -=== apache.status.scoreboard.sending_reply +=== `apache.status.scoreboard.sending_reply` type: long @@ -605,7 +605,7 @@ Sending Reply. [float] -=== apache.status.scoreboard.keepalive +=== `apache.status.scoreboard.keepalive` type: long @@ -613,7 +613,7 @@ Keep alive. [float] -=== apache.status.scoreboard.dns_lookup +=== `apache.status.scoreboard.dns_lookup` type: long @@ -621,7 +621,7 @@ Dns Lookups. [float] -=== apache.status.scoreboard.closing_connection +=== `apache.status.scoreboard.closing_connection` type: long @@ -629,7 +629,7 @@ Closing connections. [float] -=== apache.status.scoreboard.logging +=== `apache.status.scoreboard.logging` type: long @@ -637,7 +637,7 @@ Logging [float] -=== apache.status.scoreboard.gracefully_finishing +=== `apache.status.scoreboard.gracefully_finishing` type: long @@ -645,7 +645,7 @@ Gracefully finishing. [float] -=== apache.status.scoreboard.idle_cleanup +=== `apache.status.scoreboard.idle_cleanup` type: long @@ -653,7 +653,7 @@ Idle cleanups. [float] -=== apache.status.scoreboard.open_slot +=== `apache.status.scoreboard.open_slot` type: long @@ -661,7 +661,7 @@ Open slots. [float] -=== apache.status.scoreboard.waiting_for_connection +=== `apache.status.scoreboard.waiting_for_connection` type: long @@ -669,7 +669,7 @@ Waiting for connections. [float] -=== apache.status.scoreboard.total +=== `apache.status.scoreboard.total` type: long @@ -677,38 +677,38 @@ Total. [[exported-fields-beat]] -== Beat Fields +== Beat fields Contains common beat fields available in all event types. [float] -=== beat.name +=== `beat.name` The name of the Beat sending the log messages. If the Beat name is set in the configuration file, then that value is used. If it is not set, the hostname is used. To set the Beat name, use the `name` option in the configuration file. [float] -=== beat.hostname +=== `beat.hostname` The hostname as returned by the operating system on which the Beat is running. [float] -=== beat.timezone +=== `beat.timezone` The timezone as returned by the operating system on which the Beat is running. [float] -=== beat.version +=== `beat.version` The version of the beat that generated this event. [float] -=== @timestamp +=== `@timestamp` type: date @@ -722,13 +722,13 @@ The timestamp when the event log record was generated. [float] -=== tags +=== `tags` Arbitrary tags that can be set per Beat and per transaction type. [float] -=== fields +=== `fields` type: object @@ -736,14 +736,14 @@ Contains user configurable fields. [float] -== error Fields +== error fields Error fields containing additional info in case of errors. [float] -=== error.message +=== `error.message` type: text @@ -751,7 +751,7 @@ Error message. [float] -=== error.code +=== `error.code` type: long @@ -759,7 +759,7 @@ Error code. [float] -=== error.type +=== `error.type` type: keyword @@ -767,7 +767,7 @@ Error type. [[exported-fields-ceph]] -== Ceph Fields +== Ceph fields beta[] Ceph module @@ -775,21 +775,21 @@ Ceph module [float] -== ceph Fields +== ceph fields `ceph` contains the metrics that were scraped from CEPH. [float] -== cluster_disk Fields +== cluster_disk fields cluster_disk [float] -=== ceph.cluster_disk.available.bytes +=== `ceph.cluster_disk.available.bytes` type: long @@ -799,7 +799,7 @@ Available bytes of the cluster [float] -=== ceph.cluster_disk.total.bytes +=== `ceph.cluster_disk.total.bytes` type: long @@ -809,7 +809,7 @@ Total bytes of the cluster [float] -=== ceph.cluster_disk.used.bytes +=== `ceph.cluster_disk.used.bytes` type: long @@ -819,14 +819,14 @@ Used bytes of the cluster [float] -== cluster_health Fields +== cluster_health fields cluster_health [float] -=== ceph.cluster_health.overall_status +=== `ceph.cluster_health.overall_status` type: keyword @@ -834,7 +834,7 @@ Overall status of the cluster [float] -=== ceph.cluster_health.timechecks.epoch +=== `ceph.cluster_health.timechecks.epoch` type: long @@ -842,7 +842,7 @@ Map version [float] -=== ceph.cluster_health.timechecks.round.value +=== `ceph.cluster_health.timechecks.round.value` type: long @@ -850,7 +850,7 @@ timecheck round [float] -=== ceph.cluster_health.timechecks.round.status +=== `ceph.cluster_health.timechecks.round.status` type: keyword @@ -858,14 +858,14 @@ Status of the round [float] -== monitor_health Fields +== monitor_health fields monitor_health stats data [float] -=== ceph.monitor_health.available.pct +=== `ceph.monitor_health.available.pct` type: long @@ -873,7 +873,7 @@ Available percent of the MON [float] -=== ceph.monitor_health.health +=== `ceph.monitor_health.health` type: keyword @@ -881,7 +881,7 @@ Health of the MON [float] -=== ceph.monitor_health.available.kb +=== `ceph.monitor_health.available.kb` type: long @@ -889,7 +889,7 @@ Available KB of the MON [float] -=== ceph.monitor_health.total.kb +=== `ceph.monitor_health.total.kb` type: long @@ -897,7 +897,7 @@ Total KB of the MON [float] -=== ceph.monitor_health.used.kb +=== `ceph.monitor_health.used.kb` type: long @@ -905,7 +905,7 @@ Used KB of the MON [float] -=== ceph.monitor_health.last_updated +=== `ceph.monitor_health.last_updated` type: date @@ -913,7 +913,7 @@ Time when was updated [float] -=== ceph.monitor_health.name +=== `ceph.monitor_health.name` type: keyword @@ -921,7 +921,7 @@ Name of the MON [float] -=== ceph.monitor_health.store_stats.log.bytes +=== `ceph.monitor_health.store_stats.log.bytes` type: long @@ -931,7 +931,7 @@ Log bytes of MON [float] -=== ceph.monitor_health.store_stats.misc.bytes +=== `ceph.monitor_health.store_stats.misc.bytes` type: long @@ -941,7 +941,7 @@ Misc bytes of MON [float] -=== ceph.monitor_health.store_stats.sst.bytes +=== `ceph.monitor_health.store_stats.sst.bytes` type: long @@ -951,7 +951,7 @@ SST bytes of MON [float] -=== ceph.monitor_health.store_stats.total.bytes +=== `ceph.monitor_health.store_stats.total.bytes` type: long @@ -961,7 +961,7 @@ Total bytes of MON [float] -=== ceph.monitor_health.store_stats.last_updated +=== `ceph.monitor_health.store_stats.last_updated` type: long @@ -969,14 +969,14 @@ Last updated [float] -== pool_disk Fields +== pool_disk fields pool_disk [float] -=== ceph.pool_disk.id +=== `ceph.pool_disk.id` type: long @@ -984,7 +984,7 @@ Id of the pool [float] -=== ceph.pool_disk.name +=== `ceph.pool_disk.name` type: keyword @@ -992,7 +992,7 @@ Name of the pool [float] -=== ceph.pool_disk.stats.available.bytes +=== `ceph.pool_disk.stats.available.bytes` type: long @@ -1002,7 +1002,7 @@ Available bytes of the pool [float] -=== ceph.pool_disk.stats.objects +=== `ceph.pool_disk.stats.objects` type: long @@ -1010,7 +1010,7 @@ Number of objects of the pool [float] -=== ceph.pool_disk.stats.used.bytes +=== `ceph.pool_disk.stats.used.bytes` type: long @@ -1020,7 +1020,7 @@ Used bytes of the pool [float] -=== ceph.pool_disk.stats.used.kb +=== `ceph.pool_disk.stats.used.kb` type: long @@ -1028,14 +1028,14 @@ Used kb of the pool [[exported-fields-cloud]] -== Cloud Provider Metadata Fields +== Cloud provider metadata fields Metadata from cloud providers added by the add_cloud_metadata processor. [float] -=== meta.cloud.provider +=== `meta.cloud.provider` example: ec2 @@ -1043,19 +1043,19 @@ Name of the cloud provider. Possible values are ec2, gce, or digitalocean. [float] -=== meta.cloud.instance_id +=== `meta.cloud.instance_id` Instance ID of the host machine. [float] -=== meta.cloud.instance_name +=== `meta.cloud.instance_name` Instance name of the host machine. [float] -=== meta.cloud.machine_type +=== `meta.cloud.machine_type` example: t2.medium @@ -1063,7 +1063,7 @@ Machine type of the host machine. [float] -=== meta.cloud.availability_zone +=== `meta.cloud.availability_zone` example: us-east-1c @@ -1071,7 +1071,7 @@ Availability zone in which this host is running. [float] -=== meta.cloud.project_id +=== `meta.cloud.project_id` example: project-x @@ -1079,38 +1079,38 @@ Name of the project in Google Cloud. [float] -=== meta.cloud.region +=== `meta.cloud.region` Region in which this host is running. [[exported-fields-common]] -== Common Fields +== Common fields Contains common fields available in all event types. [float] -=== metricset.module +=== `metricset.module` The name of the module that generated the event. [float] -=== metricset.name +=== `metricset.name` The name of the metricset that generated the event. [float] -=== metricset.host +=== `metricset.host` Hostname of the machine from which the metricset was collected. This field may not be present when the data was collected locally. [float] -=== metricset.rtt +=== `metricset.rtt` type: long @@ -1120,7 +1120,7 @@ Event round trip time in microseconds. [float] -=== metricset.namespace +=== `metricset.namespace` type: keyword @@ -1128,7 +1128,7 @@ Namespace of dynamic metricsets. [float] -=== type +=== `type` example: metricsets @@ -1138,7 +1138,7 @@ The document type. Always set to "metricsets". [[exported-fields-couchbase]] -== Couchbase Fields +== Couchbase fields beta[] Metrics collected from Couchbase servers. @@ -1146,21 +1146,21 @@ Metrics collected from Couchbase servers. [float] -== couchbase Fields +== couchbase fields `couchbase` contains the metrics that were scraped from Couchbase. [float] -== bucket Fields +== bucket fields Couchbase bucket metrics. [float] -=== couchbase.bucket.name +=== `couchbase.bucket.name` type: keyword @@ -1168,7 +1168,7 @@ Name of the bucket. [float] -=== couchbase.bucket.type +=== `couchbase.bucket.type` type: keyword @@ -1176,7 +1176,7 @@ Type of the bucket. [float] -=== couchbase.bucket.data.used.bytes +=== `couchbase.bucket.data.used.bytes` type: long @@ -1186,7 +1186,7 @@ Size of user data within buckets of the specified state that are resident in RAM [float] -=== couchbase.bucket.disk.fetches +=== `couchbase.bucket.disk.fetches` type: long @@ -1194,7 +1194,7 @@ Number of disk fetches. [float] -=== couchbase.bucket.disk.used.bytes +=== `couchbase.bucket.disk.used.bytes` type: long @@ -1204,7 +1204,7 @@ Amount of disk used (bytes). [float] -=== couchbase.bucket.memory.used.bytes +=== `couchbase.bucket.memory.used.bytes` type: long @@ -1214,7 +1214,7 @@ Amount of memory used by the bucket (bytes). [float] -=== couchbase.bucket.quota.ram.bytes +=== `couchbase.bucket.quota.ram.bytes` type: long @@ -1224,7 +1224,7 @@ Amount of RAM used by the bucket (bytes). [float] -=== couchbase.bucket.quota.use.pct +=== `couchbase.bucket.quota.use.pct` type: scaled_float @@ -1234,7 +1234,7 @@ Percentage of RAM used (for active objects) against the configured bucket size ( [float] -=== couchbase.bucket.ops_per_sec +=== `couchbase.bucket.ops_per_sec` type: long @@ -1242,7 +1242,7 @@ Number of operations per second. [float] -=== couchbase.bucket.item_count +=== `couchbase.bucket.item_count` type: long @@ -1250,14 +1250,14 @@ Number of items associated with the bucket. [float] -== cluster Fields +== cluster fields Couchbase cluster metrics. [float] -=== couchbase.cluster.hdd.free.bytes +=== `couchbase.cluster.hdd.free.bytes` type: long @@ -1267,7 +1267,7 @@ Free hard drive space in the cluster (bytes). [float] -=== couchbase.cluster.hdd.quota.total.bytes +=== `couchbase.cluster.hdd.quota.total.bytes` type: long @@ -1277,7 +1277,7 @@ Hard drive quota total for the cluster (bytes). [float] -=== couchbase.cluster.hdd.total.bytes +=== `couchbase.cluster.hdd.total.bytes` type: long @@ -1287,7 +1287,7 @@ Total hard drive space available to the cluster (bytes). [float] -=== couchbase.cluster.hdd.used.value.bytes +=== `couchbase.cluster.hdd.used.value.bytes` type: long @@ -1297,7 +1297,7 @@ Hard drive space used by the cluster (bytes). [float] -=== couchbase.cluster.hdd.used.by_data.bytes +=== `couchbase.cluster.hdd.used.by_data.bytes` type: long @@ -1307,7 +1307,7 @@ Hard drive space used by the data in the cluster (bytes). [float] -=== couchbase.cluster.max_bucket_count +=== `couchbase.cluster.max_bucket_count` type: long @@ -1315,7 +1315,7 @@ Max bucket count setting. [float] -=== couchbase.cluster.quota.index_memory.mb +=== `couchbase.cluster.quota.index_memory.mb` type: long @@ -1323,7 +1323,7 @@ Memory quota setting for the Index service (Mbyte). [float] -=== couchbase.cluster.quota.memory.mb +=== `couchbase.cluster.quota.memory.mb` type: long @@ -1331,7 +1331,7 @@ Memory quota setting for the cluster (Mbyte). [float] -=== couchbase.cluster.ram.quota.total.value.bytes +=== `couchbase.cluster.ram.quota.total.value.bytes` type: long @@ -1341,7 +1341,7 @@ RAM quota total for the cluster (bytes). [float] -=== couchbase.cluster.ram.quota.total.per_node.bytes +=== `couchbase.cluster.ram.quota.total.per_node.bytes` type: long @@ -1351,7 +1351,7 @@ RAM quota used by the current node in the cluster (bytes). [float] -=== couchbase.cluster.ram.quota.used.value.bytes +=== `couchbase.cluster.ram.quota.used.value.bytes` type: long @@ -1361,7 +1361,7 @@ RAM quota used by the cluster (bytes). [float] -=== couchbase.cluster.ram.quota.used.per_node.bytes +=== `couchbase.cluster.ram.quota.used.per_node.bytes` type: long @@ -1371,7 +1371,7 @@ Ram quota used by the current node in the cluster (bytes) [float] -=== couchbase.cluster.ram.total.bytes +=== `couchbase.cluster.ram.total.bytes` type: long @@ -1381,7 +1381,7 @@ Total RAM available to cluster (bytes). [float] -=== couchbase.cluster.ram.used.value.bytes +=== `couchbase.cluster.ram.used.value.bytes` type: long @@ -1391,7 +1391,7 @@ RAM used by the cluster (bytes). [float] -=== couchbase.cluster.ram.used.by_data.bytes +=== `couchbase.cluster.ram.used.by_data.bytes` type: long @@ -1401,14 +1401,14 @@ RAM used by the data in the cluster (bytes). [float] -== node Fields +== node fields Couchbase node metrics. [float] -=== couchbase.node.cmd_get +=== `couchbase.node.cmd_get` type: long @@ -1416,7 +1416,7 @@ Number of get commands [float] -=== couchbase.node.couch.docs.disk_size.bytes +=== `couchbase.node.couch.docs.disk_size.bytes` type: long @@ -1426,7 +1426,7 @@ Amount of disk space used by Couch docs (bytes). [float] -=== couchbase.node.couch.docs.data_size.bytes +=== `couchbase.node.couch.docs.data_size.bytes` type: long @@ -1436,7 +1436,7 @@ Data size of Couch docs associated with a node (bytes). [float] -=== couchbase.node.couch.spatial.data_size.bytes +=== `couchbase.node.couch.spatial.data_size.bytes` type: long @@ -1444,7 +1444,7 @@ Size of object data for spatial views (bytes). [float] -=== couchbase.node.couch.spatial.disk_size.bytes +=== `couchbase.node.couch.spatial.disk_size.bytes` type: long @@ -1452,7 +1452,7 @@ Amount of disk space used by spatial views (bytes). [float] -=== couchbase.node.couch.views.disk_size.bytes +=== `couchbase.node.couch.views.disk_size.bytes` type: long @@ -1460,7 +1460,7 @@ Amount of disk space used by Couch views (bytes). [float] -=== couchbase.node.couch.views.data_size.bytes +=== `couchbase.node.couch.views.data_size.bytes` type: long @@ -1468,7 +1468,7 @@ Size of object data for Couch views (bytes). [float] -=== couchbase.node.cpu_utilization_rate.pct +=== `couchbase.node.cpu_utilization_rate.pct` type: scaled_float @@ -1476,7 +1476,7 @@ The CPU utilization rate (%). [float] -=== couchbase.node.current_items.value +=== `couchbase.node.current_items.value` type: long @@ -1484,7 +1484,7 @@ Number of current items. [float] -=== couchbase.node.current_items.total +=== `couchbase.node.current_items.total` type: long @@ -1492,7 +1492,7 @@ Total number of items associated with the node. [float] -=== couchbase.node.ep_bg_fetched +=== `couchbase.node.ep_bg_fetched` type: long @@ -1500,7 +1500,7 @@ Number of disk fetches performed since the server was started. [float] -=== couchbase.node.get_hits +=== `couchbase.node.get_hits` type: long @@ -1508,7 +1508,7 @@ Number of get hits. [float] -=== couchbase.node.hostname +=== `couchbase.node.hostname` type: keyword @@ -1516,7 +1516,7 @@ The hostname of the node. [float] -=== couchbase.node.mcd_memory.allocated.bytes +=== `couchbase.node.mcd_memory.allocated.bytes` type: long @@ -1526,7 +1526,7 @@ Amount of memcached memory allocated (bytes). [float] -=== couchbase.node.mcd_memory.reserved.bytes +=== `couchbase.node.mcd_memory.reserved.bytes` type: long @@ -1534,7 +1534,7 @@ Amount of memcached memory reserved (bytes). [float] -=== couchbase.node.memory.free.bytes +=== `couchbase.node.memory.free.bytes` type: long @@ -1542,7 +1542,7 @@ Amount of memory free for the node (bytes). [float] -=== couchbase.node.memory.total.bytes +=== `couchbase.node.memory.total.bytes` type: long @@ -1550,7 +1550,7 @@ Total memory available to the node (bytes). [float] -=== couchbase.node.memory.used.bytes +=== `couchbase.node.memory.used.bytes` type: long @@ -1558,7 +1558,7 @@ Memory used by the node (bytes). [float] -=== couchbase.node.ops +=== `couchbase.node.ops` type: long @@ -1566,7 +1566,7 @@ Number of operations performed on Couchbase. [float] -=== couchbase.node.swap.total.bytes +=== `couchbase.node.swap.total.bytes` type: long @@ -1574,7 +1574,7 @@ Total swap size allocated (bytes). [float] -=== couchbase.node.swap.used.bytes +=== `couchbase.node.swap.used.bytes` type: long @@ -1582,7 +1582,7 @@ Amount of swap space used (bytes). [float] -=== couchbase.node.uptime.sec +=== `couchbase.node.uptime.sec` type: long @@ -1590,7 +1590,7 @@ Time during which the node was in operation (sec). [float] -=== couchbase.node.vb_replica_curr_items +=== `couchbase.node.vb_replica_curr_items` type: long @@ -1598,7 +1598,7 @@ Number of items/documents that are replicas. [[exported-fields-docker-processor]] -== docker Fields +== Docker fields beta[] Docker stats collected from Docker. @@ -1607,7 +1607,7 @@ Docker stats collected from Docker. [float] -=== docker.container.id +=== `docker.container.id` type: keyword @@ -1615,7 +1615,7 @@ Unique container id. [float] -=== docker.container.image +=== `docker.container.image` type: keyword @@ -1623,7 +1623,7 @@ Name of the image the container was built on. [float] -=== docker.container.name +=== `docker.container.name` type: keyword @@ -1631,7 +1631,7 @@ Container name. [float] -=== docker.container.labels +=== `docker.container.labels` type: object @@ -1639,7 +1639,7 @@ Image labels. [[exported-fields-docker]] -== Docker Fields +== Docker fields beta[] Docker stats collected from Docker. @@ -1647,21 +1647,21 @@ Docker stats collected from Docker. [float] -== docker Fields +== docker fields Information and statistics about docker's running containers. [float] -== container Fields +== container fields Docker container metrics. [float] -=== docker.container.command +=== `docker.container.command` type: keyword @@ -1669,7 +1669,7 @@ Command that was executed in the Docker container. [float] -=== docker.container.created +=== `docker.container.created` type: date @@ -1677,7 +1677,7 @@ Date when the container was created. [float] -=== docker.container.status +=== `docker.container.status` type: keyword @@ -1685,14 +1685,14 @@ Container status. [float] -== size Fields +== size fields Container size metrics. [float] -=== docker.container.size.root_fs +=== `docker.container.size.root_fs` type: long @@ -1700,7 +1700,7 @@ Total size of all the files in the container. [float] -=== docker.container.size.rw +=== `docker.container.size.rw` type: long @@ -1708,7 +1708,7 @@ Size of the files that have been created or changed since creation. [float] -=== docker.container.tags +=== `docker.container.tags` type: array @@ -1716,14 +1716,14 @@ Image tags. [float] -== cpu Fields +== cpu fields Runtime CPU metrics. [float] -=== docker.cpu.kernel.pct +=== `docker.cpu.kernel.pct` type: scaled_float @@ -1733,7 +1733,7 @@ The system kernel consumed by the Docker server. [float] -=== docker.cpu.kernel.ticks +=== `docker.cpu.kernel.ticks` type: long @@ -1741,7 +1741,7 @@ CPU kernel ticks. [float] -=== docker.cpu.system.pct +=== `docker.cpu.system.pct` type: scaled_float @@ -1750,7 +1750,7 @@ format: percentage [float] -=== docker.cpu.system.ticks +=== `docker.cpu.system.ticks` type: long @@ -1758,7 +1758,7 @@ CPU system ticks. [float] -=== docker.cpu.user.pct +=== `docker.cpu.user.pct` type: scaled_float @@ -1767,7 +1767,7 @@ format: percentage [float] -=== docker.cpu.user.ticks +=== `docker.cpu.user.ticks` type: long @@ -1775,7 +1775,7 @@ CPU user ticks [float] -=== docker.cpu.total.pct +=== `docker.cpu.total.pct` type: scaled_float @@ -1785,14 +1785,14 @@ Total CPU usage. [float] -== diskio Fields +== diskio fields Disk I/O metrics. [float] -=== docker.diskio.reads +=== `docker.diskio.reads` type: scaled_float @@ -1800,7 +1800,7 @@ Number of reads. [float] -=== docker.diskio.writes +=== `docker.diskio.writes` type: scaled_float @@ -1808,7 +1808,7 @@ Number of writes. [float] -=== docker.diskio.total +=== `docker.diskio.total` type: scaled_float @@ -1816,14 +1816,14 @@ Number of reads and writes combined. [float] -== healthcheck Fields +== healthcheck fields Docker container metrics. [float] -=== docker.healthcheck.failingstreak +=== `docker.healthcheck.failingstreak` type: integer @@ -1831,7 +1831,7 @@ concurent failed check [float] -=== docker.healthcheck.status +=== `docker.healthcheck.status` type: keyword @@ -1839,14 +1839,14 @@ Healthcheck status code [float] -== event Fields +== event fields event fields. [float] -=== docker.healthcheck.event.end_date +=== `docker.healthcheck.event.end_date` type: date @@ -1854,7 +1854,7 @@ Healthcheck end date [float] -=== docker.healthcheck.event.start_date +=== `docker.healthcheck.event.start_date` type: date @@ -1862,7 +1862,7 @@ Healthcheck start date [float] -=== docker.healthcheck.event.output +=== `docker.healthcheck.event.output` type: keyword @@ -1870,7 +1870,7 @@ Healthcheck output [float] -=== docker.healthcheck.event.exit_code +=== `docker.healthcheck.event.exit_code` type: integer @@ -1878,21 +1878,21 @@ Healthcheck status code [float] -== image Fields +== image fields Docker image metrics. [float] -== id Fields +== id fields The image layers identifier. [float] -=== docker.image.id.current +=== `docker.image.id.current` type: keyword @@ -1900,7 +1900,7 @@ Unique image identifier given upon its creation. [float] -=== docker.image.id.parent +=== `docker.image.id.parent` type: keyword @@ -1908,7 +1908,7 @@ Identifier of the image, if it exists, from which the current image directly des [float] -=== docker.image.created +=== `docker.image.created` type: date @@ -1916,14 +1916,14 @@ Date and time when the image was created. [float] -== size Fields +== size fields Image size layers. [float] -=== docker.image.size.virtual +=== `docker.image.size.virtual` type: long @@ -1931,7 +1931,7 @@ Size of the image. [float] -=== docker.image.size.regular +=== `docker.image.size.regular` type: long @@ -1939,7 +1939,7 @@ Total size of the all cached images associated to the current image. [float] -=== docker.image.labels +=== `docker.image.labels` type: object @@ -1947,7 +1947,7 @@ Image labels. [float] -=== docker.image.tags +=== `docker.image.tags` type: array @@ -1955,7 +1955,7 @@ Image tags. [float] -== info Fields +== info fields beta[] Info metrics based on https://docs.docker.com/engine/reference/api/docker_remote_api_v1.24/#/display-system-wide-information. @@ -1963,14 +1963,14 @@ Info metrics based on https://docs.docker.com/engine/reference/api/docker_remote [float] -== containers Fields +== containers fields Overall container stats. [float] -=== docker.info.containers.paused +=== `docker.info.containers.paused` type: long @@ -1978,7 +1978,7 @@ Total number of paused containers. [float] -=== docker.info.containers.running +=== `docker.info.containers.running` type: long @@ -1986,7 +1986,7 @@ Total number of running containers. [float] -=== docker.info.containers.stopped +=== `docker.info.containers.stopped` type: long @@ -1994,7 +1994,7 @@ Total number of stopped containers. [float] -=== docker.info.containers.total +=== `docker.info.containers.total` type: long @@ -2002,7 +2002,7 @@ Total number of existing containers. [float] -=== docker.info.id +=== `docker.info.id` type: keyword @@ -2010,7 +2010,7 @@ Unique Docker host identifier. [float] -=== docker.info.images +=== `docker.info.images` type: long @@ -2018,14 +2018,14 @@ Total number of existing images. [float] -== memory Fields +== memory fields Memory metrics. [float] -=== docker.memory.fail.count +=== `docker.memory.fail.count` type: scaled_float @@ -2033,7 +2033,7 @@ Fail counter. [float] -=== docker.memory.limit +=== `docker.memory.limit` type: long @@ -2043,14 +2043,14 @@ Memory limit. [float] -== rss Fields +== rss fields RSS memory stats. [float] -=== docker.memory.rss.total +=== `docker.memory.rss.total` type: long @@ -2060,7 +2060,7 @@ Total memory resident set size. [float] -=== docker.memory.rss.pct +=== `docker.memory.rss.pct` type: scaled_float @@ -2070,14 +2070,14 @@ Memory resident set size percentage. [float] -== usage Fields +== usage fields Usage memory stats. [float] -=== docker.memory.usage.max +=== `docker.memory.usage.max` type: long @@ -2087,7 +2087,7 @@ Max memory usage. [float] -=== docker.memory.usage.pct +=== `docker.memory.usage.pct` type: scaled_float @@ -2097,7 +2097,7 @@ Memory usage percentage. [float] -=== docker.memory.usage.total +=== `docker.memory.usage.total` type: long @@ -2107,14 +2107,14 @@ Total memory usage. [float] -== network Fields +== network fields Network metrics. [float] -=== docker.network.interface +=== `docker.network.interface` type: keyword @@ -2122,14 +2122,14 @@ Network interface name. [float] -== in Fields +== in fields Incoming network stats. [float] -=== docker.network.in.bytes +=== `docker.network.in.bytes` type: long @@ -2139,7 +2139,7 @@ Total number of incoming bytes. [float] -=== docker.network.in.dropped +=== `docker.network.in.dropped` type: scaled_float @@ -2147,7 +2147,7 @@ Total number of dropped incoming packets. [float] -=== docker.network.in.errors +=== `docker.network.in.errors` type: long @@ -2155,7 +2155,7 @@ Total errors on incoming packets. [float] -=== docker.network.in.packets +=== `docker.network.in.packets` type: long @@ -2163,14 +2163,14 @@ Total number of incoming packets. [float] -== out Fields +== out fields Outgoing network stats. [float] -=== docker.network.out.bytes +=== `docker.network.out.bytes` type: long @@ -2180,7 +2180,7 @@ Total number of outgoing bytes. [float] -=== docker.network.out.dropped +=== `docker.network.out.dropped` type: scaled_float @@ -2188,7 +2188,7 @@ Total number of dropped outgoing packets. [float] -=== docker.network.out.errors +=== `docker.network.out.errors` type: long @@ -2196,7 +2196,7 @@ Total errors on outgoing packets. [float] -=== docker.network.out.packets +=== `docker.network.out.packets` type: long @@ -2204,7 +2204,7 @@ Total number of outgoing packets. [[exported-fields-dropwizard]] -== Dropwizard Fields +== Dropwizard fields beta[] Stats collected from Dropwizard. @@ -2212,26 +2212,26 @@ Stats collected from Dropwizard. [float] -== dropwizard Fields +== dropwizard fields [[exported-fields-elasticsearch]] -== Elasticsearch Fields +== Elasticsearch fields -[]experimental +experimental[] Elasticsearch module [float] -== elasticsearch Fields +== elasticsearch fields [float] -=== elasticsearch.cluster.name +=== `elasticsearch.cluster.name` type: keyword @@ -2239,14 +2239,14 @@ Elasticsearch cluster name. [float] -== node Fields +== node fields node [float] -=== elasticsearch.node.jvm.memory.heap_init.bytes +=== `elasticsearch.node.jvm.memory.heap_init.bytes` type: long @@ -2256,7 +2256,7 @@ Heap init used by the JVM in bytes. [float] -=== elasticsearch.node.jvm.version +=== `elasticsearch.node.jvm.version` type: keyword @@ -2264,7 +2264,7 @@ JVM version. [float] -=== elasticsearch.node.name +=== `elasticsearch.node.name` type: keyword @@ -2272,7 +2272,7 @@ Node name. [float] -=== elasticsearch.node.version +=== `elasticsearch.node.version` type: keyword @@ -2280,21 +2280,21 @@ Node version. [float] -== node.stats Fields +== node.stats fields node_stats [float] -== indices Fields +== indices fields Node indices stats [float] -=== elasticsearch.node.stats.indices.docs.count +=== `elasticsearch.node.stats.indices.docs.count` type: long @@ -2302,7 +2302,7 @@ Total number of existing documents. [float] -=== elasticsearch.node.stats.indices.docs.deleted +=== `elasticsearch.node.stats.indices.docs.deleted` type: long @@ -2310,7 +2310,7 @@ Total number of deleted documents. [float] -=== elasticsearch.node.stats.indices.segments.count +=== `elasticsearch.node.stats.indices.segments.count` type: long @@ -2318,7 +2318,7 @@ Total number of segments. [float] -=== elasticsearch.node.stats.indices.segments.memory.bytes +=== `elasticsearch.node.stats.indices.segments.memory.bytes` type: long @@ -2328,7 +2328,7 @@ Total size of segments in bytes. [float] -=== elasticsearch.node.stats.indices.store.size.bytes +=== `elasticsearch.node.stats.indices.store.size.bytes` type: long @@ -2336,21 +2336,21 @@ Total size of the store in bytes. [float] -== jvm.mem.pools Fields +== jvm.mem.pools fields JVM memory pool stats [float] -== old Fields +== old fields Old memory pool stats. [float] -=== elasticsearch.node.stats.jvm.mem.pools.old.max.bytes +=== `elasticsearch.node.stats.jvm.mem.pools.old.max.bytes` type: long @@ -2359,7 +2359,7 @@ format: bytes Max bytes. [float] -=== elasticsearch.node.stats.jvm.mem.pools.old.peak.bytes +=== `elasticsearch.node.stats.jvm.mem.pools.old.peak.bytes` type: long @@ -2368,7 +2368,7 @@ format: bytes Peak bytes. [float] -=== elasticsearch.node.stats.jvm.mem.pools.old.peak_max.bytes +=== `elasticsearch.node.stats.jvm.mem.pools.old.peak_max.bytes` type: long @@ -2377,7 +2377,7 @@ format: bytes Peak max bytes. [float] -=== elasticsearch.node.stats.jvm.mem.pools.old.used.bytes +=== `elasticsearch.node.stats.jvm.mem.pools.old.used.bytes` type: long @@ -2386,14 +2386,14 @@ format: bytes Used bytes. [float] -== young Fields +== young fields Young memory pool stats. [float] -=== elasticsearch.node.stats.jvm.mem.pools.young.max.bytes +=== `elasticsearch.node.stats.jvm.mem.pools.young.max.bytes` type: long @@ -2402,7 +2402,7 @@ format: bytes Max bytes. [float] -=== elasticsearch.node.stats.jvm.mem.pools.young.peak.bytes +=== `elasticsearch.node.stats.jvm.mem.pools.young.peak.bytes` type: long @@ -2411,7 +2411,7 @@ format: bytes Peak bytes. [float] -=== elasticsearch.node.stats.jvm.mem.pools.young.peak_max.bytes +=== `elasticsearch.node.stats.jvm.mem.pools.young.peak_max.bytes` type: long @@ -2420,7 +2420,7 @@ format: bytes Peak max bytes. [float] -=== elasticsearch.node.stats.jvm.mem.pools.young.used.bytes +=== `elasticsearch.node.stats.jvm.mem.pools.young.used.bytes` type: long @@ -2429,14 +2429,14 @@ format: bytes Used bytes. [float] -== survivor Fields +== survivor fields Survivor memory pool stats. [float] -=== elasticsearch.node.stats.jvm.mem.pools.survivor.max.bytes +=== `elasticsearch.node.stats.jvm.mem.pools.survivor.max.bytes` type: long @@ -2445,7 +2445,7 @@ format: bytes Max bytes. [float] -=== elasticsearch.node.stats.jvm.mem.pools.survivor.peak.bytes +=== `elasticsearch.node.stats.jvm.mem.pools.survivor.peak.bytes` type: long @@ -2454,7 +2454,7 @@ format: bytes Peak bytes. [float] -=== elasticsearch.node.stats.jvm.mem.pools.survivor.peak_max.bytes +=== `elasticsearch.node.stats.jvm.mem.pools.survivor.peak_max.bytes` type: long @@ -2463,7 +2463,7 @@ format: bytes Peak max bytes. [float] -=== elasticsearch.node.stats.jvm.mem.pools.survivor.used.bytes +=== `elasticsearch.node.stats.jvm.mem.pools.survivor.used.bytes` type: long @@ -2472,76 +2472,76 @@ format: bytes Used bytes. [float] -== jvm.gc.collectors Fields +== jvm.gc.collectors fields GC collector stats. [float] -== old.collection Fields +== old.collection fields Old collection gc. [float] -=== elasticsearch.node.stats.jvm.gc.collectors.old.collection.count +=== `elasticsearch.node.stats.jvm.gc.collectors.old.collection.count` type: long [float] -=== elasticsearch.node.stats.jvm.gc.collectors.old.collection.ms +=== `elasticsearch.node.stats.jvm.gc.collectors.old.collection.ms` type: long [float] -== young.collection Fields +== young.collection fields Young collection gc. [float] -=== elasticsearch.node.stats.jvm.gc.collectors.young.collection.count +=== `elasticsearch.node.stats.jvm.gc.collectors.young.collection.count` type: long [float] -=== elasticsearch.node.stats.jvm.gc.collectors.young.collection.ms +=== `elasticsearch.node.stats.jvm.gc.collectors.young.collection.ms` type: long [[exported-fields-golang]] -== Golang Fields +== Golang fields Golang module [float] -== golang Fields +== golang fields [float] -== expvar Fields +== expvar fields expvar [float] -=== golang.expvar.cmdline +=== `golang.expvar.cmdline` type: keyword @@ -2549,14 +2549,14 @@ The cmdline of this golang program start with. [float] -== heap Fields +== heap fields The golang program heap information exposed by expvar. [float] -=== golang.heap.cmdline +=== `golang.heap.cmdline` type: keyword @@ -2564,21 +2564,21 @@ The cmdline of this golang program start with. [float] -== gc Fields +== gc fields Garbage collector summary. [float] -== total_pause Fields +== total_pause fields Total GC pause duration over lifetime of process. [float] -=== golang.heap.gc.total_pause.ns +=== `golang.heap.gc.total_pause.ns` type: long @@ -2586,7 +2586,7 @@ Duration in Ns. [float] -=== golang.heap.gc.total_count +=== `golang.heap.gc.total_count` type: long @@ -2594,7 +2594,7 @@ Total number of GC was happened. [float] -=== golang.heap.gc.next_gc_limit +=== `golang.heap.gc.next_gc_limit` type: long @@ -2604,7 +2604,7 @@ Next collection will happen when HeapAlloc > this amount. [float] -=== golang.heap.gc.cpu_fraction +=== `golang.heap.gc.cpu_fraction` type: long @@ -2612,14 +2612,14 @@ Fraction of CPU time used by GC. [float] -== pause Fields +== pause fields Last GC pause durations during the monitoring period. [float] -=== golang.heap.gc.pause.count +=== `golang.heap.gc.pause.count` type: long @@ -2627,14 +2627,14 @@ Count of GC pause duration during this collect period. [float] -== sum Fields +== sum fields Total GC pause duration during this collect period. [float] -=== golang.heap.gc.pause.sum.ns +=== `golang.heap.gc.pause.sum.ns` type: long @@ -2642,14 +2642,14 @@ Duration in Ns. [float] -== max Fields +== max fields Max GC pause duration during this collect period. [float] -=== golang.heap.gc.pause.max.ns +=== `golang.heap.gc.pause.max.ns` type: long @@ -2657,14 +2657,14 @@ Duration in Ns. [float] -== avg Fields +== avg fields Average GC pause duration during this collect period. [float] -=== golang.heap.gc.pause.avg.ns +=== `golang.heap.gc.pause.avg.ns` type: long @@ -2672,14 +2672,14 @@ Duration in Ns. [float] -== system Fields +== system fields Heap summary,which bytes was obtained from system. [float] -=== golang.heap.system.total +=== `golang.heap.system.total` type: long @@ -2689,7 +2689,7 @@ Total bytes obtained from system (sum of XxxSys below). [float] -=== golang.heap.system.optained +=== `golang.heap.system.optained` type: long @@ -2699,7 +2699,7 @@ Via HeapSys, bytes obtained from system. heap_sys = heap_idle + heap_inuse. [float] -=== golang.heap.system.stack +=== `golang.heap.system.stack` type: long @@ -2709,7 +2709,7 @@ Bytes used by stack allocator, and these bytes was obtained from system. [float] -=== golang.heap.system.released +=== `golang.heap.system.released` type: long @@ -2719,14 +2719,14 @@ Bytes released to the OS. [float] -== allocations Fields +== allocations fields Heap allocations summary. [float] -=== golang.heap.allocations.mallocs +=== `golang.heap.allocations.mallocs` type: long @@ -2734,7 +2734,7 @@ Number of mallocs. [float] -=== golang.heap.allocations.frees +=== `golang.heap.allocations.frees` type: long @@ -2742,7 +2742,7 @@ Number of frees. [float] -=== golang.heap.allocations.objects +=== `golang.heap.allocations.objects` type: long @@ -2750,7 +2750,7 @@ Total number of allocated objects. [float] -=== golang.heap.allocations.total +=== `golang.heap.allocations.total` type: long @@ -2760,7 +2760,7 @@ Bytes allocated (even if freed) throughout the lifetime. [float] -=== golang.heap.allocations.allocated +=== `golang.heap.allocations.allocated` type: long @@ -2770,7 +2770,7 @@ Bytes allocated and not yet freed (same as Alloc above). [float] -=== golang.heap.allocations.idle +=== `golang.heap.allocations.idle` type: long @@ -2780,7 +2780,7 @@ Bytes in idle spans. [float] -=== golang.heap.allocations.active +=== `golang.heap.allocations.active` type: long @@ -2819,28 +2819,28 @@ Example field [[exported-fields-haproxy]] -== HAProxy Fields +== HAProxy fields HAProxy Module [float] -== haproxy Fields +== haproxy fields HAProxy metrics. [float] -== info Fields +== info fields General information about HAProxy processes. [float] -=== haproxy.info.processes +=== `haproxy.info.processes` type: long @@ -2848,7 +2848,7 @@ Number of processes. [float] -=== haproxy.info.process_num +=== `haproxy.info.process_num` type: long @@ -2856,7 +2856,7 @@ Process number. [float] -=== haproxy.info.pid +=== `haproxy.info.pid` type: long @@ -2864,21 +2864,21 @@ Process ID. [float] -=== haproxy.info.run_queue +=== `haproxy.info.run_queue` type: long [float] -=== haproxy.info.tasks +=== `haproxy.info.tasks` type: long [float] -=== haproxy.info.uptime.sec +=== `haproxy.info.uptime.sec` type: long @@ -2886,7 +2886,7 @@ Current uptime in seconds. [float] -=== haproxy.info.memory.max.bytes +=== `haproxy.info.memory.max.bytes` type: long @@ -2896,7 +2896,7 @@ Maximum amount of memory usage in bytes (the 'Memmax_MB' value converted to byte [float] -=== haproxy.info.ulimit_n +=== `haproxy.info.ulimit_n` type: long @@ -2904,73 +2904,73 @@ Maximum number of open files for the process. [float] -== compress Fields +== compress fields [float] -== bps Fields +== bps fields [float] -=== haproxy.info.compress.bps.in +=== `haproxy.info.compress.bps.in` type: long [float] -=== haproxy.info.compress.bps.out +=== `haproxy.info.compress.bps.out` type: long [float] -=== haproxy.info.compress.bps.rate_limit +=== `haproxy.info.compress.bps.rate_limit` type: long [float] -== connection Fields +== connection fields [float] -== rate Fields +== rate fields [float] -=== haproxy.info.connection.rate.value +=== `haproxy.info.connection.rate.value` type: long [float] -=== haproxy.info.connection.rate.limit +=== `haproxy.info.connection.rate.limit` type: long [float] -=== haproxy.info.connection.rate.max +=== `haproxy.info.connection.rate.max` type: long [float] -=== haproxy.info.connection.current +=== `haproxy.info.connection.current` type: long @@ -2978,7 +2978,7 @@ Current connections. [float] -=== haproxy.info.connection.total +=== `haproxy.info.connection.total` type: long @@ -2986,7 +2986,7 @@ Total connections. [float] -=== haproxy.info.connection.ssl.current +=== `haproxy.info.connection.ssl.current` type: long @@ -2994,7 +2994,7 @@ Current SSL connections. [float] -=== haproxy.info.connection.ssl.total +=== `haproxy.info.connection.ssl.total` type: long @@ -3002,7 +3002,7 @@ Total SSL connections. [float] -=== haproxy.info.connection.ssl.max +=== `haproxy.info.connection.ssl.max` type: long @@ -3010,7 +3010,7 @@ Maximum SSL connections. [float] -=== haproxy.info.connection.max +=== `haproxy.info.connection.max` type: long @@ -3018,136 +3018,136 @@ Maximum connections. [float] -=== haproxy.info.connection.hard_max +=== `haproxy.info.connection.hard_max` type: long [float] -=== haproxy.info.requests.total +=== `haproxy.info.requests.total` type: long [float] -=== haproxy.info.sockets.max +=== `haproxy.info.sockets.max` type: long [float] -=== haproxy.info.requests.max +=== `haproxy.info.requests.max` type: long [float] -== pipes Fields +== pipes fields [float] -=== haproxy.info.pipes.used +=== `haproxy.info.pipes.used` type: integer [float] -=== haproxy.info.pipes.free +=== `haproxy.info.pipes.free` type: integer [float] -=== haproxy.info.pipes.max +=== `haproxy.info.pipes.max` type: integer [float] -== session Fields +== session fields None [float] -=== haproxy.info.session.rate.value +=== `haproxy.info.session.rate.value` type: integer [float] -=== haproxy.info.session.rate.limit +=== `haproxy.info.session.rate.limit` type: integer [float] -=== haproxy.info.session.rate.max +=== `haproxy.info.session.rate.max` type: integer [float] -== ssl Fields +== ssl fields None [float] -=== haproxy.info.ssl.rate.value +=== `haproxy.info.ssl.rate.value` type: integer None [float] -=== haproxy.info.ssl.rate.limit +=== `haproxy.info.ssl.rate.limit` type: integer None [float] -=== haproxy.info.ssl.rate.max +=== `haproxy.info.ssl.rate.max` type: integer None [float] -== frontend Fields +== frontend fields None [float] -=== haproxy.info.ssl.frontend.key_rate.value +=== `haproxy.info.ssl.frontend.key_rate.value` type: integer None [float] -=== haproxy.info.ssl.frontend.key_rate.max +=== `haproxy.info.ssl.frontend.key_rate.max` type: integer None [float] -=== haproxy.info.ssl.frontend.session_reuse.pct +=== `haproxy.info.ssl.frontend.session_reuse.pct` type: scaled_float @@ -3156,61 +3156,61 @@ format: percent None [float] -== backend Fields +== backend fields None [float] -=== haproxy.info.ssl.backend.key_rate.value +=== `haproxy.info.ssl.backend.key_rate.value` type: integer None [float] -=== haproxy.info.ssl.backend.key_rate.max +=== `haproxy.info.ssl.backend.key_rate.max` type: integer MaxConnRate [float] -=== haproxy.info.ssl.cached_lookups +=== `haproxy.info.ssl.cached_lookups` type: long None [float] -=== haproxy.info.ssl.cache_misses +=== `haproxy.info.ssl.cache_misses` type: long None [float] -== zlib_mem_usage Fields +== zlib_mem_usage fields [float] -=== haproxy.info.zlib_mem_usage.value +=== `haproxy.info.zlib_mem_usage.value` type: integer [float] -=== haproxy.info.zlib_mem_usage.max +=== `haproxy.info.zlib_mem_usage.max` type: integer [float] -=== haproxy.info.idle.pct +=== `haproxy.info.idle.pct` type: scaled_float @@ -3219,14 +3219,14 @@ format: percent [float] -== stat Fields +== stat fields Stats collected from HAProxy processes. [float] -=== haproxy.stat.status +=== `haproxy.stat.status` type: keyword @@ -3234,7 +3234,7 @@ Status (UP, DOWN, NOLB, MAINT, or MAINT(via)...). [float] -=== haproxy.stat.weight +=== `haproxy.stat.weight` type: long @@ -3242,7 +3242,7 @@ Total weight (for backends), or server weight (for servers). [float] -=== haproxy.stat.downtime +=== `haproxy.stat.downtime` type: long @@ -3250,7 +3250,7 @@ Total downtime (in seconds). For backends, this value is the downtime for the wh [float] -=== haproxy.stat.component_type +=== `haproxy.stat.component_type` type: integer @@ -3258,7 +3258,7 @@ Component type (0=frontend, 1=backend, 2=server, or 3=socket/listener). [float] -=== haproxy.stat.process_id +=== `haproxy.stat.process_id` type: integer @@ -3266,7 +3266,7 @@ Process ID (0 for first instance, 1 for second, and so on). [float] -=== haproxy.stat.service_name +=== `haproxy.stat.service_name` type: keyword @@ -3274,7 +3274,7 @@ Service name (FRONTEND for frontend, BACKEND for backend, or any name for server [float] -=== haproxy.stat.in.bytes +=== `haproxy.stat.in.bytes` type: long @@ -3284,7 +3284,7 @@ Bytes in. [float] -=== haproxy.stat.out.bytes +=== `haproxy.stat.out.bytes` type: long @@ -3294,7 +3294,7 @@ Bytes out. [float] -=== haproxy.stat.last_change +=== `haproxy.stat.last_change` type: integer @@ -3302,7 +3302,7 @@ Number of seconds since the last UP->DOWN or DOWN->UP transition. [float] -=== haproxy.stat.throttle.pct +=== `haproxy.stat.throttle.pct` type: scaled_float @@ -3312,7 +3312,7 @@ Current throttle percentage for the server when slowstart is active, or no value [float] -=== haproxy.stat.selected.total +=== `haproxy.stat.selected.total` type: long @@ -3320,7 +3320,7 @@ Total number of times a server was selected, either for new sessions, or when re [float] -=== haproxy.stat.tracked.id +=== `haproxy.stat.tracked.id` type: long @@ -3329,7 +3329,7 @@ ID of the proxy/server if tracking is enabled. [float] -=== haproxy.stat.connection.total +=== `haproxy.stat.connection.total` type: long @@ -3337,7 +3337,7 @@ Cumulative number of connections. [float] -=== haproxy.stat.connection.retried +=== `haproxy.stat.connection.retried` type: long @@ -3345,7 +3345,7 @@ Number of times a connection to a server was retried. [float] -=== haproxy.stat.connection.time.avg +=== `haproxy.stat.connection.time.avg` type: long @@ -3354,7 +3354,7 @@ Average connect time in ms over the last 1024 requests. [float] -=== haproxy.stat.request.denied +=== `haproxy.stat.request.denied` type: long @@ -3365,7 +3365,7 @@ Requests denied because of security concerns. [float] -=== haproxy.stat.request.queued.current +=== `haproxy.stat.request.queued.current` type: long @@ -3373,7 +3373,7 @@ Current queued requests. For backends, this field reports the number of requests [float] -=== haproxy.stat.request.queued.max +=== `haproxy.stat.request.queued.max` type: long @@ -3381,7 +3381,7 @@ Maximum value of queued.current. [float] -=== haproxy.stat.request.errors +=== `haproxy.stat.request.errors` type: long @@ -3396,7 +3396,7 @@ Request errors. Some of the possible causes are: [float] -=== haproxy.stat.request.redispatched +=== `haproxy.stat.request.redispatched` type: long @@ -3404,7 +3404,7 @@ Number of times a request was redispatched to another server. For servers, this [float] -=== haproxy.stat.request.connection.errors +=== `haproxy.stat.request.connection.errors` type: long @@ -3412,13 +3412,13 @@ Number of requests that encountered an error trying to connect to a server. For [float] -== rate Fields +== rate fields [float] -=== haproxy.stat.request.rate.value +=== `haproxy.stat.request.rate.value` type: long @@ -3426,7 +3426,7 @@ Number of HTTP requests per second over the last elapsed second. [float] -=== haproxy.stat.request.rate.max +=== `haproxy.stat.request.rate.max` type: long @@ -3434,7 +3434,7 @@ Maximum number of HTTP requests per second. [float] -=== haproxy.stat.request.total +=== `haproxy.stat.request.total` type: long @@ -3443,7 +3443,7 @@ Total number of HTTP requests received. [float] -=== haproxy.stat.response.errors +=== `haproxy.stat.response.errors` type: long @@ -3452,7 +3452,7 @@ Number of response errors. This value includes the number of data transfers abor [float] -=== haproxy.stat.response.time.avg +=== `haproxy.stat.response.time.avg` type: long @@ -3460,7 +3460,7 @@ Average response time in ms over the last 1024 requests (0 for TCP). [float] -=== haproxy.stat.response.denied +=== `haproxy.stat.response.denied` type: integer @@ -3468,13 +3468,13 @@ Responses denied because of security concerns. For HTTP this is because of a mat [float] -== http Fields +== http fields [float] -=== haproxy.stat.response.http.1xx +=== `haproxy.stat.response.http.1xx` type: long @@ -3482,7 +3482,7 @@ HTTP responses with 1xx code. [float] -=== haproxy.stat.response.http.2xx +=== `haproxy.stat.response.http.2xx` type: long @@ -3490,7 +3490,7 @@ HTTP responses with 2xx code. [float] -=== haproxy.stat.response.http.3xx +=== `haproxy.stat.response.http.3xx` type: long @@ -3498,7 +3498,7 @@ HTTP responses with 3xx code. [float] -=== haproxy.stat.response.http.4xx +=== `haproxy.stat.response.http.4xx` type: long @@ -3506,7 +3506,7 @@ HTTP responses with 4xx code. [float] -=== haproxy.stat.response.http.5xx +=== `haproxy.stat.response.http.5xx` type: long @@ -3514,7 +3514,7 @@ HTTP responses with 5xx code. [float] -=== haproxy.stat.response.http.other +=== `haproxy.stat.response.http.other` type: long @@ -3523,7 +3523,7 @@ HTTP responses with other codes (protocol error). [float] -=== haproxy.stat.session.current +=== `haproxy.stat.session.current` type: long @@ -3531,7 +3531,7 @@ Number of current sessions. [float] -=== haproxy.stat.session.max +=== `haproxy.stat.session.max` type: long @@ -3539,7 +3539,7 @@ Maximum number of sessions. [float] -=== haproxy.stat.session.limit +=== `haproxy.stat.session.limit` type: long @@ -3548,7 +3548,7 @@ Configured session limit. [float] -=== haproxy.stat.session.rate.value +=== `haproxy.stat.session.rate.value` type: integer @@ -3556,7 +3556,7 @@ Number of sessions per second over the last elapsed second. [float] -=== haproxy.stat.session.rate.limit +=== `haproxy.stat.session.rate.limit` type: integer @@ -3564,7 +3564,7 @@ Configured limit on new sessions per second. [float] -=== haproxy.stat.session.rate.max +=== `haproxy.stat.session.rate.max` type: integer @@ -3572,13 +3572,13 @@ Maximum number of new sessions per second. [float] -== check Fields +== check fields [float] -=== haproxy.stat.check.status +=== `haproxy.stat.check.status` type: keyword @@ -3603,7 +3603,7 @@ Status of the last health check. One of: [float] -=== haproxy.stat.check.code +=== `haproxy.stat.check.code` type: long @@ -3611,7 +3611,7 @@ Layer 5-7 code, if available. [float] -=== haproxy.stat.check.duration +=== `haproxy.stat.check.duration` type: long @@ -3619,7 +3619,7 @@ Time in ms that it took to finish the last health check. [float] -=== haproxy.stat.check.health.last +=== `haproxy.stat.check.health.last` type: keyword @@ -3627,7 +3627,7 @@ The result of the last health check. [float] -=== haproxy.stat.check.health.fail +=== `haproxy.stat.check.health.fail` type: long @@ -3635,14 +3635,14 @@ Number of failed checks. [float] -=== haproxy.stat.check.agent.last +=== `haproxy.stat.check.agent.last` type: integer [float] -=== haproxy.stat.check.failed +=== `haproxy.stat.check.failed` type: long @@ -3650,7 +3650,7 @@ Number of checks that failed while the server was up. [float] -=== haproxy.stat.check.down +=== `haproxy.stat.check.down` type: long @@ -3658,7 +3658,7 @@ Number of UP->DOWN transitions. For backends, this value is the number of transi [float] -=== haproxy.stat.client.aborted +=== `haproxy.stat.client.aborted` type: integer @@ -3666,13 +3666,13 @@ Number of data transfers aborted by the client. [float] -== server Fields +== server fields [float] -=== haproxy.stat.server.id +=== `haproxy.stat.server.id` type: integer @@ -3680,7 +3680,7 @@ Server ID (unique inside a proxy). [float] -=== haproxy.stat.server.aborted +=== `haproxy.stat.server.aborted` type: integer @@ -3688,7 +3688,7 @@ Number of data transfers aborted by the server. This value is included in haprox [float] -=== haproxy.stat.server.active +=== `haproxy.stat.server.active` type: integer @@ -3696,7 +3696,7 @@ Number of backend servers that are active, meaning that they are healthy and can [float] -=== haproxy.stat.server.backup +=== `haproxy.stat.server.backup` type: integer @@ -3704,13 +3704,13 @@ Number of backend servers that are backup servers. [float] -== compressor Fields +== compressor fields [float] -=== haproxy.stat.compressor.in.bytes +=== `haproxy.stat.compressor.in.bytes` type: long @@ -3720,7 +3720,7 @@ Number of HTTP response bytes fed to the compressor. [float] -=== haproxy.stat.compressor.out.bytes +=== `haproxy.stat.compressor.out.bytes` type: integer @@ -3730,7 +3730,7 @@ Number of HTTP response bytes emitted by the compressor. [float] -=== haproxy.stat.compressor.bypassed.bytes +=== `haproxy.stat.compressor.bypassed.bytes` type: long @@ -3740,7 +3740,7 @@ Number of bytes that bypassed the HTTP compressor (CPU/BW limit). [float] -=== haproxy.stat.compressor.response.bytes +=== `haproxy.stat.compressor.response.bytes` type: long @@ -3750,13 +3750,13 @@ Number of HTTP responses that were compressed. [float] -== proxy Fields +== proxy fields [float] -=== haproxy.stat.proxy.id +=== `haproxy.stat.proxy.id` type: integer @@ -3764,7 +3764,7 @@ Unique proxy ID. [float] -=== haproxy.stat.proxy.name +=== `haproxy.stat.proxy.name` type: keyword @@ -3772,13 +3772,13 @@ Proxy name. [float] -== queue Fields +== queue fields [float] -=== haproxy.stat.queue.limit +=== `haproxy.stat.queue.limit` type: integer @@ -3786,7 +3786,7 @@ Configured queue limit (maxqueue) for the server, or nothing if the value of max [float] -=== haproxy.stat.queue.time.avg +=== `haproxy.stat.queue.time.avg` type: integer @@ -3794,27 +3794,27 @@ The average queue time in ms over the last 1024 requests. [[exported-fields-http]] -== HTTP Fields +== HTTP fields HTTP module [float] -== http Fields +== http fields [float] -== request Fields +== request fields HTTP request information [float] -=== http.request.header +=== `http.request.header` type: nested @@ -3822,7 +3822,7 @@ The HTTP headers sent [float] -=== http.request.method +=== `http.request.method` type: keyword @@ -3830,7 +3830,7 @@ The HTTP method used [float] -=== http.request.body +=== `http.request.body` type: keyword @@ -3838,14 +3838,14 @@ The HTTP payload sent [float] -== response Fields +== response fields HTTP response information [float] -=== http.response.header +=== `http.response.header` type: nested @@ -3853,7 +3853,7 @@ The HTTP headers received [float] -=== http.response.status_code +=== `http.response.status_code` type: keyword @@ -3861,7 +3861,7 @@ The HTTP status code [float] -=== http.response.body +=== `http.response.body` type: keyword @@ -3869,27 +3869,27 @@ The HTTP payload received [float] -== json Fields +== json fields json metricset [[exported-fields-jolokia]] -== Jolokia Fields +== Jolokia fields -[]beta +beta[] Jolokia module [float] -== jolokia Fields +== jolokia fields jolokia contains metrics exposed via jolokia agent [[exported-fields-kafka]] -== Kafka Fields +== Kafka fields Kafka module beta[] @@ -3897,27 +3897,27 @@ beta[] [float] -== kafka Fields +== kafka fields [float] -== consumergroup Fields +== consumergroup fields consumergroup [float] -== broker Fields +== broker fields Broker Consumer Group Information have been read from (Broker handling the consumer group). [float] -=== kafka.consumergroup.broker.id +=== `kafka.consumergroup.broker.id` type: long @@ -3925,7 +3925,7 @@ Broker id [float] -=== kafka.consumergroup.broker.address +=== `kafka.consumergroup.broker.address` type: keyword @@ -3933,42 +3933,42 @@ Broker address [float] -=== kafka.consumergroup.id +=== `kafka.consumergroup.id` type: keyword Consumer Group ID [float] -=== kafka.consumergroup.topic +=== `kafka.consumergroup.topic` type: keyword Topic name [float] -=== kafka.consumergroup.partition +=== `kafka.consumergroup.partition` type: long Partition ID [float] -=== kafka.consumergroup.offset +=== `kafka.consumergroup.offset` type: long consumer offset into partition being read [float] -=== kafka.consumergroup.meta +=== `kafka.consumergroup.meta` type: text custom consumer meta data string [float] -=== kafka.consumergroup.error.code +=== `kafka.consumergroup.error.code` type: long @@ -3976,49 +3976,49 @@ kafka consumer/partition error code. [float] -== client Fields +== client fields Assigned client reading events from partition [float] -=== kafka.consumergroup.client.id +=== `kafka.consumergroup.client.id` type: keyword Client ID (kafka setting client.id) [float] -=== kafka.consumergroup.client.host +=== `kafka.consumergroup.client.host` type: keyword Client host [float] -=== kafka.consumergroup.client.member_id +=== `kafka.consumergroup.client.member_id` type: keyword internal consumer group member ID [float] -== partition Fields +== partition fields partition [float] -== offset Fields +== offset fields Available offsets of the given partition. [float] -=== kafka.partition.offset.newest +=== `kafka.partition.offset.newest` type: long @@ -4026,7 +4026,7 @@ Newest offset of the partition. [float] -=== kafka.partition.offset.oldest +=== `kafka.partition.offset.oldest` type: long @@ -4034,14 +4034,14 @@ Oldest offset of the partition. [float] -== partition Fields +== partition fields Partition data. [float] -=== kafka.partition.partition.id +=== `kafka.partition.partition.id` type: long @@ -4049,7 +4049,7 @@ Partition id. [float] -=== kafka.partition.partition.leader +=== `kafka.partition.partition.leader` type: long @@ -4057,7 +4057,7 @@ Leader id (broker). [float] -=== kafka.partition.partition.isr +=== `kafka.partition.partition.isr` type: array @@ -4065,7 +4065,7 @@ List of isr ids. [float] -=== kafka.partition.partition.replica +=== `kafka.partition.partition.replica` type: long @@ -4073,7 +4073,7 @@ Replica id (broker). [float] -=== kafka.partition.partition.insync_replica +=== `kafka.partition.partition.insync_replica` type: boolean @@ -4081,7 +4081,7 @@ Indicates if replica is included in the in-sync replicate set (ISR). [float] -=== kafka.partition.partition.error.code +=== `kafka.partition.partition.error.code` type: long @@ -4089,7 +4089,7 @@ Error code from fetching partition. [float] -=== kafka.partition.topic.error.code +=== `kafka.partition.topic.error.code` type: long @@ -4097,7 +4097,7 @@ topic error code. [float] -=== kafka.partition.topic.name +=== `kafka.partition.topic.name` type: keyword @@ -4105,7 +4105,7 @@ Topic name [float] -=== kafka.partition.broker.id +=== `kafka.partition.broker.id` type: long @@ -4113,7 +4113,7 @@ Broker id [float] -=== kafka.partition.broker.address +=== `kafka.partition.broker.address` type: keyword @@ -4121,28 +4121,28 @@ Broker address [[exported-fields-kibana]] -== Kibana Fields +== Kibana fields -[]experimental +experimental[] Kibana module [float] -== kibana Fields +== kibana fields [float] -== status Fields +== status fields Status fields [float] -=== kibana.status.name +=== `kibana.status.name` type: keyword @@ -4150,7 +4150,7 @@ Kibana instance name. [float] -=== kibana.status.uuid +=== `kibana.status.uuid` type: keyword @@ -4158,7 +4158,7 @@ Kibana instance uuid. [float] -=== kibana.status.version.number +=== `kibana.status.version.number` type: keyword @@ -4166,7 +4166,7 @@ Kibana version number. [float] -=== kibana.status.status.overall.state +=== `kibana.status.status.overall.state` type: keyword @@ -4174,14 +4174,14 @@ Kibana overall state. [float] -== metrics Fields +== metrics fields Metrics fields [float] -=== kibana.status.metrics.concurrent_connections +=== `kibana.status.metrics.concurrent_connections` type: long @@ -4189,14 +4189,14 @@ Current concurrent connections. [float] -== requests Fields +== requests fields Request statistics. [float] -=== kibana.status.metrics.requests.disconnects +=== `kibana.status.metrics.requests.disconnects` type: long @@ -4204,7 +4204,7 @@ Total number of disconnected connections. [float] -=== kibana.status.metrics.requests.total +=== `kibana.status.metrics.requests.total` type: long @@ -4212,7 +4212,7 @@ Total number of connections. [[exported-fields-kubernetes-processor]] -== kubernetes Fields +== Kubernetes fields beta[] Kubernetes metadata added by the kubernetes processor @@ -4221,7 +4221,7 @@ Kubernetes metadata added by the kubernetes processor [float] -=== kubernetes.pod.name +=== `kubernetes.pod.name` type: keyword @@ -4229,7 +4229,7 @@ Kubernetes pod name [float] -=== kubernetes.namespace +=== `kubernetes.namespace` type: keyword @@ -4237,7 +4237,7 @@ Kubernetes namespace [float] -=== kubernetes.labels +=== `kubernetes.labels` type: object @@ -4245,7 +4245,7 @@ Kubernetes labels map [float] -=== kubernetes.annotations +=== `kubernetes.annotations` type: object @@ -4253,7 +4253,7 @@ Kubernetes annotations map [float] -=== kubernetes.container.name +=== `kubernetes.container.name` type: keyword @@ -4261,7 +4261,7 @@ Kubernetes container name [float] -=== kubernetes.container.image +=== `kubernetes.container.image` type: keyword @@ -4269,7 +4269,7 @@ Kubernetes container image [[exported-fields-kubernetes]] -== Kubernetes Fields +== Kubernetes fields beta[] Kubernetes metrics @@ -4277,21 +4277,21 @@ Kubernetes metrics [float] -== kubernetes Fields +== kubernetes fields Information and statistics of pods managed by kubernetes. [float] -== container Fields +== container fields kubernetes container metrics [float] -=== kubernetes.container.start_time +=== `kubernetes.container.start_time` type: date @@ -4299,7 +4299,7 @@ Start time [float] -== cpu Fields +== cpu fields CPU usage metrics @@ -4308,7 +4308,7 @@ CPU usage metrics [float] -=== kubernetes.container.cpu.usage.core.ns +=== `kubernetes.container.cpu.usage.core.ns` type: long @@ -4316,7 +4316,7 @@ Container CPU Core usage nanoseconds [float] -=== kubernetes.container.cpu.usage.nanocores +=== `kubernetes.container.cpu.usage.nanocores` type: long @@ -4324,7 +4324,7 @@ CPU used nanocores [float] -== logs Fields +== logs fields Logs info @@ -4332,7 +4332,7 @@ Logs info [float] -=== kubernetes.container.logs.available.bytes +=== `kubernetes.container.logs.available.bytes` type: long @@ -4343,7 +4343,7 @@ Logs available capacity in bytes [float] -=== kubernetes.container.logs.capacity.bytes +=== `kubernetes.container.logs.capacity.bytes` type: long @@ -4354,7 +4354,7 @@ Logs total capacity in bytes [float] -=== kubernetes.container.logs.used.bytes +=== `kubernetes.container.logs.used.bytes` type: long @@ -4365,7 +4365,7 @@ Logs used capacity in bytes [float] -=== kubernetes.container.logs.inodes.count +=== `kubernetes.container.logs.inodes.count` type: long @@ -4373,7 +4373,7 @@ Total available inodes [float] -=== kubernetes.container.logs.inodes.free +=== `kubernetes.container.logs.inodes.free` type: long @@ -4381,7 +4381,7 @@ Total free inodes [float] -=== kubernetes.container.logs.inodes.used +=== `kubernetes.container.logs.inodes.used` type: long @@ -4391,7 +4391,7 @@ Total used inodes [float] -=== kubernetes.container.memory.available.bytes +=== `kubernetes.container.memory.available.bytes` type: long @@ -4402,7 +4402,7 @@ Total available memory [float] -=== kubernetes.container.memory.usage.bytes +=== `kubernetes.container.memory.usage.bytes` type: long @@ -4413,7 +4413,7 @@ Total memory usage [float] -=== kubernetes.container.memory.rss.bytes +=== `kubernetes.container.memory.rss.bytes` type: long @@ -4424,7 +4424,7 @@ RSS memory usage [float] -=== kubernetes.container.memory.workingset.bytes +=== `kubernetes.container.memory.workingset.bytes` type: long @@ -4434,7 +4434,7 @@ Working set memory usage [float] -=== kubernetes.container.memory.pagefaults +=== `kubernetes.container.memory.pagefaults` type: long @@ -4442,7 +4442,7 @@ Number of page faults [float] -=== kubernetes.container.memory.majorpagefaults +=== `kubernetes.container.memory.majorpagefaults` type: long @@ -4452,7 +4452,7 @@ Number of major page faults [float] -=== kubernetes.container.rootfs.capacity.bytes +=== `kubernetes.container.rootfs.capacity.bytes` type: long @@ -4463,7 +4463,7 @@ Root filesystem total capacity in bytes [float] -=== kubernetes.container.rootfs.available.bytes +=== `kubernetes.container.rootfs.available.bytes` type: long @@ -4474,7 +4474,7 @@ Root filesystem total available in bytes [float] -=== kubernetes.container.rootfs.used.bytes +=== `kubernetes.container.rootfs.used.bytes` type: long @@ -4485,7 +4485,7 @@ Root filesystem total used in bytes [float] -=== kubernetes.container.rootfs.inodes.used +=== `kubernetes.container.rootfs.inodes.used` type: long @@ -4493,14 +4493,14 @@ Used inodes [float] -== event Fields +== event fields The Kubernetes events metricset collects events that are generated by objects running inside of Kubernetes [float] -=== kubernetes.event.count +=== `kubernetes.event.count` type: long @@ -4508,7 +4508,7 @@ Count field records the number of times the particular event has occured [float] -=== kubernetes.event.message +=== `kubernetes.event.message` type: keyword @@ -4516,7 +4516,7 @@ Message recorded for the given event [float] -=== kubernetes.event.reason +=== `kubernetes.event.reason` type: keyword @@ -4524,7 +4524,7 @@ Reason recorded for the given event [float] -=== kubernetes.event.type +=== `kubernetes.event.type` type: keyword @@ -4532,7 +4532,7 @@ Type of the given event [float] -== metadata Fields +== metadata fields Metadata associated with the given event @@ -4540,7 +4540,7 @@ Metadata associated with the given event [float] -=== kubernetes.event.metadata.timestamp.created +=== `kubernetes.event.metadata.timestamp.created` type: date @@ -4548,7 +4548,7 @@ Timestamp of creation of the given event [float] -=== kubernetes.event.metadata.timestamp.deleted +=== `kubernetes.event.metadata.timestamp.deleted` type: date @@ -4556,7 +4556,7 @@ Timestamp of deletion of the given event [float] -=== kubernetes.event.metadata.name +=== `kubernetes.event.metadata.name` type: keyword @@ -4564,7 +4564,7 @@ Name of the event [float] -=== kubernetes.event.metadata.namespace +=== `kubernetes.event.metadata.namespace` type: keyword @@ -4572,7 +4572,7 @@ Namespace in which event was generated [float] -=== kubernetes.event.metadata.resource_version +=== `kubernetes.event.metadata.resource_version` type: keyword @@ -4580,7 +4580,7 @@ Version of the event resource [float] -=== kubernetes.event.metadata.uid +=== `kubernetes.event.metadata.uid` type: keyword @@ -4588,7 +4588,7 @@ Unique identifier to the event object [float] -=== kubernetes.event.metadata.self_link +=== `kubernetes.event.metadata.self_link` type: keyword @@ -4596,14 +4596,14 @@ URL representing the event [float] -== involved_object Fields +== involved_object fields Metadata associated with the given involved object [float] -=== kubernetes.event.involved_object.api_version +=== `kubernetes.event.involved_object.api_version` type: keyword @@ -4611,7 +4611,7 @@ API version of the object [float] -=== kubernetes.event.involved_object.kind +=== `kubernetes.event.involved_object.kind` type: keyword @@ -4619,7 +4619,7 @@ API kind of the object [float] -=== kubernetes.event.involved_object.name +=== `kubernetes.event.involved_object.name` type: keyword @@ -4627,7 +4627,7 @@ name of the object [float] -=== kubernetes.event.involved_object.resource_version +=== `kubernetes.event.involved_object.resource_version` type: keyword @@ -4635,7 +4635,7 @@ resource version of the object [float] -=== kubernetes.event.involved_object.uid +=== `kubernetes.event.involved_object.uid` type: keyword @@ -4643,14 +4643,14 @@ UUID version of the object [float] -== node Fields +== node fields kubernetes node metrics [float] -=== kubernetes.node.name +=== `kubernetes.node.name` type: keyword @@ -4658,7 +4658,7 @@ Node name [float] -=== kubernetes.node.start_time +=== `kubernetes.node.start_time` type: date @@ -4666,7 +4666,7 @@ Start time [float] -== cpu Fields +== cpu fields CPU usage metrics @@ -4675,7 +4675,7 @@ CPU usage metrics [float] -=== kubernetes.node.cpu.usage.core.ns +=== `kubernetes.node.cpu.usage.core.ns` type: long @@ -4683,7 +4683,7 @@ Node CPU Core usage nanoseconds [float] -=== kubernetes.node.cpu.usage.nanocores +=== `kubernetes.node.cpu.usage.nanocores` type: long @@ -4693,7 +4693,7 @@ CPU used nanocores [float] -=== kubernetes.node.memory.available.bytes +=== `kubernetes.node.memory.available.bytes` type: long @@ -4704,7 +4704,7 @@ Total available memory [float] -=== kubernetes.node.memory.usage.bytes +=== `kubernetes.node.memory.usage.bytes` type: long @@ -4715,7 +4715,7 @@ Total memory usage [float] -=== kubernetes.node.memory.rss.bytes +=== `kubernetes.node.memory.rss.bytes` type: long @@ -4726,7 +4726,7 @@ RSS memory usage [float] -=== kubernetes.node.memory.workingset.bytes +=== `kubernetes.node.memory.workingset.bytes` type: long @@ -4736,7 +4736,7 @@ Working set memory usage [float] -=== kubernetes.node.memory.pagefaults +=== `kubernetes.node.memory.pagefaults` type: long @@ -4744,7 +4744,7 @@ Number of page faults [float] -=== kubernetes.node.memory.majorpagefaults +=== `kubernetes.node.memory.majorpagefaults` type: long @@ -4754,7 +4754,7 @@ Number of major page faults [float] -=== kubernetes.node.network.rx.bytes +=== `kubernetes.node.network.rx.bytes` type: long @@ -4764,7 +4764,7 @@ Received bytes [float] -=== kubernetes.node.network.rx.errors +=== `kubernetes.node.network.rx.errors` type: long @@ -4773,7 +4773,7 @@ Rx errors [float] -=== kubernetes.node.network.tx.bytes +=== `kubernetes.node.network.tx.bytes` type: long @@ -4783,7 +4783,7 @@ Transmitted bytes [float] -=== kubernetes.node.network.tx.errors +=== `kubernetes.node.network.tx.errors` type: long @@ -4793,7 +4793,7 @@ Tx errors [float] -=== kubernetes.node.fs.capacity.bytes +=== `kubernetes.node.fs.capacity.bytes` type: long @@ -4804,7 +4804,7 @@ Filesystem total capacity in bytes [float] -=== kubernetes.node.fs.available.bytes +=== `kubernetes.node.fs.available.bytes` type: long @@ -4815,7 +4815,7 @@ Filesystem total available in bytes [float] -=== kubernetes.node.fs.used.bytes +=== `kubernetes.node.fs.used.bytes` type: long @@ -4826,7 +4826,7 @@ Filesystem total used in bytes [float] -=== kubernetes.node.fs.inodes.used +=== `kubernetes.node.fs.inodes.used` type: long @@ -4834,7 +4834,7 @@ Number of used inodes [float] -=== kubernetes.node.fs.inodes.count +=== `kubernetes.node.fs.inodes.count` type: long @@ -4842,7 +4842,7 @@ Number of inodes [float] -=== kubernetes.node.fs.inodes.free +=== `kubernetes.node.fs.inodes.free` type: long @@ -4853,7 +4853,7 @@ Number of free inodes [float] -=== kubernetes.node.runtime.imagefs.capacity.bytes +=== `kubernetes.node.runtime.imagefs.capacity.bytes` type: long @@ -4864,7 +4864,7 @@ Image filesystem total capacity in bytes [float] -=== kubernetes.node.runtime.imagefs.available.bytes +=== `kubernetes.node.runtime.imagefs.available.bytes` type: long @@ -4875,7 +4875,7 @@ Image filesystem total available in bytes [float] -=== kubernetes.node.runtime.imagefs.used.bytes +=== `kubernetes.node.runtime.imagefs.used.bytes` type: long @@ -4885,14 +4885,14 @@ Image filesystem total used in bytes [float] -== pod Fields +== pod fields kubernetes pod metrics [float] -=== kubernetes.pod.start_time +=== `kubernetes.pod.start_time` type: date @@ -4902,7 +4902,7 @@ Start time [float] -=== kubernetes.pod.network.rx.bytes +=== `kubernetes.pod.network.rx.bytes` type: long @@ -4912,7 +4912,7 @@ Received bytes [float] -=== kubernetes.pod.network.rx.errors +=== `kubernetes.pod.network.rx.errors` type: long @@ -4921,7 +4921,7 @@ Rx errors [float] -=== kubernetes.pod.network.tx.bytes +=== `kubernetes.pod.network.tx.bytes` type: long @@ -4931,7 +4931,7 @@ Transmitted bytes [float] -=== kubernetes.pod.network.tx.errors +=== `kubernetes.pod.network.tx.errors` type: long @@ -4939,14 +4939,14 @@ Tx errors [float] -== container Fields +== container fields kubernetes container metrics [float] -=== kubernetes.container.id +=== `kubernetes.container.id` type: keyword @@ -4954,7 +4954,7 @@ Container id [float] -=== kubernetes.container.status.phase +=== `kubernetes.container.status.phase` type: keyword @@ -4962,7 +4962,7 @@ Container phase (running, waiting, terminated) [float] -=== kubernetes.container.status.ready +=== `kubernetes.container.status.ready` type: boolean @@ -4970,7 +4970,7 @@ Container ready status [float] -=== kubernetes.container.status.restarts +=== `kubernetes.container.status.restarts` type: integer @@ -4979,7 +4979,7 @@ Container restarts count [float] -=== kubernetes.container.cpu.limit.nanocores +=== `kubernetes.container.cpu.limit.nanocores` type: long @@ -4987,7 +4987,7 @@ Container CPU nanocores limit [float] -=== kubernetes.container.cpu.request.nanocores +=== `kubernetes.container.cpu.request.nanocores` type: long @@ -4996,7 +4996,7 @@ Container CPU requested nanocores [float] -=== kubernetes.container.memory.limit.bytes +=== `kubernetes.container.memory.limit.bytes` type: long @@ -5006,7 +5006,7 @@ Container memory limit in bytes [float] -=== kubernetes.container.memory.request.bytes +=== `kubernetes.container.memory.request.bytes` type: long @@ -5016,14 +5016,14 @@ Container requested memory in bytes [float] -== deployment Fields +== deployment fields kubernetes deployment metrics [float] -=== kubernetes.deployment.name +=== `kubernetes.deployment.name` type: keyword @@ -5031,7 +5031,7 @@ Kubernetes deployment name [float] -=== kubernetes.deployment.paused +=== `kubernetes.deployment.paused` type: boolean @@ -5039,14 +5039,14 @@ Kubernetes deployment paused status [float] -== replicas Fields +== replicas fields Kubernetes deployment replicas info [float] -=== kubernetes.deployment.replicas.desired +=== `kubernetes.deployment.replicas.desired` type: integer @@ -5054,7 +5054,7 @@ Deployment number of desired replicas (spec) [float] -=== kubernetes.deployment.replicas.available +=== `kubernetes.deployment.replicas.available` type: integer @@ -5062,7 +5062,7 @@ Deployment available replicas [float] -=== kubernetes.deployment.replicas.unavailable +=== `kubernetes.deployment.replicas.unavailable` type: integer @@ -5070,7 +5070,7 @@ Deployment unavailable replicas [float] -=== kubernetes.deployment.replicas.updated +=== `kubernetes.deployment.replicas.updated` type: integer @@ -5078,7 +5078,7 @@ Deployment updated replicas [float] -== node Fields +== node fields kubernetes node metrics @@ -5086,7 +5086,7 @@ kubernetes node metrics [float] -=== kubernetes.node.status.ready +=== `kubernetes.node.status.ready` type: keyword @@ -5094,7 +5094,7 @@ Node ready status (true, false or unknown) [float] -=== kubernetes.node.status.unschedulable +=== `kubernetes.node.status.unschedulable` type: boolean @@ -5103,7 +5103,7 @@ Node unschedulable status [float] -=== kubernetes.node.cpu.allocatable.cores +=== `kubernetes.node.cpu.allocatable.cores` type: long @@ -5111,7 +5111,7 @@ Node CPU allocatable cores [float] -=== kubernetes.node.cpu.capacity.cores +=== `kubernetes.node.cpu.capacity.cores` type: long @@ -5120,7 +5120,7 @@ Node CPU capacity cores [float] -=== kubernetes.node.memory.allocatable.bytes +=== `kubernetes.node.memory.allocatable.bytes` type: long @@ -5130,7 +5130,7 @@ Node allocatable memory in bytes [float] -=== kubernetes.node.memory.capacity.bytes +=== `kubernetes.node.memory.capacity.bytes` type: long @@ -5141,7 +5141,7 @@ Node memory capacity in bytes [float] -=== kubernetes.node.pod.allocatable.total +=== `kubernetes.node.pod.allocatable.total` type: long @@ -5149,7 +5149,7 @@ Node allocatable pods [float] -=== kubernetes.node.pod.capacity.total +=== `kubernetes.node.pod.capacity.total` type: long @@ -5157,14 +5157,14 @@ Node pod capacity [float] -== pod Fields +== pod fields kubernetes pod metrics [float] -=== kubernetes.pod.ip +=== `kubernetes.pod.ip` type: ip @@ -5172,7 +5172,7 @@ Kubernetes pod IP [float] -=== kubernetes.pod.host_ip +=== `kubernetes.pod.host_ip` type: ip @@ -5180,14 +5180,14 @@ Kubernetes pod host IP [float] -== status Fields +== status fields Kubernetes pod status metrics [float] -=== kubernetes.pod.status.phase +=== `kubernetes.pod.status.phase` type: keyword @@ -5195,7 +5195,7 @@ Kubernetes pod phase (Running, Pending...) [float] -=== kubernetes.pod.status.ready +=== `kubernetes.pod.status.ready` type: keyword @@ -5203,7 +5203,7 @@ Kubernetes pod ready status (true, false or unknown) [float] -=== kubernetes.pod.status.scheduled +=== `kubernetes.pod.status.scheduled` type: keyword @@ -5211,14 +5211,14 @@ Kubernetes pod scheduled status (true, false, unknown) [float] -== replicaset Fields +== replicaset fields kubernetes replica set metrics [float] -=== kubernetes.replicaset.name +=== `kubernetes.replicaset.name` type: keyword @@ -5226,14 +5226,14 @@ Kubernetes replica set name [float] -== replicas Fields +== replicas fields Kubernetes replica set paused status [float] -=== kubernetes.replicaset.replicas.available +=== `kubernetes.replicaset.replicas.available` type: long @@ -5241,7 +5241,7 @@ The number of replicas per ReplicaSet [float] -=== kubernetes.replicaset.replicas.desired +=== `kubernetes.replicaset.replicas.desired` type: long @@ -5249,7 +5249,7 @@ The number of replicas per ReplicaSet [float] -=== kubernetes.replicaset.replicas.ready +=== `kubernetes.replicaset.replicas.ready` type: long @@ -5257,7 +5257,7 @@ The number of ready replicas per ReplicaSet [float] -=== kubernetes.replicaset.replicas.observed +=== `kubernetes.replicaset.replicas.observed` type: long @@ -5265,7 +5265,7 @@ The generation observed by the ReplicaSet controller [float] -=== kubernetes.replicaset.replicas.labeled +=== `kubernetes.replicaset.replicas.labeled` type: long @@ -5273,14 +5273,14 @@ The number of fully labeled replicas per ReplicaSet [float] -== system Fields +== system fields kubernetes system containers metrics [float] -=== kubernetes.system.container +=== `kubernetes.system.container` type: keyword @@ -5288,7 +5288,7 @@ Container name [float] -=== kubernetes.system.start_time +=== `kubernetes.system.start_time` type: date @@ -5296,7 +5296,7 @@ Start time [float] -== cpu Fields +== cpu fields CPU usage metrics @@ -5305,7 +5305,7 @@ CPU usage metrics [float] -=== kubernetes.system.cpu.usage.core.ns +=== `kubernetes.system.cpu.usage.core.ns` type: long @@ -5313,7 +5313,7 @@ CPU Core usage nanoseconds [float] -=== kubernetes.system.cpu.usage.nanocores +=== `kubernetes.system.cpu.usage.nanocores` type: long @@ -5323,7 +5323,7 @@ CPU used nanocores [float] -=== kubernetes.system.memory.usage.bytes +=== `kubernetes.system.memory.usage.bytes` type: long @@ -5334,7 +5334,7 @@ Total memory usage [float] -=== kubernetes.system.memory.rss.bytes +=== `kubernetes.system.memory.rss.bytes` type: long @@ -5345,7 +5345,7 @@ RSS memory usage [float] -=== kubernetes.system.memory.workingset.bytes +=== `kubernetes.system.memory.workingset.bytes` type: long @@ -5355,7 +5355,7 @@ Working set memory usage [float] -=== kubernetes.system.memory.pagefaults +=== `kubernetes.system.memory.pagefaults` type: long @@ -5363,7 +5363,7 @@ Number of page faults [float] -=== kubernetes.system.memory.majorpagefaults +=== `kubernetes.system.memory.majorpagefaults` type: long @@ -5371,14 +5371,14 @@ Number of major page faults [float] -== volume Fields +== volume fields kubernetes volume metrics [float] -=== kubernetes.volume.name +=== `kubernetes.volume.name` type: keyword @@ -5388,7 +5388,7 @@ Volume name [float] -=== kubernetes.volume.fs.capacity.bytes +=== `kubernetes.volume.fs.capacity.bytes` type: long @@ -5399,7 +5399,7 @@ Filesystem total capacity in bytes [float] -=== kubernetes.volume.fs.available.bytes +=== `kubernetes.volume.fs.available.bytes` type: long @@ -5410,7 +5410,7 @@ Filesystem total available in bytes [float] -=== kubernetes.volume.fs.used.bytes +=== `kubernetes.volume.fs.used.bytes` type: long @@ -5421,7 +5421,7 @@ Filesystem total used in bytes [float] -=== kubernetes.volume.fs.inodes.used +=== `kubernetes.volume.fs.inodes.used` type: long @@ -5429,7 +5429,7 @@ Used inodes [float] -=== kubernetes.volume.fs.inodes.free +=== `kubernetes.volume.fs.inodes.free` type: long @@ -5437,7 +5437,7 @@ Free inodes [float] -=== kubernetes.volume.fs.inodes.count +=== `kubernetes.volume.fs.inodes.count` type: long @@ -5445,28 +5445,28 @@ Total inodes [[exported-fields-memcached]] -== Memcached Fields +== Memcached fields -[]beta +beta[] Memcached module [float] -== memcached Fields +== memcached fields [float] -== stats Fields +== stats fields stats [float] -=== memcached.stats.pid +=== `memcached.stats.pid` type: long @@ -5474,7 +5474,7 @@ Current process ID of the Memcached task. [float] -=== memcached.stats.uptime.sec +=== `memcached.stats.uptime.sec` type: long @@ -5482,7 +5482,7 @@ Memcached server uptime. [float] -=== memcached.stats.threads +=== `memcached.stats.threads` type: long @@ -5490,7 +5490,7 @@ Number of threads used by the current Memcached server process. [float] -=== memcached.stats.connections.current +=== `memcached.stats.connections.current` type: long @@ -5498,7 +5498,7 @@ Number of open connections to this Memcached server, should be the same value on [float] -=== memcached.stats.connections.total +=== `memcached.stats.connections.total` type: long @@ -5506,7 +5506,7 @@ Numer of successful connect attempts to this server since it has been started. [float] -=== memcached.stats.get.hits +=== `memcached.stats.get.hits` type: long @@ -5514,7 +5514,7 @@ Number of successful "get" commands (cache hits) since startup, divide them by t [float] -=== memcached.stats.get.misses +=== `memcached.stats.get.misses` type: long @@ -5522,7 +5522,7 @@ Number of failed "get" requests because nothing was cached for this key or the c [float] -=== memcached.stats.cmd.get +=== `memcached.stats.cmd.get` type: long @@ -5530,7 +5530,7 @@ Number of "get" commands received since server startup not counting if they were [float] -=== memcached.stats.cmd.set +=== `memcached.stats.cmd.set` type: long @@ -5538,7 +5538,7 @@ Number of "set" commands serviced since startup. [float] -=== memcached.stats.read.bytes +=== `memcached.stats.read.bytes` type: long @@ -5546,7 +5546,7 @@ Total number of bytes received from the network by this server. [float] -=== memcached.stats.written.bytes +=== `memcached.stats.written.bytes` type: long @@ -5554,7 +5554,7 @@ Total number of bytes send to the network by this server. [float] -=== memcached.stats.items.current +=== `memcached.stats.items.current` type: long @@ -5562,7 +5562,7 @@ Number of items currently in this server's cache. [float] -=== memcached.stats.items.total +=== `memcached.stats.items.total` type: long @@ -5570,7 +5570,7 @@ Number of items stored ever stored on this server. This is no "maximum item coun [float] -=== memcached.stats.evictions +=== `memcached.stats.evictions` type: long @@ -5578,124 +5578,124 @@ Number of objects removed from the cache to free up memory for new items because [[exported-fields-mongodb]] -== MongoDB Fields +== MongoDB fields Metrics collected from MongoDB servers. [float] -== mongodb Fields +== mongodb fields MongoDB metrics. [float] -== dbstats Fields +== dbstats fields dbstats provides an overview of a particular mongo database. This document is most concerned with data volumes of a database. [float] -=== mongodb.dbstats.avg_obj_size.bytes +=== `mongodb.dbstats.avg_obj_size.bytes` type: long format: bytes [float] -=== mongodb.dbstats.collections +=== `mongodb.dbstats.collections` type: integer [float] -=== mongodb.dbstats.data_size.bytes +=== `mongodb.dbstats.data_size.bytes` type: long format: bytes [float] -=== mongodb.dbstats.db +=== `mongodb.dbstats.db` type: keyword [float] -=== mongodb.dbstats.file_size.bytes +=== `mongodb.dbstats.file_size.bytes` type: long format: bytes [float] -=== mongodb.dbstats.index_size.bytes +=== `mongodb.dbstats.index_size.bytes` type: long format: bytes [float] -=== mongodb.dbstats.indexes +=== `mongodb.dbstats.indexes` type: long [float] -=== mongodb.dbstats.num_extents +=== `mongodb.dbstats.num_extents` type: long [float] -=== mongodb.dbstats.objects +=== `mongodb.dbstats.objects` type: long [float] -=== mongodb.dbstats.storage_size.bytes +=== `mongodb.dbstats.storage_size.bytes` type: long format: bytes [float] -=== mongodb.dbstats.ns_size_mb.mb +=== `mongodb.dbstats.ns_size_mb.mb` type: long [float] -=== mongodb.dbstats.data_file_version.major +=== `mongodb.dbstats.data_file_version.major` type: long [float] -=== mongodb.dbstats.data_file_version.minor +=== `mongodb.dbstats.data_file_version.minor` type: long [float] -=== mongodb.dbstats.extent_free_list.num +=== `mongodb.dbstats.extent_free_list.num` type: long [float] -=== mongodb.dbstats.extent_free_list.size.bytes +=== `mongodb.dbstats.extent_free_list.size.bytes` type: long format: bytes [float] -== status Fields +== status fields MongoDB server status metrics. [float] -=== mongodb.status.version +=== `mongodb.status.version` type: keyword @@ -5703,7 +5703,7 @@ Instance version. [float] -=== mongodb.status.uptime.ms +=== `mongodb.status.uptime.ms` type: long @@ -5711,7 +5711,7 @@ Instance uptime in milliseconds. [float] -=== mongodb.status.local_time +=== `mongodb.status.local_time` type: date @@ -5719,7 +5719,7 @@ Local time as reported by the MongoDB instance. [float] -=== mongodb.status.asserts.regular +=== `mongodb.status.asserts.regular` type: long @@ -5727,7 +5727,7 @@ Number of regular assertions produced by the server. [float] -=== mongodb.status.asserts.warning +=== `mongodb.status.asserts.warning` type: long @@ -5735,7 +5735,7 @@ Number of warning assertions produced by the server. [float] -=== mongodb.status.asserts.msg +=== `mongodb.status.asserts.msg` type: long @@ -5743,7 +5743,7 @@ Number of msg assertions produced by the server. [float] -=== mongodb.status.asserts.user +=== `mongodb.status.asserts.user` type: long @@ -5751,7 +5751,7 @@ Number of user assertions produced by the server. [float] -=== mongodb.status.asserts.rollovers +=== `mongodb.status.asserts.rollovers` type: long @@ -5759,14 +5759,14 @@ Number of rollovers assertions produced by the server. [float] -== background_flushing Fields +== background_flushing fields Data about the process MongoDB uses to write data to disk. This data is only available for instances that use the MMAPv1 storage engine. [float] -=== mongodb.status.background_flushing.flushes +=== `mongodb.status.background_flushing.flushes` type: long @@ -5774,7 +5774,7 @@ A counter that collects the number of times the database has flushed all writes [float] -=== mongodb.status.background_flushing.total.ms +=== `mongodb.status.background_flushing.total.ms` type: long @@ -5782,7 +5782,7 @@ The total number of milliseconds (ms) that the mongod processes have spent writi [float] -=== mongodb.status.background_flushing.average.ms +=== `mongodb.status.background_flushing.average.ms` type: long @@ -5790,7 +5790,7 @@ The average time spent flushing to disk per flush event. [float] -=== mongodb.status.background_flushing.last.ms +=== `mongodb.status.background_flushing.last.ms` type: long @@ -5798,7 +5798,7 @@ The amount of time, in milliseconds, that the last flush operation took to compl [float] -=== mongodb.status.background_flushing.last_finished +=== `mongodb.status.background_flushing.last_finished` type: date @@ -5806,14 +5806,14 @@ A timestamp of the last completed flush operation. [float] -== connections Fields +== connections fields Data regarding the current status of incoming connections and availability of the database server. [float] -=== mongodb.status.connections.current +=== `mongodb.status.connections.current` type: long @@ -5821,7 +5821,7 @@ The number of connections to the database server from clients. This number inclu [float] -=== mongodb.status.connections.available +=== `mongodb.status.connections.available` type: long @@ -5829,7 +5829,7 @@ The number of unused available incoming connections the database can provide. [float] -=== mongodb.status.connections.total_created +=== `mongodb.status.connections.total_created` type: long @@ -5837,14 +5837,14 @@ A count of all incoming connections created to the server. This number includes [float] -== journaling Fields +== journaling fields Data about the journaling-related operations and performance. Journaling information only appears for mongod instances that use the MMAPv1 storage engine and have journaling enabled. [float] -=== mongodb.status.journaling.commits +=== `mongodb.status.journaling.commits` type: long @@ -5852,7 +5852,7 @@ The number of transactions written to the journal during the last journal group [float] -=== mongodb.status.journaling.journaled.mb +=== `mongodb.status.journaling.journaled.mb` type: long @@ -5860,7 +5860,7 @@ The amount of data in megabytes (MB) written to journal during the last journal [float] -=== mongodb.status.journaling.write_to_data_files.mb +=== `mongodb.status.journaling.write_to_data_files.mb` type: long @@ -5868,7 +5868,7 @@ The amount of data in megabytes (MB) written from journal to the data files duri [float] -=== mongodb.status.journaling.compression +=== `mongodb.status.journaling.compression` type: long @@ -5876,7 +5876,7 @@ The compression ratio of the data written to the journal. [float] -=== mongodb.status.journaling.commits_in_write_lock +=== `mongodb.status.journaling.commits_in_write_lock` type: long @@ -5884,7 +5884,7 @@ Count of the commits that occurred while a write lock was held. Commits in a wri [float] -=== mongodb.status.journaling.early_commits +=== `mongodb.status.journaling.early_commits` type: long @@ -5892,14 +5892,14 @@ The number of times MongoDB requested a commit before the scheduled journal grou [float] -== times Fields +== times fields Information about the performance of the mongod instance during the various phases of journaling in the last journal group commit interval. [float] -=== mongodb.status.journaling.times.dt.ms +=== `mongodb.status.journaling.times.dt.ms` type: long @@ -5907,7 +5907,7 @@ The amount of time over which MongoDB collected the times data. Use this field t [float] -=== mongodb.status.journaling.times.prep_log_buffer.ms +=== `mongodb.status.journaling.times.prep_log_buffer.ms` type: long @@ -5915,7 +5915,7 @@ The amount of time spent preparing to write to the journal. Smaller values indic [float] -=== mongodb.status.journaling.times.write_to_journal.ms +=== `mongodb.status.journaling.times.write_to_journal.ms` type: long @@ -5923,7 +5923,7 @@ The amount of time spent actually writing to the journal. File system speeds and [float] -=== mongodb.status.journaling.times.write_to_data_files.ms +=== `mongodb.status.journaling.times.write_to_data_files.ms` type: long @@ -5931,7 +5931,7 @@ The amount of time spent writing to data files after journaling. File system spe [float] -=== mongodb.status.journaling.times.remap_private_view.ms +=== `mongodb.status.journaling.times.remap_private_view.ms` type: long @@ -5939,7 +5939,7 @@ The amount of time spent remapping copy-on-write memory mapped views. Smaller va [float] -=== mongodb.status.journaling.times.commits.ms +=== `mongodb.status.journaling.times.commits.ms` type: long @@ -5947,7 +5947,7 @@ The amount of time spent for commits. [float] -=== mongodb.status.journaling.times.commits_in_write_lock.ms +=== `mongodb.status.journaling.times.commits_in_write_lock.ms` type: long @@ -5955,14 +5955,14 @@ The amount of time spent for commits that occurred while a write lock was held. [float] -== extra_info Fields +== extra_info fields Platform specific data. [float] -=== mongodb.status.extra_info.heap_usage.bytes +=== `mongodb.status.extra_info.heap_usage.bytes` type: long @@ -5972,7 +5972,7 @@ The total size in bytes of heap space used by the database process. Only availab [float] -=== mongodb.status.extra_info.page_faults +=== `mongodb.status.extra_info.page_faults` type: long @@ -5980,14 +5980,14 @@ The total number of page faults that require disk operations. Page faults refer [float] -== network Fields +== network fields Platform specific data. [float] -=== mongodb.status.network.in.bytes +=== `mongodb.status.network.in.bytes` type: long @@ -5997,7 +5997,7 @@ The amount of network traffic, in bytes, received by this database. [float] -=== mongodb.status.network.out.bytes +=== `mongodb.status.network.out.bytes` type: long @@ -6007,7 +6007,7 @@ The amount of network traffic, in bytes, sent from this database. [float] -=== mongodb.status.network.requests +=== `mongodb.status.network.requests` type: long @@ -6015,14 +6015,14 @@ The total number of requests received by the server. [float] -== opcounters Fields +== opcounters fields An overview of database operations by type. [float] -=== mongodb.status.opcounters.insert +=== `mongodb.status.opcounters.insert` type: long @@ -6030,7 +6030,7 @@ The total number of insert operations received since the mongod instance last st [float] -=== mongodb.status.opcounters.query +=== `mongodb.status.opcounters.query` type: long @@ -6038,7 +6038,7 @@ The total number of queries received since the mongod instance last started. [float] -=== mongodb.status.opcounters.update +=== `mongodb.status.opcounters.update` type: long @@ -6046,7 +6046,7 @@ The total number of update operations received since the mongod instance last st [float] -=== mongodb.status.opcounters.delete +=== `mongodb.status.opcounters.delete` type: long @@ -6054,7 +6054,7 @@ The total number of delete operations received since the mongod instance last st [float] -=== mongodb.status.opcounters.getmore +=== `mongodb.status.opcounters.getmore` type: long @@ -6062,7 +6062,7 @@ The total number of getmore operations received since the mongod instance last s [float] -=== mongodb.status.opcounters.command +=== `mongodb.status.opcounters.command` type: long @@ -6070,14 +6070,14 @@ The total number of commands issued to the database since the mongod instance la [float] -== opcounters_replicated Fields +== opcounters_replicated fields An overview of database replication operations by type. [float] -=== mongodb.status.opcounters_replicated.insert +=== `mongodb.status.opcounters_replicated.insert` type: long @@ -6085,7 +6085,7 @@ The total number of replicated insert operations received since the mongod insta [float] -=== mongodb.status.opcounters_replicated.query +=== `mongodb.status.opcounters_replicated.query` type: long @@ -6093,7 +6093,7 @@ The total number of replicated queries received since the mongod instance last s [float] -=== mongodb.status.opcounters_replicated.update +=== `mongodb.status.opcounters_replicated.update` type: long @@ -6101,7 +6101,7 @@ The total number of replicated update operations received since the mongod insta [float] -=== mongodb.status.opcounters_replicated.delete +=== `mongodb.status.opcounters_replicated.delete` type: long @@ -6109,7 +6109,7 @@ The total number of replicated delete operations received since the mongod insta [float] -=== mongodb.status.opcounters_replicated.getmore +=== `mongodb.status.opcounters_replicated.getmore` type: long @@ -6117,7 +6117,7 @@ The total number of replicated getmore operations received since the mongod inst [float] -=== mongodb.status.opcounters_replicated.command +=== `mongodb.status.opcounters_replicated.command` type: long @@ -6125,14 +6125,14 @@ The total number of replicated commands issued to the database since the mongod [float] -== memory Fields +== memory fields Data about the current memory usage of the mongod server. [float] -=== mongodb.status.memory.bits +=== `mongodb.status.memory.bits` type: long @@ -6140,7 +6140,7 @@ Either 64 or 32, depending on which target architecture was specified during the [float] -=== mongodb.status.memory.resident.mb +=== `mongodb.status.memory.resident.mb` type: long @@ -6148,7 +6148,7 @@ The amount of RAM, in megabytes (MB), currently used by the database process. [float] -=== mongodb.status.memory.virtual.mb +=== `mongodb.status.memory.virtual.mb` type: long @@ -6156,7 +6156,7 @@ The amount, in megabytes (MB), of virtual memory used by the mongod process. [float] -=== mongodb.status.memory.mapped.mb +=== `mongodb.status.memory.mapped.mb` type: long @@ -6164,7 +6164,7 @@ The amount of mapped memory, in megabytes (MB), used by the database. Because Mo [float] -=== mongodb.status.memory.mapped_with_journal.mb +=== `mongodb.status.memory.mapped_with_journal.mb` type: long @@ -6172,7 +6172,7 @@ The amount of mapped memory, in megabytes (MB), including the memory used for jo [float] -=== mongodb.status.write_backs_queued +=== `mongodb.status.write_backs_queued` type: boolean @@ -6180,7 +6180,7 @@ True when there are operations from a mongos instance queued for retrying. [float] -=== mongodb.status.storage_engine.name +=== `mongodb.status.storage_engine.name` type: keyword @@ -6188,21 +6188,21 @@ A string that represents the name of the current storage engine. [float] -== wired_tiger Fields +== wired_tiger fields Statistics about the WiredTiger storage engine. [float] -== concurrent_transactions Fields +== concurrent_transactions fields Statistics about the transactions currently in progress. [float] -=== mongodb.status.wired_tiger.concurrent_transactions.write.out +=== `mongodb.status.wired_tiger.concurrent_transactions.write.out` type: long @@ -6210,7 +6210,7 @@ Number of concurrent write transaction in progress. [float] -=== mongodb.status.wired_tiger.concurrent_transactions.write.available +=== `mongodb.status.wired_tiger.concurrent_transactions.write.available` type: long @@ -6218,7 +6218,7 @@ Number of concurrent write tickets available. [float] -=== mongodb.status.wired_tiger.concurrent_transactions.write.total_tickets +=== `mongodb.status.wired_tiger.concurrent_transactions.write.total_tickets` type: long @@ -6226,7 +6226,7 @@ Number of total write tickets. [float] -=== mongodb.status.wired_tiger.concurrent_transactions.read.out +=== `mongodb.status.wired_tiger.concurrent_transactions.read.out` type: long @@ -6234,7 +6234,7 @@ Number of concurrent read transaction in progress. [float] -=== mongodb.status.wired_tiger.concurrent_transactions.read.available +=== `mongodb.status.wired_tiger.concurrent_transactions.read.available` type: long @@ -6242,7 +6242,7 @@ Number of concurrent read tickets available. [float] -=== mongodb.status.wired_tiger.concurrent_transactions.read.total_tickets +=== `mongodb.status.wired_tiger.concurrent_transactions.read.total_tickets` type: long @@ -6250,14 +6250,14 @@ Number of total read tickets. [float] -== cache Fields +== cache fields Statistics about the cache and page evictions from the cache. [float] -=== mongodb.status.wired_tiger.cache.maximum.bytes +=== `mongodb.status.wired_tiger.cache.maximum.bytes` type: long @@ -6267,7 +6267,7 @@ Maximum cache size. [float] -=== mongodb.status.wired_tiger.cache.used.bytes +=== `mongodb.status.wired_tiger.cache.used.bytes` type: long @@ -6277,7 +6277,7 @@ Size in byte of the data currently in cache. [float] -=== mongodb.status.wired_tiger.cache.dirty.bytes +=== `mongodb.status.wired_tiger.cache.dirty.bytes` type: long @@ -6287,7 +6287,7 @@ Size in bytes of the dirty data in the cache. [float] -=== mongodb.status.wired_tiger.cache.pages.read +=== `mongodb.status.wired_tiger.cache.pages.read` type: long @@ -6295,7 +6295,7 @@ Number of pages read into the cache. [float] -=== mongodb.status.wired_tiger.cache.pages.write +=== `mongodb.status.wired_tiger.cache.pages.write` type: long @@ -6303,7 +6303,7 @@ Number of pages written from the cache. [float] -=== mongodb.status.wired_tiger.cache.pages.evicted +=== `mongodb.status.wired_tiger.cache.pages.evicted` type: long @@ -6311,14 +6311,14 @@ Number of pages evicted from the cache. [float] -== log Fields +== log fields Statistics about the write ahead log used by WiredTiger. [float] -=== mongodb.status.wired_tiger.log.size.bytes +=== `mongodb.status.wired_tiger.log.size.bytes` type: long @@ -6328,7 +6328,7 @@ Total log size in bytes. [float] -=== mongodb.status.wired_tiger.log.write.bytes +=== `mongodb.status.wired_tiger.log.write.bytes` type: long @@ -6338,7 +6338,7 @@ Number of bytes written into the log. [float] -=== mongodb.status.wired_tiger.log.max_file_size.bytes +=== `mongodb.status.wired_tiger.log.max_file_size.bytes` type: long @@ -6348,7 +6348,7 @@ Maximum file size. [float] -=== mongodb.status.wired_tiger.log.flushes +=== `mongodb.status.wired_tiger.log.flushes` type: long @@ -6356,7 +6356,7 @@ Number of flush operations. [float] -=== mongodb.status.wired_tiger.log.writes +=== `mongodb.status.wired_tiger.log.writes` type: long @@ -6364,7 +6364,7 @@ Number of write operations. [float] -=== mongodb.status.wired_tiger.log.scans +=== `mongodb.status.wired_tiger.log.scans` type: long @@ -6372,7 +6372,7 @@ Number of scan operations. [float] -=== mongodb.status.wired_tiger.log.syncs +=== `mongodb.status.wired_tiger.log.syncs` type: long @@ -6380,35 +6380,35 @@ Number of sync operations. [[exported-fields-mysql]] -== MySQL Fields +== MySQL fields MySQL server status metrics collected from MySQL. [float] -== mysql Fields +== mysql fields `mysql` contains the metrics that were obtained from MySQL query. [float] -== status Fields +== status fields `status` contains the metrics that were obtained by the status SQL query. [float] -== aborted Fields +== aborted fields Aborted status fields. [float] -=== mysql.status.aborted.clients +=== `mysql.status.aborted.clients` type: long @@ -6416,7 +6416,7 @@ The number of connections that were aborted because the client died without clos [float] -=== mysql.status.aborted.connects +=== `mysql.status.aborted.connects` type: long @@ -6424,34 +6424,34 @@ The number of failed attempts to connect to the MySQL server. [float] -== binlog Fields +== binlog fields [float] -=== mysql.status.binlog.cache.disk_use +=== `mysql.status.binlog.cache.disk_use` type: long [float] -=== mysql.status.binlog.cache.use +=== `mysql.status.binlog.cache.use` type: long [float] -== bytes Fields +== bytes fields Bytes stats. [float] -=== mysql.status.bytes.received +=== `mysql.status.bytes.received` type: long @@ -6461,7 +6461,7 @@ The number of bytes received from all clients. [float] -=== mysql.status.bytes.sent +=== `mysql.status.bytes.sent` type: long @@ -6471,14 +6471,14 @@ The number of bytes sent to all clients. [float] -== threads Fields +== threads fields Threads stats. [float] -=== mysql.status.threads.cached +=== `mysql.status.threads.cached` type: long @@ -6486,7 +6486,7 @@ The number of cached threads. [float] -=== mysql.status.threads.created +=== `mysql.status.threads.created` type: long @@ -6494,7 +6494,7 @@ The number of created threads. [float] -=== mysql.status.threads.connected +=== `mysql.status.threads.connected` type: long @@ -6502,7 +6502,7 @@ The number of connected threads. [float] -=== mysql.status.threads.running +=== `mysql.status.threads.running` type: long @@ -6510,122 +6510,122 @@ The number of running threads. [float] -=== mysql.status.connections +=== `mysql.status.connections` type: long [float] -== created Fields +== created fields [float] -=== mysql.status.created.tmp.disk_tables +=== `mysql.status.created.tmp.disk_tables` type: long [float] -=== mysql.status.created.tmp.files +=== `mysql.status.created.tmp.files` type: long [float] -=== mysql.status.created.tmp.tables +=== `mysql.status.created.tmp.tables` type: long [float] -== delayed Fields +== delayed fields [float] -=== mysql.status.delayed.errors +=== `mysql.status.delayed.errors` type: long [float] -=== mysql.status.delayed.insert_threads +=== `mysql.status.delayed.insert_threads` type: long [float] -=== mysql.status.delayed.writes +=== `mysql.status.delayed.writes` type: long [float] -=== mysql.status.flush_commands +=== `mysql.status.flush_commands` type: long [float] -=== mysql.status.max_used_connections +=== `mysql.status.max_used_connections` type: long [float] -== open Fields +== open fields [float] -=== mysql.status.open.files +=== `mysql.status.open.files` type: long [float] -=== mysql.status.open.streams +=== `mysql.status.open.streams` type: long [float] -=== mysql.status.open.tables +=== `mysql.status.open.tables` type: long [float] -=== mysql.status.opened_tables +=== `mysql.status.opened_tables` type: long [float] -== command Fields +== command fields [float] -=== mysql.status.command.delete +=== `mysql.status.command.delete` type: long @@ -6633,7 +6633,7 @@ The number of DELETE queries since startup. [float] -=== mysql.status.command.insert +=== `mysql.status.command.insert` type: long @@ -6641,7 +6641,7 @@ The number of INSERT queries since startup. [float] -=== mysql.status.command.select +=== `mysql.status.command.select` type: long @@ -6649,7 +6649,7 @@ The number of SELECT queries since startup. [float] -=== mysql.status.command.update +=== `mysql.status.command.update` type: long @@ -6657,28 +6657,28 @@ The number of UPDATE queries since startup. [[exported-fields-nginx]] -== Nginx Fields +== Nginx fields Nginx server status metrics collected from various modules. [float] -== nginx Fields +== nginx fields `nginx` contains the metrics that were scraped from nginx. [float] -== stubstatus Fields +== stubstatus fields `stubstatus` contains the metrics that were scraped from the ngx_http_stub_status_module status page. [float] -=== nginx.stubstatus.hostname +=== `nginx.stubstatus.hostname` type: keyword @@ -6686,7 +6686,7 @@ Nginx hostname. [float] -=== nginx.stubstatus.active +=== `nginx.stubstatus.active` type: long @@ -6694,7 +6694,7 @@ The current number of active client connections including Waiting connections. [float] -=== nginx.stubstatus.accepts +=== `nginx.stubstatus.accepts` type: long @@ -6702,7 +6702,7 @@ The total number of accepted client connections. [float] -=== nginx.stubstatus.handled +=== `nginx.stubstatus.handled` type: long @@ -6710,7 +6710,7 @@ The total number of handled client connections. [float] -=== nginx.stubstatus.dropped +=== `nginx.stubstatus.dropped` type: long @@ -6718,7 +6718,7 @@ The total number of dropped client connections. [float] -=== nginx.stubstatus.requests +=== `nginx.stubstatus.requests` type: long @@ -6726,7 +6726,7 @@ The total number of client requests. [float] -=== nginx.stubstatus.current +=== `nginx.stubstatus.current` type: long @@ -6734,7 +6734,7 @@ The current number of client requests. [float] -=== nginx.stubstatus.reading +=== `nginx.stubstatus.reading` type: long @@ -6742,7 +6742,7 @@ The current number of connections where Nginx is reading the request header. [float] -=== nginx.stubstatus.writing +=== `nginx.stubstatus.writing` type: long @@ -6750,7 +6750,7 @@ The current number of connections where Nginx is writing the response back to th [float] -=== nginx.stubstatus.waiting +=== `nginx.stubstatus.waiting` type: long @@ -6758,7 +6758,7 @@ The current number of idle client connections waiting for a request. [[exported-fields-php_fpm]] -== PHP-FPM Fields +== PHP_FPM fields beta[] PHP-FPM server status metrics collected from PHP-FPM. @@ -6766,21 +6766,21 @@ PHP-FPM server status metrics collected from PHP-FPM. [float] -== php_fpm Fields +== php_fpm fields `php_fpm` contains the metrics that were obtained from PHP-FPM status page call. [float] -== pool Fields +== pool fields `pool` contains the metrics that were obtained from the PHP-FPM process pool. [float] -=== php_fpm.pool.name +=== `php_fpm.pool.name` type: keyword @@ -6788,14 +6788,14 @@ The name of the pool. [float] -== connections Fields +== connections fields Connection state specific statistics. [float] -=== php_fpm.pool.connections.accepted +=== `php_fpm.pool.connections.accepted` type: long @@ -6803,7 +6803,7 @@ The number of incoming requests that the PHP-FPM server has accepted; when a con [float] -=== php_fpm.pool.connections.queued +=== `php_fpm.pool.connections.queued` type: long @@ -6811,14 +6811,14 @@ The current number of connections that have been initiated, but not yet accepted [float] -== processes Fields +== processes fields Process state specific statistics. [float] -=== php_fpm.pool.processes.idle +=== `php_fpm.pool.processes.idle` type: long @@ -6826,7 +6826,7 @@ The number of servers in the `waiting to process` state (i.e. not currently serv [float] -=== php_fpm.pool.processes.active +=== `php_fpm.pool.processes.active` type: long @@ -6834,7 +6834,7 @@ The number of servers current processing a page - the minimum is `1` (so even on [float] -=== php_fpm.pool.slow_requests +=== `php_fpm.pool.slow_requests` type: long @@ -6842,28 +6842,28 @@ The number of times a request execution time has exceeded `request_slowlog_timeo [[exported-fields-postgresql]] -== PostgreSQL Fields +== PostgreSQL fields Metrics collected from PostgreSQL servers. [float] -== postgresql Fields +== postgresql fields PostgreSQL metrics. [float] -== activity Fields +== activity fields One document per server process, showing information related to the current activity of that process, such as state and current query. Collected by querying pg_stat_activity. [float] -=== postgresql.activity.database.oid +=== `postgresql.activity.database.oid` type: long @@ -6871,7 +6871,7 @@ OID of the database this backend is connected to. [float] -=== postgresql.activity.database.name +=== `postgresql.activity.database.name` type: keyword @@ -6879,7 +6879,7 @@ Name of the database this backend is connected to. [float] -=== postgresql.activity.pid +=== `postgresql.activity.pid` type: long @@ -6887,7 +6887,7 @@ Process ID of this backend. [float] -=== postgresql.activity.user.id +=== `postgresql.activity.user.id` type: long @@ -6895,31 +6895,31 @@ OID of the user logged into this backend. [float] -=== postgresql.activity.user.name +=== `postgresql.activity.user.name` Name of the user logged into this backend. [float] -=== postgresql.activity.application_name +=== `postgresql.activity.application_name` Name of the application that is connected to this backend. [float] -=== postgresql.activity.client.address +=== `postgresql.activity.client.address` IP address of the client connected to this backend. [float] -=== postgresql.activity.client.hostname +=== `postgresql.activity.client.hostname` Host name of the connected client, as reported by a reverse DNS lookup of client_addr. [float] -=== postgresql.activity.client.port +=== `postgresql.activity.client.port` type: long @@ -6927,7 +6927,7 @@ TCP port number that the client is using for communication with this backend, or [float] -=== postgresql.activity.backend_start +=== `postgresql.activity.backend_start` type: date @@ -6935,7 +6935,7 @@ Time when this process was started, i.e., when the client connected to the serve [float] -=== postgresql.activity.transaction_start +=== `postgresql.activity.transaction_start` type: date @@ -6943,7 +6943,7 @@ Time when this process' current transaction was started. [float] -=== postgresql.activity.query_start +=== `postgresql.activity.query_start` type: date @@ -6951,7 +6951,7 @@ Time when the currently active query was started, or if state is not active, whe [float] -=== postgresql.activity.state_change +=== `postgresql.activity.state_change` type: date @@ -6959,7 +6959,7 @@ Time when the state was last changed. [float] -=== postgresql.activity.waiting +=== `postgresql.activity.waiting` type: boolean @@ -6967,7 +6967,7 @@ True if this backend is currently waiting on a lock. [float] -=== postgresql.activity.state +=== `postgresql.activity.state` Current overall state of this backend. Possible values are: @@ -6983,20 +6983,20 @@ Current overall state of this backend. Possible values are: [float] -=== postgresql.activity.query +=== `postgresql.activity.query` Text of this backend's most recent query. If state is active this field shows the currently executing query. In all other states, it shows the last query that was executed. [float] -== bgwriter Fields +== bgwriter fields Statistics about the background writer process's activity. Collected using the pg_stat_bgwriter query. [float] -=== postgresql.bgwriter.checkpoints.scheduled +=== `postgresql.bgwriter.checkpoints.scheduled` type: long @@ -7004,7 +7004,7 @@ Number of scheduled checkpoints that have been performed. [float] -=== postgresql.bgwriter.checkpoints.requested +=== `postgresql.bgwriter.checkpoints.requested` type: long @@ -7012,7 +7012,7 @@ Number of requested checkpoints that have been performed. [float] -=== postgresql.bgwriter.checkpoints.times.write.ms +=== `postgresql.bgwriter.checkpoints.times.write.ms` type: float @@ -7020,7 +7020,7 @@ Total amount of time that has been spent in the portion of checkpoint processing [float] -=== postgresql.bgwriter.checkpoints.times.sync.ms +=== `postgresql.bgwriter.checkpoints.times.sync.ms` type: float @@ -7028,7 +7028,7 @@ Total amount of time that has been spent in the portion of checkpoint processing [float] -=== postgresql.bgwriter.buffers.checkpoints +=== `postgresql.bgwriter.buffers.checkpoints` type: long @@ -7036,7 +7036,7 @@ Number of buffers written during checkpoints. [float] -=== postgresql.bgwriter.buffers.clean +=== `postgresql.bgwriter.buffers.clean` type: long @@ -7044,7 +7044,7 @@ Number of buffers written by the background writer. [float] -=== postgresql.bgwriter.buffers.clean_full +=== `postgresql.bgwriter.buffers.clean_full` type: long @@ -7052,7 +7052,7 @@ Number of times the background writer stopped a cleaning scan because it had wri [float] -=== postgresql.bgwriter.buffers.backend +=== `postgresql.bgwriter.buffers.backend` type: long @@ -7060,7 +7060,7 @@ Number of buffers written directly by a backend. [float] -=== postgresql.bgwriter.buffers.backend_fsync +=== `postgresql.bgwriter.buffers.backend_fsync` type: long @@ -7068,7 +7068,7 @@ Number of times a backend had to execute its own fsync call (normally the backgr [float] -=== postgresql.bgwriter.buffers.allocated +=== `postgresql.bgwriter.buffers.allocated` type: long @@ -7076,7 +7076,7 @@ Number of buffers allocated. [float] -=== postgresql.bgwriter.stats_reset +=== `postgresql.bgwriter.stats_reset` type: date @@ -7084,14 +7084,14 @@ Time at which these statistics were last reset. [float] -== database Fields +== database fields One row per database, showing database-wide statistics. Collected by querying pg_stat_database [float] -=== postgresql.database.oid +=== `postgresql.database.oid` type: long @@ -7099,7 +7099,7 @@ OID of the database this backend is connected to. [float] -=== postgresql.database.name +=== `postgresql.database.name` type: keyword @@ -7107,7 +7107,7 @@ Name of the database this backend is connected to. [float] -=== postgresql.database.number_of_backends +=== `postgresql.database.number_of_backends` type: long @@ -7115,7 +7115,7 @@ Number of backends currently connected to this database. [float] -=== postgresql.database.transactions.commit +=== `postgresql.database.transactions.commit` type: long @@ -7123,7 +7123,7 @@ Number of transactions in this database that have been committed. [float] -=== postgresql.database.transactions.rollback +=== `postgresql.database.transactions.rollback` type: long @@ -7131,7 +7131,7 @@ Number of transactions in this database that have been rolled back. [float] -=== postgresql.database.blocks.read +=== `postgresql.database.blocks.read` type: long @@ -7139,7 +7139,7 @@ Number of disk blocks read in this database. [float] -=== postgresql.database.blocks.hit +=== `postgresql.database.blocks.hit` type: long @@ -7147,7 +7147,7 @@ Number of times disk blocks were found already in the buffer cache, so that a re [float] -=== postgresql.database.blocks.time.read.ms +=== `postgresql.database.blocks.time.read.ms` type: long @@ -7155,7 +7155,7 @@ Time spent reading data file blocks by backends in this database, in millisecond [float] -=== postgresql.database.blocks.time.write.ms +=== `postgresql.database.blocks.time.write.ms` type: long @@ -7163,7 +7163,7 @@ Time spent writing data file blocks by backends in this database, in millisecond [float] -=== postgresql.database.rows.returned +=== `postgresql.database.rows.returned` type: long @@ -7171,7 +7171,7 @@ Number of rows returned by queries in this database. [float] -=== postgresql.database.rows.fetched +=== `postgresql.database.rows.fetched` type: long @@ -7179,7 +7179,7 @@ Number of rows fetched by queries in this database. [float] -=== postgresql.database.rows.inserted +=== `postgresql.database.rows.inserted` type: long @@ -7187,7 +7187,7 @@ Number of rows inserted by queries in this database. [float] -=== postgresql.database.rows.updated +=== `postgresql.database.rows.updated` type: long @@ -7195,7 +7195,7 @@ Number of rows updated by queries in this database. [float] -=== postgresql.database.rows.deleted +=== `postgresql.database.rows.deleted` type: long @@ -7203,7 +7203,7 @@ Number of rows deleted by queries in this database. [float] -=== postgresql.database.conflicts +=== `postgresql.database.conflicts` type: long @@ -7211,7 +7211,7 @@ Number of queries canceled due to conflicts with recovery in this database. [float] -=== postgresql.database.temporary.files +=== `postgresql.database.temporary.files` type: long @@ -7219,7 +7219,7 @@ Number of temporary files created by queries in this database. All temporary fil [float] -=== postgresql.database.temporary.bytes +=== `postgresql.database.temporary.bytes` type: long @@ -7227,7 +7227,7 @@ Total amount of data written to temporary files by queries in this database. All [float] -=== postgresql.database.deadlocks +=== `postgresql.database.deadlocks` type: long @@ -7235,7 +7235,7 @@ Number of deadlocks detected in this database. [float] -=== postgresql.database.stats_reset +=== `postgresql.database.stats_reset` type: date @@ -7243,7 +7243,7 @@ Time at which these statistics were last reset. [[exported-fields-prometheus]] -== Prometheus Fields +== Prometheus fields beta[] Stats collected from Prometheus. @@ -7251,27 +7251,27 @@ Stats collected from Prometheus. [float] -== prometheus Fields +== prometheus fields [float] -== stats Fields +== stats fields Stats about the Prometheus server. [float] -== notifications Fields +== notifications fields Notification stats. [float] -=== prometheus.stats.notifications.queue_length +=== `prometheus.stats.notifications.queue_length` type: long @@ -7279,7 +7279,7 @@ Current queue length. [float] -=== prometheus.stats.notifications.dropped +=== `prometheus.stats.notifications.dropped` type: long @@ -7287,7 +7287,7 @@ Number of dropped queue events. [float] -=== prometheus.stats.processes.open_fds +=== `prometheus.stats.processes.open_fds` type: long @@ -7295,7 +7295,7 @@ Number of open file descriptors. [float] -=== prometheus.stats.storage.chunks_to_persist +=== `prometheus.stats.storage.chunks_to_persist` type: long @@ -7303,28 +7303,28 @@ Number of memory chunks that are not yet persisted to disk. [[exported-fields-rabbitmq]] -== RabbitMQ Fields +== RabbitMQ fields -[]experimental +experimental[] RabbitMQ module [float] -== rabbitmq Fields +== rabbitmq fields [float] -== node Fields +== node fields node [float] -=== rabbitmq.node.disk.free.bytes +=== `rabbitmq.node.disk.free.bytes` type: long @@ -7334,7 +7334,7 @@ Disk free space in bytes. [float] -=== rabbitmq.node.disk.free.limit.bytes +=== `rabbitmq.node.disk.free.limit.bytes` type: long @@ -7344,7 +7344,7 @@ Point at which the disk alarm will go off. [float] -=== rabbitmq.node.fd.total +=== `rabbitmq.node.fd.total` type: long @@ -7352,7 +7352,7 @@ File descriptors available. [float] -=== rabbitmq.node.fd.used +=== `rabbitmq.node.fd.used` type: long @@ -7360,7 +7360,7 @@ Used file descriptors. [float] -=== rabbitmq.node.gc.num.count +=== `rabbitmq.node.gc.num.count` type: long @@ -7368,7 +7368,7 @@ Number of GC operations. [float] -=== rabbitmq.node.gc.reclaimed.bytes +=== `rabbitmq.node.gc.reclaimed.bytes` type: long @@ -7378,7 +7378,7 @@ GC bytes reclaimed. [float] -=== rabbitmq.node.io.file_handle.open_attempt.avg.ms +=== `rabbitmq.node.io.file_handle.open_attempt.avg.ms` type: long @@ -7386,7 +7386,7 @@ File handle open avg time [float] -=== rabbitmq.node.io.file_handle.open_attempt.count +=== `rabbitmq.node.io.file_handle.open_attempt.count` type: long @@ -7394,7 +7394,7 @@ File handle open attempts [float] -=== rabbitmq.node.io.read.avg.ms +=== `rabbitmq.node.io.read.avg.ms` type: long @@ -7402,7 +7402,7 @@ File handle read avg time [float] -=== rabbitmq.node.io.read.bytes +=== `rabbitmq.node.io.read.bytes` type: long @@ -7412,7 +7412,7 @@ Data read in bytes [float] -=== rabbitmq.node.io.read.count +=== `rabbitmq.node.io.read.count` type: long @@ -7420,7 +7420,7 @@ Data read operations [float] -=== rabbitmq.node.io.reopen.count +=== `rabbitmq.node.io.reopen.count` type: long @@ -7428,7 +7428,7 @@ Data reopen operations [float] -=== rabbitmq.node.io.seek.avg.ms +=== `rabbitmq.node.io.seek.avg.ms` type: long @@ -7436,7 +7436,7 @@ Data seek avg time [float] -=== rabbitmq.node.io.seek.count +=== `rabbitmq.node.io.seek.count` type: long @@ -7444,7 +7444,7 @@ Data seek operations [float] -=== rabbitmq.node.io.sync.avg.ms +=== `rabbitmq.node.io.sync.avg.ms` type: long @@ -7452,7 +7452,7 @@ Data sync avg time [float] -=== rabbitmq.node.io.sync.count +=== `rabbitmq.node.io.sync.count` type: long @@ -7460,7 +7460,7 @@ Data sync operations [float] -=== rabbitmq.node.io.write.avg.ms +=== `rabbitmq.node.io.write.avg.ms` type: long @@ -7468,7 +7468,7 @@ Data write avg time [float] -=== rabbitmq.node.io.write.bytes +=== `rabbitmq.node.io.write.bytes` type: long @@ -7478,7 +7478,7 @@ Data write in bytes [float] -=== rabbitmq.node.io.write.count +=== `rabbitmq.node.io.write.count` type: long @@ -7486,7 +7486,7 @@ Data write operations [float] -=== rabbitmq.node.mem.limit.bytes +=== `rabbitmq.node.mem.limit.bytes` type: long @@ -7496,7 +7496,7 @@ Point at which the memory alarm will go off. [float] -=== rabbitmq.node.mem.used.bytes +=== `rabbitmq.node.mem.used.bytes` type: long @@ -7504,7 +7504,7 @@ Memory used in bytes. [float] -=== rabbitmq.node.mnesia.disk.tx.count +=== `rabbitmq.node.mnesia.disk.tx.count` type: long @@ -7512,7 +7512,7 @@ Number of Mnesia transactions which have been performed that required writes to [float] -=== rabbitmq.node.mnesia.ram.tx.count +=== `rabbitmq.node.mnesia.ram.tx.count` type: long @@ -7520,7 +7520,7 @@ Number of Mnesia transactions which have been performed that did not require wri [float] -=== rabbitmq.node.msg.store_read.count +=== `rabbitmq.node.msg.store_read.count` type: long @@ -7528,7 +7528,7 @@ Number of messages which have been read from the message store. [float] -=== rabbitmq.node.msg.store_write.count +=== `rabbitmq.node.msg.store_write.count` type: long @@ -7536,7 +7536,7 @@ Number of messages which have been written to the message store. [float] -=== rabbitmq.node.name +=== `rabbitmq.node.name` type: keyword @@ -7544,7 +7544,7 @@ Node name [float] -=== rabbitmq.node.proc.total +=== `rabbitmq.node.proc.total` type: long @@ -7552,7 +7552,7 @@ Maximum number of Erlang processes. [float] -=== rabbitmq.node.proc.used +=== `rabbitmq.node.proc.used` type: long @@ -7560,7 +7560,7 @@ Number of Erlang processes in use. [float] -=== rabbitmq.node.processors +=== `rabbitmq.node.processors` type: long @@ -7568,7 +7568,7 @@ Number of cores detected and usable by Erlang. [float] -=== rabbitmq.node.queue.index.journal_write.count +=== `rabbitmq.node.queue.index.journal_write.count` type: long @@ -7576,7 +7576,7 @@ Number of records written to the queue index journal. [float] -=== rabbitmq.node.queue.index.read.count +=== `rabbitmq.node.queue.index.read.count` type: long @@ -7584,7 +7584,7 @@ Number of records read from the queue index. [float] -=== rabbitmq.node.queue.index.write.count +=== `rabbitmq.node.queue.index.write.count` type: long @@ -7592,7 +7592,7 @@ Number of records written to the queue index. [float] -=== rabbitmq.node.run.queue +=== `rabbitmq.node.run.queue` type: long @@ -7600,7 +7600,7 @@ Average number of Erlang processes waiting to run. [float] -=== rabbitmq.node.socket.total +=== `rabbitmq.node.socket.total` type: long @@ -7608,7 +7608,7 @@ File descriptors available for use as sockets. [float] -=== rabbitmq.node.socket.used +=== `rabbitmq.node.socket.used` type: long @@ -7616,7 +7616,7 @@ File descriptors used as sockets. [float] -=== rabbitmq.node.type +=== `rabbitmq.node.type` type: keyword @@ -7624,7 +7624,7 @@ Node type. [float] -=== rabbitmq.node.uptime +=== `rabbitmq.node.uptime` type: long @@ -7632,35 +7632,35 @@ Node uptime. [[exported-fields-redis]] -== Redis Fields +== Redis fields Redis metrics collected from Redis. [float] -== redis Fields +== redis fields `redis` contains the information and statistics from Redis. [float] -== info Fields +== info fields `info` contains the information and statistics returned by the `INFO` command. [float] -== clients Fields +== clients fields Redis client stats. [float] -=== redis.info.clients.connected +=== `redis.info.clients.connected` type: long @@ -7668,7 +7668,7 @@ Number of client connections (excluding connections from slaves). [float] -=== redis.info.clients.longest_output_list +=== `redis.info.clients.longest_output_list` type: long @@ -7676,7 +7676,7 @@ Longest output list among current client connections. [float] -=== redis.info.clients.biggest_input_buf +=== `redis.info.clients.biggest_input_buf` type: long @@ -7684,7 +7684,7 @@ Biggest input buffer among current client connections. [float] -=== redis.info.clients.blocked +=== `redis.info.clients.blocked` type: long @@ -7692,14 +7692,14 @@ Number of clients pending on a blocking call (BLPOP, BRPOP, BRPOPLPUSH). [float] -== cluster Fields +== cluster fields Redis cluster information. [float] -=== redis.info.cluster.enabled +=== `redis.info.cluster.enabled` type: boolean @@ -7707,14 +7707,14 @@ Indicates that the Redis cluster is enabled. [float] -== cpu Fields +== cpu fields Redis CPU stats [float] -=== redis.info.cpu.used.sys +=== `redis.info.cpu.used.sys` type: scaled_float @@ -7722,7 +7722,7 @@ System CPU consumed by the Redis server. [float] -=== redis.info.cpu.used.sys_children +=== `redis.info.cpu.used.sys_children` type: scaled_float @@ -7730,7 +7730,7 @@ User CPU consumed by the Redis server. [float] -=== redis.info.cpu.used.user +=== `redis.info.cpu.used.user` type: scaled_float @@ -7738,7 +7738,7 @@ System CPU consumed by the background processes. [float] -=== redis.info.cpu.used.user_children +=== `redis.info.cpu.used.user_children` type: scaled_float @@ -7746,14 +7746,14 @@ User CPU consumed by the background processes. [float] -== memory Fields +== memory fields Redis memory stats. [float] -=== redis.info.memory.used.value +=== `redis.info.memory.used.value` type: long @@ -7762,7 +7762,7 @@ format: bytes Used memory. [float] -=== redis.info.memory.used.rss +=== `redis.info.memory.used.rss` type: long @@ -7772,7 +7772,7 @@ Used memory rss. [float] -=== redis.info.memory.used.peak +=== `redis.info.memory.used.peak` type: long @@ -7782,7 +7782,7 @@ Used memory peak. [float] -=== redis.info.memory.used.lua +=== `redis.info.memory.used.lua` type: long @@ -7792,7 +7792,7 @@ Used memory lua. [float] -=== redis.info.memory.allocator +=== `redis.info.memory.allocator` type: keyword @@ -7800,446 +7800,446 @@ Memory allocator. [float] -== persistence Fields +== persistence fields Redis CPU stats. [float] -=== redis.info.persistence.loading +=== `redis.info.persistence.loading` type: boolean None [float] -== rdb Fields +== rdb fields None [float] -=== redis.info.persistence.rdb.last_save.changes_since +=== `redis.info.persistence.rdb.last_save.changes_since` type: long None [float] -=== redis.info.persistence.rdb.bgsave.in_progress +=== `redis.info.persistence.rdb.bgsave.in_progress` type: boolean None [float] -=== redis.info.persistence.rdb.last_save.time +=== `redis.info.persistence.rdb.last_save.time` type: long None [float] -=== redis.info.persistence.rdb.bgsave.last_status +=== `redis.info.persistence.rdb.bgsave.last_status` type: keyword None [float] -=== redis.info.persistence.rdb.bgsave.last_time.sec +=== `redis.info.persistence.rdb.bgsave.last_time.sec` type: long None [float] -=== redis.info.persistence.rdb.bgsave.current_time.sec +=== `redis.info.persistence.rdb.bgsave.current_time.sec` type: long None [float] -== aof Fields +== aof fields None [float] -=== redis.info.persistence.aof.enabled +=== `redis.info.persistence.aof.enabled` type: boolean None [float] -=== redis.info.persistence.aof.rewrite.in_progress +=== `redis.info.persistence.aof.rewrite.in_progress` type: boolean None [float] -=== redis.info.persistence.aof.rewrite.scheduled +=== `redis.info.persistence.aof.rewrite.scheduled` type: boolean None [float] -=== redis.info.persistence.aof.rewrite.last_time.sec +=== `redis.info.persistence.aof.rewrite.last_time.sec` type: long None [float] -=== redis.info.persistence.aof.rewrite.current_time.sec +=== `redis.info.persistence.aof.rewrite.current_time.sec` type: long None [float] -=== redis.info.persistence.aof.bgrewrite.last_status +=== `redis.info.persistence.aof.bgrewrite.last_status` type: keyword None [float] -=== redis.info.persistence.aof.write.last_status +=== `redis.info.persistence.aof.write.last_status` type: keyword None [float] -== replication Fields +== replication fields Replication [float] -=== redis.info.replication.role +=== `redis.info.replication.role` type: keyword None [float] -=== redis.info.replication.connected_slaves +=== `redis.info.replication.connected_slaves` type: long None [float] -=== redis.info.replication.master_offset +=== `redis.info.replication.master_offset` type: long None [float] -=== redis.info.replication.backlog.active +=== `redis.info.replication.backlog.active` type: long None [float] -=== redis.info.replication.backlog.size +=== `redis.info.replication.backlog.size` type: long None [float] -=== redis.info.replication.backlog.first_byte_offset +=== `redis.info.replication.backlog.first_byte_offset` type: long None [float] -=== redis.info.replication.backlog.histlen +=== `redis.info.replication.backlog.histlen` type: long None [float] -== server Fields +== server fields Server info [float] -=== redis.info.server.version +=== `redis.info.server.version` type: keyword None [float] -=== redis.info.server.git_sha1 +=== `redis.info.server.git_sha1` type: keyword None [float] -=== redis.info.server.git_dirty +=== `redis.info.server.git_dirty` type: keyword None [float] -=== redis.info.server.build_id +=== `redis.info.server.build_id` type: keyword None [float] -=== redis.info.server.mode +=== `redis.info.server.mode` type: keyword None [float] -=== redis.info.server.os +=== `redis.info.server.os` type: keyword None [float] -=== redis.info.server.arch_bits +=== `redis.info.server.arch_bits` type: keyword None [float] -=== redis.info.server.multiplexing_api +=== `redis.info.server.multiplexing_api` type: keyword None [float] -=== redis.info.server.gcc_version +=== `redis.info.server.gcc_version` type: keyword None [float] -=== redis.info.server.process_id +=== `redis.info.server.process_id` type: long None [float] -=== redis.info.server.run_id +=== `redis.info.server.run_id` type: keyword None [float] -=== redis.info.server.tcp_port +=== `redis.info.server.tcp_port` type: long None [float] -=== redis.info.server.uptime +=== `redis.info.server.uptime` type: long None [float] -=== redis.info.server.hz +=== `redis.info.server.hz` type: long None [float] -=== redis.info.server.lru_clock +=== `redis.info.server.lru_clock` type: long None [float] -=== redis.info.server.config_file +=== `redis.info.server.config_file` type: keyword None [float] -== stats Fields +== stats fields Redis stats. [float] -=== redis.info.stats.connections.received +=== `redis.info.stats.connections.received` type: long Total number of connections received. [float] -=== redis.info.stats.connections.rejected +=== `redis.info.stats.connections.rejected` type: long Total number of connections rejected. [float] -=== redis.info.stats.commands_processed +=== `redis.info.stats.commands_processed` type: long Total number of commands preocessed. [float] -=== redis.info.stats.net.input.bytes +=== `redis.info.stats.net.input.bytes` type: long Total network input in bytes. [float] -=== redis.info.stats.net.output.bytes +=== `redis.info.stats.net.output.bytes` type: long Total network output in bytes. [float] -=== redis.info.stats.instantaneous.ops_per_sec +=== `redis.info.stats.instantaneous.ops_per_sec` type: long None [float] -=== redis.info.stats.instantaneous.input_kbps +=== `redis.info.stats.instantaneous.input_kbps` type: scaled_float None [float] -=== redis.info.stats.instantaneous.output_kbps +=== `redis.info.stats.instantaneous.output_kbps` type: scaled_float None [float] -=== redis.info.stats.sync.full +=== `redis.info.stats.sync.full` type: long None [float] -=== redis.info.stats.sync.partial.ok +=== `redis.info.stats.sync.partial.ok` type: long None [float] -=== redis.info.stats.sync.partial.err +=== `redis.info.stats.sync.partial.err` type: long None [float] -=== redis.info.stats.keys.expired +=== `redis.info.stats.keys.expired` type: long None [float] -=== redis.info.stats.keys.evicted +=== `redis.info.stats.keys.evicted` type: long None [float] -=== redis.info.stats.keyspace.hits +=== `redis.info.stats.keyspace.hits` type: long None [float] -=== redis.info.stats.keyspace.misses +=== `redis.info.stats.keyspace.misses` type: long None [float] -=== redis.info.stats.pubsub.channels +=== `redis.info.stats.pubsub.channels` type: long None [float] -=== redis.info.stats.pubsub.patterns +=== `redis.info.stats.pubsub.patterns` type: long None [float] -=== redis.info.stats.latest_fork_usec +=== `redis.info.stats.latest_fork_usec` type: long None [float] -=== redis.info.stats.migrate_cached_sockets +=== `redis.info.stats.migrate_cached_sockets` type: long None [float] -== keyspace Fields +== keyspace fields `keyspace` contains the information about the keyspaces returned by the `INFO` command. [float] -=== redis.keyspace.id +=== `redis.keyspace.id` type: keyword @@ -8247,7 +8247,7 @@ Keyspace identifier. [float] -=== redis.keyspace.avg_ttl +=== `redis.keyspace.avg_ttl` type: long @@ -8255,7 +8255,7 @@ Average ttl. [float] -=== redis.keyspace.keys +=== `redis.keyspace.keys` type: long @@ -8263,35 +8263,35 @@ Number of keys in the keyspace. [float] -=== redis.keyspace.expires +=== `redis.keyspace.expires` type: long [[exported-fields-system]] -== System Fields +== System fields System status metrics, like CPU and memory usage, that are collected from the operating system. [float] -== system Fields +== system fields `system` contains local system metrics. [float] -== core Fields +== core fields `system-core` contains CPU metrics for a single core of a multi-core system. [float] -=== system.core.id +=== `system.core.id` type: long @@ -8299,7 +8299,7 @@ CPU Core number. [float] -=== system.core.user.pct +=== `system.core.user.pct` type: scaled_float @@ -8309,7 +8309,7 @@ The percentage of CPU time spent in user space. [float] -=== system.core.user.ticks +=== `system.core.user.ticks` type: long @@ -8317,7 +8317,7 @@ The amount of CPU time spent in user space. [float] -=== system.core.system.pct +=== `system.core.system.pct` type: scaled_float @@ -8327,7 +8327,7 @@ The percentage of CPU time spent in kernel space. [float] -=== system.core.system.ticks +=== `system.core.system.ticks` type: long @@ -8335,7 +8335,7 @@ The amount of CPU time spent in kernel space. [float] -=== system.core.nice.pct +=== `system.core.nice.pct` type: scaled_float @@ -8345,7 +8345,7 @@ The percentage of CPU time spent on low-priority processes. [float] -=== system.core.nice.ticks +=== `system.core.nice.ticks` type: long @@ -8353,7 +8353,7 @@ The amount of CPU time spent on low-priority processes. [float] -=== system.core.idle.pct +=== `system.core.idle.pct` type: scaled_float @@ -8363,7 +8363,7 @@ The percentage of CPU time spent idle. [float] -=== system.core.idle.ticks +=== `system.core.idle.ticks` type: long @@ -8371,7 +8371,7 @@ The amount of CPU time spent idle. [float] -=== system.core.iowait.pct +=== `system.core.iowait.pct` type: scaled_float @@ -8381,7 +8381,7 @@ The percentage of CPU time spent in wait (on disk). [float] -=== system.core.iowait.ticks +=== `system.core.iowait.ticks` type: long @@ -8389,7 +8389,7 @@ The amount of CPU time spent in wait (on disk). [float] -=== system.core.irq.pct +=== `system.core.irq.pct` type: scaled_float @@ -8399,7 +8399,7 @@ The percentage of CPU time spent servicing and handling hardware interrupts. [float] -=== system.core.irq.ticks +=== `system.core.irq.ticks` type: long @@ -8407,7 +8407,7 @@ The amount of CPU time spent servicing and handling hardware interrupts. [float] -=== system.core.softirq.pct +=== `system.core.softirq.pct` type: scaled_float @@ -8417,7 +8417,7 @@ The percentage of CPU time spent servicing and handling software interrupts. [float] -=== system.core.softirq.ticks +=== `system.core.softirq.ticks` type: long @@ -8425,7 +8425,7 @@ The amount of CPU time spent servicing and handling software interrupts. [float] -=== system.core.steal.pct +=== `system.core.steal.pct` type: scaled_float @@ -8435,7 +8435,7 @@ The percentage of CPU time spent in involuntary wait by the virtual CPU while th [float] -=== system.core.steal.ticks +=== `system.core.steal.ticks` type: long @@ -8443,14 +8443,14 @@ The amount of CPU time spent in involuntary wait by the virtual CPU while the hy [float] -== cpu Fields +== cpu fields `cpu` contains local CPU stats. [float] -=== system.cpu.cores +=== `system.cpu.cores` type: long @@ -8458,7 +8458,7 @@ The number of CPU cores present on the host. The non-normalized percentages will [float] -=== system.cpu.user.pct +=== `system.cpu.user.pct` type: scaled_float @@ -8468,7 +8468,7 @@ The percentage of CPU time spent in user space. On multi-core systems, you can h [float] -=== system.cpu.system.pct +=== `system.cpu.system.pct` type: scaled_float @@ -8478,7 +8478,7 @@ The percentage of CPU time spent in kernel space. [float] -=== system.cpu.nice.pct +=== `system.cpu.nice.pct` type: scaled_float @@ -8488,7 +8488,7 @@ The percentage of CPU time spent on low-priority processes. [float] -=== system.cpu.idle.pct +=== `system.cpu.idle.pct` type: scaled_float @@ -8498,7 +8498,7 @@ The percentage of CPU time spent idle. [float] -=== system.cpu.iowait.pct +=== `system.cpu.iowait.pct` type: scaled_float @@ -8508,7 +8508,7 @@ The percentage of CPU time spent in wait (on disk). [float] -=== system.cpu.irq.pct +=== `system.cpu.irq.pct` type: scaled_float @@ -8518,7 +8518,7 @@ The percentage of CPU time spent servicing and handling hardware interrupts. [float] -=== system.cpu.softirq.pct +=== `system.cpu.softirq.pct` type: scaled_float @@ -8528,7 +8528,7 @@ The percentage of CPU time spent servicing and handling software interrupts. [float] -=== system.cpu.steal.pct +=== `system.cpu.steal.pct` type: scaled_float @@ -8538,7 +8538,7 @@ The percentage of CPU time spent in involuntary wait by the virtual CPU while th [float] -=== system.cpu.user.norm.pct +=== `system.cpu.user.norm.pct` type: scaled_float @@ -8548,7 +8548,7 @@ The percentage of CPU time spent in user space. [float] -=== system.cpu.system.norm.pct +=== `system.cpu.system.norm.pct` type: scaled_float @@ -8558,7 +8558,7 @@ The percentage of CPU time spent in kernel space. [float] -=== system.cpu.nice.norm.pct +=== `system.cpu.nice.norm.pct` type: scaled_float @@ -8568,7 +8568,7 @@ The percentage of CPU time spent on low-priority processes. [float] -=== system.cpu.idle.norm.pct +=== `system.cpu.idle.norm.pct` type: scaled_float @@ -8578,7 +8578,7 @@ The percentage of CPU time spent idle. [float] -=== system.cpu.iowait.norm.pct +=== `system.cpu.iowait.norm.pct` type: scaled_float @@ -8588,7 +8588,7 @@ The percentage of CPU time spent in wait (on disk). [float] -=== system.cpu.irq.norm.pct +=== `system.cpu.irq.norm.pct` type: scaled_float @@ -8598,7 +8598,7 @@ The percentage of CPU time spent servicing and handling hardware interrupts. [float] -=== system.cpu.softirq.norm.pct +=== `system.cpu.softirq.norm.pct` type: scaled_float @@ -8608,7 +8608,7 @@ The percentage of CPU time spent servicing and handling software interrupts. [float] -=== system.cpu.steal.norm.pct +=== `system.cpu.steal.norm.pct` type: scaled_float @@ -8618,7 +8618,7 @@ The percentage of CPU time spent in involuntary wait by the virtual CPU while th [float] -=== system.cpu.user.ticks +=== `system.cpu.user.ticks` type: long @@ -8626,7 +8626,7 @@ The amount of CPU time spent in user space. [float] -=== system.cpu.system.ticks +=== `system.cpu.system.ticks` type: long @@ -8634,7 +8634,7 @@ The amount of CPU time spent in kernel space. [float] -=== system.cpu.nice.ticks +=== `system.cpu.nice.ticks` type: long @@ -8642,7 +8642,7 @@ The amount of CPU time spent on low-priority processes. [float] -=== system.cpu.idle.ticks +=== `system.cpu.idle.ticks` type: long @@ -8650,7 +8650,7 @@ The amount of CPU time spent idle. [float] -=== system.cpu.iowait.ticks +=== `system.cpu.iowait.ticks` type: long @@ -8658,7 +8658,7 @@ The amount of CPU time spent in wait (on disk). [float] -=== system.cpu.irq.ticks +=== `system.cpu.irq.ticks` type: long @@ -8666,7 +8666,7 @@ The amount of CPU time spent servicing and handling hardware interrupts. [float] -=== system.cpu.softirq.ticks +=== `system.cpu.softirq.ticks` type: long @@ -8674,7 +8674,7 @@ The amount of CPU time spent servicing and handling software interrupts. [float] -=== system.cpu.steal.ticks +=== `system.cpu.steal.ticks` type: long @@ -8682,14 +8682,14 @@ The amount of CPU time spent in involuntary wait by the virtual CPU while the hy [float] -== diskio Fields +== diskio fields `disk` contains disk IO metrics collected from the operating system. [float] -=== system.diskio.name +=== `system.diskio.name` type: keyword @@ -8699,7 +8699,7 @@ The disk name. [float] -=== system.diskio.serial_number +=== `system.diskio.serial_number` type: keyword @@ -8707,7 +8707,7 @@ The disk's serial number. This may not be provided by all operating systems. [float] -=== system.diskio.read.count +=== `system.diskio.read.count` type: long @@ -8715,7 +8715,7 @@ The total number of reads completed successfully. [float] -=== system.diskio.write.count +=== `system.diskio.write.count` type: long @@ -8723,7 +8723,7 @@ The total number of writes completed successfully. [float] -=== system.diskio.read.bytes +=== `system.diskio.read.bytes` type: long @@ -8733,7 +8733,7 @@ The total number of bytes read successfully. On Linux this is the number of sect [float] -=== system.diskio.write.bytes +=== `system.diskio.write.bytes` type: long @@ -8743,7 +8743,7 @@ The total number of bytes written successfully. On Linux this is the number of s [float] -=== system.diskio.read.time +=== `system.diskio.read.time` type: long @@ -8751,7 +8751,7 @@ The total number of milliseconds spent by all reads. [float] -=== system.diskio.write.time +=== `system.diskio.write.time` type: long @@ -8759,7 +8759,7 @@ The total number of milliseconds spent by all writes. [float] -=== system.diskio.io.time +=== `system.diskio.io.time` type: long @@ -8767,14 +8767,14 @@ The total number of of milliseconds spent doing I/Os. [float] -== filesystem Fields +== filesystem fields `filesystem` contains local filesystem stats. [float] -=== system.filesystem.available +=== `system.filesystem.available` type: long @@ -8784,7 +8784,7 @@ The disk space available to an unprivileged user in bytes. [float] -=== system.filesystem.device_name +=== `system.filesystem.device_name` type: keyword @@ -8792,7 +8792,7 @@ The disk name. For example: `/dev/disk1` [float] -=== system.filesystem.mount_point +=== `system.filesystem.mount_point` type: keyword @@ -8800,7 +8800,7 @@ The mounting point. For example: `/` [float] -=== system.filesystem.files +=== `system.filesystem.files` type: long @@ -8808,7 +8808,7 @@ The total number of file nodes in the file system. [float] -=== system.filesystem.free +=== `system.filesystem.free` type: long @@ -8818,7 +8818,7 @@ The disk space available in bytes. [float] -=== system.filesystem.free_files +=== `system.filesystem.free_files` type: long @@ -8826,7 +8826,7 @@ The number of free file nodes in the file system. [float] -=== system.filesystem.total +=== `system.filesystem.total` type: long @@ -8836,7 +8836,7 @@ The total disk space in bytes. [float] -=== system.filesystem.used.bytes +=== `system.filesystem.used.bytes` type: long @@ -8846,7 +8846,7 @@ The used disk space in bytes. [float] -=== system.filesystem.used.pct +=== `system.filesystem.used.pct` type: scaled_float @@ -8856,34 +8856,34 @@ The percentage of used disk space. [float] -== fsstat Fields +== fsstat fields `system.fsstat` contains filesystem metrics aggregated from all mounted filesystems, similar with what `df -a` prints out. [float] -=== system.fsstat.count +=== `system.fsstat.count` type: long Number of file systems found. [float] -=== system.fsstat.total_files +=== `system.fsstat.total_files` type: long Total number of files. [float] -== total_size Fields +== total_size fields Nested file system docs. [float] -=== system.fsstat.total_size.free +=== `system.fsstat.total_size.free` type: long @@ -8893,7 +8893,7 @@ Total free space. [float] -=== system.fsstat.total_size.used +=== `system.fsstat.total_size.used` type: long @@ -8903,7 +8903,7 @@ Total used space. [float] -=== system.fsstat.total_size.total +=== `system.fsstat.total_size.total` type: long @@ -8913,14 +8913,14 @@ Total space (used plus free). [float] -== load Fields +== load fields CPU load averages. [float] -=== system.load.1 +=== `system.load.1` type: scaled_float @@ -8928,7 +8928,7 @@ Load average for the last minute. [float] -=== system.load.5 +=== `system.load.5` type: scaled_float @@ -8936,7 +8936,7 @@ Load average for the last 5 minutes. [float] -=== system.load.15 +=== `system.load.15` type: scaled_float @@ -8944,7 +8944,7 @@ Load average for the last 15 minutes. [float] -=== system.load.norm.1 +=== `system.load.norm.1` type: scaled_float @@ -8952,7 +8952,7 @@ Load for the last minute divided by the number of cores. [float] -=== system.load.norm.5 +=== `system.load.norm.5` type: scaled_float @@ -8960,7 +8960,7 @@ Load for the last 5 minutes divided by the number of cores. [float] -=== system.load.norm.15 +=== `system.load.norm.15` type: scaled_float @@ -8968,7 +8968,7 @@ Load for the last 15 minutes divided by the number of cores. [float] -=== system.load.cores +=== `system.load.cores` type: long @@ -8976,14 +8976,14 @@ The number of CPU cores present on the host. [float] -== memory Fields +== memory fields `memory` contains local memory stats. [float] -=== system.memory.total +=== `system.memory.total` type: long @@ -8993,7 +8993,7 @@ Total memory. [float] -=== system.memory.used.bytes +=== `system.memory.used.bytes` type: long @@ -9003,7 +9003,7 @@ Used memory. [float] -=== system.memory.free +=== `system.memory.free` type: long @@ -9013,7 +9013,7 @@ The total amount of free memory in bytes. This value does not include memory con [float] -=== system.memory.used.pct +=== `system.memory.used.pct` type: scaled_float @@ -9023,14 +9023,14 @@ The percentage of used memory. [float] -== actual Fields +== actual fields Actual memory used and free. [float] -=== system.memory.actual.used.bytes +=== `system.memory.actual.used.bytes` type: long @@ -9040,7 +9040,7 @@ Actual used memory in bytes. It represents the difference between the total and [float] -=== system.memory.actual.free +=== `system.memory.actual.free` type: long @@ -9050,7 +9050,7 @@ Actual free memory in bytes. It is calculated based on the OS. On Linux it consi [float] -=== system.memory.actual.used.pct +=== `system.memory.actual.used.pct` type: scaled_float @@ -9060,13 +9060,13 @@ The percentage of actual used memory. [float] -== swap Fields +== swap fields This group contains statistics related to the swap memory usage on the system. [float] -=== system.memory.swap.total +=== `system.memory.swap.total` type: long @@ -9076,7 +9076,7 @@ Total swap memory. [float] -=== system.memory.swap.used.bytes +=== `system.memory.swap.used.bytes` type: long @@ -9086,7 +9086,7 @@ Used swap memory. [float] -=== system.memory.swap.free +=== `system.memory.swap.free` type: long @@ -9096,7 +9096,7 @@ Available swap memory. [float] -=== system.memory.swap.used.pct +=== `system.memory.swap.used.pct` type: scaled_float @@ -9106,14 +9106,14 @@ The percentage of used swap memory. [float] -== network Fields +== network fields `network` contains network IO metrics for a single network interface. [float] -=== system.network.name +=== `system.network.name` type: keyword @@ -9123,7 +9123,7 @@ The network interface name. [float] -=== system.network.out.bytes +=== `system.network.out.bytes` type: long @@ -9133,7 +9133,7 @@ The number of bytes sent. [float] -=== system.network.in.bytes +=== `system.network.in.bytes` type: long @@ -9143,7 +9143,7 @@ The number of bytes received. [float] -=== system.network.out.packets +=== `system.network.out.packets` type: long @@ -9151,7 +9151,7 @@ The number of packets sent. [float] -=== system.network.in.packets +=== `system.network.in.packets` type: long @@ -9159,7 +9159,7 @@ The number or packets received. [float] -=== system.network.in.errors +=== `system.network.in.errors` type: long @@ -9167,7 +9167,7 @@ The number of errors while receiving. [float] -=== system.network.out.errors +=== `system.network.out.errors` type: long @@ -9175,7 +9175,7 @@ The number of errors while sending. [float] -=== system.network.in.dropped +=== `system.network.in.dropped` type: long @@ -9183,7 +9183,7 @@ The number of incoming packets that were dropped. [float] -=== system.network.out.dropped +=== `system.network.out.dropped` type: long @@ -9191,14 +9191,14 @@ The number of outgoing packets that were dropped. This value is always 0 on Darw [float] -== process Fields +== process fields `process` contains process metadata, CPU metrics, and memory metrics. [float] -=== system.process.name +=== `system.process.name` type: keyword @@ -9206,7 +9206,7 @@ The process name. [float] -=== system.process.state +=== `system.process.state` type: keyword @@ -9214,7 +9214,7 @@ The process state. For example: "running". [float] -=== system.process.pid +=== `system.process.pid` type: long @@ -9222,7 +9222,7 @@ The process pid. [float] -=== system.process.ppid +=== `system.process.ppid` type: long @@ -9230,7 +9230,7 @@ The process parent pid. [float] -=== system.process.pgid +=== `system.process.pgid` type: long @@ -9238,7 +9238,7 @@ The process group id. [float] -=== system.process.cmdline +=== `system.process.cmdline` type: keyword @@ -9246,7 +9246,7 @@ The full command-line used to start the process, including the arguments separat [float] -=== system.process.username +=== `system.process.username` type: keyword @@ -9254,7 +9254,7 @@ The username of the user that created the process. If the username cannot be det [float] -=== system.process.cwd +=== `system.process.cwd` type: keyword @@ -9262,7 +9262,7 @@ The current working directory of the process. This field is only available on Li [float] -=== system.process.env +=== `system.process.env` type: object @@ -9270,13 +9270,13 @@ The environment variables used to start the process. The data is available on Fr [float] -== cpu Fields +== cpu fields CPU-specific statistics per process. [float] -=== system.process.cpu.user +=== `system.process.cpu.user` type: long @@ -9284,7 +9284,7 @@ The amount of CPU time the process spent in user space. [float] -=== system.process.cpu.total.pct +=== `system.process.cpu.total.pct` type: scaled_float @@ -9294,7 +9294,7 @@ The percentage of CPU time spent by the process since the last update. Its value [float] -=== system.process.cpu.total.norm.pct +=== `system.process.cpu.total.norm.pct` type: scaled_float @@ -9304,7 +9304,7 @@ The percentage of CPU time spent by the process since the last event. This value [float] -=== system.process.cpu.system +=== `system.process.cpu.system` type: long @@ -9312,7 +9312,7 @@ The amount of CPU time the process spent in kernel space. [float] -=== system.process.cpu.total.ticks +=== `system.process.cpu.total.ticks` type: long @@ -9320,7 +9320,7 @@ The total CPU time spent by the process. [float] -=== system.process.cpu.start_time +=== `system.process.cpu.start_time` type: date @@ -9328,13 +9328,13 @@ The time when the process was started. [float] -== memory Fields +== memory fields Memory-specific statistics per process. [float] -=== system.process.memory.size +=== `system.process.memory.size` type: long @@ -9344,7 +9344,7 @@ The total virtual memory the process has. [float] -=== system.process.memory.rss.bytes +=== `system.process.memory.rss.bytes` type: long @@ -9354,7 +9354,7 @@ The Resident Set Size. The amount of memory the process occupied in main memory [float] -=== system.process.memory.rss.pct +=== `system.process.memory.rss.pct` type: scaled_float @@ -9364,7 +9364,7 @@ The percentage of memory the process occupied in main memory (RAM). [float] -=== system.process.memory.share +=== `system.process.memory.share` type: long @@ -9374,21 +9374,21 @@ The shared memory the process uses. [float] -== fd Fields +== fd fields File descriptor usage metrics. This set of metrics is available for Linux and FreeBSD. [float] -=== system.process.fd.open +=== `system.process.fd.open` type: long The number of file descriptors open by the process. [float] -=== system.process.fd.limit.soft +=== `system.process.fd.limit.soft` type: long @@ -9396,7 +9396,7 @@ The soft limit on the number of file descriptors opened by the process. The soft [float] -=== system.process.fd.limit.hard +=== `system.process.fd.limit.hard` type: long @@ -9404,14 +9404,14 @@ The hard limit on the number of file descriptors opened by the process. The hard [float] -== cgroup Fields +== cgroup fields Metrics and limits from the cgroup of which the task is a member. cgroup metrics are reported when the process has membership in a non-root cgroup. These metrics are only available on Linux. [float] -=== system.process.cgroup.id +=== `system.process.cgroup.id` type: keyword @@ -9419,7 +9419,7 @@ The ID common to all cgroups associated with this task. If there isn't a common [float] -=== system.process.cgroup.path +=== `system.process.cgroup.path` type: keyword @@ -9427,21 +9427,21 @@ The path to the cgroup relative to the cgroup subsystem's mountpoint. If there i [float] -== cpu Fields +== cpu fields The cpu subsystem schedules CPU access for tasks in the cgroup. Access can be controlled by two separate schedulers, CFS and RT. CFS stands for completely fair scheduler which proportionally divides the CPU time between cgroups based on weight. RT stands for real time scheduler which sets a maximum amount of CPU time that processes in the cgroup can consume during a given period. [float] -=== system.process.cgroup.cpu.id +=== `system.process.cgroup.cpu.id` type: keyword ID of the cgroup. [float] -=== system.process.cgroup.cpu.path +=== `system.process.cgroup.cpu.path` type: keyword @@ -9449,7 +9449,7 @@ Path to the cgroup relative to the cgroup subsystem's mountpoint. [float] -=== system.process.cgroup.cpu.cfs.period.us +=== `system.process.cgroup.cpu.cfs.period.us` type: long @@ -9457,7 +9457,7 @@ Period of time in microseconds for how regularly a cgroup's access to CPU resour [float] -=== system.process.cgroup.cpu.cfs.quota.us +=== `system.process.cgroup.cpu.cfs.quota.us` type: long @@ -9465,7 +9465,7 @@ Total amount of time in microseconds for which all tasks in a cgroup can run dur [float] -=== system.process.cgroup.cpu.cfs.shares +=== `system.process.cgroup.cpu.cfs.shares` type: long @@ -9473,7 +9473,7 @@ An integer value that specifies a relative share of CPU time available to the ta [float] -=== system.process.cgroup.cpu.rt.period.us +=== `system.process.cgroup.cpu.rt.period.us` type: long @@ -9481,7 +9481,7 @@ Period of time in microseconds for how regularly a cgroup's access to CPU resour [float] -=== system.process.cgroup.cpu.rt.runtime.us +=== `system.process.cgroup.cpu.rt.runtime.us` type: long @@ -9489,7 +9489,7 @@ Period of time in microseconds for the longest continuous period in which the ta [float] -=== system.process.cgroup.cpu.stats.periods +=== `system.process.cgroup.cpu.stats.periods` type: long @@ -9497,7 +9497,7 @@ Number of period intervals (as specified in cpu.cfs.period.us) that have elapsed [float] -=== system.process.cgroup.cpu.stats.throttled.periods +=== `system.process.cgroup.cpu.stats.throttled.periods` type: long @@ -9505,7 +9505,7 @@ Number of times tasks in a cgroup have been throttled (that is, not allowed to r [float] -=== system.process.cgroup.cpu.stats.throttled.ns +=== `system.process.cgroup.cpu.stats.throttled.ns` type: long @@ -9513,20 +9513,20 @@ The total time duration (in nanoseconds) for which tasks in a cgroup have been t [float] -== cpuacct Fields +== cpuacct fields CPU accounting metrics. [float] -=== system.process.cgroup.cpuacct.id +=== `system.process.cgroup.cpuacct.id` type: keyword ID of the cgroup. [float] -=== system.process.cgroup.cpuacct.path +=== `system.process.cgroup.cpuacct.path` type: keyword @@ -9534,7 +9534,7 @@ Path to the cgroup relative to the cgroup subsystem's mountpoint. [float] -=== system.process.cgroup.cpuacct.total.ns +=== `system.process.cgroup.cpuacct.total.ns` type: long @@ -9542,21 +9542,21 @@ Total CPU time in nanoseconds consumed by all tasks in the cgroup. [float] -=== system.process.cgroup.cpuacct.stats.user.ns +=== `system.process.cgroup.cpuacct.stats.user.ns` type: long CPU time consumed by tasks in user mode. [float] -=== system.process.cgroup.cpuacct.stats.system.ns +=== `system.process.cgroup.cpuacct.stats.system.ns` type: long CPU time consumed by tasks in user (kernel) mode. [float] -=== system.process.cgroup.cpuacct.percpu +=== `system.process.cgroup.cpuacct.percpu` type: object @@ -9564,20 +9564,20 @@ CPU time (in nanoseconds) consumed on each CPU by all tasks in this cgroup. [float] -== memory Fields +== memory fields Memory limits and metrics. [float] -=== system.process.cgroup.memory.id +=== `system.process.cgroup.memory.id` type: keyword ID of the cgroup. [float] -=== system.process.cgroup.memory.path +=== `system.process.cgroup.memory.path` type: keyword @@ -9585,7 +9585,7 @@ Path to the cgroup relative to the cgroup subsystem's mountpoint. [float] -=== system.process.cgroup.memory.mem.usage.bytes +=== `system.process.cgroup.memory.mem.usage.bytes` type: long @@ -9595,7 +9595,7 @@ Total memory usage by processes in the cgroup (in bytes). [float] -=== system.process.cgroup.memory.mem.usage.max.bytes +=== `system.process.cgroup.memory.mem.usage.max.bytes` type: long @@ -9605,7 +9605,7 @@ The maximum memory used by processes in the cgroup (in bytes). [float] -=== system.process.cgroup.memory.mem.limit.bytes +=== `system.process.cgroup.memory.mem.limit.bytes` type: long @@ -9615,7 +9615,7 @@ The maximum amount of user memory in bytes (including file cache) that tasks in [float] -=== system.process.cgroup.memory.mem.failures +=== `system.process.cgroup.memory.mem.failures` type: long @@ -9623,7 +9623,7 @@ The number of times that the memory limit (mem.limit.bytes) was reached. [float] -=== system.process.cgroup.memory.memsw.usage.bytes +=== `system.process.cgroup.memory.memsw.usage.bytes` type: long @@ -9633,7 +9633,7 @@ The sum of current memory usage plus swap space used by processes in the cgroup [float] -=== system.process.cgroup.memory.memsw.usage.max.bytes +=== `system.process.cgroup.memory.memsw.usage.max.bytes` type: long @@ -9643,7 +9643,7 @@ The maximum amount of memory and swap space used by processes in the cgroup (in [float] -=== system.process.cgroup.memory.memsw.limit.bytes +=== `system.process.cgroup.memory.memsw.limit.bytes` type: long @@ -9653,7 +9653,7 @@ The maximum amount for the sum of memory and swap usage that tasks in the cgroup [float] -=== system.process.cgroup.memory.memsw.failures +=== `system.process.cgroup.memory.memsw.failures` type: long @@ -9661,7 +9661,7 @@ The number of times that the memory plus swap space limit (memsw.limit.bytes) wa [float] -=== system.process.cgroup.memory.kmem.usage.bytes +=== `system.process.cgroup.memory.kmem.usage.bytes` type: long @@ -9671,7 +9671,7 @@ Total kernel memory usage by processes in the cgroup (in bytes). [float] -=== system.process.cgroup.memory.kmem.usage.max.bytes +=== `system.process.cgroup.memory.kmem.usage.max.bytes` type: long @@ -9681,7 +9681,7 @@ The maximum kernel memory used by processes in the cgroup (in bytes). [float] -=== system.process.cgroup.memory.kmem.limit.bytes +=== `system.process.cgroup.memory.kmem.limit.bytes` type: long @@ -9691,7 +9691,7 @@ The maximum amount of kernel memory that tasks in the cgroup are allowed to use. [float] -=== system.process.cgroup.memory.kmem.failures +=== `system.process.cgroup.memory.kmem.failures` type: long @@ -9699,7 +9699,7 @@ The number of times that the memory limit (kmem.limit.bytes) was reached. [float] -=== system.process.cgroup.memory.kmem_tcp.usage.bytes +=== `system.process.cgroup.memory.kmem_tcp.usage.bytes` type: long @@ -9709,7 +9709,7 @@ Total memory usage for TCP buffers in bytes. [float] -=== system.process.cgroup.memory.kmem_tcp.usage.max.bytes +=== `system.process.cgroup.memory.kmem_tcp.usage.max.bytes` type: long @@ -9719,7 +9719,7 @@ The maximum memory used for TCP buffers by processes in the cgroup (in bytes). [float] -=== system.process.cgroup.memory.kmem_tcp.limit.bytes +=== `system.process.cgroup.memory.kmem_tcp.limit.bytes` type: long @@ -9729,7 +9729,7 @@ The maximum amount of memory for TCP buffers that tasks in the cgroup are allowe [float] -=== system.process.cgroup.memory.kmem_tcp.failures +=== `system.process.cgroup.memory.kmem_tcp.failures` type: long @@ -9737,7 +9737,7 @@ The number of times that the memory limit (kmem_tcp.limit.bytes) was reached. [float] -=== system.process.cgroup.memory.stats.active_anon.bytes +=== `system.process.cgroup.memory.stats.active_anon.bytes` type: long @@ -9747,7 +9747,7 @@ Anonymous and swap cache on active least-recently-used (LRU) list, including tmp [float] -=== system.process.cgroup.memory.stats.active_file.bytes +=== `system.process.cgroup.memory.stats.active_file.bytes` type: long @@ -9756,7 +9756,7 @@ format: bytes File-backed memory on active LRU list, in bytes. [float] -=== system.process.cgroup.memory.stats.cache.bytes +=== `system.process.cgroup.memory.stats.cache.bytes` type: long @@ -9765,7 +9765,7 @@ format: bytes Page cache, including tmpfs (shmem), in bytes. [float] -=== system.process.cgroup.memory.stats.hierarchical_memory_limit.bytes +=== `system.process.cgroup.memory.stats.hierarchical_memory_limit.bytes` type: long @@ -9775,7 +9775,7 @@ Memory limit for the hierarchy that contains the memory cgroup, in bytes. [float] -=== system.process.cgroup.memory.stats.hierarchical_memsw_limit.bytes +=== `system.process.cgroup.memory.stats.hierarchical_memsw_limit.bytes` type: long @@ -9785,7 +9785,7 @@ Memory plus swap limit for the hierarchy that contains the memory cgroup, in byt [float] -=== system.process.cgroup.memory.stats.inactive_anon.bytes +=== `system.process.cgroup.memory.stats.inactive_anon.bytes` type: long @@ -9795,7 +9795,7 @@ Anonymous and swap cache on inactive LRU list, including tmpfs (shmem), in bytes [float] -=== system.process.cgroup.memory.stats.inactive_file.bytes +=== `system.process.cgroup.memory.stats.inactive_file.bytes` type: long @@ -9805,7 +9805,7 @@ File-backed memory on inactive LRU list, in bytes. [float] -=== system.process.cgroup.memory.stats.mapped_file.bytes +=== `system.process.cgroup.memory.stats.mapped_file.bytes` type: long @@ -9815,7 +9815,7 @@ Size of memory-mapped mapped files, including tmpfs (shmem), in bytes. [float] -=== system.process.cgroup.memory.stats.page_faults +=== `system.process.cgroup.memory.stats.page_faults` type: long @@ -9823,7 +9823,7 @@ Number of times that a process in the cgroup triggered a page fault. [float] -=== system.process.cgroup.memory.stats.major_page_faults +=== `system.process.cgroup.memory.stats.major_page_faults` type: long @@ -9831,7 +9831,7 @@ Number of times that a process in the cgroup triggered a major fault. "Major" fa [float] -=== system.process.cgroup.memory.stats.pages_in +=== `system.process.cgroup.memory.stats.pages_in` type: long @@ -9839,7 +9839,7 @@ Number of pages paged into memory. This is a counter. [float] -=== system.process.cgroup.memory.stats.pages_out +=== `system.process.cgroup.memory.stats.pages_out` type: long @@ -9847,7 +9847,7 @@ Number of pages paged out of memory. This is a counter. [float] -=== system.process.cgroup.memory.stats.rss.bytes +=== `system.process.cgroup.memory.stats.rss.bytes` type: long @@ -9857,7 +9857,7 @@ Anonymous and swap cache (includes transparent hugepages), not including tmpfs ( [float] -=== system.process.cgroup.memory.stats.rss_huge.bytes +=== `system.process.cgroup.memory.stats.rss_huge.bytes` type: long @@ -9867,7 +9867,7 @@ Number of bytes of anonymous transparent hugepages. [float] -=== system.process.cgroup.memory.stats.swap.bytes +=== `system.process.cgroup.memory.stats.swap.bytes` type: long @@ -9877,7 +9877,7 @@ Swap usage, in bytes. [float] -=== system.process.cgroup.memory.stats.unevictable.bytes +=== `system.process.cgroup.memory.stats.unevictable.bytes` type: long @@ -9887,20 +9887,20 @@ Memory that cannot be reclaimed, in bytes. [float] -== blkio Fields +== blkio fields Block IO metrics. [float] -=== system.process.cgroup.blkio.id +=== `system.process.cgroup.blkio.id` type: keyword ID of the cgroup. [float] -=== system.process.cgroup.blkio.path +=== `system.process.cgroup.blkio.path` type: keyword @@ -9908,7 +9908,7 @@ Path to the cgroup relative to the cgroup subsystems mountpoint. [float] -=== system.process.cgroup.blkio.total.bytes +=== `system.process.cgroup.blkio.total.bytes` type: long @@ -9918,7 +9918,7 @@ Total number of bytes transferred to and from all block devices by processes in [float] -=== system.process.cgroup.blkio.total.ios +=== `system.process.cgroup.blkio.total.ios` type: long @@ -9926,14 +9926,14 @@ Total number of I/O operations performed on all devices by processes in the cgro [float] -== process.summary Fields +== process.summary fields Summary metrics for the processes running on the host. [float] -=== system.process.summary.total +=== `system.process.summary.total` type: long @@ -9941,7 +9941,7 @@ Total number of processes on this host. [float] -=== system.process.summary.running +=== `system.process.summary.running` type: long @@ -9949,7 +9949,7 @@ Number of running processes on this host. [float] -=== system.process.summary.idle +=== `system.process.summary.idle` type: long @@ -9957,7 +9957,7 @@ Number of idle processes on this host. [float] -=== system.process.summary.sleeping +=== `system.process.summary.sleeping` type: long @@ -9965,7 +9965,7 @@ Number of sleeping processes on this host. [float] -=== system.process.summary.stopped +=== `system.process.summary.stopped` type: long @@ -9973,7 +9973,7 @@ Number of stopped processes on this host. [float] -=== system.process.summary.zombie +=== `system.process.summary.zombie` type: long @@ -9981,7 +9981,7 @@ Number of zombie processes on this host. [float] -=== system.process.summary.unknown +=== `system.process.summary.unknown` type: long @@ -9989,14 +9989,14 @@ Number of processes for which the state couldn't be retrieved or is unknown. [float] -== socket Fields +== socket fields TCP sockets that are active. [float] -=== system.socket.direction +=== `system.socket.direction` type: keyword @@ -10006,7 +10006,7 @@ How the socket was initiated. Possible values are incoming, outgoing, or listeni [float] -=== system.socket.family +=== `system.socket.family` type: keyword @@ -10016,7 +10016,7 @@ Address family. [float] -=== system.socket.local.ip +=== `system.socket.local.ip` type: ip @@ -10026,7 +10026,7 @@ Local IP address. This can be an IPv4 or IPv6 address. [float] -=== system.socket.local.port +=== `system.socket.local.port` type: long @@ -10036,7 +10036,7 @@ Local port. [float] -=== system.socket.remote.ip +=== `system.socket.remote.ip` type: ip @@ -10046,7 +10046,7 @@ Remote IP address. This can be an IPv4 or IPv6 address. [float] -=== system.socket.remote.port +=== `system.socket.remote.port` type: long @@ -10056,7 +10056,7 @@ Remote port. [float] -=== system.socket.remote.host +=== `system.socket.remote.host` type: keyword @@ -10066,7 +10066,7 @@ PTR record associated with the remote IP. It is obtained via reverse IP lookup. [float] -=== system.socket.remote.etld_plus_one +=== `system.socket.remote.etld_plus_one` type: keyword @@ -10076,7 +10076,7 @@ The effective top-level domain (eTLD) of the remote host plus one more label. Fo [float] -=== system.socket.remote.host_error +=== `system.socket.remote.host_error` type: keyword @@ -10084,7 +10084,7 @@ Error describing the cause of the reverse lookup failure. [float] -=== system.socket.process.pid +=== `system.socket.process.pid` type: long @@ -10092,7 +10092,7 @@ ID of the process that opened the socket. [float] -=== system.socket.process.command +=== `system.socket.process.command` type: keyword @@ -10100,14 +10100,14 @@ Name of the command (limited to 20 chars by the OS). [float] -=== system.socket.process.cmdline +=== `system.socket.process.cmdline` type: keyword [float] -=== system.socket.process.exe +=== `system.socket.process.exe` type: keyword @@ -10115,7 +10115,7 @@ Absolute path to the executable. [float] -=== system.socket.user.id +=== `system.socket.user.id` type: long @@ -10123,7 +10123,7 @@ UID of the user running the process. [float] -=== system.socket.user.name +=== `system.socket.user.name` type: keyword @@ -10131,27 +10131,27 @@ Name of the user running the process. [[exported-fields-vsphere]] -== vSphere Fields +== vSphere fields vSphere module [float] -== vsphere Fields +== vsphere fields [float] -== datastore Fields +== datastore fields datastore [float] -=== vsphere.datastore.datacenter +=== `vsphere.datastore.datacenter` type: keyword @@ -10159,7 +10159,7 @@ Datacenter name [float] -=== vsphere.datastore.name +=== `vsphere.datastore.name` type: keyword @@ -10167,7 +10167,7 @@ Datastore name [float] -=== vsphere.datastore.fstype +=== `vsphere.datastore.fstype` type: keyword @@ -10175,7 +10175,7 @@ Filesystem type [float] -=== vsphere.datastore.capacity.total.bytes +=== `vsphere.datastore.capacity.total.bytes` type: long @@ -10185,7 +10185,7 @@ Total bytes of the datastore [float] -=== vsphere.datastore.capacity.free.bytes +=== `vsphere.datastore.capacity.free.bytes` type: long @@ -10195,7 +10195,7 @@ Free bytes of the datastore [float] -=== vsphere.datastore.capacity.used.bytes +=== `vsphere.datastore.capacity.used.bytes` type: long @@ -10205,7 +10205,7 @@ Used bytes of the datastore [float] -=== vsphere.datastore.capacity.used.pct +=== `vsphere.datastore.capacity.used.pct` type: long @@ -10215,14 +10215,14 @@ Used percent of the datastore [float] -== host Fields +== host fields host [float] -=== vsphere.host.datacenter +=== `vsphere.host.datacenter` type: keyword @@ -10230,7 +10230,7 @@ Datacenter name [float] -=== vsphere.host.name +=== `vsphere.host.name` type: keyword @@ -10238,7 +10238,7 @@ Host name [float] -=== vsphere.host.cpu.used.mhz +=== `vsphere.host.cpu.used.mhz` type: long @@ -10246,7 +10246,7 @@ Used CPU in Mhz [float] -=== vsphere.host.cpu.total.mhz +=== `vsphere.host.cpu.total.mhz` type: long @@ -10254,7 +10254,7 @@ Total CPU in Mhz [float] -=== vsphere.host.cpu.free.mhz +=== `vsphere.host.cpu.free.mhz` type: long @@ -10262,7 +10262,7 @@ Free CPU in Mhz [float] -=== vsphere.host.memory.used.bytes +=== `vsphere.host.memory.used.bytes` type: long @@ -10272,7 +10272,7 @@ Used Memory in bytes [float] -=== vsphere.host.memory.total.bytes +=== `vsphere.host.memory.total.bytes` type: long @@ -10282,7 +10282,7 @@ Total Memory in bytes [float] -=== vsphere.host.memory.free.bytes +=== `vsphere.host.memory.free.bytes` type: long @@ -10292,14 +10292,14 @@ Free Memory in bytes [float] -== virtualmachine Fields +== virtualmachine fields virtualmachine [float] -=== vsphere.virtualmachine.datacenter +=== `vsphere.virtualmachine.datacenter` type: keyword @@ -10307,7 +10307,7 @@ Datacenter name [float] -=== vsphere.virtualmachine.name +=== `vsphere.virtualmachine.name` type: keyword @@ -10315,7 +10315,7 @@ Virtual Machine name [float] -=== vsphere.virtualmachine.cpu.used.mhz +=== `vsphere.virtualmachine.cpu.used.mhz` type: long @@ -10323,7 +10323,7 @@ Used CPU in Mhz [float] -=== vsphere.virtualmachine.memory.used.guest.bytes +=== `vsphere.virtualmachine.memory.used.guest.bytes` type: long @@ -10333,7 +10333,7 @@ Used Memory of Guest in bytes [float] -=== vsphere.virtualmachine.memory.used.host.bytes +=== `vsphere.virtualmachine.memory.used.host.bytes` type: long @@ -10343,7 +10343,7 @@ Used Memory of Host in bytes [float] -=== vsphere.virtualmachine.memory.total.guest.bytes +=== `vsphere.virtualmachine.memory.total.guest.bytes` type: long @@ -10353,7 +10353,7 @@ Total Memory of Guest in bytes [float] -=== vsphere.virtualmachine.memory.free.guest.bytes +=== `vsphere.virtualmachine.memory.free.guest.bytes` type: long @@ -10363,45 +10363,45 @@ Free Memory of Guest in bytes [float] -=== vsphere.virtualmachine.custom_fields +=== `vsphere.virtualmachine.custom_fields` type: object [[exported-fields-windows]] -== Windows Fields +== Windows fields -[]beta Module for Windows +beta[] Module for Windows [float] -== windows Fields +== windows fields [[exported-fields-zookeeper]] -== ZooKeeper Fields +== ZooKeeper fields ZooKeeper metrics collected by the four-letter monitoring commands. [float] -== zookeeper Fields +== zookeeper fields `zookeeper` contains the metrics reported by ZooKeeper commands. [float] -== mntr Fields +== mntr fields `mntr` contains the metrics reported by the four-letter `mntr` command. [float] -=== zookeeper.mntr.hostname +=== `zookeeper.mntr.hostname` type: keyword @@ -10409,7 +10409,7 @@ ZooKeeper hostname. [float] -=== zookeeper.mntr.approximate_data_size +=== `zookeeper.mntr.approximate_data_size` type: long @@ -10417,7 +10417,7 @@ Approximate size of ZooKeeper data. [float] -=== zookeeper.mntr.latency.avg +=== `zookeeper.mntr.latency.avg` type: long @@ -10425,7 +10425,7 @@ Average latency between ensemble hosts in milliseconds. [float] -=== zookeeper.mntr.ephemerals_count +=== `zookeeper.mntr.ephemerals_count` type: long @@ -10433,7 +10433,7 @@ Number of ephemeral znodes. [float] -=== zookeeper.mntr.followers +=== `zookeeper.mntr.followers` type: long @@ -10441,7 +10441,7 @@ Number of followers seen by the current host. [float] -=== zookeeper.mntr.max_file_descriptor_count +=== `zookeeper.mntr.max_file_descriptor_count` type: long @@ -10449,7 +10449,7 @@ Maximum number of file descriptors allowed for the ZooKeeper process. [float] -=== zookeeper.mntr.latency.max +=== `zookeeper.mntr.latency.max` type: long @@ -10457,7 +10457,7 @@ Maximum latency in milliseconds. [float] -=== zookeeper.mntr.latency.min +=== `zookeeper.mntr.latency.min` type: long @@ -10465,7 +10465,7 @@ Minimum latency in milliseconds. [float] -=== zookeeper.mntr.num_alive_connections +=== `zookeeper.mntr.num_alive_connections` type: long @@ -10473,7 +10473,7 @@ Number of connections to ZooKeeper that are currently alive. [float] -=== zookeeper.mntr.open_file_descriptor_count +=== `zookeeper.mntr.open_file_descriptor_count` type: long @@ -10481,7 +10481,7 @@ Number of file descriptors open by the ZooKeeper process. [float] -=== zookeeper.mntr.outstanding_requests +=== `zookeeper.mntr.outstanding_requests` type: long @@ -10489,7 +10489,7 @@ Number of outstanding requests that need to be processed by the cluster. [float] -=== zookeeper.mntr.packets.received +=== `zookeeper.mntr.packets.received` type: long @@ -10497,7 +10497,7 @@ Number of ZooKeeper network packets received. [float] -=== zookeeper.mntr.packets.sent +=== `zookeeper.mntr.packets.sent` type: long @@ -10505,7 +10505,7 @@ Number of ZooKeeper network packets sent. [float] -=== zookeeper.mntr.pending_syncs +=== `zookeeper.mntr.pending_syncs` type: long @@ -10513,7 +10513,7 @@ Number of pending syncs to carry out to ZooKeeper ensemble followers. [float] -=== zookeeper.mntr.server_state +=== `zookeeper.mntr.server_state` type: keyword @@ -10521,7 +10521,7 @@ Role in the ZooKeeper ensemble. [float] -=== zookeeper.mntr.synced_followers +=== `zookeeper.mntr.synced_followers` type: long @@ -10529,7 +10529,7 @@ Number of synced followers reported when a node server_state is leader. [float] -=== zookeeper.mntr.version +=== `zookeeper.mntr.version` type: keyword @@ -10537,7 +10537,7 @@ ZooKeeper version and build string reported. [float] -=== zookeeper.mntr.watch_count +=== `zookeeper.mntr.watch_count` type: long @@ -10545,7 +10545,7 @@ Number of watches currently set on the local ZooKeeper process. [float] -=== zookeeper.mntr.znode_count +=== `zookeeper.mntr.znode_count` type: long diff --git a/metricbeat/docs/modules/php_fpm.asciidoc b/metricbeat/docs/modules/php_fpm.asciidoc index 53ffdf0809b..a0ce2a288e4 100644 --- a/metricbeat/docs/modules/php_fpm.asciidoc +++ b/metricbeat/docs/modules/php_fpm.asciidoc @@ -3,7 +3,7 @@ This file is generated! See scripts/docs_collector.py //// [[metricbeat-module-php_fpm]] -== PHP-FPM module +== PHP_FPM module beta[] @@ -34,14 +34,14 @@ location ~ /status { [float] === Compatibility -The PHP-FPM metricsets were tested with PHP 7.1.1 and are expected to +The PHP_FPM metricsets were tested with PHP 7.1.1 and are expected to work with all versions >= 5. [float] === Example configuration -The PHP-FPM module supports the standard configuration options that are described +The PHP_FPM module supports the standard configuration options that are described in <>. Here is an example configuration: [source,yaml] diff --git a/metricbeat/docs/modules_list.asciidoc b/metricbeat/docs/modules_list.asciidoc index 61cef2e27ca..7b5a7b22ef0 100644 --- a/metricbeat/docs/modules_list.asciidoc +++ b/metricbeat/docs/modules_list.asciidoc @@ -21,7 +21,7 @@ This file is generated! See scripts/docs_collector.py * <> * <> * <> - * <> + * <> * <> * <> * <> diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index 2061b943aa2..d9c291f168c 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -314,7 +314,7 @@ metricbeat.modules: # Path to server status. Default server-status #server_status_path: "server-status" -#------------------------------- PHP-FPM Module ------------------------------ +#------------------------------- PHP_FPM Module ------------------------------ - module: php_fpm metricsets: ["pool"] period: 10s diff --git a/metricbeat/module/aerospike/_meta/fields.yml b/metricbeat/module/aerospike/_meta/fields.yml index 184eaaa4772..788548fd1b1 100644 --- a/metricbeat/module/aerospike/_meta/fields.yml +++ b/metricbeat/module/aerospike/_meta/fields.yml @@ -1,7 +1,7 @@ - key: aerospike title: "Aerospike" description: > - []experimental + experimental[] Aerospike module fields: diff --git a/metricbeat/module/elasticsearch/_meta/fields.yml b/metricbeat/module/elasticsearch/_meta/fields.yml index 9cd0bd9a6c7..4c9dfe3aed6 100644 --- a/metricbeat/module/elasticsearch/_meta/fields.yml +++ b/metricbeat/module/elasticsearch/_meta/fields.yml @@ -1,7 +1,7 @@ - key: elasticsearch title: "Elasticsearch" description: > - []experimental + experimental[] Elasticsearch module short_config: false diff --git a/metricbeat/module/jolokia/_meta/fields.yml b/metricbeat/module/jolokia/_meta/fields.yml index 4e69eef344a..b39d92ed317 100644 --- a/metricbeat/module/jolokia/_meta/fields.yml +++ b/metricbeat/module/jolokia/_meta/fields.yml @@ -1,7 +1,7 @@ - key: jolokia title: "Jolokia" description: > - []beta + beta[] Jolokia module short_config: false diff --git a/metricbeat/module/kibana/_meta/fields.yml b/metricbeat/module/kibana/_meta/fields.yml index 40774070ee5..f25c1113dc1 100644 --- a/metricbeat/module/kibana/_meta/fields.yml +++ b/metricbeat/module/kibana/_meta/fields.yml @@ -1,7 +1,7 @@ - key: kibana title: "Kibana" description: > - []experimental + experimental[] Kibana module short_config: false diff --git a/metricbeat/module/memcached/_meta/fields.yml b/metricbeat/module/memcached/_meta/fields.yml index 6e5aab73367..e38fd3298d9 100644 --- a/metricbeat/module/memcached/_meta/fields.yml +++ b/metricbeat/module/memcached/_meta/fields.yml @@ -1,7 +1,7 @@ - key: memcached title: "Memcached" description: > - []beta + beta[] Memcached module short_config: false diff --git a/metricbeat/module/php_fpm/_meta/docs.asciidoc b/metricbeat/module/php_fpm/_meta/docs.asciidoc index 6292070038a..13925f11981 100644 --- a/metricbeat/module/php_fpm/_meta/docs.asciidoc +++ b/metricbeat/module/php_fpm/_meta/docs.asciidoc @@ -1,4 +1,4 @@ -== PHP-FPM module +== PHP_FPM module beta[] @@ -29,5 +29,5 @@ location ~ /status { [float] === Compatibility -The PHP-FPM metricsets were tested with PHP 7.1.1 and are expected to +The PHP_FPM metricsets were tested with PHP 7.1.1 and are expected to work with all versions >= 5. diff --git a/metricbeat/module/php_fpm/_meta/fields.yml b/metricbeat/module/php_fpm/_meta/fields.yml index 769b3b627cd..4bc86937b9b 100644 --- a/metricbeat/module/php_fpm/_meta/fields.yml +++ b/metricbeat/module/php_fpm/_meta/fields.yml @@ -1,5 +1,5 @@ - key: php_fpm - title: "PHP-FPM" + title: "PHP_FPM" description: > beta[] diff --git a/metricbeat/module/php_fpm/pool/_meta/docs.asciidoc b/metricbeat/module/php_fpm/pool/_meta/docs.asciidoc index 83fcf358c52..9e5beeaab70 100644 --- a/metricbeat/module/php_fpm/pool/_meta/docs.asciidoc +++ b/metricbeat/module/php_fpm/pool/_meta/docs.asciidoc @@ -1,3 +1,3 @@ -=== PHP-FPM pool metricset +=== PHP_FPM pool metricset -This is the `pool` metricset of the PHP-FPM module. +This is the `pool` metricset of the PHP_FPM module. diff --git a/metricbeat/module/rabbitmq/_meta/fields.yml b/metricbeat/module/rabbitmq/_meta/fields.yml index 2f1dcef1335..c48366efae9 100644 --- a/metricbeat/module/rabbitmq/_meta/fields.yml +++ b/metricbeat/module/rabbitmq/_meta/fields.yml @@ -1,7 +1,7 @@ - key: rabbitmq title: "RabbitMQ" description: > - []experimental + experimental[] RabbitMQ module fields: diff --git a/metricbeat/module/windows/_meta/fields.yml b/metricbeat/module/windows/_meta/fields.yml index e62c86f6ead..0a6aa5af948 100644 --- a/metricbeat/module/windows/_meta/fields.yml +++ b/metricbeat/module/windows/_meta/fields.yml @@ -1,7 +1,7 @@ - key: windows title: "Windows" description: > - []beta + beta[] Module for Windows short_config: false fields: diff --git a/metricbeat/scripts/module/docs.asciidoc b/metricbeat/scripts/module/docs.asciidoc index db958928fa4..3447dd2758a 100644 --- a/metricbeat/scripts/module/docs.asciidoc +++ b/metricbeat/scripts/module/docs.asciidoc @@ -1,4 +1,4 @@ -== {module} Module +== {module} module -This is the {module} Module. +This is the {module} module. diff --git a/metricbeat/scripts/module/fields.yml b/metricbeat/scripts/module/fields.yml index f0043e3ee42..af7f34ab1fe 100644 --- a/metricbeat/scripts/module/fields.yml +++ b/metricbeat/scripts/module/fields.yml @@ -1,9 +1,9 @@ - key: {module} title: "{module}" description: > - []experimental + experimental[] - {module} Module + {module} module fields: - name: {module} type: group diff --git a/packetbeat/docs/fields.asciidoc b/packetbeat/docs/fields.asciidoc index ca4431030fc..1b46a625647 100644 --- a/packetbeat/docs/fields.asciidoc +++ b/packetbeat/docs/fields.asciidoc @@ -4,7 +4,7 @@ This file is generated! See _meta/fields.yml and scripts/generate_field_docs.py //// [[exported-fields]] -= Exported Fields += Exported fields [partintro] @@ -36,14 +36,14 @@ grouped in the following categories: -- [[exported-fields-amqp]] -== AMQP Fields +== AMQP fields AMQP specific event fields. [float] -=== amqp.reply-code +=== `amqp.reply-code` type: long @@ -53,7 +53,7 @@ AMQP reply code to an error, similar to http reply-code [float] -=== amqp.reply-text +=== `amqp.reply-text` type: keyword @@ -61,7 +61,7 @@ Text explaining the error. [float] -=== amqp.class-id +=== `amqp.class-id` type: long @@ -69,7 +69,7 @@ Failing method class. [float] -=== amqp.method-id +=== `amqp.method-id` type: long @@ -77,7 +77,7 @@ Failing method ID. [float] -=== amqp.exchange +=== `amqp.exchange` type: keyword @@ -85,7 +85,7 @@ Name of the exchange. [float] -=== amqp.exchange-type +=== `amqp.exchange-type` type: keyword @@ -95,7 +95,7 @@ Exchange type. [float] -=== amqp.passive +=== `amqp.passive` type: boolean @@ -103,7 +103,7 @@ If set, do not create exchange/queue. [float] -=== amqp.durable +=== `amqp.durable` type: boolean @@ -111,7 +111,7 @@ If set, request a durable exchange/queue. [float] -=== amqp.exclusive +=== `amqp.exclusive` type: boolean @@ -119,7 +119,7 @@ If set, request an exclusive queue. [float] -=== amqp.auto-delete +=== `amqp.auto-delete` type: boolean @@ -127,7 +127,7 @@ If set, auto-delete queue when unused. [float] -=== amqp.no-wait +=== `amqp.no-wait` type: boolean @@ -135,13 +135,13 @@ If set, the server will not respond to the method. [float] -=== amqp.consumer-tag +=== `amqp.consumer-tag` Identifier for the consumer, valid within the current channel. [float] -=== amqp.delivery-tag +=== `amqp.delivery-tag` type: long @@ -149,7 +149,7 @@ The server-assigned and channel-specific delivery tag. [float] -=== amqp.message-count +=== `amqp.message-count` type: long @@ -157,7 +157,7 @@ The number of messages in the queue, which will be zero for newly-declared queue [float] -=== amqp.consumer-count +=== `amqp.consumer-count` type: long @@ -165,7 +165,7 @@ The number of consumers of a queue. [float] -=== amqp.routing-key +=== `amqp.routing-key` type: keyword @@ -173,7 +173,7 @@ Message routing key. [float] -=== amqp.no-ack +=== `amqp.no-ack` type: boolean @@ -181,7 +181,7 @@ If set, the server does not expect acknowledgements for messages. [float] -=== amqp.no-local +=== `amqp.no-local` type: boolean @@ -189,7 +189,7 @@ If set, the server will not send messages to the connection that published them. [float] -=== amqp.if-unused +=== `amqp.if-unused` type: boolean @@ -197,7 +197,7 @@ Delete only if unused. [float] -=== amqp.if-empty +=== `amqp.if-empty` type: boolean @@ -205,7 +205,7 @@ Delete only if empty. [float] -=== amqp.queue +=== `amqp.queue` type: keyword @@ -213,7 +213,7 @@ The queue name identifies the queue within the vhost. [float] -=== amqp.redelivered +=== `amqp.redelivered` type: boolean @@ -221,7 +221,7 @@ Indicates that the message has been previously delivered to this or another clie [float] -=== amqp.multiple +=== `amqp.multiple` type: boolean @@ -229,7 +229,7 @@ Acknowledge multiple messages. [float] -=== amqp.arguments +=== `amqp.arguments` type: object @@ -237,7 +237,7 @@ Optional additional arguments passed to some methods. Can be of various types. [float] -=== amqp.mandatory +=== `amqp.mandatory` type: boolean @@ -245,7 +245,7 @@ Indicates mandatory routing. [float] -=== amqp.immediate +=== `amqp.immediate` type: boolean @@ -253,7 +253,7 @@ Request immediate delivery. [float] -=== amqp.content-type +=== `amqp.content-type` type: keyword @@ -263,7 +263,7 @@ MIME content type. [float] -=== amqp.content-encoding +=== `amqp.content-encoding` type: keyword @@ -271,7 +271,7 @@ MIME content encoding. [float] -=== amqp.headers +=== `amqp.headers` type: object @@ -279,7 +279,7 @@ Message header field table. [float] -=== amqp.delivery-mode +=== `amqp.delivery-mode` type: keyword @@ -287,7 +287,7 @@ Non-persistent (1) or persistent (2). [float] -=== amqp.priority +=== `amqp.priority` type: long @@ -295,7 +295,7 @@ Message priority, 0 to 9. [float] -=== amqp.correlation-id +=== `amqp.correlation-id` type: keyword @@ -303,7 +303,7 @@ Application correlation identifier. [float] -=== amqp.reply-to +=== `amqp.reply-to` type: keyword @@ -311,7 +311,7 @@ Address to reply to. [float] -=== amqp.expiration +=== `amqp.expiration` type: keyword @@ -319,7 +319,7 @@ Message expiration specification. [float] -=== amqp.message-id +=== `amqp.message-id` type: keyword @@ -327,7 +327,7 @@ Application message identifier. [float] -=== amqp.timestamp +=== `amqp.timestamp` type: keyword @@ -335,7 +335,7 @@ Message timestamp. [float] -=== amqp.type +=== `amqp.type` type: keyword @@ -343,7 +343,7 @@ Message type name. [float] -=== amqp.user-id +=== `amqp.user-id` type: keyword @@ -351,7 +351,7 @@ Creating user id. [float] -=== amqp.app-id +=== `amqp.app-id` type: keyword @@ -359,38 +359,38 @@ Creating application id. [[exported-fields-beat]] -== Beat Fields +== Beat fields Contains common beat fields available in all event types. [float] -=== beat.name +=== `beat.name` The name of the Beat sending the log messages. If the Beat name is set in the configuration file, then that value is used. If it is not set, the hostname is used. To set the Beat name, use the `name` option in the configuration file. [float] -=== beat.hostname +=== `beat.hostname` The hostname as returned by the operating system on which the Beat is running. [float] -=== beat.timezone +=== `beat.timezone` The timezone as returned by the operating system on which the Beat is running. [float] -=== beat.version +=== `beat.version` The version of the beat that generated this event. [float] -=== @timestamp +=== `@timestamp` type: date @@ -404,13 +404,13 @@ The timestamp when the event log record was generated. [float] -=== tags +=== `tags` Arbitrary tags that can be set per Beat and per transaction type. [float] -=== fields +=== `fields` type: object @@ -418,14 +418,14 @@ Contains user configurable fields. [float] -== error Fields +== error fields Error fields containing additional info in case of errors. [float] -=== error.message +=== `error.message` type: text @@ -433,7 +433,7 @@ Error message. [float] -=== error.code +=== `error.code` type: long @@ -441,7 +441,7 @@ Error code. [float] -=== error.type +=== `error.type` type: keyword @@ -449,612 +449,612 @@ Error type. [[exported-fields-cassandra]] -== Cassandra Fields +== Cassandra fields Cassandra v4/3 specific event fields. [float] -== cassandra Fields +== cassandra fields Information about the Cassandra request and response. [float] -== request Fields +== request fields Cassandra request. [float] -== headers Fields +== headers fields Cassandra request headers. [float] -=== cassandra.request.headers.version +=== `cassandra.request.headers.version` type: long The version of the protocol. [float] -=== cassandra.request.headers.flags +=== `cassandra.request.headers.flags` type: keyword Flags applying to this frame. [float] -=== cassandra.request.headers.stream +=== `cassandra.request.headers.stream` type: keyword A frame has a stream id. If a client sends a request message with the stream id X, it is guaranteed that the stream id of the response to that message will be X. [float] -=== cassandra.request.headers.op +=== `cassandra.request.headers.op` type: keyword An operation type that distinguishes the actual message. [float] -=== cassandra.request.headers.length +=== `cassandra.request.headers.length` type: long A integer representing the length of the body of the frame (a frame is limited to 256MB in length). [float] -=== cassandra.request.query +=== `cassandra.request.query` type: keyword The CQL query which client send to cassandra. [float] -== response Fields +== response fields Cassandra response. [float] -== headers Fields +== headers fields Cassandra response headers, the structure is as same as request's header. [float] -=== cassandra.response.headers.version +=== `cassandra.response.headers.version` type: long The version of the protocol. [float] -=== cassandra.response.headers.flags +=== `cassandra.response.headers.flags` type: keyword Flags applying to this frame. [float] -=== cassandra.response.headers.stream +=== `cassandra.response.headers.stream` type: keyword A frame has a stream id. If a client sends a request message with the stream id X, it is guaranteed that the stream id of the response to that message will be X. [float] -=== cassandra.response.headers.op +=== `cassandra.response.headers.op` type: keyword An operation type that distinguishes the actual message. [float] -=== cassandra.response.headers.length +=== `cassandra.response.headers.length` type: long A integer representing the length of the body of the frame (a frame is limited to 256MB in length). [float] -== result Fields +== result fields Details about the returned result. [float] -=== cassandra.response.result.type +=== `cassandra.response.result.type` type: keyword Cassandra result type. [float] -== rows Fields +== rows fields Details about the rows. [float] -=== cassandra.response.result.rows.num_rows +=== `cassandra.response.result.rows.num_rows` type: long Representing the number of rows present in this result. [float] -== meta Fields +== meta fields Composed of result metadata. [float] -=== cassandra.response.result.rows.meta.keyspace +=== `cassandra.response.result.rows.meta.keyspace` type: keyword Only present after set Global_tables_spec, the keyspace name. [float] -=== cassandra.response.result.rows.meta.table +=== `cassandra.response.result.rows.meta.table` type: keyword Only present after set Global_tables_spec, the table name. [float] -=== cassandra.response.result.rows.meta.flags +=== `cassandra.response.result.rows.meta.flags` type: keyword Provides information on the formatting of the remaining information. [float] -=== cassandra.response.result.rows.meta.col_count +=== `cassandra.response.result.rows.meta.col_count` type: long Representing the number of columns selected by the query that produced this result. [float] -=== cassandra.response.result.rows.meta.pkey_columns +=== `cassandra.response.result.rows.meta.pkey_columns` type: long Representing the PK columns index and counts. [float] -=== cassandra.response.result.rows.meta.paging_state +=== `cassandra.response.result.rows.meta.paging_state` type: keyword The paging_state is a bytes value that should be used in QUERY/EXECUTE to continue paging and retrieve the remainder of the result for this query. [float] -=== cassandra.response.result.keyspace +=== `cassandra.response.result.keyspace` type: keyword Indicating the name of the keyspace that has been set. [float] -== schema_change Fields +== schema_change fields The result to a schema_change message. [float] -=== cassandra.response.result.schema_change.change +=== `cassandra.response.result.schema_change.change` type: keyword Representing the type of changed involved. [float] -=== cassandra.response.result.schema_change.keyspace +=== `cassandra.response.result.schema_change.keyspace` type: keyword This describes which keyspace has changed. [float] -=== cassandra.response.result.schema_change.table +=== `cassandra.response.result.schema_change.table` type: keyword This describes which table has changed. [float] -=== cassandra.response.result.schema_change.object +=== `cassandra.response.result.schema_change.object` type: keyword This describes the name of said affected object (either the table, user type, function, or aggregate name). [float] -=== cassandra.response.result.schema_change.target +=== `cassandra.response.result.schema_change.target` type: keyword Target could be "FUNCTION" or "AGGREGATE", multiple arguments. [float] -=== cassandra.response.result.schema_change.name +=== `cassandra.response.result.schema_change.name` type: keyword The function/aggregate name. [float] -=== cassandra.response.result.schema_change.args +=== `cassandra.response.result.schema_change.args` type: keyword One string for each argument type (as CQL type). [float] -== prepared Fields +== prepared fields The result to a PREPARE message. [float] -=== cassandra.response.result.prepared.prepared_id +=== `cassandra.response.result.prepared.prepared_id` type: keyword Representing the prepared query ID. [float] -== req_meta Fields +== req_meta fields This describes the request metadata. [float] -=== cassandra.response.result.prepared.req_meta.keyspace +=== `cassandra.response.result.prepared.req_meta.keyspace` type: keyword Only present after set Global_tables_spec, the keyspace name. [float] -=== cassandra.response.result.prepared.req_meta.table +=== `cassandra.response.result.prepared.req_meta.table` type: keyword Only present after set Global_tables_spec, the table name. [float] -=== cassandra.response.result.prepared.req_meta.flags +=== `cassandra.response.result.prepared.req_meta.flags` type: keyword Provides information on the formatting of the remaining information. [float] -=== cassandra.response.result.prepared.req_meta.col_count +=== `cassandra.response.result.prepared.req_meta.col_count` type: long Representing the number of columns selected by the query that produced this result. [float] -=== cassandra.response.result.prepared.req_meta.pkey_columns +=== `cassandra.response.result.prepared.req_meta.pkey_columns` type: long Representing the PK columns index and counts. [float] -=== cassandra.response.result.prepared.req_meta.paging_state +=== `cassandra.response.result.prepared.req_meta.paging_state` type: keyword The paging_state is a bytes value that should be used in QUERY/EXECUTE to continue paging and retrieve the remainder of the result for this query. [float] -== resp_meta Fields +== resp_meta fields This describes the metadata for the result set. [float] -=== cassandra.response.result.prepared.resp_meta.keyspace +=== `cassandra.response.result.prepared.resp_meta.keyspace` type: keyword Only present after set Global_tables_spec, the keyspace name. [float] -=== cassandra.response.result.prepared.resp_meta.table +=== `cassandra.response.result.prepared.resp_meta.table` type: keyword Only present after set Global_tables_spec, the table name. [float] -=== cassandra.response.result.prepared.resp_meta.flags +=== `cassandra.response.result.prepared.resp_meta.flags` type: keyword Provides information on the formatting of the remaining information. [float] -=== cassandra.response.result.prepared.resp_meta.col_count +=== `cassandra.response.result.prepared.resp_meta.col_count` type: long Representing the number of columns selected by the query that produced this result. [float] -=== cassandra.response.result.prepared.resp_meta.pkey_columns +=== `cassandra.response.result.prepared.resp_meta.pkey_columns` type: long Representing the PK columns index and counts. [float] -=== cassandra.response.result.prepared.resp_meta.paging_state +=== `cassandra.response.result.prepared.resp_meta.paging_state` type: keyword The paging_state is a bytes value that should be used in QUERY/EXECUTE to continue paging and retrieve the remainder of the result for this query. [float] -=== cassandra.response.supported +=== `cassandra.response.supported` type: object Indicates which startup options are supported by the server. This message comes as a response to an OPTIONS message. [float] -== authentication Fields +== authentication fields Indicates that the server requires authentication, and which authentication mechanism to use. [float] -=== cassandra.response.authentication.class +=== `cassandra.response.authentication.class` type: keyword Indicates the full class name of the IAuthenticator in use [float] -=== cassandra.response.warnings +=== `cassandra.response.warnings` type: keyword The text of the warnings, only occur when Warning flag was set. [float] -== event Fields +== event fields Event pushed by the server. A client will only receive events for the types it has REGISTERed to. [float] -=== cassandra.response.event.type +=== `cassandra.response.event.type` type: keyword Representing the event type. [float] -=== cassandra.response.event.change +=== `cassandra.response.event.change` type: keyword The message corresponding respectively to the type of change followed by the address of the new/removed node. [float] -=== cassandra.response.event.host +=== `cassandra.response.event.host` type: keyword Representing the node ip. [float] -=== cassandra.response.event.port +=== `cassandra.response.event.port` type: long Representing the node port. [float] -== schema_change Fields +== schema_change fields The events details related to schema change. [float] -=== cassandra.response.event.schema_change.change +=== `cassandra.response.event.schema_change.change` type: keyword Representing the type of changed involved. [float] -=== cassandra.response.event.schema_change.keyspace +=== `cassandra.response.event.schema_change.keyspace` type: keyword This describes which keyspace has changed. [float] -=== cassandra.response.event.schema_change.table +=== `cassandra.response.event.schema_change.table` type: keyword This describes which table has changed. [float] -=== cassandra.response.event.schema_change.object +=== `cassandra.response.event.schema_change.object` type: keyword This describes the name of said affected object (either the table, user type, function, or aggregate name). [float] -=== cassandra.response.event.schema_change.target +=== `cassandra.response.event.schema_change.target` type: keyword Target could be "FUNCTION" or "AGGREGATE", multiple arguments. [float] -=== cassandra.response.event.schema_change.name +=== `cassandra.response.event.schema_change.name` type: keyword The function/aggregate name. [float] -=== cassandra.response.event.schema_change.args +=== `cassandra.response.event.schema_change.args` type: keyword One string for each argument type (as CQL type). [float] -== error Fields +== error fields Indicates an error processing a request. The body of the message will be an error code followed by a error message. Then, depending on the exception, more content may follow. [float] -=== cassandra.response.error.code +=== `cassandra.response.error.code` type: long The error code of the Cassandra response. [float] -=== cassandra.response.error.msg +=== `cassandra.response.error.msg` type: keyword The error message of the Cassandra response. [float] -=== cassandra.response.error.type +=== `cassandra.response.error.type` type: keyword The error type of the Cassandra response. [float] -== details Fields +== details fields The details of the error. [float] -=== cassandra.response.error.details.read_consistency +=== `cassandra.response.error.details.read_consistency` type: keyword Representing the consistency level of the query that triggered the exception. [float] -=== cassandra.response.error.details.required +=== `cassandra.response.error.details.required` type: long Representing the number of nodes that should be alive to respect consistency level. [float] -=== cassandra.response.error.details.alive +=== `cassandra.response.error.details.alive` type: long Representing the number of replicas that were known to be alive when the request had been processed (since an unavailable exception has been triggered). [float] -=== cassandra.response.error.details.received +=== `cassandra.response.error.details.received` type: long Representing the number of nodes having acknowledged the request. [float] -=== cassandra.response.error.details.blockfor +=== `cassandra.response.error.details.blockfor` type: long Representing the number of replicas whose acknowledgement is required to achieve consistency level. [float] -=== cassandra.response.error.details.write_type +=== `cassandra.response.error.details.write_type` type: keyword Describe the type of the write that timed out. [float] -=== cassandra.response.error.details.data_present +=== `cassandra.response.error.details.data_present` type: boolean It means the replica that was asked for data had responded. [float] -=== cassandra.response.error.details.keyspace +=== `cassandra.response.error.details.keyspace` type: keyword The keyspace of the failed function. [float] -=== cassandra.response.error.details.table +=== `cassandra.response.error.details.table` type: keyword The keyspace of the failed function. [float] -=== cassandra.response.error.details.stmt_id +=== `cassandra.response.error.details.stmt_id` type: keyword Representing the unknown ID. [float] -=== cassandra.response.error.details.num_failures +=== `cassandra.response.error.details.num_failures` type: keyword Representing the number of nodes that experience a failure while executing the request. [float] -=== cassandra.response.error.details.function +=== `cassandra.response.error.details.function` type: keyword The name of the failed function. [float] -=== cassandra.response.error.details.arg_types +=== `cassandra.response.error.details.arg_types` type: keyword One string for each argument type (as CQL type) of the failed function. [[exported-fields-cloud]] -== Cloud Provider Metadata Fields +== Cloud provider metadata fields Metadata from cloud providers added by the add_cloud_metadata processor. [float] -=== meta.cloud.provider +=== `meta.cloud.provider` example: ec2 @@ -1062,19 +1062,19 @@ Name of the cloud provider. Possible values are ec2, gce, or digitalocean. [float] -=== meta.cloud.instance_id +=== `meta.cloud.instance_id` Instance ID of the host machine. [float] -=== meta.cloud.instance_name +=== `meta.cloud.instance_name` Instance name of the host machine. [float] -=== meta.cloud.machine_type +=== `meta.cloud.machine_type` example: t2.medium @@ -1082,7 +1082,7 @@ Machine type of the host machine. [float] -=== meta.cloud.availability_zone +=== `meta.cloud.availability_zone` example: us-east-1c @@ -1090,7 +1090,7 @@ Availability zone in which this host is running. [float] -=== meta.cloud.project_id +=== `meta.cloud.project_id` example: project-x @@ -1098,44 +1098,44 @@ Name of the project in Google Cloud. [float] -=== meta.cloud.region +=== `meta.cloud.region` Region in which this host is running. [[exported-fields-common]] -== Common Fields +== Common fields These fields contain data about the environment in which the transaction or flow was captured. [float] -=== server +=== `server` The name of the server that served the transaction. [float] -=== client_server +=== `client_server` The name of the server that initiated the transaction. [float] -=== service +=== `service` The name of the logical service that served the transaction. [float] -=== client_service +=== `client_service` The name of the logical service that initiated the transaction. [float] -=== ip +=== `ip` format: dotted notation. @@ -1143,7 +1143,7 @@ The IP address of the server that served the transaction. [float] -=== client_ip +=== `client_ip` format: dotted notation. @@ -1151,7 +1151,7 @@ The IP address of the server that initiated the transaction. [float] -=== real_ip +=== `real_ip` format: Dotted notation. @@ -1160,13 +1160,13 @@ Unless this field is disabled, it always has a value, and it matches the `client [float] -== client_geoip Fields +== client_geoip fields The GeoIP information of the client. [float] -=== client_geoip.location +=== `client_geoip.location` type: geo_point @@ -1176,7 +1176,7 @@ The GeoIP location of the `client_ip` address. This field is available only if y [float] -=== client_port +=== `client_port` format: dotted notation. @@ -1184,7 +1184,7 @@ The layer 4 port of the process that initiated the transaction. [float] -=== transport +=== `transport` example: udp @@ -1192,7 +1192,7 @@ The transport protocol used for the transaction. If not specified, then tcp is a [float] -=== type +=== `type` required: True @@ -1200,7 +1200,7 @@ The type of the transaction (for example, HTTP, MySQL, Redis, or RUM) or "flow" [float] -=== port +=== `port` format: dotted notation. @@ -1208,32 +1208,32 @@ The layer 4 port of the process that served the transaction. [float] -=== proc +=== `proc` The name of the process that served the transaction. [float] -=== client_proc +=== `client_proc` The name of the process that initiated the transaction. [float] -=== release +=== `release` The software release of the service serving the transaction. This can be the commit id or a semantic version. [[exported-fields-dns]] -== DNS Fields +== DNS fields DNS-specific event fields. [float] -=== dns.id +=== `dns.id` type: long @@ -1241,7 +1241,7 @@ The DNS packet identifier assigned by the program that generated the query. The [float] -=== dns.op_code +=== `dns.op_code` example: QUERY @@ -1249,7 +1249,7 @@ The DNS operation code that specifies the kind of query in the message. This val [float] -=== dns.flags.authoritative +=== `dns.flags.authoritative` type: boolean @@ -1257,7 +1257,7 @@ A DNS flag specifying that the responding server is an authority for the domain [float] -=== dns.flags.recursion_available +=== `dns.flags.recursion_available` type: boolean @@ -1265,7 +1265,7 @@ A DNS flag specifying whether recursive query support is available in the name s [float] -=== dns.flags.recursion_desired +=== `dns.flags.recursion_desired` type: boolean @@ -1273,7 +1273,7 @@ A DNS flag specifying that the client directs the server to pursue a query recur [float] -=== dns.flags.authentic_data +=== `dns.flags.authentic_data` type: boolean @@ -1281,7 +1281,7 @@ A DNS flag specifying that the recursive server considers the response authentic [float] -=== dns.flags.checking_disabled +=== `dns.flags.checking_disabled` type: boolean @@ -1289,7 +1289,7 @@ A DNS flag specifying that the client disables the server signature validation o [float] -=== dns.flags.truncated_response +=== `dns.flags.truncated_response` type: boolean @@ -1297,14 +1297,14 @@ A DNS flag specifying that only the first 512 bytes of the reply were returned. [float] -=== dns.response_code +=== `dns.response_code` example: NOERROR The DNS status code. [float] -=== dns.question.name +=== `dns.question.name` example: www.google.com. @@ -1312,28 +1312,28 @@ The domain name being queried. If the name field contains non-printable characte [float] -=== dns.question.type +=== `dns.question.type` example: AAAA The type of records being queried. [float] -=== dns.question.class +=== `dns.question.class` example: IN The class of of records being queried. [float] -=== dns.question.etld_plus_one +=== `dns.question.etld_plus_one` example: amazon.co.uk. The effective top-level domain (eTLD) plus one more label. For example, the eTLD+1 for "foo.bar.golang.org." is "golang.org.". The data for determining the eTLD comes from an embedded copy of the data from http://publicsuffix.org. [float] -=== dns.answers +=== `dns.answers` type: object @@ -1341,7 +1341,7 @@ An array containing a dictionary about each answer section returned by the serve [float] -=== dns.answers_count +=== `dns.answers_count` type: long @@ -1349,28 +1349,28 @@ The number of resource records contained in the `dns.answers` field. [float] -=== dns.answers.name +=== `dns.answers.name` example: example.com. The domain name to which this resource record pertains. [float] -=== dns.answers.type +=== `dns.answers.type` example: MX The type of data contained in this resource record. [float] -=== dns.answers.class +=== `dns.answers.class` example: IN The class of DNS data contained in this resource record. [float] -=== dns.answers.ttl +=== `dns.answers.ttl` type: long @@ -1378,13 +1378,13 @@ The time interval in seconds that this resource record may be cached before it s [float] -=== dns.answers.data +=== `dns.answers.data` The data describing the resource. The meaning of this data depends on the type and class of the resource record. [float] -=== dns.authorities +=== `dns.authorities` type: object @@ -1392,7 +1392,7 @@ An array containing a dictionary for each authority section from the answer. [float] -=== dns.authorities_count +=== `dns.authorities_count` type: long @@ -1400,28 +1400,28 @@ The number of resource records contained in the `dns.authorities` field. The `dn [float] -=== dns.authorities.name +=== `dns.authorities.name` example: example.com. The domain name to which this resource record pertains. [float] -=== dns.authorities.type +=== `dns.authorities.type` example: NS The type of data contained in this resource record. [float] -=== dns.authorities.class +=== `dns.authorities.class` example: IN The class of DNS data contained in this resource record. [float] -=== dns.additionals +=== `dns.additionals` type: object @@ -1429,7 +1429,7 @@ An array containing a dictionary for each additional section from the answer. [float] -=== dns.additionals_count +=== `dns.additionals_count` type: long @@ -1437,28 +1437,28 @@ The number of resource records contained in the `dns.additionals` field. The `dn [float] -=== dns.additionals.name +=== `dns.additionals.name` example: example.com. The domain name to which this resource record pertains. [float] -=== dns.additionals.type +=== `dns.additionals.type` example: NS The type of data contained in this resource record. [float] -=== dns.additionals.class +=== `dns.additionals.class` example: IN The class of DNS data contained in this resource record. [float] -=== dns.additionals.ttl +=== `dns.additionals.ttl` type: long @@ -1466,41 +1466,41 @@ The time interval in seconds that this resource record may be cached before it s [float] -=== dns.additionals.data +=== `dns.additionals.data` The data describing the resource. The meaning of this data depends on the type and class of the resource record. [float] -=== dns.opt.version +=== `dns.opt.version` example: 0 The EDNS version. [float] -=== dns.opt.do +=== `dns.opt.do` type: boolean If set, the transaction uses DNSSEC. [float] -=== dns.opt.ext_rcode +=== `dns.opt.ext_rcode` example: BADVERS Extended response code field. [float] -=== dns.opt.udp_size +=== `dns.opt.udp_size` type: long Requestor's UDP payload size (in bytes). [[exported-fields-docker-processor]] -== docker Fields +== Docker fields beta[] Docker stats collected from Docker. @@ -1509,7 +1509,7 @@ Docker stats collected from Docker. [float] -=== docker.container.id +=== `docker.container.id` type: keyword @@ -1517,7 +1517,7 @@ Unique container id. [float] -=== docker.container.image +=== `docker.container.image` type: keyword @@ -1525,7 +1525,7 @@ Name of the image the container was built on. [float] -=== docker.container.name +=== `docker.container.name` type: keyword @@ -1533,7 +1533,7 @@ Container name. [float] -=== docker.container.labels +=== `docker.container.labels` type: object @@ -1541,14 +1541,14 @@ Image labels. [[exported-fields-flows_event]] -== Flow Event Fields +== Flow Event fields These fields contain data about the flow itself. [float] -=== start_time +=== `start_time` type: date @@ -1562,7 +1562,7 @@ The time, the first packet for the flow has been seen. [float] -=== last_time +=== `last_time` type: date @@ -1576,50 +1576,50 @@ The time, the most recent processed packet for the flow has been seen. [float] -=== final +=== `final` Indicates if event is last event in flow. If final is false, the event reports an intermediate flow state only. [float] -=== flow_id +=== `flow_id` Internal flow id based on connection meta data and address. [float] -=== vlan +=== `vlan` Innermost VLAN address used in network packets. [float] -=== outer_vlan +=== `outer_vlan` Second innermost VLAN address used in network packets. [float] -== source Fields +== source fields Properties of the source host [float] -=== source.mac +=== `source.mac` Source MAC address as indicated by first packet seen for the current flow. [float] -=== source.ip +=== `source.ip` Innermost IPv4 source address as indicated by first packet seen for the current flow. [float] -=== source.ip_location +=== `source.ip_location` type: geo_point @@ -1629,13 +1629,13 @@ The GeoIP location of the `ip_source` IP address. The field is a string containi [float] -=== source.outer_ip +=== `source.outer_ip` Second innermost IPv4 source address as indicated by first packet seen for the current flow. [float] -=== source.outer_ip_location +=== `source.outer_ip_location` type: geo_point @@ -1645,13 +1645,13 @@ The GeoIP location of the `outer_ip_source` IP address. The field is a string co [float] -=== source.ipv6 +=== `source.ipv6` Innermost IPv6 source address as indicated by first packet seen for the current flow. [float] -=== source.ipv6_location +=== `source.ipv6_location` type: geo_point @@ -1661,13 +1661,13 @@ The GeoIP location of the `ipv6_source` IP address. The field is a string contai [float] -=== source.outer_ipv6 +=== `source.outer_ipv6` Second innermost IPv6 source address as indicated by first packet seen for the current flow. [float] -=== source.outer_ipv6_location +=== `source.outer_ipv6_location` type: geo_point @@ -1677,20 +1677,20 @@ The GeoIP location of the `outer_ipv6_source` IP address. The field is a string [float] -=== source.port +=== `source.port` Source port number as indicated by first packet seen for the current flow. [float] -== stats Fields +== stats fields Object with source to destination flow measurements. [float] -=== source.stats.net_packets_total +=== `source.stats.net_packets_total` type: long @@ -1698,7 +1698,7 @@ Total number of packets [float] -=== source.stats.net_bytes_total +=== `source.stats.net_bytes_total` type: long @@ -1706,26 +1706,26 @@ Total number of bytes [float] -== dest Fields +== dest fields Properties of the destination host [float] -=== dest.mac +=== `dest.mac` Destination MAC address as indicated by first packet seen for the current flow. [float] -=== dest.ip +=== `dest.ip` Innermost IPv4 destination address as indicated by first packet seen for the current flow. [float] -=== dest.ip_location +=== `dest.ip_location` type: geo_point @@ -1735,13 +1735,13 @@ The GeoIP location of the `ip_dest` IP address. The field is a string containing [float] -=== dest.outer_ip +=== `dest.outer_ip` Second innermost IPv4 destination address as indicated by first packet seen for the current flow. [float] -=== dest.outer_ip_location +=== `dest.outer_ip_location` type: geo_point @@ -1751,13 +1751,13 @@ The GeoIP location of the `outer_ip_dest` IP address. The field is a string cont [float] -=== dest.ipv6 +=== `dest.ipv6` Innermost IPv6 destination address as indicated by first packet seen for the current flow. [float] -=== dest.ipv6_location +=== `dest.ipv6_location` type: geo_point @@ -1767,13 +1767,13 @@ The GeoIP location of the `ipv6_dest` IP address. The field is a string containi [float] -=== dest.outer_ipv6 +=== `dest.outer_ipv6` Second innermost IPv6 destination address as indicated by first packet seen for the current flow. [float] -=== dest.outer_ipv6_location +=== `dest.outer_ipv6_location` type: geo_point @@ -1783,20 +1783,20 @@ The GeoIP location of the `outer_ipv6_dest` IP address. The field is a string co [float] -=== dest.port +=== `dest.port` Destination port number as indicated by first packet seen for the current flow. [float] -== stats Fields +== stats fields Object with destination to source flow measurements. [float] -=== dest.stats.net_packets_total +=== `dest.stats.net_packets_total` type: long @@ -1804,7 +1804,7 @@ Total number of packets [float] -=== dest.stats.net_bytes_total +=== `dest.stats.net_bytes_total` type: long @@ -1812,43 +1812,43 @@ Total number of bytes [float] -=== icmp_id +=== `icmp_id` ICMP id used in ICMP based flow. [float] -=== connection_id +=== `connection_id` optional TCP connection id [[exported-fields-http]] -== HTTP Fields +== HTTP fields HTTP-specific event fields. [float] -== http Fields +== http fields Information about the HTTP request and response. [float] -== request Fields +== request fields HTTP request [float] -=== http.request.params +=== `http.request.params` The query parameters or form values. The query parameters are available in the Request-URI and the form values are set in the HTTP body when the content-type is set to `x-www-form-urlencoded`. [float] -=== http.request.headers +=== `http.request.headers` type: object @@ -1856,34 +1856,34 @@ A map containing the captured header fields from the request. Which headers to c [float] -=== http.request.body +=== `http.request.body` type: text The body of the HTTP request. [float] -== response Fields +== response fields HTTP response [float] -=== http.response.code +=== `http.response.code` example: 404 The HTTP status code. [float] -=== http.response.phrase +=== `http.response.phrase` example: Not found. The HTTP status phrase. [float] -=== http.response.headers +=== `http.response.headers` type: object @@ -1891,12 +1891,12 @@ A map containing the captured header fields from the response. Which headers to [float] -=== http.response.body +=== `http.response.body` The body of the HTTP response. [[exported-fields-icmp]] -== ICMP Fields +== ICMP fields ICMP specific event fields. @@ -1904,54 +1904,54 @@ ICMP specific event fields. [float] -=== icmp.version +=== `icmp.version` The version of the ICMP protocol. [float] -=== icmp.request.message +=== `icmp.request.message` type: keyword A human readable form of the request. [float] -=== icmp.request.type +=== `icmp.request.type` type: long The request type. [float] -=== icmp.request.code +=== `icmp.request.code` type: long The request code. [float] -=== icmp.response.message +=== `icmp.response.message` type: keyword A human readable form of the response. [float] -=== icmp.response.type +=== `icmp.response.type` type: long The response type. [float] -=== icmp.response.code +=== `icmp.response.code` type: long The response code. [[exported-fields-kubernetes-processor]] -== kubernetes Fields +== Kubernetes fields beta[] Kubernetes metadata added by the kubernetes processor @@ -1960,7 +1960,7 @@ Kubernetes metadata added by the kubernetes processor [float] -=== kubernetes.pod.name +=== `kubernetes.pod.name` type: keyword @@ -1968,7 +1968,7 @@ Kubernetes pod name [float] -=== kubernetes.namespace +=== `kubernetes.namespace` type: keyword @@ -1976,7 +1976,7 @@ Kubernetes namespace [float] -=== kubernetes.labels +=== `kubernetes.labels` type: object @@ -1984,7 +1984,7 @@ Kubernetes labels map [float] -=== kubernetes.annotations +=== `kubernetes.annotations` type: object @@ -1992,7 +1992,7 @@ Kubernetes annotations map [float] -=== kubernetes.container.name +=== `kubernetes.container.name` type: keyword @@ -2000,7 +2000,7 @@ Kubernetes container name [float] -=== kubernetes.container.image +=== `kubernetes.container.image` type: keyword @@ -2008,14 +2008,14 @@ Kubernetes container image [[exported-fields-memcache]] -== Memcache Fields +== Memcache fields Memcached-specific event fields [float] -=== memcache.protocol_type +=== `memcache.protocol_type` type: keyword @@ -2023,7 +2023,7 @@ The memcache protocol implementation. The value can be "binary" for binary-based [float] -=== memcache.request.line +=== `memcache.request.line` type: keyword @@ -2031,7 +2031,7 @@ The raw command line for unknown commands ONLY. [float] -=== memcache.request.command +=== `memcache.request.command` type: keyword @@ -2039,7 +2039,7 @@ The memcache command being requested in the memcache text protocol. For example [float] -=== memcache.response.command +=== `memcache.response.command` type: keyword @@ -2047,7 +2047,7 @@ Either the text based protocol response message type or the name of the originat [float] -=== memcache.request.type +=== `memcache.request.type` type: keyword @@ -2055,7 +2055,7 @@ The memcache command classification. This value can be "UNKNOWN", "Load", "Store [float] -=== memcache.response.type +=== `memcache.response.type` type: keyword @@ -2063,7 +2063,7 @@ The memcache command classification. This value can be "UNKNOWN", "Load", "Store [float] -=== memcache.response.error_msg +=== `memcache.response.error_msg` type: keyword @@ -2071,7 +2071,7 @@ The optional error message in the memcache response (text based protocol only). [float] -=== memcache.request.opcode +=== `memcache.request.opcode` type: keyword @@ -2079,7 +2079,7 @@ The binary protocol message opcode name. [float] -=== memcache.response.opcode +=== `memcache.response.opcode` type: keyword @@ -2087,7 +2087,7 @@ The binary protocol message opcode name. [float] -=== memcache.request.opcode_value +=== `memcache.request.opcode_value` type: long @@ -2095,7 +2095,7 @@ The binary protocol message opcode value. [float] -=== memcache.response.opcode_value +=== `memcache.response.opcode_value` type: long @@ -2103,7 +2103,7 @@ The binary protocol message opcode value. [float] -=== memcache.request.opaque +=== `memcache.request.opaque` type: long @@ -2111,7 +2111,7 @@ The binary protocol opaque header value used for correlating request with respon [float] -=== memcache.response.opaque +=== `memcache.response.opaque` type: long @@ -2119,7 +2119,7 @@ The binary protocol opaque header value used for correlating request with respon [float] -=== memcache.request.vbucket +=== `memcache.request.vbucket` type: long @@ -2127,7 +2127,7 @@ The vbucket index sent in the binary message. [float] -=== memcache.response.status +=== `memcache.response.status` type: keyword @@ -2135,7 +2135,7 @@ The textual representation of the response error code (binary protocol only). [float] -=== memcache.response.status_code +=== `memcache.response.status_code` type: long @@ -2143,7 +2143,7 @@ The status code value returned in the response (binary protocol only). [float] -=== memcache.request.keys +=== `memcache.request.keys` type: array @@ -2151,7 +2151,7 @@ The list of keys sent in the store or load commands. [float] -=== memcache.response.keys +=== `memcache.response.keys` type: array @@ -2159,7 +2159,7 @@ The list of keys returned for the load command (if present). [float] -=== memcache.request.count_values +=== `memcache.request.count_values` type: long @@ -2167,7 +2167,7 @@ The number of values found in the memcache request message. If the command does [float] -=== memcache.response.count_values +=== `memcache.response.count_values` type: long @@ -2175,7 +2175,7 @@ The number of values found in the memcache response message. If the command does [float] -=== memcache.request.values +=== `memcache.request.values` type: array @@ -2183,7 +2183,7 @@ The list of base64 encoded values sent with the request (if present). [float] -=== memcache.response.values +=== `memcache.response.values` type: array @@ -2191,7 +2191,7 @@ The list of base64 encoded values sent with the response (if present). [float] -=== memcache.request.bytes +=== `memcache.request.bytes` type: long @@ -2201,7 +2201,7 @@ The byte count of the values being transferred. [float] -=== memcache.response.bytes +=== `memcache.response.bytes` type: long @@ -2211,7 +2211,7 @@ The byte count of the values being transferred. [float] -=== memcache.request.delta +=== `memcache.request.delta` type: long @@ -2219,7 +2219,7 @@ The counter increment/decrement delta value. [float] -=== memcache.request.initial +=== `memcache.request.initial` type: long @@ -2227,7 +2227,7 @@ The counter increment/decrement initial value parameter (binary protocol only). [float] -=== memcache.request.verbosity +=== `memcache.request.verbosity` type: long @@ -2235,7 +2235,7 @@ The value of the memcache "verbosity" command. [float] -=== memcache.request.raw_args +=== `memcache.request.raw_args` type: keyword @@ -2243,7 +2243,7 @@ The text protocol raw arguments for the "stats ..." and "lru crawl ..." commands [float] -=== memcache.request.source_class +=== `memcache.request.source_class` type: long @@ -2251,7 +2251,7 @@ The source class id in 'slab reassign' command. [float] -=== memcache.request.dest_class +=== `memcache.request.dest_class` type: long @@ -2259,7 +2259,7 @@ The destination class id in 'slab reassign' command. [float] -=== memcache.request.automove +=== `memcache.request.automove` type: keyword @@ -2267,7 +2267,7 @@ The automove mode in the 'slab automove' command expressed as a string. This val [float] -=== memcache.request.flags +=== `memcache.request.flags` type: long @@ -2275,7 +2275,7 @@ The memcache command flags sent in the request (if present). [float] -=== memcache.response.flags +=== `memcache.response.flags` type: long @@ -2283,7 +2283,7 @@ The memcache message flags sent in the response (if present). [float] -=== memcache.request.exptime +=== `memcache.request.exptime` type: long @@ -2291,7 +2291,7 @@ The data expiry time in seconds sent with the memcache command (if present). If [float] -=== memcache.request.sleep_us +=== `memcache.request.sleep_us` type: long @@ -2299,7 +2299,7 @@ The sleep setting in microseconds for the 'lru_crawler sleep' command. [float] -=== memcache.response.value +=== `memcache.response.value` type: long @@ -2307,7 +2307,7 @@ The counter value returned by a counter operation. [float] -=== memcache.request.noreply +=== `memcache.request.noreply` type: boolean @@ -2315,7 +2315,7 @@ Set to true if noreply was set in the request. The `memcache.response` field wil [float] -=== memcache.request.quiet +=== `memcache.request.quiet` type: boolean @@ -2323,7 +2323,7 @@ Set to true if the binary protocol message is to be treated as a quiet message. [float] -=== memcache.request.cas_unique +=== `memcache.request.cas_unique` type: long @@ -2331,7 +2331,7 @@ The CAS (compare-and-swap) identifier if present. [float] -=== memcache.response.cas_unique +=== `memcache.response.cas_unique` type: long @@ -2339,7 +2339,7 @@ The CAS (compare-and-swap) identifier to be used with CAS-based updates (if pres [float] -=== memcache.response.stats +=== `memcache.response.stats` type: array @@ -2347,7 +2347,7 @@ The list of statistic values returned. Each entry is a dictionary with the field [float] -=== memcache.response.version +=== `memcache.response.version` type: keyword @@ -2355,7 +2355,7 @@ The returned memcache version string. [[exported-fields-mongodb]] -== MongoDb Fields +== MongoDb fields MongoDB-specific event fields. These fields mirror closely the fields for the MongoDB wire protocol. The higher level fields (for example, `query` and `resource`) apply to MongoDB events as well. @@ -2363,19 +2363,19 @@ MongoDB-specific event fields. These fields mirror closely the fields for the Mo [float] -=== mongodb.error +=== `mongodb.error` If the MongoDB request has resulted in an error, this field contains the error message returned by the server. [float] -=== mongodb.fullCollectionName +=== `mongodb.fullCollectionName` The full collection name. The full collection name is the concatenation of the database name with the collection name, using a dot (.) for the concatenation. For example, for the database foo and the collection bar, the full collection name is foo.bar. [float] -=== mongodb.numberToSkip +=== `mongodb.numberToSkip` type: long @@ -2383,7 +2383,7 @@ Sets the number of documents to omit - starting from the first document in the r [float] -=== mongodb.numberToReturn +=== `mongodb.numberToReturn` type: long @@ -2391,7 +2391,7 @@ The requested maximum number of documents to be returned. [float] -=== mongodb.numberReturned +=== `mongodb.numberReturned` type: long @@ -2399,121 +2399,121 @@ The number of documents in the reply. [float] -=== mongodb.startingFrom +=== `mongodb.startingFrom` Where in the cursor this reply is starting. [float] -=== mongodb.query +=== `mongodb.query` A JSON document that represents the query. The query will contain one or more elements, all of which must match for a document to be included in the result set. Possible elements include $query, $orderby, $hint, $explain, and $snapshot. [float] -=== mongodb.returnFieldsSelector +=== `mongodb.returnFieldsSelector` A JSON document that limits the fields in the returned documents. The returnFieldsSelector contains one or more elements, each of which is the name of a field that should be returned, and the integer value 1. [float] -=== mongodb.selector +=== `mongodb.selector` A BSON document that specifies the query for selecting the document to update or delete. [float] -=== mongodb.update +=== `mongodb.update` A BSON document that specifies the update to be performed. For information on specifying updates, see the Update Operations documentation from the MongoDB Manual. [float] -=== mongodb.cursorId +=== `mongodb.cursorId` The cursor identifier returned in the OP_REPLY. This must be the value that was returned from the database. [float] -== rpc Fields +== rpc fields OncRPC specific event fields. [float] -=== rpc.xid +=== `rpc.xid` RPC message transaction identifier. [float] -=== rpc.call_size +=== `rpc.call_size` type: long RPC call size with argument. [float] -=== rpc.reply_size +=== `rpc.reply_size` type: long RPC reply size with argument. [float] -=== rpc.status +=== `rpc.status` RPC message reply status. [float] -=== rpc.time +=== `rpc.time` type: long RPC message processing time. [float] -=== rpc.time_str +=== `rpc.time_str` RPC message processing time in human readable form. [float] -=== rpc.auth_flavor +=== `rpc.auth_flavor` RPC authentication flavor. [float] -=== rpc.cred.uid +=== `rpc.cred.uid` type: long RPC caller's user id, in case of auth-unix. [float] -=== rpc.cred.gid +=== `rpc.cred.gid` type: long RPC caller's group id, in case of auth-unix. [float] -=== rpc.cred.gids +=== `rpc.cred.gids` RPC caller's secondary group ids, in case of auth-unix. [float] -=== rpc.cred.stamp +=== `rpc.cred.stamp` type: long Arbitrary ID which the caller machine may generate. [float] -=== rpc.cred.machinename +=== `rpc.cred.machinename` The name of the caller's machine. [[exported-fields-mysql]] -== MySQL Fields +== MySQL fields MySQL-specific event fields. @@ -2521,7 +2521,7 @@ MySQL-specific event fields. [float] -=== mysql.iserror +=== `mysql.iserror` type: boolean @@ -2529,7 +2529,7 @@ If the MySQL query returns an error, this field is set to true. [float] -=== mysql.affected_rows +=== `mysql.affected_rows` type: long @@ -2537,31 +2537,31 @@ If the MySQL command is successful, this field contains the affected number of r [float] -=== mysql.insert_id +=== `mysql.insert_id` If the INSERT query is successful, this field contains the id of the newly inserted row. [float] -=== mysql.num_fields +=== `mysql.num_fields` If the SELECT query is successful, this field is set to the number of fields returned. [float] -=== mysql.num_rows +=== `mysql.num_rows` If the SELECT query is successful, this field is set to the number of rows returned. [float] -=== mysql.query +=== `mysql.query` The row mysql query as read from the transaction's request. [float] -=== mysql.error_code +=== `mysql.error_code` type: long @@ -2569,50 +2569,50 @@ The error code returned by MySQL. [float] -=== mysql.error_message +=== `mysql.error_message` The error info message returned by MySQL. [[exported-fields-nfs]] -== NFS Fields +== NFS fields NFS v4/3 specific event fields. [float] -=== nfs.version +=== `nfs.version` type: long NFS protocol version number. [float] -=== nfs.minor_version +=== `nfs.minor_version` type: long NFS protocol minor version number. [float] -=== nfs.tag +=== `nfs.tag` NFS v4 COMPOUND operation tag. [float] -=== nfs.opcode +=== `nfs.opcode` NFS operation name, or main operation name, in case of COMPOUND calls. [float] -=== nfs.status +=== `nfs.status` NFS operation reply status. [[exported-fields-pgsql]] -== PostgreSQL Fields +== PostgreSQL fields PostgreSQL-specific event fields. @@ -2620,13 +2620,13 @@ PostgreSQL-specific event fields. [float] -=== pgsql.query +=== `pgsql.query` The row pgsql query as read from the transaction's request. [float] -=== pgsql.iserror +=== `pgsql.iserror` type: boolean @@ -2634,42 +2634,42 @@ If the PgSQL query returns an error, this field is set to true. [float] -=== pgsql.error_code +=== `pgsql.error_code` type: long The PostgreSQL error code. [float] -=== pgsql.error_message +=== `pgsql.error_message` The PostgreSQL error message. [float] -=== pgsql.error_severity +=== `pgsql.error_severity` The PostgreSQL error severity. [float] -=== pgsql.num_fields +=== `pgsql.num_fields` If the SELECT query if successful, this field is set to the number of fields returned. [float] -=== pgsql.num_rows +=== `pgsql.num_rows` If the SELECT query if successful, this field is set to the number of rows returned. [[exported-fields-raw]] -== Raw Fields +== Raw fields These fields contain the raw transaction data. [float] -=== request +=== `request` type: text @@ -2677,7 +2677,7 @@ For text protocols, this is the request as seen on the wire (application layer o [float] -=== response +=== `response` type: text @@ -2685,7 +2685,7 @@ For text protocols, this is the response as seen on the wire (application layer [[exported-fields-redis]] -== Redis Fields +== Redis fields Redis-specific event fields. @@ -2693,19 +2693,19 @@ Redis-specific event fields. [float] -=== redis.return_value +=== `redis.return_value` The return value of the Redis command in a human readable format. [float] -=== redis.error +=== `redis.error` If the Redis command has resulted in an error, this field contains the error message returned by the Redis server. [[exported-fields-thrift]] -== Thrift-RPC Fields +== Thrift-RPC fields Thrift-RPC specific event fields. @@ -2713,38 +2713,38 @@ Thrift-RPC specific event fields. [float] -=== thrift.params +=== `thrift.params` The RPC method call parameters in a human readable format. If the IDL files are available, the parameters use names whenever possible. Otherwise, the IDs from the message are used. [float] -=== thrift.service +=== `thrift.service` The name of the Thrift-RPC service as defined in the IDL files. [float] -=== thrift.return_value +=== `thrift.return_value` The value returned by the Thrift-RPC call. This is encoded in a human readable format. [float] -=== thrift.exceptions +=== `thrift.exceptions` If the call resulted in exceptions, this field contains the exceptions in a human readable format. [[exported-fields-trans_event]] -== Transaction Event Fields +== Transaction Event fields These fields contain data about the transaction itself. [float] -=== direction +=== `direction` required: True @@ -2752,7 +2752,7 @@ Indicates whether the transaction is inbound (emitted by server) or outbound (em [float] -=== status +=== `status` required: True @@ -2760,19 +2760,19 @@ The high level status of the transaction. The way to compute this value depends [float] -=== method +=== `method` The command/verb/method of the transaction. For HTTP, this is the method name (GET, POST, PUT, and so on), for SQL this is the verb (SELECT, UPDATE, DELETE, and so on). [float] -=== resource +=== `resource` The logical resource that this transaction refers to. For HTTP, this is the URL path up to the last slash (/). For example, if the URL is `/users/1`, the resource is `/users`. For databases, the resource is typically the table name. The field is not filled for all transaction types. [float] -=== path +=== `path` required: True @@ -2780,7 +2780,7 @@ The path the transaction refers to. For HTTP, this is the URL. For SQL databases [float] -=== query +=== `query` type: keyword @@ -2788,7 +2788,7 @@ The query in a human readable format. For HTTP, it will typically be something l [float] -=== params +=== `params` type: text @@ -2796,20 +2796,20 @@ The request parameters. For HTTP, these are the POST or GET parameters. For Thri [float] -=== notes +=== `notes` Messages from Packetbeat itself. This field usually contains error messages for interpreting the raw data. This information can be helpful for troubleshooting. [[exported-fields-trans_measurements]] -== Measurements (Transactions) Fields +== Measurements (Transactions) fields These fields contain measurements related to the transaction. [float] -=== responsetime +=== `responsetime` type: long @@ -2817,14 +2817,14 @@ The wall clock time it took to complete the transaction. The precision is in mil [float] -=== cpu_time +=== `cpu_time` type: long The CPU time it took to complete the transaction. [float] -=== bytes_in +=== `bytes_in` type: long @@ -2834,7 +2834,7 @@ The number of bytes of the request. Note that this size is the application layer [float] -=== bytes_out +=== `bytes_out` type: long @@ -2844,7 +2844,7 @@ The number of bytes of the response. Note that this size is the application laye [float] -=== dnstime +=== `dnstime` type: long @@ -2852,7 +2852,7 @@ The time it takes to query the name server for a given request. This is typicall [float] -=== connecttime +=== `connecttime` type: long @@ -2860,7 +2860,7 @@ The time it takes for the TCP connection to be established for the given transac [float] -=== loadtime +=== `loadtime` type: long @@ -2868,7 +2868,7 @@ The time it takes for the content to be loaded. This is typically used for RUM ( [float] -=== domloadtime +=== `domloadtime` type: long diff --git a/winlogbeat/_meta/fields.yml b/winlogbeat/_meta/fields.yml index 51b416de74e..d86496bb2ba 100644 --- a/winlogbeat/_meta/fields.yml +++ b/winlogbeat/_meta/fields.yml @@ -18,7 +18,7 @@ - key: eventlog - title: Event Log Record + title: Event log record description: > Contains data from a Windows event log record. fields: diff --git a/winlogbeat/docs/fields.asciidoc b/winlogbeat/docs/fields.asciidoc index f0918dffd33..f71f471caf9 100644 --- a/winlogbeat/docs/fields.asciidoc +++ b/winlogbeat/docs/fields.asciidoc @@ -4,7 +4,7 @@ This file is generated! See _meta/fields.yml and scripts/generate_field_docs.py //// [[exported-fields]] -= Exported Fields += Exported fields [partintro] @@ -21,38 +21,38 @@ grouped in the following categories: -- [[exported-fields-beat]] -== Beat Fields +== Beat fields Contains common beat fields available in all event types. [float] -=== beat.name +=== `beat.name` The name of the Beat sending the log messages. If the Beat name is set in the configuration file, then that value is used. If it is not set, the hostname is used. To set the Beat name, use the `name` option in the configuration file. [float] -=== beat.hostname +=== `beat.hostname` The hostname as returned by the operating system on which the Beat is running. [float] -=== beat.timezone +=== `beat.timezone` The timezone as returned by the operating system on which the Beat is running. [float] -=== beat.version +=== `beat.version` The version of the beat that generated this event. [float] -=== @timestamp +=== `@timestamp` type: date @@ -66,13 +66,13 @@ The timestamp when the event log record was generated. [float] -=== tags +=== `tags` Arbitrary tags that can be set per Beat and per transaction type. [float] -=== fields +=== `fields` type: object @@ -80,14 +80,14 @@ Contains user configurable fields. [float] -== error Fields +== error fields Error fields containing additional info in case of errors. [float] -=== error.message +=== `error.message` type: text @@ -95,7 +95,7 @@ Error message. [float] -=== error.code +=== `error.code` type: long @@ -103,7 +103,7 @@ Error code. [float] -=== error.type +=== `error.type` type: keyword @@ -111,14 +111,14 @@ Error type. [[exported-fields-cloud]] -== Cloud Provider Metadata Fields +== Cloud provider metadata fields Metadata from cloud providers added by the add_cloud_metadata processor. [float] -=== meta.cloud.provider +=== `meta.cloud.provider` example: ec2 @@ -126,19 +126,19 @@ Name of the cloud provider. Possible values are ec2, gce, or digitalocean. [float] -=== meta.cloud.instance_id +=== `meta.cloud.instance_id` Instance ID of the host machine. [float] -=== meta.cloud.instance_name +=== `meta.cloud.instance_name` Instance name of the host machine. [float] -=== meta.cloud.machine_type +=== `meta.cloud.machine_type` example: t2.medium @@ -146,7 +146,7 @@ Machine type of the host machine. [float] -=== meta.cloud.availability_zone +=== `meta.cloud.availability_zone` example: us-east-1c @@ -154,7 +154,7 @@ Availability zone in which this host is running. [float] -=== meta.cloud.project_id +=== `meta.cloud.project_id` example: project-x @@ -162,20 +162,20 @@ Name of the project in Google Cloud. [float] -=== meta.cloud.region +=== `meta.cloud.region` Region in which this host is running. [[exported-fields-common]] -== Common Winlogbeat Fields +== Common Winlogbeat fields Contains common fields available in all event types. [float] -=== type +=== `type` required: True @@ -184,7 +184,7 @@ The Event Logging API was designed for Windows Server 2003, Windows XP, or Windo [[exported-fields-docker-processor]] -== docker Fields +== Docker fields beta[] Docker stats collected from Docker. @@ -193,7 +193,7 @@ Docker stats collected from Docker. [float] -=== docker.container.id +=== `docker.container.id` type: keyword @@ -201,7 +201,7 @@ Unique container id. [float] -=== docker.container.image +=== `docker.container.image` type: keyword @@ -209,7 +209,7 @@ Name of the image the container was built on. [float] -=== docker.container.name +=== `docker.container.name` type: keyword @@ -217,7 +217,7 @@ Container name. [float] -=== docker.container.labels +=== `docker.container.labels` type: object @@ -225,14 +225,14 @@ Image labels. [[exported-fields-eventlog]] -== Event Log Record Fields +== Event log record fields Contains data from a Windows event log record. [float] -=== activity_id +=== `activity_id` type: keyword @@ -242,7 +242,7 @@ A globally unique identifier that identifies the current activity. The events th [float] -=== computer_name +=== `computer_name` type: keyword @@ -252,7 +252,7 @@ The name of the computer that generated the record. When using Windows event for [float] -=== event_data +=== `event_data` type: object @@ -262,7 +262,7 @@ The event-specific data. This field is mutually exclusive with `user_data`. If y [float] -=== event_id +=== `event_id` type: long @@ -272,7 +272,7 @@ The event identifier. The value is specific to the source of the event. [float] -=== keywords +=== `keywords` type: keyword @@ -282,7 +282,7 @@ The keywords are used to classify an event. [float] -=== log_name +=== `log_name` type: keyword @@ -292,7 +292,7 @@ The name of the event log from which this record was read. This value is one of [float] -=== level +=== `level` type: keyword @@ -302,7 +302,7 @@ The level of the event. There are five levels of events that can be logged: Succ [float] -=== message +=== `message` type: text @@ -312,7 +312,7 @@ The message from the event log record. [float] -=== message_error +=== `message_error` type: keyword @@ -322,7 +322,7 @@ The error that occurred while reading and formatting the message from the log. [float] -=== record_number +=== `record_number` type: keyword @@ -332,7 +332,7 @@ The record number of the event log record. The first record written to an event [float] -=== related_activity_id +=== `related_activity_id` type: keyword @@ -342,7 +342,7 @@ A globally unique identifier that identifies the activity to which control was t [float] -=== opcode +=== `opcode` type: keyword @@ -352,7 +352,7 @@ The opcode defined in the event. Task and opcode are typically used to identify [float] -=== provider_guid +=== `provider_guid` type: keyword @@ -362,7 +362,7 @@ A globally unique identifier that identifies the provider that logged the event. [float] -=== process_id +=== `process_id` type: long @@ -372,7 +372,7 @@ The process_id identifies the process that generated the event. [float] -=== source_name +=== `source_name` type: keyword @@ -382,7 +382,7 @@ The source of the event log record (the application or service that logged the r [float] -=== task +=== `task` type: keyword @@ -392,7 +392,7 @@ The task defined in the event. Task and opcode are typically used to identify th [float] -=== thread_id +=== `thread_id` type: long @@ -402,7 +402,7 @@ The thread_id identifies the thread that generated the event. [float] -=== user_data +=== `user_data` type: object @@ -412,7 +412,7 @@ The event specific data. This field is mutually exclusive with `event_data`. [float] -=== user.identifier +=== `user.identifier` type: keyword @@ -426,7 +426,7 @@ If Winlogbeat cannot resolve the SID to a name, then the `user.name`, `user.doma [float] -=== user.name +=== `user.name` type: keyword @@ -436,7 +436,7 @@ The name of the account associated with this event. [float] -=== user.domain +=== `user.domain` type: keyword @@ -446,7 +446,7 @@ The domain that the account associated with this event is a member of. [float] -=== user.type +=== `user.type` type: keyword @@ -456,7 +456,7 @@ The type of account associated with this event. [float] -=== version +=== `version` type: long @@ -465,7 +465,7 @@ required: False The version number of the event's definition. [float] -=== xml +=== `xml` type: text @@ -477,7 +477,7 @@ The XML representation of the event is useful for troubleshooting purposes. The [[exported-fields-kubernetes-processor]] -== kubernetes Fields +== Kubernetes fields beta[] Kubernetes metadata added by the kubernetes processor @@ -486,7 +486,7 @@ Kubernetes metadata added by the kubernetes processor [float] -=== kubernetes.pod.name +=== `kubernetes.pod.name` type: keyword @@ -494,7 +494,7 @@ Kubernetes pod name [float] -=== kubernetes.namespace +=== `kubernetes.namespace` type: keyword @@ -502,7 +502,7 @@ Kubernetes namespace [float] -=== kubernetes.labels +=== `kubernetes.labels` type: object @@ -510,7 +510,7 @@ Kubernetes labels map [float] -=== kubernetes.annotations +=== `kubernetes.annotations` type: object @@ -518,7 +518,7 @@ Kubernetes annotations map [float] -=== kubernetes.container.name +=== `kubernetes.container.name` type: keyword @@ -526,7 +526,7 @@ Kubernetes container name [float] -=== kubernetes.container.image +=== `kubernetes.container.image` type: keyword From f240148065af94d55c5149e444482b9635801f27 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Fri, 28 Jul 2017 03:19:26 -0400 Subject: [PATCH 014/139] Remove generated beat.yml (#4767) The beat.yml is generated and does not need to be stored in the repo. --- auditbeat/_meta/beat.yml | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 auditbeat/_meta/beat.yml diff --git a/auditbeat/_meta/beat.yml b/auditbeat/_meta/beat.yml deleted file mode 100644 index 0804f607ac9..00000000000 --- a/auditbeat/_meta/beat.yml +++ /dev/null @@ -1,32 +0,0 @@ -###################### Auditbeat Configuration Example ######################### - -# This is an example configuration file highlighting only the most common -# options. The auditbeat.reference.yml file from the same directory contains all -# the supported options with more comments. You can use it as a reference. -# -# You can find the full configuration reference here: -# https://www.elastic.co/guide/en/beats/auditbeat/index.html - -#========================== Modules configuration ============================= -auditbeat.modules: - -- module: audit - metricsets: [kernel] - kernel.audit_rules: | - # Define audit rules here. - # Create file watches (-w) or syscall audits (-a or -A). For example: - #-w /etc/passwd -p wa -k identity - #-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -k access - -- module: audit - metricsets: [file] - file.paths: - binaries: - - /bin - - /usr/bin - - /sbin - - /usr/sbin - conf: - - /etc - - From 4ce5360d08cd94d9d982a6cce57a8da1b59cc185 Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Fri, 28 Jul 2017 17:17:49 +0300 Subject: [PATCH 015/139] Fix mixed up modules configuration (#4772) * Fix mixed up modules configuration Fixes #4761. Due to combining pointer and reference passing we ended up with passing the same module pointer to multiple filesets. The pointer was correct during initialization, but wrong during run time. Also added an Info with the enabled modules / filesets. --- CHANGELOG.asciidoc | 2 + filebeat/beater/filebeat.go | 3 + filebeat/fileset/config.go | 2 - filebeat/fileset/modules.go | 34 +++++++--- filebeat/fileset/modules_integration_test.go | 4 +- filebeat/fileset/modules_test.go | 66 +++++++++++--------- 6 files changed, 71 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 5feb82d68a0..23dc77a48b7 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -32,6 +32,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Filebeat* +- Fix issue where the `fileset.module` could have the wrong value. {issue}4761[4761] + *Heartbeat* *Metricbeat* diff --git a/filebeat/beater/filebeat.go b/filebeat/beater/filebeat.go index 2b47adcc1ac..b0619722e4d 100644 --- a/filebeat/beater/filebeat.go +++ b/filebeat/beater/filebeat.go @@ -56,6 +56,9 @@ func New(b *beat.Beat, rawConfig *common.Config) (beat.Beater, error) { if err != nil { return nil, err } + if !moduleRegistry.Empty() { + logp.Info("Enabled modules/filesets: %s", moduleRegistry.InfoString()) + } moduleProspectors, err := moduleRegistry.GetProspectorConfigs() if err != nil { diff --git a/filebeat/fileset/config.go b/filebeat/fileset/config.go index 57dc98b1483..7a20fa158c8 100644 --- a/filebeat/fileset/config.go +++ b/filebeat/fileset/config.go @@ -15,5 +15,3 @@ type FilesetConfig struct { Var map[string]interface{} `config:"var"` Prospector map[string]interface{} `config:"prospector"` } - -var defaultFilesetConfig = FilesetConfig{} diff --git a/filebeat/fileset/modules.go b/filebeat/fileset/modules.go index d9c364efb8d..398997df139 100644 --- a/filebeat/fileset/modules.go +++ b/filebeat/fileset/modules.go @@ -22,7 +22,7 @@ type ModuleRegistry struct { // newModuleRegistry reads and loads the configured module into the registry. func newModuleRegistry(modulesPath string, - moduleConfigs []ModuleConfig, + moduleConfigs []*ModuleConfig, overrides *ModuleOverrides, beatVersion string) (*ModuleRegistry, error) { @@ -43,7 +43,7 @@ func newModuleRegistry(modulesPath string, for _, filesetName := range moduleFilesets { fcfg, exists := mcfg.Filesets[filesetName] if !exists { - fcfg = &defaultFilesetConfig + fcfg = &FilesetConfig{} } fcfg, err = applyOverrides(fcfg, mcfg.Module, filesetName, overrides) @@ -55,7 +55,7 @@ func newModuleRegistry(modulesPath string, continue } - fileset, err := New(modulesPath, filesetName, &mcfg, fcfg) + fileset, err := New(modulesPath, filesetName, mcfg, fcfg) if err != nil { return nil, err } @@ -100,13 +100,13 @@ func NewModuleRegistry(moduleConfigs []*common.Config, beatVersion string) (*Mod if err != nil { return nil, err } - mcfgs := []ModuleConfig{} + mcfgs := []*ModuleConfig{} for _, moduleConfig := range moduleConfigs { mcfg, err := mcfgFromConfig(moduleConfig) if err != nil { return nil, fmt.Errorf("Error unpacking module config: %v", err) } - mcfgs = append(mcfgs, *mcfg) + mcfgs = append(mcfgs, mcfg) } mcfgs, err = appendWithoutDuplicates(mcfgs, modulesCLIList) if err != nil { @@ -209,7 +209,7 @@ func applyOverrides(fcfg *FilesetConfig, // appendWithoutDuplicates appends basic module configuration for each module in the // modules list, unless the same module is not already loaded. -func appendWithoutDuplicates(moduleConfigs []ModuleConfig, modules []string) ([]ModuleConfig, error) { +func appendWithoutDuplicates(moduleConfigs []*ModuleConfig, modules []string) ([]*ModuleConfig, error) { if len(modules) == 0 { return moduleConfigs, nil } @@ -226,7 +226,7 @@ func appendWithoutDuplicates(moduleConfigs []ModuleConfig, modules []string) ([] // add the non duplicates to the list for _, module := range modules { if _, exists := modulesMap[module]; !exists { - moduleConfigs = append(moduleConfigs, ModuleConfig{Module: module}) + moduleConfigs = append(moduleConfigs, &ModuleConfig{Module: module}) } } return moduleConfigs, nil @@ -285,6 +285,26 @@ func (reg *ModuleRegistry) LoadPipelines(esClient PipelineLoader) error { return nil } +// InfoString returns the enabled modules and filesets in a single string, ready to +// be shown to the user +func (reg *ModuleRegistry) InfoString() string { + var result string + for module, filesets := range reg.registry { + var filesetNames string + for name, _ := range filesets { + if filesetNames != "" { + filesetNames += ", " + } + filesetNames += name + } + if result != "" { + result += ", " + } + result += fmt.Sprintf("%s (%s)", module, filesetNames) + } + return result +} + // checkAvailableProcessors calls the /_nodes/ingest API and verifies that all processors listed // in the requiredProcessors list are available in Elasticsearch. Returns nil if all required // processors are available. diff --git a/filebeat/fileset/modules_integration_test.go b/filebeat/fileset/modules_integration_test.go index 02c7d12f14e..a0ca7d00688 100644 --- a/filebeat/fileset/modules_integration_test.go +++ b/filebeat/fileset/modules_integration_test.go @@ -68,8 +68,8 @@ func TestSetupNginx(t *testing.T) { modulesPath, err := filepath.Abs("../module") assert.NoError(t, err) - configs := []ModuleConfig{ - {Module: "nginx"}, + configs := []*ModuleConfig{ + &ModuleConfig{Module: "nginx"}, } reg, err := newModuleRegistry(modulesPath, configs, nil, "5.2.0") diff --git a/filebeat/fileset/modules_test.go b/filebeat/fileset/modules_test.go index f5a6e83b68f..da4e34ec3c0 100644 --- a/filebeat/fileset/modules_test.go +++ b/filebeat/fileset/modules_test.go @@ -26,11 +26,11 @@ func TestNewModuleRegistry(t *testing.T) { modulesPath, err := filepath.Abs("../module") assert.NoError(t, err) - configs := []ModuleConfig{ - {Module: "nginx"}, - {Module: "mysql"}, - {Module: "system"}, - {Module: "auditd"}, + configs := []*ModuleConfig{ + &ModuleConfig{Module: "nginx"}, + &ModuleConfig{Module: "mysql"}, + &ModuleConfig{Module: "system"}, + &ModuleConfig{Module: "auditd"}, } reg, err := newModuleRegistry(modulesPath, configs, nil, "5.2.0") @@ -58,8 +58,16 @@ func TestNewModuleRegistry(t *testing.T) { for module, filesets := range reg.registry { for name, fileset := range filesets { - _, err = fileset.getProspectorConfig() + cfg, err := fileset.getProspectorConfig() assert.NoError(t, err, fmt.Sprintf("module: %s, fileset: %s", module, name)) + + moduleName, err := cfg.String("_module_name", -1) + assert.NoError(t, err) + assert.Equal(t, module, moduleName) + + filesetName, err := cfg.String("_fileset_name", -1) + assert.NoError(t, err) + assert.Equal(t, name, filesetName) } } } @@ -70,8 +78,8 @@ func TestNewModuleRegistryConfig(t *testing.T) { falseVar := false - configs := []ModuleConfig{ - { + configs := []*ModuleConfig{ + &ModuleConfig{ Module: "nginx", Filesets: map[string]*FilesetConfig{ "access": { @@ -84,7 +92,7 @@ func TestNewModuleRegistryConfig(t *testing.T) { }, }, }, - { + &ModuleConfig{ Module: "mysql", Enabled: &falseVar, }, @@ -191,24 +199,24 @@ func TestAppendWithoutDuplicates(t *testing.T) { falseVar := false tests := []struct { name string - configs []ModuleConfig + configs []*ModuleConfig modules []string - expected []ModuleConfig + expected []*ModuleConfig }{ { name: "just modules", - configs: []ModuleConfig{}, + configs: []*ModuleConfig{}, modules: []string{"moduleA", "moduleB", "moduleC"}, - expected: []ModuleConfig{ - {Module: "moduleA"}, - {Module: "moduleB"}, - {Module: "moduleC"}, + expected: []*ModuleConfig{ + &ModuleConfig{Module: "moduleA"}, + &ModuleConfig{Module: "moduleB"}, + &ModuleConfig{Module: "moduleC"}, }, }, { name: "eliminate a duplicate, no override", - configs: []ModuleConfig{ - { + configs: []*ModuleConfig{ + &ModuleConfig{ Module: "moduleB", Filesets: map[string]*FilesetConfig{ "fileset": { @@ -220,8 +228,8 @@ func TestAppendWithoutDuplicates(t *testing.T) { }, }, modules: []string{"moduleA", "moduleB", "moduleC"}, - expected: []ModuleConfig{ - { + expected: []*ModuleConfig{ + &ModuleConfig{ Module: "moduleB", Filesets: map[string]*FilesetConfig{ "fileset": { @@ -231,14 +239,14 @@ func TestAppendWithoutDuplicates(t *testing.T) { }, }, }, - {Module: "moduleA"}, - {Module: "moduleC"}, + &ModuleConfig{Module: "moduleA"}, + &ModuleConfig{Module: "moduleC"}, }, }, { name: "disabled config", - configs: []ModuleConfig{ - { + configs: []*ModuleConfig{ + &ModuleConfig{ Module: "moduleB", Enabled: &falseVar, Filesets: map[string]*FilesetConfig{ @@ -251,8 +259,8 @@ func TestAppendWithoutDuplicates(t *testing.T) { }, }, modules: []string{"moduleA", "moduleB", "moduleC"}, - expected: []ModuleConfig{ - { + expected: []*ModuleConfig{ + &ModuleConfig{ Module: "moduleB", Enabled: &falseVar, Filesets: map[string]*FilesetConfig{ @@ -263,9 +271,9 @@ func TestAppendWithoutDuplicates(t *testing.T) { }, }, }, - {Module: "moduleA"}, - {Module: "moduleB"}, - {Module: "moduleC"}, + &ModuleConfig{Module: "moduleA"}, + &ModuleConfig{Module: "moduleB"}, + &ModuleConfig{Module: "moduleC"}, }, }, } From 8887cdf06605dd113b4a22906dce54dd03f9eb8f Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Fri, 28 Jul 2017 11:26:32 -0400 Subject: [PATCH 016/139] Update test to use named field in composite literal Fixes a `go vet` warning. module/audit/kernel/audit_linux_test.go:31: github.com/elastic/beats/vendor/github.com/elastic/go-libaudit.AuditClient composite literal uses unkeyed fields --- auditbeat/module/audit/kernel/audit_linux_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auditbeat/module/audit/kernel/audit_linux_test.go b/auditbeat/module/audit/kernel/audit_linux_test.go index 72ce6999fc1..7e3cc227dca 100644 --- a/auditbeat/module/audit/kernel/audit_linux_test.go +++ b/auditbeat/module/audit/kernel/audit_linux_test.go @@ -28,7 +28,7 @@ func TestData(t *testing.T) { ms := mbtest.NewPushMetricSet(t, getConfig()) auditMetricSet := ms.(*MetricSet) auditMetricSet.client.Close() - auditMetricSet.client = &libaudit.AuditClient{mock} + auditMetricSet.client = &libaudit.AuditClient{Netlink: mock} events, errs := mbtest.RunPushMetricSet(time.Second, ms) if len(errs) > 0 { From 2f7e829c4b2c9ee419d7ec513294b1a10c7414a6 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Fri, 28 Jul 2017 11:33:53 -0400 Subject: [PATCH 017/139] Update Metricbeat field docs --- metricbeat/docs/fields.asciidoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 94fc717a31a..ca75ffbf3f3 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -2790,7 +2790,7 @@ Bytes in non-idle span. [[exported-fields-graphite]] -== graphite Fields +== graphite fields []experimental graphite Module @@ -2798,20 +2798,20 @@ graphite Module [float] -== graphite Fields +== graphite fields [float] -== server Fields +== server fields server [float] -=== graphite.server.example +=== `graphite.server.example` type: keyword From dd8c5fd76c64ce4f15cc2e767f0ec8ec52729eb5 Mon Sep 17 00:00:00 2001 From: Ron Cohen Date: Fri, 28 Jul 2017 22:05:40 +0200 Subject: [PATCH 018/139] List files violating goimports style (#4782) before: $ make check Code differs from goimports' style make: *** [check] Error 1 after: $ make check ./utility/map_str_enhancer_test.go Code differs from goimports' style ^ make: *** [check] Error 1 --- libbeat/scripts/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbeat/scripts/Makefile b/libbeat/scripts/Makefile index d7163eed4cb..93f626c02c4 100755 --- a/libbeat/scripts/Makefile +++ b/libbeat/scripts/Makefile @@ -101,7 +101,7 @@ crosscompile: $(GOFILES) check: python-env ## @build Checks project and source code if everything is according to standard @go vet ${GOPACKAGES} @go get $(GOIMPORTS_REPO) - @goimports -local ${GOIMPORTS_LOCAL_PREFIX} -l ${GOFILES_NOVENDOR} | (! grep . -q) || (echo "Code differs from goimports' style" && false) + @goimports -local ${GOIMPORTS_LOCAL_PREFIX} -l ${GOFILES_NOVENDOR} | (! grep .) || (echo "Code differs from goimports' style ^" && false) @${FIND} -name *.py -exec autopep8 -d --max-line-length 120 {} \; | (! grep . -q) || (echo "Code differs from autopep8's style" && false) .PHONY: fmt From 10b73be31514471ca7dfd2d68ee543c18bc0dd1f Mon Sep 17 00:00:00 2001 From: Vijay Samuel Date: Mon, 31 Jul 2017 01:18:18 -0700 Subject: [PATCH 019/139] Fixing pod name indexer to use both namespace, pod name to frame index key (#4775) * Fixing pod name indexer to use both namespace, pod name to frame index key * Adding field pattern matcher to support pod name indexer matching --- CHANGELOG.asciidoc | 2 + .../add_kubernetes_metadata/indexing.go | 56 +++++++++++++++++-- .../add_kubernetes_metadata/indexing_test.go | 51 ++++++++++++++++- 3 files changed, 102 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 23dc77a48b7..8d52e5b23a9 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -67,6 +67,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Affecting all Beats* +- Fix pod name indexer to use both namespace, pod name to frame index key {pull}4775[4775] + *Filebeat* *Heartbeat* diff --git a/libbeat/processors/add_kubernetes_metadata/indexing.go b/libbeat/processors/add_kubernetes_metadata/indexing.go index f4471983e01..aa03b32f321 100644 --- a/libbeat/processors/add_kubernetes_metadata/indexing.go +++ b/libbeat/processors/add_kubernetes_metadata/indexing.go @@ -6,13 +6,19 @@ import ( "sync" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/common/fmtstr" + "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/libbeat/outputs/codec" + "github.com/elastic/beats/libbeat/outputs/codec/format" + "github.com/elastic/beats/libbeat/publisher/beat" ) //Names of indexers and matchers that have been defined. const ( - PodNameIndexerName = "pod_name" - FieldMatcherName = "fields" - ContainerIndexerName = "container" + ContainerIndexerName = "container" + PodNameIndexerName = "pod_name" + FieldMatcherName = "fields" + FieldFormatMatcherName = "field_format" ) // Indexing is the singleton Register instance where all Indexers and Matchers @@ -244,14 +250,14 @@ func (p *PodNameIndexer) GetMetadata(pod *Pod) []MetadataIndex { data := p.genMeta.GenerateMetaData(pod) return []MetadataIndex{ { - Index: pod.Metadata.Name, + Index: fmt.Sprintf("%s/%s", pod.Metadata.Namespace, pod.Metadata.Name), Data: data, }, } } func (p *PodNameIndexer) GetIndexes(pod *Pod) []string { - return []string{pod.Metadata.Name} + return []string{fmt.Sprintf("%s/%s", pod.Metadata.Namespace, pod.Metadata.Name)} } // ContainerIndexer indexes pods based on all their containers IDs @@ -329,3 +335,43 @@ func (f *FieldMatcher) MetadataIndex(event common.MapStr) string { return "" } + +type FieldFormatMatcher struct { + Codec codec.Codec +} + +func NewFieldFormatMatcher(cfg common.Config) (Matcher, error) { + config := struct { + Format string `config:"format"` + }{} + + err := cfg.Unpack(&config) + if err != nil { + return nil, fmt.Errorf("fail to unpack the `format` configuration of `field_format` matcher: %s", err) + } + + if config.Format == "" { + return nil, fmt.Errorf("`format` of `field_format` matcher can't be empty") + } + + return &FieldFormatMatcher{ + Codec: format.New(fmtstr.MustCompileEvent(config.Format)), + }, nil + +} + +func (f *FieldFormatMatcher) MetadataIndex(event common.MapStr) string { + bytes, err := f.Codec.Encode("", &beat.Event{ + Fields: event, + }) + + if err != nil { + logp.Debug("kubernetes", "Unable to apply field format pattern on event") + } + + if len(bytes) == 0 { + return "" + } + + return string(bytes) +} diff --git a/libbeat/processors/add_kubernetes_metadata/indexing_test.go b/libbeat/processors/add_kubernetes_metadata/indexing_test.go index 5589c31a33c..9a36fc4868a 100644 --- a/libbeat/processors/add_kubernetes_metadata/indexing_test.go +++ b/libbeat/processors/add_kubernetes_metadata/indexing_test.go @@ -1,6 +1,7 @@ package add_kubernetes_metadata import ( + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -31,7 +32,7 @@ func TestPodIndexer(t *testing.T) { indexers := podIndexer.GetMetadata(&pod) assert.Equal(t, len(indexers), 1) - assert.Equal(t, indexers[0].Index, podName) + assert.Equal(t, indexers[0].Index, fmt.Sprintf("%s/%s", ns, podName)) expected := common.MapStr{ "pod": common.MapStr{ @@ -47,7 +48,7 @@ func TestPodIndexer(t *testing.T) { indices := podIndexer.GetIndexes(&pod) assert.Equal(t, len(indices), 1) - assert.Equal(t, indices[0], podName) + assert.Equal(t, indices[0], fmt.Sprintf("%s/%s", ns, podName)) } func TestContainerIndexer(t *testing.T) { @@ -255,3 +256,49 @@ func TestFilteredGenMetaExclusion(t *testing.T) { ok, _ = labelMap.HasKey("x") assert.Equal(t, ok, false) } + +func TestFieldFormatMatcher(t *testing.T) { + testCfg := map[string]interface{}{} + fieldCfg, err := common.NewConfigFrom(testCfg) + + assert.Nil(t, err) + matcher, err := NewFieldFormatMatcher(*fieldCfg) + assert.NotNil(t, err) + + testCfg["format"] = `%{[namespace]}/%{[pod]}` + fieldCfg, _ = common.NewConfigFrom(testCfg) + + matcher, err = NewFieldFormatMatcher(*fieldCfg) + assert.NotNil(t, matcher) + assert.Nil(t, err) + + event := common.MapStr{ + "namespace": "foo", + "pod": "bar", + } + + out := matcher.MetadataIndex(event) + assert.Equal(t, "foo/bar", out) + + event = common.MapStr{ + "foo": "bar", + } + out = matcher.MetadataIndex(event) + assert.Empty(t, out) + + testCfg["format"] = `%{[dimensions.namespace]}/%{[dimensions.pod]}` + fieldCfg, _ = common.NewConfigFrom(testCfg) + matcher, err = NewFieldFormatMatcher(*fieldCfg) + assert.NotNil(t, matcher) + assert.Nil(t, err) + + event = common.MapStr{ + "dimensions": common.MapStr{ + "pod": "bar", + "namespace": "foo", + }, + } + + out = matcher.MetadataIndex(event) + assert.Equal(t, "foo/bar", out) +} From 60d83e7bbd71acae9943a625a60b65c7129acba0 Mon Sep 17 00:00:00 2001 From: Monica Sarbu Date: Mon, 31 Jul 2017 11:42:09 +0300 Subject: [PATCH 020/139] Add setup.template.settings in the reference.yml files (#4791) --- auditbeat/auditbeat.reference.yml | 6 ++++++ filebeat/filebeat.reference.yml | 6 ++++++ heartbeat/heartbeat.reference.yml | 6 ++++++ libbeat/_meta/config.reference.yml | 6 ++++++ metricbeat/metricbeat.reference.yml | 6 ++++++ packetbeat/packetbeat.reference.yml | 6 ++++++ winlogbeat/winlogbeat.reference.yml | 6 ++++++ 7 files changed, 42 insertions(+) diff --git a/auditbeat/auditbeat.reference.yml b/auditbeat/auditbeat.reference.yml index 279d62d0bee..ee584fd7add 100644 --- a/auditbeat/auditbeat.reference.yml +++ b/auditbeat/auditbeat.reference.yml @@ -684,6 +684,12 @@ output.elasticsearch: # Overwrite existing template #setup.template.overwrite: false +# Elasticsearch template settings +setup.template.settings: + index.number_of_shards: 1 + index.codec: best_compression + #_source.enabled: false + #============================== Kibana ===================================== # Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. diff --git a/filebeat/filebeat.reference.yml b/filebeat/filebeat.reference.yml index 9bc5c28e20e..23a8cbe7006 100644 --- a/filebeat/filebeat.reference.yml +++ b/filebeat/filebeat.reference.yml @@ -1076,6 +1076,12 @@ output.elasticsearch: # Overwrite existing template #setup.template.overwrite: false +# Elasticsearch template settings +setup.template.settings: + index.number_of_shards: 1 + index.codec: best_compression + #_source.enabled: false + #============================== Kibana ===================================== # Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. diff --git a/heartbeat/heartbeat.reference.yml b/heartbeat/heartbeat.reference.yml index 5c0c035a54e..3ee8cc9b94f 100644 --- a/heartbeat/heartbeat.reference.yml +++ b/heartbeat/heartbeat.reference.yml @@ -834,6 +834,12 @@ output.elasticsearch: # Overwrite existing template #setup.template.overwrite: false +# Elasticsearch template settings +setup.template.settings: + index.number_of_shards: 1 + index.codec: best_compression + #_source.enabled: false + #============================== Kibana ===================================== # Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. diff --git a/libbeat/_meta/config.reference.yml b/libbeat/_meta/config.reference.yml index 4a089c6f364..420a1d6de13 100644 --- a/libbeat/_meta/config.reference.yml +++ b/libbeat/_meta/config.reference.yml @@ -620,6 +620,12 @@ output.elasticsearch: # Overwrite existing template #setup.template.overwrite: false +# Elasticsearch template settings +setup.template.settings: + index.number_of_shards: 1 + index.codec: best_compression + #_source.enabled: false + #============================== Kibana ===================================== # Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index d9c291f168c..9361ab4b73c 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -1043,6 +1043,12 @@ output.elasticsearch: # Overwrite existing template #setup.template.overwrite: false +# Elasticsearch template settings +setup.template.settings: + index.number_of_shards: 1 + index.codec: best_compression + #_source.enabled: false + #============================== Kibana ===================================== # Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. diff --git a/packetbeat/packetbeat.reference.yml b/packetbeat/packetbeat.reference.yml index 34663929cdc..1a4a4de64fc 100644 --- a/packetbeat/packetbeat.reference.yml +++ b/packetbeat/packetbeat.reference.yml @@ -1072,6 +1072,12 @@ output.elasticsearch: # Overwrite existing template #setup.template.overwrite: false +# Elasticsearch template settings +setup.template.settings: + index.number_of_shards: 1 + index.codec: best_compression + #_source.enabled: false + #============================== Kibana ===================================== # Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. diff --git a/winlogbeat/winlogbeat.reference.yml b/winlogbeat/winlogbeat.reference.yml index dd6e8f237ab..4b629eb98dd 100644 --- a/winlogbeat/winlogbeat.reference.yml +++ b/winlogbeat/winlogbeat.reference.yml @@ -649,6 +649,12 @@ output.elasticsearch: # Overwrite existing template #setup.template.overwrite: false +# Elasticsearch template settings +setup.template.settings: + index.number_of_shards: 1 + index.codec: best_compression + #_source.enabled: false + #============================== Kibana ===================================== # Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. From 2bf347529c5ad9c8f414d6d37a3a884b1137737b Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Mon, 31 Jul 2017 21:27:26 +0300 Subject: [PATCH 021/139] Pin FPM version (#4790) --- dev-tools/packer/docker/fpm-image/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/packer/docker/fpm-image/Dockerfile b/dev-tools/packer/docker/fpm-image/Dockerfile index 8ca1d7b6715..d049b8ec818 100644 --- a/dev-tools/packer/docker/fpm-image/Dockerfile +++ b/dev-tools/packer/docker/fpm-image/Dockerfile @@ -8,4 +8,4 @@ RUN \ apt-get install -y --no-install-recommends \ build-essential ruby-dev rpm zip dos2unix libgmp3-dev -RUN gem install fpm +RUN gem install fpm -v 1.9.2 From 231dc54e1514732fd1d8e15bad735dcbc00189c6 Mon Sep 17 00:00:00 2001 From: Steffen Siering Date: Mon, 31 Jul 2017 22:21:41 +0200 Subject: [PATCH 022/139] Pipeline cleanups (#4776) * Rename publisher/broker package to publisher/queue * Move global pipeline loading to the pipeline package --- filebeat/channel/factory.go | 7 +- generator/beat/{beat}/beater/{beat}.go.tmpl | 23 +- heartbeat/beater/manager.go | 7 +- libbeat/beat/beat.go | 63 ++--- libbeat/mock/mockbeat.go | 21 +- .../report/elasticsearch/elasticsearch.go | 10 +- libbeat/publisher/bc/publisher/async.go | 154 ------------ libbeat/publisher/bc/publisher/client.go | 221 ------------------ libbeat/publisher/bc/publisher/opts.go | 56 ----- libbeat/publisher/bc/publisher/pipeline.go | 98 -------- libbeat/publisher/bc/publisher/publish.go | 127 ---------- libbeat/publisher/bc/publisher/sync.go | 104 --------- libbeat/publisher/beat/pipeline.go | 5 +- libbeat/publisher/broker/broker_reg.go | 38 --- libbeat/publisher/broker/brokertest/doc.go | 3 - libbeat/publisher/broker/membroker/doc.go | 4 - libbeat/publisher/pipeline/batch.go | 6 +- libbeat/publisher/pipeline/client.go | 7 +- libbeat/publisher/pipeline/config.go | 11 +- libbeat/publisher/pipeline/consumer.go | 26 +-- libbeat/publisher/pipeline/controller.go | 8 +- libbeat/publisher/pipeline/module.go | 131 +++++++++++ libbeat/publisher/pipeline/pipeline.go | 87 +++---- libbeat/publisher/pipeline/pipeline_ack.go | 10 +- .../membroker => queue/memqueue}/ackloop.go | 2 +- .../membroker => queue/memqueue}/broker.go | 22 +- .../membroker => queue/memqueue}/buf.go | 2 +- .../membroker => queue/memqueue}/config.go | 2 +- .../membroker => queue/memqueue}/consume.go | 6 +- libbeat/publisher/queue/memqueue/doc.go | 4 + .../membroker => queue/memqueue}/eventloop.go | 2 +- .../memqueue}/internal_api.go | 2 +- .../membroker => queue/memqueue}/log.go | 4 +- .../membroker => queue/memqueue}/produce.go | 6 +- .../memqueue/queue_test.go} | 18 +- .../{broker/broker.go => queue/queue.go} | 48 ++-- libbeat/publisher/queue/queue_reg.go | 38 +++ libbeat/publisher/queue/queuetest/doc.go | 3 + .../brokertest => queue/queuetest}/event.go | 2 +- .../brokertest => queue/queuetest}/log.go | 2 +- .../queuetest}/producer_cancel.go | 12 +- .../queuetest/queuetest.go} | 42 ++-- libbeat/publisher/testing/testing.go | 9 +- metricbeat/mb/module/connector.go | 7 +- metricbeat/mb/module/factory.go | 6 +- packetbeat/beater/packetbeat.go | 6 +- packetbeat/publish/publish.go | 9 +- packetbeat/publish/publish_test.go | 6 - winlogbeat/beater/eventlogger.go | 7 +- winlogbeat/beater/winlogbeat.go | 3 +- 50 files changed, 418 insertions(+), 1079 deletions(-) delete mode 100644 libbeat/publisher/bc/publisher/async.go delete mode 100644 libbeat/publisher/bc/publisher/client.go delete mode 100644 libbeat/publisher/bc/publisher/opts.go delete mode 100644 libbeat/publisher/bc/publisher/pipeline.go delete mode 100644 libbeat/publisher/bc/publisher/publish.go delete mode 100644 libbeat/publisher/bc/publisher/sync.go delete mode 100644 libbeat/publisher/broker/broker_reg.go delete mode 100644 libbeat/publisher/broker/brokertest/doc.go delete mode 100644 libbeat/publisher/broker/membroker/doc.go create mode 100644 libbeat/publisher/pipeline/module.go rename libbeat/publisher/{broker/membroker => queue/memqueue}/ackloop.go (99%) rename libbeat/publisher/{broker/membroker => queue/memqueue}/broker.go (92%) rename libbeat/publisher/{broker/membroker => queue/memqueue}/buf.go (99%) rename libbeat/publisher/{broker/membroker => queue/memqueue}/config.go (96%) rename libbeat/publisher/{broker/membroker => queue/memqueue}/consume.go (94%) create mode 100644 libbeat/publisher/queue/memqueue/doc.go rename libbeat/publisher/{broker/membroker => queue/memqueue}/eventloop.go (99%) rename libbeat/publisher/{broker/membroker => queue/memqueue}/internal_api.go (97%) rename libbeat/publisher/{broker/membroker => queue/memqueue}/log.go (65%) rename libbeat/publisher/{broker/membroker => queue/memqueue}/produce.go (95%) rename libbeat/publisher/{broker/membroker/broker_test.go => queue/memqueue/queue_test.go} (62%) rename libbeat/publisher/{broker/broker.go => queue/queue.go} (58%) create mode 100644 libbeat/publisher/queue/queue_reg.go create mode 100644 libbeat/publisher/queue/queuetest/doc.go rename libbeat/publisher/{broker/brokertest => queue/queuetest}/event.go (94%) rename libbeat/publisher/{broker/brokertest => queue/queuetest}/log.go (99%) rename libbeat/publisher/{broker/brokertest => queue/queuetest}/producer_cancel.go (84%) rename libbeat/publisher/{broker/brokertest/brokertest.go => queue/queuetest/queuetest.go} (88%) diff --git a/filebeat/channel/factory.go b/filebeat/channel/factory.go index 226299e0213..956019dc313 100644 --- a/filebeat/channel/factory.go +++ b/filebeat/channel/factory.go @@ -3,13 +3,12 @@ package channel import ( "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/bc/publisher" "github.com/elastic/beats/libbeat/publisher/beat" ) type OutletFactory struct { done <-chan struct{} - pipeline publisher.Publisher + pipeline beat.Pipeline eventer beat.ClientEventer wgEvents eventCounter @@ -48,7 +47,7 @@ type prospectorOutletConfig struct { // connecting a prospector to the publisher pipeline. func NewOutletFactory( done <-chan struct{}, - pipeline publisher.Publisher, + pipeline beat.Pipeline, wgEvents eventCounter, ) *OutletFactory { o := &OutletFactory{ @@ -102,7 +101,7 @@ func (f *OutletFactory) Create(cfg *common.Config) (Outleter, error) { } } - client, err := f.pipeline.ConnectX(beat.ClientConfig{ + client, err := f.pipeline.ConnectWith(beat.ClientConfig{ PublishMode: beat.GuaranteedSend, EventMetadata: config.EventMetadata, Meta: meta, diff --git a/generator/beat/{beat}/beater/{beat}.go.tmpl b/generator/beat/{beat}/beater/{beat}.go.tmpl index 13a31d6e502..0a27be3639f 100644 --- a/generator/beat/{beat}/beater/{beat}.go.tmpl +++ b/generator/beat/{beat}/beater/{beat}.go.tmpl @@ -7,7 +7,7 @@ import ( "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/bc/publisher" + pub "github.com/elastic/beats/libbeat/publisher/beat" "{beat_path}/config" ) @@ -15,7 +15,7 @@ import ( type {Beat} struct { done chan struct{} config config.Config - client publisher.Client + client pub.Client } // Creates beater @@ -35,7 +35,12 @@ func New(b *beat.Beat, cfg *common.Config) (beat.Beater, error) { func (bt *{Beat}) Run(b *beat.Beat) error { logp.Info("{beat} is running! Hit CTRL-C to stop it.") - bt.client = b.Publisher.Connect() + var err error + bt.client, err = b.Publisher.Connect() + if err != nil { + return err + } + ticker := time.NewTicker(bt.config.Period) counter := 1 for { @@ -45,12 +50,14 @@ func (bt *{Beat}) Run(b *beat.Beat) error { case <-ticker.C: } - event := common.MapStr{ - "@timestamp": common.Time(time.Now()), - "type": b.Info.Name, - "counter": counter, + event := pub.Event{ + Timestamp: time.Now(), + Fields: common.MapStr{ + "type": b.Info.Name, + "counter": counter, + }, } - bt.client.PublishEvent(event) + bt.client.Publish(event) logp.Info("Event sent") counter++ } diff --git a/heartbeat/beater/manager.go b/heartbeat/beater/manager.go index 195069a7840..980c2333fa1 100644 --- a/heartbeat/beater/manager.go +++ b/heartbeat/beater/manager.go @@ -10,7 +10,6 @@ import ( "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/bc/publisher" "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/heartbeat/monitors" @@ -35,7 +34,7 @@ type monitor struct { active map[string]monitorTask - pipeline publisher.Publisher + pipeline beat.Pipeline } type monitorTask struct { @@ -66,7 +65,7 @@ var defaultFilePollInterval = 5 * time.Second const defaultEventType = "monitor" func newMonitorManager( - pipeline publisher.Publisher, + pipeline beat.Pipeline, jobControl jobControl, registry *monitors.Registrar, configs []*common.Config, @@ -207,7 +206,7 @@ func (m *monitor) Update(configs []*common.Config) error { } // create connection per monitorTask - client, err := m.pipeline.ConnectX(beat.ClientConfig{ + client, err := m.pipeline.ConnectWith(beat.ClientConfig{ EventMetadata: t.config.EventMetadata, Processor: processors, }) diff --git a/libbeat/beat/beat.go b/libbeat/beat/beat.go index c27016c860a..59fade43459 100644 --- a/libbeat/beat/beat.go +++ b/libbeat/beat/beat.go @@ -56,8 +56,8 @@ import ( "github.com/elastic/beats/libbeat/outputs/elasticsearch" "github.com/elastic/beats/libbeat/paths" "github.com/elastic/beats/libbeat/plugin" - "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/bc/publisher" + "github.com/elastic/beats/libbeat/publisher/beat" + "github.com/elastic/beats/libbeat/publisher/pipeline" svc "github.com/elastic/beats/libbeat/service" "github.com/elastic/beats/libbeat/template" "github.com/elastic/beats/libbeat/version" @@ -108,10 +108,10 @@ type SetupMLCallback func(*Beat) error // Beat contains the basic beat data and the publisher client used to publish // events. type Beat struct { - Info common.BeatInfo // beat metadata. - RawConfig *common.Config // Raw config that can be unpacked to get Beat specific config data. - Config BeatConfig // Common Beat configuration data. - Publisher publisher.Publisher // Publisher + Info common.BeatInfo // beat metadata. + RawConfig *common.Config // Raw config that can be unpacked to get Beat specific config data. + Config BeatConfig // Common Beat configuration data. + Publisher beat.Pipeline // Publisher pipeline SetupMLCallback SetupMLCallback // setup callback for ML job configs InSetupCmd bool // this is set to true when the `setup` command is called @@ -119,16 +119,24 @@ type Beat struct { // BeatConfig struct contains the basic configuration of every beat type BeatConfig struct { - Shipper publisher.ShipperConfig `config:",inline"` - Output common.ConfigNamespace `config:"output"` - Monitoring *common.Config `config:"xpack.monitoring"` - Logging logp.Logging `config:"logging"` - Processors processors.PluginConfig `config:"processors"` - Path paths.Path `config:"path"` - Dashboards *common.Config `config:"setup.dashboards"` - Template *common.Config `config:"setup.template"` - Kibana *common.Config `config:"setup.kibana"` - Http *common.Config `config:"http"` + // beat top-level settings + Name string `config:"name"` + MaxProcs int `config:"max_procs"` + + // beat internal components configurations + HTTP *common.Config `config:"http"` + Path paths.Path `config:"path"` + Logging logp.Logging `config:"logging"` + + // output/publishing related configurations + Pipeline pipeline.Config `config:",inline"` + Monitoring *common.Config `config:"xpack.monitoring"` + Output common.ConfigNamespace `config:"output"` + + // 'setup' configurations + Dashboards *common.Config `config:"setup.dashboards"` + Template *common.Config `config:"setup.template"` + Kibana *common.Config `config:"setup.kibana"` } var ( @@ -238,10 +246,6 @@ func (b *Beat) createBeater(bt Creator) (Beater, error) { } logp.Info("Setup Beat: %s; Version: %s", b.Info.Beat, b.Info.Version) - processors, err := processors.New(b.Config.Processors) - if err != nil { - return nil, fmt.Errorf("error initializing processors: %v", err) - } err = b.registerTemplateLoading() if err != nil { @@ -249,16 +253,16 @@ func (b *Beat) createBeater(bt Creator) (Beater, error) { } debugf("Initializing output plugins") - publisher, err := publisher.New(b.Info, b.Config.Output, b.Config.Shipper, processors) + pipeline, err := pipeline.Load(b.Info, b.Config.Pipeline, b.Config.Output) if err != nil { return nil, fmt.Errorf("error initializing publisher: %v", err) } // TODO: some beats race on shutdown with publisher.Stop -> do not call Stop yet, // but refine publisher to disconnect clients on stop automatically - // defer publisher.Stop() + // defer pipeline.Close() - b.Publisher = publisher + b.Publisher = pipeline beater, err := bt(b, sub) if err != nil { return nil, err @@ -317,8 +321,8 @@ func (b *Beat) launch(bt Creator) error { defer logp.Info("%s stopped.", b.Info.Beat) defer logp.LogTotalExpvars(&b.Config.Logging) - if b.Config.Http.Enabled() { - api.Start(b.Config.Http, b.Info) + if b.Config.HTTP.Enabled() { + api.Start(b.Config.HTTP, b.Info) } return beater.Run(b) @@ -458,7 +462,7 @@ func (b *Beat) configure() error { return err } - if name := b.Config.Shipper.Name; name != "" { + if name := b.Config.Name; name != "" { b.Info.Name = name } @@ -482,11 +486,8 @@ func (b *Beat) configure() error { logp.Info("Beat UUID: %v", b.Info.UUID) - if b.Config.Shipper.MaxProcs != nil { - maxProcs := *b.Config.Shipper.MaxProcs - if maxProcs > 0 { - runtime.GOMAXPROCS(maxProcs) - } + if maxProcs := b.Config.MaxProcs; maxProcs > 0 { + runtime.GOMAXPROCS(maxProcs) } return nil diff --git a/libbeat/mock/mockbeat.go b/libbeat/mock/mockbeat.go index 6f17424d3d8..dd1f2529590 100644 --- a/libbeat/mock/mockbeat.go +++ b/libbeat/mock/mockbeat.go @@ -6,7 +6,7 @@ import ( "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/bc/publisher" + pub "github.com/elastic/beats/libbeat/publisher/beat" ) ///*** Mock Beat Setup ***/// @@ -16,7 +16,7 @@ var Name = "mockbeat" type Mockbeat struct { done chan struct{} - client publisher.Client + client pub.Client } // Creates beater @@ -29,13 +29,20 @@ func New(b *beat.Beat, _ *common.Config) (beat.Beater, error) { /// *** Beater interface methods ***/// func (mb *Mockbeat) Run(b *beat.Beat) error { - mb.client = b.Publisher.Connect() + var err error + + mb.client, err = b.Publisher.Connect() + if err != nil { + return err + } // Wait until mockbeat is done - mb.client.PublishEvent(common.MapStr{ - "@timestamp": common.Time(time.Now()), - "type": "mock", - "message": "Mockbeat is alive!", + mb.client.Publish(pub.Event{ + Timestamp: time.Now(), + Fields: common.MapStr{ + "type": "mock", + "message": "Mockbeat is alive!", + }, }) <-mb.done return nil diff --git a/libbeat/monitoring/report/elasticsearch/elasticsearch.go b/libbeat/monitoring/report/elasticsearch/elasticsearch.go index 94f1939209c..00adffa58e0 100644 --- a/libbeat/monitoring/report/elasticsearch/elasticsearch.go +++ b/libbeat/monitoring/report/elasticsearch/elasticsearch.go @@ -17,9 +17,9 @@ import ( "github.com/elastic/beats/libbeat/outputs/outil" "github.com/elastic/beats/libbeat/outputs/transport" "github.com/elastic/beats/libbeat/publisher/beat" - "github.com/elastic/beats/libbeat/publisher/broker" - "github.com/elastic/beats/libbeat/publisher/broker/membroker" "github.com/elastic/beats/libbeat/publisher/pipeline" + "github.com/elastic/beats/libbeat/publisher/queue" + "github.com/elastic/beats/libbeat/publisher/queue/memqueue" ) type reporter struct { @@ -104,8 +104,8 @@ func makeReporter(beat common.BeatInfo, cfg *common.Config) (report.Reporter, er out.Clients = append(out.Clients, client) } - brokerFactory := func(e broker.Eventer) (broker.Broker, error) { - return membroker.NewBroker(membroker.Settings{ + queueFactory := func(e queue.Eventer) (queue.Queue, error) { + return memqueue.NewBroker(memqueue.Settings{ Eventer: e, Events: 20, }), nil @@ -115,7 +115,7 @@ func makeReporter(beat common.BeatInfo, cfg *common.Config) (report.Reporter, er pipeline, err := pipeline.New( monitoring, - brokerFactory, out, pipeline.Settings{ + queueFactory, out, pipeline.Settings{ WaitClose: 0, WaitCloseMode: pipeline.NoWaitOnClose, }) diff --git a/libbeat/publisher/bc/publisher/async.go b/libbeat/publisher/bc/publisher/async.go deleted file mode 100644 index 84af2ddd461..00000000000 --- a/libbeat/publisher/bc/publisher/async.go +++ /dev/null @@ -1,154 +0,0 @@ -package publisher - -import ( - "sync" - - "github.com/elastic/beats/libbeat/common/op" - "github.com/elastic/beats/libbeat/publisher/beat" -) - -type asyncClient struct { - done <-chan struct{} - - client beat.Client - acker *asyncACKer - - guaranteedClient beat.Client - guaranteedAcker *asyncACKer -} - -type asyncACKer struct { - // Note: mutex is required for sending the message item to the - // asyncACKer and publishing all events, so no two users of the async client can - // interleave events. This is a limitation enforced by the - // old publisher API to be removed - // Note: normally every go-routine wanting to publish should have it's own - // client instance. That is, no contention on the mutex is really expected. - // Still, the mutex is used as additional safety measure - count int - - mutex sync.Mutex - waiting []message -} - -func newAsyncClient(pub *BeatPublisher, done <-chan struct{}) (*asyncClient, error) { - c := &asyncClient{ - done: done, - acker: newAsyncACKer(), - guaranteedAcker: newAsyncACKer(), - } - - var err error - c.guaranteedClient, err = pub.pipeline.ConnectWith(beat.ClientConfig{ - PublishMode: beat.GuaranteedSend, - ACKCount: c.guaranteedAcker.onACK, - }) - if err != nil { - return nil, err - } - - c.client, err = pub.pipeline.ConnectWith(beat.ClientConfig{ - ACKCount: c.acker.onACK, - }) - if err != nil { - c.guaranteedClient.Close() - return nil, err - } - - go func() { - // closer - <-done - c.guaranteedClient.Close() - c.client.Close() - }() - - return c, nil -} - -func newAsyncACKer() *asyncACKer { - return &asyncACKer{} -} - -func (c *asyncClient) publish(m message) bool { - if *publishDisabled { - debug("publisher disabled") - op.SigCompleted(m.context.Signal) - return true - } - - count := len(m.data) - single := count == 0 - if single { - count = 1 - } - - client := c.client - acker := c.acker - if m.context.Guaranteed { - client = c.guaranteedClient - acker = c.guaranteedAcker - } - - acker.add(m) - if single { - client.Publish(m.datum) - } else { - client.PublishAll(m.data) - } - - return true -} - -func (a *asyncACKer) add(msg message) { - a.mutex.Lock() - a.waiting = append(a.waiting, msg) - a.mutex.Unlock() -} - -func (a *asyncACKer) onACK(count int) { - for count > 0 { - cnt := a.count - if cnt == 0 { - // we're not waiting for a message its ACK yet -> advance to next message - // object and retry - a.mutex.Lock() - if len(a.waiting) == 0 { - a.mutex.Unlock() - return - } - - active := a.waiting[0] - cnt = len(active.data) - a.mutex.Unlock() - - if cnt == 0 { - cnt = 1 - } - a.count = cnt - continue - } - - acked := count - if acked > cnt { - acked = cnt - } - cnt -= acked - count -= acked - - a.count = cnt - finished := cnt == 0 - if finished { - var msg message - - a.mutex.Lock() - // finished active message - msg = a.waiting[0] - a.waiting = a.waiting[1:] - a.mutex.Unlock() - - if sig := msg.context.Signal; sig != nil { - sig.Completed() - } - } - } -} diff --git a/libbeat/publisher/bc/publisher/client.go b/libbeat/publisher/bc/publisher/client.go deleted file mode 100644 index 3da1b11f42c..00000000000 --- a/libbeat/publisher/bc/publisher/client.go +++ /dev/null @@ -1,221 +0,0 @@ -package publisher - -import ( - "errors" - "time" - - "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/common/op" - "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/publisher/beat" -) - -// Metrics that can retrieved through the expvar web interface. -var ( - publishedEvents = monitoring.NewInt(nil, "publisher.events.count") -) - -var ( - ErrClientClosed = errors.New("client closed") -) - -// Client is used by beats to publish new events. -// -// The publish methods add fields that are common to all events. Both methods -// add the 'beat' field that contains name and hostname. Also they add 'tags' -// and 'fields'. -// -// Event publishers can override the default index for an event by adding a -// 'beat' field whose value is a common.MapStr that contains an 'index' field -// specifying the destination index. -// -// event := common.MapStr{ -// // Setting a custom index for a single event. -// "beat": common.MapStr{"index": "custom-index"}, -// } -// -// Event publishers can add fields and tags to an event. The fields will take -// precedence over the global fields defined in the shipper configuration. -// -// event := common.MapStr{ -// // Add custom fields to the root of the event. -// common.EventMetadataKey: common.EventMetadata{ -// UnderRoot: true, -// Fields: common.MapStr{"env": "production"} -// } -// } -type Client interface { - // Close disconnects the Client from the publisher pipeline. - Close() error - - // PublishEvent publishes one event with given options. If Sync option is set, - // PublishEvent will block until output plugins report success or failure state - // being returned by this method. - PublishEvent(event common.MapStr, opts ...ClientOption) bool - - // PublishEvents publishes multiple events with given options. If Guaranteed - // option is set, PublishEvent will block until output plugins report - // success or failure state being returned by this method. - PublishEvents(events []common.MapStr, opts ...ClientOption) bool -} - -type client struct { - canceler *op.Canceler - - publisher *BeatPublisher - sync *syncClient - async *asyncClient -} - -type message struct { - client *client - context Context - datum beat.Event - data []beat.Event -} - -type sender interface { - publish(message) bool -} - -func newClient(pub *BeatPublisher) *client { - c := &client{ - canceler: op.NewCanceler(), - publisher: pub, - } - return c -} - -func (c *client) Close() error { - if c == nil { - return nil - } - - c.canceler.Cancel() - - // atomic decrement clients counter - c.publisher.numClients.Dec() - return nil -} - -func (c *client) PublishEvent(event common.MapStr, opts ...ClientOption) bool { - var metadata common.MapStr - meta, ctx, pipeline, err := c.getPipeline(opts) - if err != nil { - panic(err) - } - - if len(meta) != 0 { - if len(meta) != 1 { - logp.Debug("publish", "too many metadata, pick first") - } - metadata = meta[0] - } - - publishedEvents.Add(1) - return pipeline.publish(message{ - client: c, - context: ctx, - datum: makeEvent(event, metadata), - }) -} - -func (c *client) PublishEvents(events []common.MapStr, opts ...ClientOption) bool { - var metadataAll common.MapStr - meta, ctx, pipeline, err := c.getPipeline(opts) - if err != nil { - panic(err) - } - - if len(meta) != 0 && len(events) != len(meta) { - if len(meta) != 1 { - logp.Debug("publish", - "Number of metadata elements does not match number of events => dropping metadata") - meta = nil - } else { - metadataAll = meta[0] - meta = nil - } - } - - data := make([]beat.Event, 0, len(events)) - for i, event := range events { - metadata := metadataAll - if meta != nil { - metadata = meta[i] - } - data = append(data, makeEvent(event, metadata)) - } - - if len(data) == 0 { - logp.Debug("filter", "No events to publish") - return true - } - - publishedEvents.Add(int64(len(data))) - return pipeline.publish(message{client: c, context: ctx, data: data}) -} - -func (c *client) getPipeline(opts []ClientOption) ([]common.MapStr, Context, sender, error) { - var err error - values, ctx := MakeContext(opts) - - if ctx.Sync { - if c.sync == nil { - c.sync, err = newSyncClient(c.publisher, c.canceler.Done()) - if err != nil { - return nil, ctx, nil, err - } - } - return values, ctx, c.sync, nil - } - - if c.async == nil { - c.async, err = newAsyncClient(c.publisher, c.canceler.Done()) - if err != nil { - return nil, ctx, nil, err - } - } - return values, ctx, c.async, nil -} - -func MakeContext(opts []ClientOption) ([]common.MapStr, Context) { - var ctx Context - var meta []common.MapStr - for _, opt := range opts { - var m []common.MapStr - m, ctx = opt(ctx) - if m != nil { - if meta == nil { - meta = m - } else { - meta = append(meta, m...) - } - } - } - return meta, ctx -} - -func makeEvent(fields common.MapStr, meta common.MapStr) beat.Event { - if logp.IsDebug("publish") { - logp.Debug("publish", "Publish: %s", fields.StringToPrint()) - } - - var ts time.Time - switch value := fields["@timestamp"].(type) { - case time.Time: - ts = value - case common.Time: - ts = time.Time(value) - default: - ts = time.Now() - } - delete(fields, "@timestamp") - - return beat.Event{ - Timestamp: ts, - Meta: meta, - Fields: fields, - } -} diff --git a/libbeat/publisher/bc/publisher/opts.go b/libbeat/publisher/bc/publisher/opts.go deleted file mode 100644 index 1df74eb65ee..00000000000 --- a/libbeat/publisher/bc/publisher/opts.go +++ /dev/null @@ -1,56 +0,0 @@ -package publisher - -import ( - "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/common/op" -) - -// ClientOption allows API users to set additional options when publishing events. -type ClientOption func(option Context) ([]common.MapStr, Context) - -// Guaranteed option will retry publishing the event, until send attempt have -// been ACKed by output plugin. -func Guaranteed(o Context) ([]common.MapStr, Context) { - o.Guaranteed = true - return nil, o -} - -// Sync option will block the event publisher until an event has been ACKed by -// the output plugin or failed. -func Sync(o Context) ([]common.MapStr, Context) { - o.Sync = true - return nil, o -} - -func Signal(signaler op.Signaler) ClientOption { - return func(ctx Context) ([]common.MapStr, Context) { - if ctx.Signal == nil { - ctx.Signal = signaler - } else { - ctx.Signal = op.CombineSignalers(ctx.Signal, signaler) - } - return nil, ctx - } -} - -func Metadata(m common.MapStr) ClientOption { - if len(m) == 0 { - return nilOption - } - return func(ctx Context) ([]common.MapStr, Context) { - return []common.MapStr{m}, ctx - } -} - -func MetadataBatch(m []common.MapStr) ClientOption { - if len(m) == 0 { - return nilOption - } - return func(ctx Context) ([]common.MapStr, Context) { - return m, ctx - } -} - -func nilOption(o Context) ([]common.MapStr, Context) { - return nil, o -} diff --git a/libbeat/publisher/bc/publisher/pipeline.go b/libbeat/publisher/bc/publisher/pipeline.go deleted file mode 100644 index 4aa30378ed7..00000000000 --- a/libbeat/publisher/bc/publisher/pipeline.go +++ /dev/null @@ -1,98 +0,0 @@ -package publisher - -import ( - "errors" - "fmt" - - "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/outputs" - "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/broker" - "github.com/elastic/beats/libbeat/publisher/pipeline" -) - -func createPipeline( - beatInfo common.BeatInfo, - shipper ShipperConfig, - processors *processors.Processors, - outcfg common.ConfigNamespace, -) (*pipeline.Pipeline, error) { - - reg := monitoring.Default.GetRegistry("libbeat") - if reg == nil { - reg = monitoring.Default.NewRegistry("libbeat") - } - - var out outputs.Group - if !(*publishDisabled) { - var err error - - if !outcfg.IsSet() { - msg := "No outputs are defined. Please define one under the output section." - logp.Info(msg) - return nil, errors.New(msg) - } - - // TODO: add support to unload/reassign outStats on output reloading - outReg := reg.NewRegistry("output") - outStats := outputs.MakeStats(outReg) - - out, err = outputs.Load(beatInfo, &outStats, outcfg.Name(), outcfg.Config()) - if err != nil { - return nil, err - } - - monitoring.NewString(outReg, "type").Set(outcfg.Name()) - } - - name := shipper.Name - if name == "" { - name = beatInfo.Hostname - } - - settings := pipeline.Settings{ - WaitClose: 0, - WaitCloseMode: pipeline.NoWaitOnClose, - Disabled: *publishDisabled, - Processors: processors, - Annotations: pipeline.Annotations{ - Event: shipper.EventMetadata, - Beat: common.MapStr{ - "name": name, - "hostname": beatInfo.Hostname, - "version": beatInfo.Version, - }, - }, - } - - brokerType := "mem" - if b := shipper.Queue.Name(); b != "" { - brokerType = b - } - - brokerFactory := broker.FindFactory(brokerType) - if brokerFactory == nil { - return nil, fmt.Errorf("'%v' is no valid queue type", brokerType) - } - - brokerConfig := shipper.Queue.Config() - if brokerConfig == nil { - brokerConfig = common.NewConfig() - } - - p, err := pipeline.New( - monitoring.Default.GetRegistry("libbeat"), - func(eventer broker.Eventer) (broker.Broker, error) { - return brokerFactory(eventer, brokerConfig) - }, - out, settings, - ) - if err != nil { - return nil, err - } - - logp.Info("Publisher name: %s", name) - return p, err -} diff --git a/libbeat/publisher/bc/publisher/publish.go b/libbeat/publisher/bc/publisher/publish.go deleted file mode 100644 index ab3312be2be..00000000000 --- a/libbeat/publisher/bc/publisher/publish.go +++ /dev/null @@ -1,127 +0,0 @@ -package publisher - -import ( - "flag" - - "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/common/atomic" - "github.com/elastic/beats/libbeat/common/op" - "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" -) - -// command line flags -var publishDisabled *bool - -var debug = logp.MakeDebug("publish") - -type Context struct { - publishOptions - Signal op.Signaler -} - -type publishOptions struct { - Guaranteed bool - Sync bool -} - -type TransactionalEventPublisher interface { - PublishTransaction(transaction op.Signaler, events []common.MapStr) -} - -type Publisher interface { - Connect() Client - ConnectX(beat.ClientConfig) (beat.Client, error) - SetACKHandler(beat.PipelineACKHandler) error -} - -type BeatPublisher struct { - disabled bool - name string - - // keep count of clients connected to publisher. A publisher is allowed to - // Stop only if all clients have been disconnected - numClients atomic.Uint32 - - pipeline beat.Pipeline -} - -type ShipperConfig struct { - common.EventMetadata `config:",inline"` // Fields and tags to add to each event. - Name string `config:"name"` - Queue common.ConfigNamespace `config:"queue"` - - // internal publisher queue sizes - MaxProcs *int `config:"max_procs"` -} - -func init() { - publishDisabled = flag.Bool("N", false, "Disable actual publishing for testing") -} - -// Create new PublisherType -func New( - beat common.BeatInfo, - output common.ConfigNamespace, - shipper ShipperConfig, - processors *processors.Processors, -) (*BeatPublisher, error) { - publisher := BeatPublisher{} - if err := publisher.init(beat, output, shipper, processors); err != nil { - return nil, err - } - - return &publisher, nil -} - -func (publisher *BeatPublisher) init( - beat common.BeatInfo, - outConfig common.ConfigNamespace, - shipper ShipperConfig, - processors *processors.Processors, -) error { - var err error - publisher.disabled = *publishDisabled - if publisher.disabled { - logp.Info("Dry run mode. All output types except the file based one are disabled.") - } - - publisher.name = shipper.Name - if publisher.name == "" { - publisher.name = beat.Hostname - } - - publisher.pipeline, err = createPipeline(beat, shipper, processors, outConfig) - if err != nil { - return err - } - - logp.Info("Publisher name: %s", publisher.name) - return nil -} - -func (publisher *BeatPublisher) Stop() { - if publisher.numClients.Load() > 0 { - panic("All clients must disconnect before shutting down publisher pipeline") - } - - publisher.pipeline.Close() -} - -func (publisher *BeatPublisher) Connect() Client { - publisher.numClients.Inc() - return newClient(publisher) -} - -func (publisher *BeatPublisher) ConnectX(config beat.ClientConfig) (beat.Client, error) { - return publisher.pipeline.ConnectWith(config) -} - -func (publisher *BeatPublisher) SetACKHandler(h beat.PipelineACKHandler) error { - return publisher.pipeline.SetACKHandler(h) -} - -func (publisher *BeatPublisher) GetName() string { - return publisher.name -} diff --git a/libbeat/publisher/bc/publisher/sync.go b/libbeat/publisher/bc/publisher/sync.go deleted file mode 100644 index 3e8336701cf..00000000000 --- a/libbeat/publisher/bc/publisher/sync.go +++ /dev/null @@ -1,104 +0,0 @@ -package publisher - -import ( - "github.com/elastic/beats/libbeat/common/op" - "github.com/elastic/beats/libbeat/publisher/beat" -) - -type syncClient struct { - client beat.Client - guaranteedClient beat.Client - done <-chan struct{} - active syncMsgContext -} - -type syncMsgContext struct { - count int - sig chan struct{} -} - -func newSyncClient(pub *BeatPublisher, done <-chan struct{}) (*syncClient, error) { - // always assume sync client is used with 'guarnateed' flag (true for filebeat and winlogbeat) - - c := &syncClient{done: done} - c.active.init() - - var err error - c.guaranteedClient, err = pub.pipeline.ConnectWith(beat.ClientConfig{ - PublishMode: beat.GuaranteedSend, - ACKCount: c.onACK, - }) - if err != nil { - return nil, err - } - - c.client, err = pub.pipeline.ConnectWith(beat.ClientConfig{ - ACKCount: c.onACK, - }) - if err != nil { - c.guaranteedClient.Close() - return nil, err - } - - go func() { - <-done - c.client.Close() - c.guaranteedClient.Close() - }() - - return c, nil -} - -func (c *syncClient) onACK(count int) { - c.active.count -= count - if c.active.count < 0 { - panic("negative event count") - } - - if c.active.count == 0 { - c.active.sig <- struct{}{} - } -} - -func (c *syncClient) publish(m message) bool { - if *publishDisabled { - debug("publisher disabled") - op.SigCompleted(m.context.Signal) - return true - } - - count := len(m.data) - single := count == 0 - if single { - count = 1 - } - - client := c.client - if m.context.Guaranteed { - client = c.guaranteedClient - } - - c.active.count = count - if single { - client.Publish(m.datum) - } else { - client.PublishAll(m.data) - } - - // wait for event or close - select { - case <-c.done: - return false - case <-c.active.sig: - } - - if s := m.context.Signal; s != nil { - s.Completed() - } - - return true -} - -func (ctx *syncMsgContext) init() { - ctx.sig = make(chan struct{}, 1) -} diff --git a/libbeat/publisher/beat/pipeline.go b/libbeat/publisher/beat/pipeline.go index 654337bae0d..86023601fa3 100644 --- a/libbeat/publisher/beat/pipeline.go +++ b/libbeat/publisher/beat/pipeline.go @@ -7,7 +7,6 @@ import ( ) type Pipeline interface { - Close() error Connect() (Client, error) ConnectWith(ClientConfig) (Client, error) SetACKHandler(PipelineACKHandler) error @@ -73,9 +72,9 @@ type ClientEventer interface { Closing() // Closing indicates the client is being shutdown next Closed() // Closed indicates the client being fully shutdown - Published() // event been has successfully forwarded to the publisher pipeline + Published() // event has been successfully forwarded to the publisher pipeline FilteredOut(Event) // event has been filtered out/dropped by processors - DroppedOnPublish(Event) // event has been dropped, while waiting for the broker + DroppedOnPublish(Event) // event has been dropped, while waiting for the queue } // PipelineACKHandler configures some pipeline-wide event ACK handler. diff --git a/libbeat/publisher/broker/broker_reg.go b/libbeat/publisher/broker/broker_reg.go deleted file mode 100644 index 683292e1d16..00000000000 --- a/libbeat/publisher/broker/broker_reg.go +++ /dev/null @@ -1,38 +0,0 @@ -package broker - -import ( - "fmt" - - "github.com/elastic/beats/libbeat/common" -) - -// Global broker type registry for configuring and loading a broker instance -// via common.Config -var brokerReg = map[string]Factory{} - -// RegisterType registers a new broker type. -func RegisterType(name string, f Factory) { - if brokerReg[name] != nil { - panic(fmt.Errorf("broker type '%v' exists already", name)) - } - brokerReg[name] = f -} - -// FindFactory retrieves a broker types constructor. Returns nil if broker type is unknown -func FindFactory(name string) Factory { - return brokerReg[name] -} - -// Load instantiates a new broker. -func Load(eventer Eventer, config common.ConfigNamespace) (Broker, error) { - t, cfg := config.Name(), config.Config() - if t == "" { - t = "mem" - } - - factory := FindFactory(t) - if factory == nil { - return nil, fmt.Errorf("broker type %v undefined", t) - } - return factory(eventer, cfg) -} diff --git a/libbeat/publisher/broker/brokertest/doc.go b/libbeat/publisher/broker/brokertest/doc.go deleted file mode 100644 index 67525dfbbf9..00000000000 --- a/libbeat/publisher/broker/brokertest/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package brokertest provides common functionality tests all broker implementations -// must pass. These tests guarantee a broker fits well into the publisher pipeline. -package brokertest diff --git a/libbeat/publisher/broker/membroker/doc.go b/libbeat/publisher/broker/membroker/doc.go deleted file mode 100644 index c96df29fa75..00000000000 --- a/libbeat/publisher/broker/membroker/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Package membroker provides an in-memory publisher.Broker implementation for -// use with the publisher pipeline. -// The broker implementation is registered as broker type "mem". -package membroker diff --git a/libbeat/publisher/pipeline/batch.go b/libbeat/publisher/pipeline/batch.go index 06d28276442..ddb222f0b02 100644 --- a/libbeat/publisher/pipeline/batch.go +++ b/libbeat/publisher/pipeline/batch.go @@ -4,11 +4,11 @@ import ( "sync" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/broker" + "github.com/elastic/beats/libbeat/publisher/queue" ) type Batch struct { - original broker.Batch + original queue.Batch ctx *batchContext ttl int events []publisher.Event @@ -25,7 +25,7 @@ var batchPool = sync.Pool{ }, } -func newBatch(ctx *batchContext, original broker.Batch, ttl int) *Batch { +func newBatch(ctx *batchContext, original queue.Batch, ttl int) *Batch { if original == nil { panic("empty batch") } diff --git a/libbeat/publisher/pipeline/client.go b/libbeat/publisher/pipeline/client.go index c8e3f3e3d5a..d2582ee917e 100644 --- a/libbeat/publisher/pipeline/client.go +++ b/libbeat/publisher/pipeline/client.go @@ -6,19 +6,18 @@ import ( "github.com/elastic/beats/libbeat/common/atomic" "github.com/elastic/beats/libbeat/publisher" "github.com/elastic/beats/libbeat/publisher/beat" - "github.com/elastic/beats/libbeat/publisher/broker" + "github.com/elastic/beats/libbeat/publisher/queue" ) -// client connects a beat with the processors and pipeline broker. +// client connects a beat with the processors and pipeline queue. // // TODO: All ackers currently drop any late incoming ACK. Some beats still might // be interested in handling/waiting for event ACKs more globally // -> add support for not dropping pending ACKs type client struct { - // active connection to broker pipeline *Pipeline processors beat.Processor - producer broker.Producer + producer queue.Producer mutex sync.Mutex acker acker diff --git a/libbeat/publisher/pipeline/config.go b/libbeat/publisher/pipeline/config.go index 11d2ea0ea97..6c74721e525 100644 --- a/libbeat/publisher/pipeline/config.go +++ b/libbeat/publisher/pipeline/config.go @@ -3,17 +3,20 @@ package pipeline import ( "errors" "fmt" - "time" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/processors" "github.com/elastic/beats/libbeat/publisher/beat" ) // Config object for loading a pipeline instance via Load. type Config struct { - WaitShutdown time.Duration `config:"wait_shutdown"` - Broker common.ConfigNamespace `config:"broker"` - Output common.ConfigNamespace `config:"output"` + // Event processing configurations + common.EventMetadata `config:",inline"` // Fields and tags to add to each event. + Processors processors.PluginConfig `config:"processors"` + + // Event queue + Queue common.ConfigNamespace `config:"queue"` } // validateClientConfig checks a ClientConfig can be used with (*Pipeline).ConnectWith. diff --git a/libbeat/publisher/pipeline/consumer.go b/libbeat/publisher/pipeline/consumer.go index d7980cf89e1..391824cfff9 100644 --- a/libbeat/publisher/pipeline/consumer.go +++ b/libbeat/publisher/pipeline/consumer.go @@ -3,10 +3,10 @@ package pipeline import ( "github.com/elastic/beats/libbeat/common/atomic" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/broker" + "github.com/elastic/beats/libbeat/publisher/queue" ) -// eventConsumer collects and forwards events from the broker to the outputs work queue. +// eventConsumer collects and forwards events from the queue to the outputs work queue. // The eventConsumer is managed by the controller and receives additional pause signals // from the retryer in case of too many events failing to be send or if retryer // is receiving cancelled batches from outputs to be closed on output reloading. @@ -20,15 +20,15 @@ type eventConsumer struct { wait atomic.Bool sig chan consumerSignal - broker broker.Broker - consumer broker.Consumer + queue queue.Queue + consumer queue.Consumer out *outputGroup } type consumerSignal struct { tag consumerEventTag - consumer broker.Consumer + consumer queue.Consumer out *outputGroup } @@ -42,7 +42,7 @@ const ( func newEventConsumer( log *logp.Logger, - broker broker.Broker, + queue queue.Queue, ctx *batchContext, ) *eventConsumer { c := &eventConsumer{ @@ -51,8 +51,8 @@ func newEventConsumer( sig: make(chan consumerSignal, 3), out: nil, - broker: broker, - consumer: broker.Consumer(), + queue: queue, + consumer: queue.Consumer(), ctx: ctx, } @@ -106,15 +106,15 @@ func (c *eventConsumer) updOutput(grp *outputGroup) { out: grp, } - // update eventConsumer with new broker connection - c.consumer = c.broker.Consumer() + // update eventConsumer with new queue connection + c.consumer = c.queue.Consumer() c.sig <- consumerSignal{ tag: sigConsumerUpdateInput, consumer: c.consumer, } } -func (c *eventConsumer) loop(consumer broker.Consumer) { +func (c *eventConsumer) loop(consumer queue.Consumer) { log := c.logger log.Debug("start pipeline event consumer") @@ -147,14 +147,14 @@ func (c *eventConsumer) loop(consumer broker.Consumer) { for { if !paused && c.out != nil && consumer != nil && batch == nil { out = c.out.workQueue - brokerBatch, err := consumer.Get(c.out.batchSize) + queueBatch, err := consumer.Get(c.out.batchSize) if err != nil { out = nil consumer = nil continue } - batch = newBatch(c.ctx, brokerBatch, c.out.timeToLive) + batch = newBatch(c.ctx, queueBatch, c.out.timeToLive) paused = c.paused() if paused { out = nil diff --git a/libbeat/publisher/pipeline/controller.go b/libbeat/publisher/pipeline/controller.go index 1b8b9424503..d6e75e770e1 100644 --- a/libbeat/publisher/pipeline/controller.go +++ b/libbeat/publisher/pipeline/controller.go @@ -3,7 +3,7 @@ package pipeline import ( "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs" - "github.com/elastic/beats/libbeat/publisher/broker" + "github.com/elastic/beats/libbeat/publisher/queue" ) // outputController manages the pipelines output capabilites, like: @@ -14,7 +14,7 @@ type outputController struct { logger *logp.Logger observer *observer - broker broker.Broker + queue queue.Queue retryer *retryer consumer *eventConsumer @@ -41,12 +41,12 @@ type outputWorker interface { func newOutputController( log *logp.Logger, observer *observer, - b broker.Broker, + b queue.Queue, ) *outputController { c := &outputController{ logger: log, observer: observer, - broker: b, + queue: b, } ctx := &batchContext{} diff --git a/libbeat/publisher/pipeline/module.go b/libbeat/publisher/pipeline/module.go new file mode 100644 index 00000000000..3e8f269f021 --- /dev/null +++ b/libbeat/publisher/pipeline/module.go @@ -0,0 +1,131 @@ +package pipeline + +import ( + "errors" + "flag" + "fmt" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/libbeat/monitoring" + "github.com/elastic/beats/libbeat/outputs" + "github.com/elastic/beats/libbeat/processors" + "github.com/elastic/beats/libbeat/publisher/queue" +) + +// Global pipeline module for loading the main pipeline from a configuration object + +// command line flags +var publishDisabled = false + +const defaultQueueType = "mem" + +func init() { + flag.BoolVar(&publishDisabled, "N", false, "Disable actual publishing for testing") +} + +// Load uses a Config object to create a new complete Pipeline instance with +// configured queue and outputs. +func Load( + beatInfo common.BeatInfo, + config Config, + outcfg common.ConfigNamespace, +) (*Pipeline, error) { + if publishDisabled { + logp.Info("Dry run mode. All output types except the file based one are disabled.") + } + + processors, err := processors.New(config.Processors) + if err != nil { + return nil, fmt.Errorf("error initializing processors: %v", err) + } + + reg := monitoring.Default.GetRegistry("libbeat") + if reg == nil { + reg = monitoring.Default.NewRegistry("libbeat") + } + + name := beatInfo.Name + settings := Settings{ + WaitClose: 0, + WaitCloseMode: NoWaitOnClose, + Disabled: publishDisabled, + Processors: processors, + Annotations: Annotations{ + Event: config.EventMetadata, + Beat: common.MapStr{ + "name": name, + "hostname": beatInfo.Hostname, + "version": beatInfo.Version, + }, + }, + } + + queueBuilder, err := createQueueBuilder(config.Queue) + if err != nil { + return nil, err + } + + out, err := loadOutput(beatInfo, reg, outcfg) + if err != nil { + return nil, err + } + + p, err := New(reg, queueBuilder, out, settings) + if err != nil { + return nil, err + } + + logp.Info("Publisher name: %s", name) + return p, err +} + +func loadOutput( + beatInfo common.BeatInfo, + reg *monitoring.Registry, + outcfg common.ConfigNamespace, +) (outputs.Group, error) { + if publishDisabled { + return outputs.Group{}, nil + } + + if !outcfg.IsSet() { + msg := "No outputs are defined. Please define one under the output section." + logp.Info(msg) + return outputs.Fail(errors.New(msg)) + } + + // TODO: add support to unload/reassign outStats on output reloading + outReg := reg.NewRegistry("output") + outStats := outputs.MakeStats(outReg) + + out, err := outputs.Load(beatInfo, &outStats, outcfg.Name(), outcfg.Config()) + if err != nil { + return outputs.Fail(err) + } + + monitoring.NewString(outReg, "type").Set(outcfg.Name()) + + return out, nil +} + +func createQueueBuilder(config common.ConfigNamespace) (func(queue.Eventer) (queue.Queue, error), error) { + queueType := defaultQueueType + if b := config.Name(); b != "" { + queueType = b + } + + queueFactory := queue.FindFactory(queueType) + if queueFactory == nil { + return nil, fmt.Errorf("'%v' is no valid queue type", queueType) + } + + queueConfig := config.Config() + if queueConfig == nil { + queueConfig = common.NewConfig() + } + + return func(eventer queue.Eventer) (queue.Queue, error) { + return queueFactory(eventer, queueConfig) + }, nil +} diff --git a/libbeat/publisher/pipeline/pipeline.go b/libbeat/publisher/pipeline/pipeline.go index 1aad1945c9c..aa62bb95601 100644 --- a/libbeat/publisher/pipeline/pipeline.go +++ b/libbeat/publisher/pipeline/pipeline.go @@ -1,4 +1,4 @@ -// Package pipeline combines all publisher functionality (processors, broker, +// Package pipeline combines all publisher functionality (processors, queue, // outputs) to create instances of complete publisher pipelines, beats can // connect to publish events to. package pipeline @@ -17,25 +17,25 @@ import ( "github.com/elastic/beats/libbeat/processors" "github.com/elastic/beats/libbeat/publisher" "github.com/elastic/beats/libbeat/publisher/beat" - "github.com/elastic/beats/libbeat/publisher/broker" + "github.com/elastic/beats/libbeat/publisher/queue" ) // Pipeline implementation providint all beats publisher functionality. -// The pipeline consists of clients, processors, a central broker, an output +// The pipeline consists of clients, processors, a central queue, an output // controller and the actual outputs. -// The broker implementing the broker.Broker interface is the most entral entity +// The queue implementing the queue.Queue interface is the most entral entity // to the pipeline, providing support for pushung, batching and pulling events. // The pipeline adds different ACKing strategies and wait close support on top -// of the broker. For handling ACKs, the pipeline keeps track of filtered out events, +// of the queue. For handling ACKs, the pipeline keeps track of filtered out events, // to be ACKed to the client in correct order. // The output controller configures a (potentially reloadable) set of load -// balanced output clients. Events will be pulled from the broker and pushed to +// balanced output clients. Events will be pulled from the queue and pushed to // the output clients using a shared work queue for the active outputs.Group. // Processors in the pipeline are executed in the clients go-routine, before -// entering the broker. No filtering/processing will occur on the output side. +// entering the queue. No filtering/processing will occur on the output side. type Pipeline struct { logger *logp.Logger - broker broker.Broker + queue queue.Queue output *outputController observer observer @@ -122,49 +122,14 @@ type waitCloser struct { events sync.WaitGroup } -type brokerFactory func(broker.Eventer) (broker.Broker, error) +type queueFactory func(queue.Eventer) (queue.Queue, error) -// Load uses a Config object to create a new complete Pipeline instance with -// configured broker and outputs. -func Load( - beatInfo common.BeatInfo, - monitoring *monitoring.Registry, - config Config, -) (*Pipeline, error) { - if !config.Output.IsSet() { - return nil, errors.New("no output configured") - } - - brokerFactory := func(e broker.Eventer) (broker.Broker, error) { - return broker.Load(e, config.Broker) - } - - output, err := outputs.Load(beatInfo, nil, config.Output.Name(), config.Output.Config()) - if err != nil { - return nil, err - } - - // TODO: configure pipeline processors - pipeline, err := New(monitoring, brokerFactory, output, Settings{ - WaitClose: config.WaitShutdown, - WaitCloseMode: WaitOnPipelineClose, - }) - if err != nil { - for _, c := range output.Clients { - c.Close() - } - return nil, err - } - - return pipeline, nil -} - -// New create a new Pipeline instance from a broker instance and a set of outputs. -// The new pipeline will take ownership of broker and outputs. On Close, the -// broker and outputs will be closed. +// New create a new Pipeline instance from a queue instance and a set of outputs. +// The new pipeline will take ownership of queue and outputs. On Close, the +// queue and outputs will be closed. func New( metrics *monitoring.Registry, - brokerFactory brokerFactory, + queueFactory queueFactory, out outputs.Group, settings Settings, ) (*Pipeline, error) { @@ -211,19 +176,19 @@ func New( if settings.WaitCloseMode == WaitOnPipelineClose && settings.WaitClose > 0 { p.waitCloser = &waitCloser{} - // waitCloser decrements counter on broker ACK (not per client) + // waitCloser decrements counter on queue ACK (not per client) p.eventer.waitClose = p.waitCloser } - p.broker, err = brokerFactory(&p.eventer) + p.queue, err = queueFactory(&p.eventer) if err != nil { return nil, err } - p.eventSema = newSema(p.broker.BufferConfig().Events) + p.eventSema = newSema(p.queue.BufferConfig().Events) p.observer.init(metrics) - p.output = newOutputController(log, &p.observer, p.broker) + p.output = newOutputController(log, &p.observer, p.queue) p.output.Set(out) return p, nil @@ -268,7 +233,7 @@ func (p *Pipeline) SetACKHandler(handler beat.PipelineACKHandler) error { return nil } -// Close stops the pipeline, outputs and broker. +// Close stops the pipeline, outputs and queue. // If WaitClose with WaitOnPipelineClose mode is configured, Close will block // for a duration of WaitClose, if there are still active events in the pipeline. // Note: clients must be closed before calling Close. @@ -296,13 +261,13 @@ func (p *Pipeline) Close() error { // TODO: close/disconnect still active clients - // close output before shutting down broker + // close output before shutting down queue p.output.Close() - // shutdown broker - err := p.broker.Close() + // shutdown queue + err := p.queue.Close() if err != nil { - log.Err("pipeline broker shutdown error: ", err) + log.Err("pipeline queue shutdown error: ", err) } p.observer.cleanup() @@ -354,8 +319,8 @@ func (p *Pipeline) ConnectWith(cfg beat.ClientConfig) (beat.Client, error) { processors := p.newProcessorPipeline(cfg) acker := p.makeACKer(processors != nil, &cfg, waitClose) - producerCfg := broker.ProducerConfig{ - // only cancel events from broker if acker is configured + producerCfg := queue.ProducerConfig{ + // only cancel events from queue if acker is configured // and no pipeline-wide ACK handler is registered DropOnCancel: acker != nil && p.eventer.cb == nil, } @@ -377,7 +342,7 @@ func (p *Pipeline) ConnectWith(cfg beat.ClientConfig) (beat.Client, error) { acker = nilACKer } - producer := p.broker.Producer(producerCfg) + producer := p.queue.Producer(producerCfg) client := &client{ pipeline: p, isOpen: atomic.MakeBool(true), @@ -401,7 +366,7 @@ func (e *pipelineEventer) OnACK(n int) { wc.dec(n) } if e.cb != nil { - e.cb.reportBrokerACK(n) + e.cb.reportQueueACK(n) } } diff --git a/libbeat/publisher/pipeline/pipeline_ack.go b/libbeat/publisher/pipeline/pipeline_ack.go index a79b465b7e5..eb4d1abc556 100644 --- a/libbeat/publisher/pipeline/pipeline_ack.go +++ b/libbeat/publisher/pipeline/pipeline_ack.go @@ -111,8 +111,8 @@ func (b *pipelineEventsACK) createEventACKer(canDrop bool, sema *sema, fn func([ } // pipelineEventCB internally handles active ACKs in the pipeline. -// It receives ACK events from the broker and the individual clients. -// Once the broker returns an ACK to the pipelineEventCB, the worker loop will collect +// It receives ACK events from the queue and the individual clients. +// Once the queue returns an ACK to the pipelineEventCB, the worker loop will collect // events from all clients having published events in the last batch of events // being ACKed. // the PipelineACKHandler will be notified, once all events being ACKed @@ -194,7 +194,7 @@ func (p *pipelineEventCB) close() { // Note: the call blocks, until the ACK handler has collected all active events // from all clients. This ensure an ACK event being fully 'captured' // by the pipeline, before receiving/processing another ACK event. -// In the meantime the broker has the chance of batching-up more ACK events, +// In the meantime the queue has the chance of batching-up more ACK events, // such that only one ACK event is being reported to the pipeline handler func (p *pipelineEventCB) onEvents(events []beat.Event, acked int) { p.pushMsg(eventsMsg{events: events, total: len(events), acked: acked}) @@ -215,7 +215,7 @@ func (p *pipelineEventCB) pushMsg(msg eventsMsg) { } // Starts a new ACKed event. -func (p *pipelineEventCB) reportBrokerACK(acked int) { +func (p *pipelineEventCB) reportQueueACK(acked int) { p.acks <- acked } @@ -285,7 +285,7 @@ func (p *pipelineEventCB) collect(count int) (exit bool) { } } - // signal clients we processed all active ACKs, as reported by broker + // signal clients we processed all active ACKs, as reported by queue for _, sig := range signalers { close(sig) } diff --git a/libbeat/publisher/broker/membroker/ackloop.go b/libbeat/publisher/queue/memqueue/ackloop.go similarity index 99% rename from libbeat/publisher/broker/membroker/ackloop.go rename to libbeat/publisher/queue/memqueue/ackloop.go index 505b91a2441..f5a117383cc 100644 --- a/libbeat/publisher/broker/membroker/ackloop.go +++ b/libbeat/publisher/queue/memqueue/ackloop.go @@ -1,4 +1,4 @@ -package membroker +package memqueue // ackLoop implements the brokers asynchronous ACK worker. // Multiple concurrent ACKs from consecutive published batches will be batched up by the diff --git a/libbeat/publisher/broker/membroker/broker.go b/libbeat/publisher/queue/memqueue/broker.go similarity index 92% rename from libbeat/publisher/broker/membroker/broker.go rename to libbeat/publisher/queue/memqueue/broker.go index c6f353bcf7b..f570921f6a9 100644 --- a/libbeat/publisher/broker/membroker/broker.go +++ b/libbeat/publisher/queue/memqueue/broker.go @@ -1,4 +1,4 @@ -package membroker +package memqueue import ( "fmt" @@ -8,7 +8,7 @@ import ( "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/broker" + "github.com/elastic/beats/libbeat/publisher/queue" ) type Broker struct { @@ -29,7 +29,7 @@ type Broker struct { acks chan int scheduledACKs chan chanList - eventer broker.Eventer + eventer queue.Eventer // wait group for worker shutdown wg sync.WaitGroup @@ -37,7 +37,7 @@ type Broker struct { } type Settings struct { - Eventer broker.Eventer + Eventer queue.Eventer Events int FlushMinEvents int FlushTimeout time.Duration @@ -57,10 +57,10 @@ type chanList struct { } func init() { - broker.RegisterType("mem", create) + queue.RegisterType("mem", create) } -func create(eventer broker.Eventer, cfg *common.Config) (broker.Broker, error) { +func create(eventer queue.Eventer, cfg *common.Config) (queue.Queue, error) { config := defaultConfig if err := cfg.Unpack(&config); err != nil { return nil, err @@ -74,7 +74,7 @@ func create(eventer broker.Eventer, cfg *common.Config) (broker.Broker, error) { }), nil } -// NewBroker creates a new in-memory broker holding up to sz number of events. +// NewBroker creates a new broker based in-memory queue holding up to sz number of events. // If waitOnClose is set to true, the broker will block on Close, until all internal // workers handling incoming messages and ACKs have been shut down. func NewBroker( @@ -147,17 +147,17 @@ func (b *Broker) Close() error { return nil } -func (b *Broker) BufferConfig() broker.BufferConfig { - return broker.BufferConfig{ +func (b *Broker) BufferConfig() queue.BufferConfig { + return queue.BufferConfig{ Events: b.buf.Size(), } } -func (b *Broker) Producer(cfg broker.ProducerConfig) broker.Producer { +func (b *Broker) Producer(cfg queue.ProducerConfig) queue.Producer { return newProducer(b, cfg.ACK, cfg.OnDrop, cfg.DropOnCancel) } -func (b *Broker) Consumer() broker.Consumer { +func (b *Broker) Consumer() queue.Consumer { return newConsumer(b) } diff --git a/libbeat/publisher/broker/membroker/buf.go b/libbeat/publisher/queue/memqueue/buf.go similarity index 99% rename from libbeat/publisher/broker/membroker/buf.go rename to libbeat/publisher/queue/memqueue/buf.go index 0e9ad9bf019..1386fd97b10 100644 --- a/libbeat/publisher/broker/membroker/buf.go +++ b/libbeat/publisher/queue/memqueue/buf.go @@ -1,4 +1,4 @@ -package membroker +package memqueue import ( "fmt" diff --git a/libbeat/publisher/broker/membroker/config.go b/libbeat/publisher/queue/memqueue/config.go similarity index 96% rename from libbeat/publisher/broker/membroker/config.go rename to libbeat/publisher/queue/memqueue/config.go index 2616b1aeb83..ef843484a37 100644 --- a/libbeat/publisher/broker/membroker/config.go +++ b/libbeat/publisher/queue/memqueue/config.go @@ -1,4 +1,4 @@ -package membroker +package memqueue import ( "errors" diff --git a/libbeat/publisher/broker/membroker/consume.go b/libbeat/publisher/queue/memqueue/consume.go similarity index 94% rename from libbeat/publisher/broker/membroker/consume.go rename to libbeat/publisher/queue/memqueue/consume.go index 1a82d651269..560c58e4a80 100644 --- a/libbeat/publisher/broker/membroker/consume.go +++ b/libbeat/publisher/queue/memqueue/consume.go @@ -1,4 +1,4 @@ -package membroker +package memqueue import ( "errors" @@ -6,7 +6,7 @@ import ( "github.com/elastic/beats/libbeat/common/atomic" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/broker" + "github.com/elastic/beats/libbeat/publisher/queue" ) type consumer struct { @@ -45,7 +45,7 @@ func newConsumer(b *Broker) *consumer { } } -func (c *consumer) Get(sz int) (broker.Batch, error) { +func (c *consumer) Get(sz int) (queue.Batch, error) { // log := c.broker.logger if c.closed.Load() { diff --git a/libbeat/publisher/queue/memqueue/doc.go b/libbeat/publisher/queue/memqueue/doc.go new file mode 100644 index 00000000000..159c2ba7fec --- /dev/null +++ b/libbeat/publisher/queue/memqueue/doc.go @@ -0,0 +1,4 @@ +// Package memqueue provides an in-memory queue.Queue implementation for +// use with the publisher pipeline. +// The queue implementation is registered as queue type "mem". +package memqueue diff --git a/libbeat/publisher/broker/membroker/eventloop.go b/libbeat/publisher/queue/memqueue/eventloop.go similarity index 99% rename from libbeat/publisher/broker/membroker/eventloop.go rename to libbeat/publisher/queue/memqueue/eventloop.go index e1e73d95fad..773317e5254 100644 --- a/libbeat/publisher/broker/membroker/eventloop.go +++ b/libbeat/publisher/queue/memqueue/eventloop.go @@ -1,4 +1,4 @@ -package membroker +package memqueue import ( "time" diff --git a/libbeat/publisher/broker/membroker/internal_api.go b/libbeat/publisher/queue/memqueue/internal_api.go similarity index 97% rename from libbeat/publisher/broker/membroker/internal_api.go rename to libbeat/publisher/queue/memqueue/internal_api.go index e0a4281b10a..211ae657fe9 100644 --- a/libbeat/publisher/broker/membroker/internal_api.go +++ b/libbeat/publisher/queue/memqueue/internal_api.go @@ -1,4 +1,4 @@ -package membroker +package memqueue import "github.com/elastic/beats/libbeat/publisher" diff --git a/libbeat/publisher/broker/membroker/log.go b/libbeat/publisher/queue/memqueue/log.go similarity index 65% rename from libbeat/publisher/broker/membroker/log.go rename to libbeat/publisher/queue/memqueue/log.go index c83ae4213cf..4f3be49ffcc 100644 --- a/libbeat/publisher/broker/membroker/log.go +++ b/libbeat/publisher/queue/memqueue/log.go @@ -1,4 +1,4 @@ -package membroker +package memqueue import ( "github.com/elastic/beats/libbeat/logp" @@ -9,4 +9,4 @@ type logger interface { Debugf(string, ...interface{}) } -var defaultLogger logger = logp.NewLogger("membroker") +var defaultLogger logger = logp.NewLogger("memqueue") diff --git a/libbeat/publisher/broker/membroker/produce.go b/libbeat/publisher/queue/memqueue/produce.go similarity index 95% rename from libbeat/publisher/broker/membroker/produce.go rename to libbeat/publisher/queue/memqueue/produce.go index 8dc1ea1f63d..bede007c3f2 100644 --- a/libbeat/publisher/broker/membroker/produce.go +++ b/libbeat/publisher/queue/memqueue/produce.go @@ -1,10 +1,10 @@ -package membroker +package memqueue import ( "github.com/elastic/beats/libbeat/common/atomic" "github.com/elastic/beats/libbeat/publisher" "github.com/elastic/beats/libbeat/publisher/beat" - "github.com/elastic/beats/libbeat/publisher/broker" + "github.com/elastic/beats/libbeat/publisher/queue" ) type forgetfullProducer struct { @@ -35,7 +35,7 @@ type produceState struct { type ackHandler func(count int) -func newProducer(b *Broker, cb ackHandler, dropCB func(beat.Event), dropOnCancel bool) broker.Producer { +func newProducer(b *Broker, cb ackHandler, dropCB func(beat.Event), dropOnCancel bool) queue.Producer { openState := openState{ isOpen: atomic.MakeBool(true), done: make(chan struct{}), diff --git a/libbeat/publisher/broker/membroker/broker_test.go b/libbeat/publisher/queue/memqueue/queue_test.go similarity index 62% rename from libbeat/publisher/broker/membroker/broker_test.go rename to libbeat/publisher/queue/memqueue/queue_test.go index 6cbe92dd5f9..eda01937907 100644 --- a/libbeat/publisher/broker/membroker/broker_test.go +++ b/libbeat/publisher/queue/memqueue/queue_test.go @@ -1,4 +1,4 @@ -package membroker +package memqueue import ( "flag" @@ -6,8 +6,8 @@ import ( "testing" "time" - "github.com/elastic/beats/libbeat/publisher/broker" - "github.com/elastic/beats/libbeat/publisher/broker/brokertest" + "github.com/elastic/beats/libbeat/publisher/queue" + "github.com/elastic/beats/libbeat/publisher/queue/queuetest" ) var seed int64 @@ -34,22 +34,22 @@ func TestProduceConsumer(t *testing.T) { t.Log("batchSize: ", batchSize) t.Log("bufferSize: ", bufferSize) - factory := makeTestBroker(bufferSize) + factory := makeTestQueue(bufferSize) t.Run("single", func(t *testing.T) { - brokertest.TestSingleProducerConsumer(t, events, batchSize, factory) + queuetest.TestSingleProducerConsumer(t, events, batchSize, factory) }) t.Run("multi", func(t *testing.T) { - brokertest.TestMultiProducerConsumer(t, events, batchSize, factory) + queuetest.TestMultiProducerConsumer(t, events, batchSize, factory) }) } func TestProducerCancelRemovesEvents(t *testing.T) { - brokertest.TestProducerCancelRemovesEvents(t, makeTestBroker(1024)) + queuetest.TestProducerCancelRemovesEvents(t, makeTestQueue(1024)) } -func makeTestBroker(sz int) brokertest.BrokerFactory { - return func() broker.Broker { +func makeTestQueue(sz int) queuetest.QueueFactory { + return func() queue.Queue { return NewBroker(Settings{Events: sz, WaitOnClose: true}) } } diff --git a/libbeat/publisher/broker/broker.go b/libbeat/publisher/queue/queue.go similarity index 58% rename from libbeat/publisher/broker/broker.go rename to libbeat/publisher/queue/queue.go index aeb19da5354..6e19da004e5 100644 --- a/libbeat/publisher/broker/broker.go +++ b/libbeat/publisher/queue/queue.go @@ -1,4 +1,4 @@ -package broker +package queue import ( "io" @@ -8,24 +8,24 @@ import ( "github.com/elastic/beats/libbeat/publisher/beat" ) -// Factory for creating a broker used by a pipeline instance. -type Factory func(Eventer, *common.Config) (Broker, error) +// Factory for creating a queue used by a pipeline instance. +type Factory func(Eventer, *common.Config) (Queue, error) -// Eventer listens to special events to be send by broker implementations. +// Eventer listens to special events to be send by queue implementations. type Eventer interface { OnACK(int) // number of consecutively published messages, acked by producers } -// Broker is responsible for accepting, forwarding and ACKing events. -// A broker will receive and buffer single events from its producers. -// Consumers will receive events in batches from the brokers buffers. +// Queue is responsible for accepting, forwarding and ACKing events. +// A queue will receive and buffer single events from its producers. +// Consumers will receive events in batches from the queues buffers. // Once a consumer has finished processing a batch, it must ACK the batch, for -// the broker to advance its buffers. Events in progress or ACKed are not readable -// from the broker. -// When the broker decides it is safe to progress (events have been ACKed by +// the queue to advance its buffers. Events in progress or ACKed are not readable +// from the queue. +// When the queue decides it is safe to progress (events have been ACKed by // consumer or flush to some other intermediate storage), it will send an ACK signal // with the number of ACKed events to the Producer (ACK happens in batches). -type Broker interface { +type Queue interface { io.Closer BufferConfig() BufferConfig @@ -40,33 +40,33 @@ type Broker interface { // but still dropping events, the pipeline can use the buffer information, // to define an upper bound of events being active in the pipeline. type BufferConfig struct { - Events int // can be <= 0, if broker can not determine limit + Events int // can be <= 0, if queue can not determine limit } // ProducerConfig as used by the Pipeline to configure some custom callbacks -// between pipeline and broker. +// between pipeline and queue. type ProducerConfig struct { // if ACK is set, the callback will be called with number of events produced - // by the producer instance and being ACKed by the broker. + // by the producer instance and being ACKed by the queue. ACK func(count int) - // OnDrop provided to the broker, to report events being silently dropped by - // the broker. For example an async producer close and publish event, + // OnDrop provided to the queue, to report events being silently dropped by + // the queue. For example an async producer close and publish event, // with close happening early might result in the event being dropped. The callback - // gives a brokers user a chance to keep track of total number of events - // being buffered by the broker. + // gives a queue user a chance to keep track of total number of events + // being buffered by the queue. OnDrop func(beat.Event) - // DropOnCancel is a hint to the broker to drop events if the producer disconnects + // DropOnCancel is a hint to the queue to drop events if the producer disconnects // via Cancel. DropOnCancel bool } // Producer interface to be used by the pipelines client to forward events to be -// published to the broker. -// When a producer calls `Cancel`, it's up to the broker to send or remove +// published to the queue. +// When a producer calls `Cancel`, it's up to the queue to send or remove // events not yet ACKed. -// Note: A broker is still allowed to send the ACK signal after Cancel. The +// Note: A queue is still allowed to send the ACK signal after Cancel. The // pipeline client must filter out ACKs after cancel. type Producer interface { Publish(event publisher.Event) bool @@ -76,14 +76,14 @@ type Producer interface { // Consumer interface to be used by the pipeline output workers. // The `Get` method retrieves a batch of events up to size `sz`. If sz <= 0, -// the batch size is up to the broker. +// the batch size is up to the queue. type Consumer interface { Get(sz int) (Batch, error) Close() error } // Batch of events to be returned to Consumers. The `ACK` method will send the -// ACK signal to the broker. +// ACK signal to the queue. type Batch interface { Events() []publisher.Event ACK() diff --git a/libbeat/publisher/queue/queue_reg.go b/libbeat/publisher/queue/queue_reg.go new file mode 100644 index 00000000000..b445c6424bf --- /dev/null +++ b/libbeat/publisher/queue/queue_reg.go @@ -0,0 +1,38 @@ +package queue + +import ( + "fmt" + + "github.com/elastic/beats/libbeat/common" +) + +// Global queue type registry for configuring and loading a queue instance +// via common.Config +var queueReg = map[string]Factory{} + +// RegisterType registers a new queue type. +func RegisterType(name string, f Factory) { + if queueReg[name] != nil { + panic(fmt.Errorf("queue type '%v' exists already", name)) + } + queueReg[name] = f +} + +// FindFactory retrieves a queue types constructor. Returns nil if queue type is unknown +func FindFactory(name string) Factory { + return queueReg[name] +} + +// Load instantiates a new queue. +func Load(eventer Eventer, config common.ConfigNamespace) (Queue, error) { + t, cfg := config.Name(), config.Config() + if t == "" { + t = "mem" + } + + factory := FindFactory(t) + if factory == nil { + return nil, fmt.Errorf("queue type %v undefined", t) + } + return factory(eventer, cfg) +} diff --git a/libbeat/publisher/queue/queuetest/doc.go b/libbeat/publisher/queue/queuetest/doc.go new file mode 100644 index 00000000000..9ed1958e0e6 --- /dev/null +++ b/libbeat/publisher/queue/queuetest/doc.go @@ -0,0 +1,3 @@ +// Package queuetest provides common functionality tests all queue implementations +// must pass. These tests guarantee a queue fits well into the publisher pipeline. +package queuetest diff --git a/libbeat/publisher/broker/brokertest/event.go b/libbeat/publisher/queue/queuetest/event.go similarity index 94% rename from libbeat/publisher/broker/brokertest/event.go rename to libbeat/publisher/queue/queuetest/event.go index 12830e07e3e..2225927197d 100644 --- a/libbeat/publisher/broker/brokertest/event.go +++ b/libbeat/publisher/queue/queuetest/event.go @@ -1,4 +1,4 @@ -package brokertest +package queuetest import ( "time" diff --git a/libbeat/publisher/broker/brokertest/log.go b/libbeat/publisher/queue/queuetest/log.go similarity index 99% rename from libbeat/publisher/broker/brokertest/log.go rename to libbeat/publisher/queue/queuetest/log.go index 2647e7110a9..00b98e7728b 100644 --- a/libbeat/publisher/broker/brokertest/log.go +++ b/libbeat/publisher/queue/queuetest/log.go @@ -1,4 +1,4 @@ -package brokertest +package queuetest import ( "bufio" diff --git a/libbeat/publisher/broker/brokertest/producer_cancel.go b/libbeat/publisher/queue/queuetest/producer_cancel.go similarity index 84% rename from libbeat/publisher/broker/brokertest/producer_cancel.go rename to libbeat/publisher/queue/queuetest/producer_cancel.go index c8db1f5f2d9..4340c12208f 100644 --- a/libbeat/publisher/broker/brokertest/producer_cancel.go +++ b/libbeat/publisher/queue/queuetest/producer_cancel.go @@ -1,4 +1,4 @@ -package brokertest +package queuetest import ( "testing" @@ -7,16 +7,16 @@ import ( "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/broker" + "github.com/elastic/beats/libbeat/publisher/queue" ) // TestSingleProducerConsumer tests buffered events for a producer getting // cancelled will not be consumed anymore. Concurrent producer/consumer pairs // might still have active events not yet ACKed (not tested here). // -// Note: brokers not requiring consumers to ACK a events in order to +// Note: queues not requiring consumers to ACK a events in order to // return ACKs to the producer are not supported by this test. -func TestProducerCancelRemovesEvents(t *testing.T, factory BrokerFactory) { +func TestProducerCancelRemovesEvents(t *testing.T, factory QueueFactory) { fn := withLogOutput(func(t *testing.T) { var ( i int @@ -29,7 +29,7 @@ func TestProducerCancelRemovesEvents(t *testing.T, factory BrokerFactory) { defer b.Close() log.Debug("create first producer") - producer := b.Producer(broker.ProducerConfig{ + producer := b.Producer(queue.ProducerConfig{ ACK: func(int) {}, // install function pointer, so 'cancel' will remove events DropOnCancel: true, }) @@ -47,7 +47,7 @@ func TestProducerCancelRemovesEvents(t *testing.T, factory BrokerFactory) { // reconnect and send some more events log.Debug("connect new producer") - producer = b.Producer(broker.ProducerConfig{}) + producer = b.Producer(queue.ProducerConfig{}) for ; i < N2; i++ { log.Debugf("send event %v to new producer", i) producer.Publish(makeEvent(common.MapStr{ diff --git a/libbeat/publisher/broker/brokertest/brokertest.go b/libbeat/publisher/queue/queuetest/queuetest.go similarity index 88% rename from libbeat/publisher/broker/brokertest/brokertest.go rename to libbeat/publisher/queue/queuetest/queuetest.go index 48920e7eda4..38c4b0c635c 100644 --- a/libbeat/publisher/broker/brokertest/brokertest.go +++ b/libbeat/publisher/queue/queuetest/queuetest.go @@ -1,21 +1,21 @@ -package brokertest +package queuetest import ( "sync" "testing" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/broker" + "github.com/elastic/beats/libbeat/publisher/queue" ) -type BrokerFactory func() broker.Broker +type QueueFactory func() queue.Queue -type workerFactory func(*sync.WaitGroup, interface{}, *TestLogger, broker.Broker) func() +type workerFactory func(*sync.WaitGroup, interface{}, *TestLogger, queue.Queue) func() func TestSingleProducerConsumer( t *testing.T, events, batchSize int, - factory BrokerFactory, + factory QueueFactory, ) { tests := []struct { name string @@ -49,9 +49,9 @@ func TestSingleProducerConsumer( log := NewTestLogger(t) log.Debug("run test: ", test.name) - broker := factory() + queue := factory() defer func() { - err := broker.Close() + err := queue.Close() if err != nil { t.Error(err) } @@ -59,8 +59,8 @@ func TestSingleProducerConsumer( var wg sync.WaitGroup - go test.producers(&wg, nil, log, broker)() - go test.consumers(&wg, nil, log, broker)() + go test.producers(&wg, nil, log, queue)() + go test.consumers(&wg, nil, log, queue)() wg.Wait() })) @@ -71,7 +71,7 @@ func TestSingleProducerConsumer( func TestMultiProducerConsumer( t *testing.T, events, batchSize int, - factory BrokerFactory, + factory QueueFactory, ) { tests := []struct { name string @@ -192,9 +192,9 @@ func TestMultiProducerConsumer( log := NewTestLogger(t) log.Debug("run test: ", test.name) - broker := factory() + queue := factory() defer func() { - err := broker.Close() + err := queue.Close() if err != nil { t.Error(err) } @@ -202,8 +202,8 @@ func TestMultiProducerConsumer( var wg sync.WaitGroup - go test.producers(&wg, nil, log, broker)() - go test.consumers(&wg, nil, log, broker)() + go test.producers(&wg, nil, log, queue)() + go test.consumers(&wg, nil, log, queue)() wg.Wait() })) @@ -213,10 +213,10 @@ func TestMultiProducerConsumer( func multiple( fns ...workerFactory, ) workerFactory { - return func(wg *sync.WaitGroup, info interface{}, log *TestLogger, broker broker.Broker) func() { + return func(wg *sync.WaitGroup, info interface{}, log *TestLogger, queue queue.Queue) func() { runners := make([]func(), len(fns)) for i, gen := range fns { - runners[i] = gen(wg, info, log, broker) + runners[i] = gen(wg, info, log, queue) } return func() { @@ -231,8 +231,8 @@ func makeProducer( maxEvents int, waitACK bool, makeFields func(int) common.MapStr, -) func(*sync.WaitGroup, interface{}, *TestLogger, broker.Broker) func() { - return func(wg *sync.WaitGroup, info interface{}, log *TestLogger, b broker.Broker) func() { +) func(*sync.WaitGroup, interface{}, *TestLogger, queue.Queue) func() { + return func(wg *sync.WaitGroup, info interface{}, log *TestLogger, b queue.Queue) func() { wg.Add(1) return func() { defer wg.Done() @@ -259,7 +259,7 @@ func makeProducer( } } - producer := b.Producer(broker.ProducerConfig{ + producer := b.Producer(queue.ProducerConfig{ ACK: ackCB, }) for i := 0; i < maxEvents; i++ { @@ -276,14 +276,14 @@ func makeConsumer(maxEvents, batchSize int) workerFactory { } func multiConsumer(numConsumers, maxEvents, batchSize int) workerFactory { - return func(wg *sync.WaitGroup, info interface{}, log *TestLogger, b broker.Broker) func() { + return func(wg *sync.WaitGroup, info interface{}, log *TestLogger, b queue.Queue) func() { wg.Add(1) return func() { defer wg.Done() var events sync.WaitGroup - consumers := make([]broker.Consumer, numConsumers) + consumers := make([]queue.Consumer, numConsumers) for i := range consumers { consumers[i] = b.Consumer() } diff --git a/libbeat/publisher/testing/testing.go b/libbeat/publisher/testing/testing.go index 38c808cff39..4228a8ca05f 100644 --- a/libbeat/publisher/testing/testing.go +++ b/libbeat/publisher/testing/testing.go @@ -2,7 +2,6 @@ package testing // ChanClient implements Client interface, forwarding published events to some import ( - "github.com/elastic/beats/libbeat/publisher/bc/publisher" "github.com/elastic/beats/libbeat/publisher/beat" ) @@ -16,15 +15,15 @@ type ChanClient struct { Channel chan beat.Event } -func PublisherWithClient(client beat.Client) publisher.Publisher { +func PublisherWithClient(client beat.Client) beat.Pipeline { return &TestPublisher{client} } -func (pub *TestPublisher) Connect() publisher.Client { - panic("Not supported") +func (pub *TestPublisher) Connect() (beat.Client, error) { + return pub.client, nil } -func (pub *TestPublisher) ConnectX(_ beat.ClientConfig) (beat.Client, error) { +func (pub *TestPublisher) ConnectWith(_ beat.ClientConfig) (beat.Client, error) { return pub.client, nil } diff --git a/metricbeat/mb/module/connector.go b/metricbeat/mb/module/connector.go index e9de37243b1..f2bd16c39a6 100644 --- a/metricbeat/mb/module/connector.go +++ b/metricbeat/mb/module/connector.go @@ -3,14 +3,13 @@ package module import ( "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/bc/publisher" "github.com/elastic/beats/libbeat/publisher/beat" ) // Connector configures ann establishes a beat.Client for publishing events // to the publisher pipeline. type Connector struct { - pipeline publisher.Publisher + pipeline beat.Pipeline processors *processors.Processors eventMeta common.EventMetadata } @@ -20,7 +19,7 @@ type connectorConfig struct { common.EventMetadata `config:",inline"` // Fields and tags to add to events. } -func NewConnector(pipeline publisher.Publisher, c *common.Config) (*Connector, error) { +func NewConnector(pipeline beat.Pipeline, c *common.Config) (*Connector, error) { config := connectorConfig{} if err := c.Unpack(&config); err != nil { return nil, err @@ -39,7 +38,7 @@ func NewConnector(pipeline publisher.Publisher, c *common.Config) (*Connector, e } func (c *Connector) Connect() (beat.Client, error) { - return c.pipeline.ConnectX(beat.ClientConfig{ + return c.pipeline.ConnectWith(beat.ClientConfig{ EventMetadata: c.eventMeta, Processor: c.processors, }) diff --git a/metricbeat/mb/module/factory.go b/metricbeat/mb/module/factory.go index b2123bd79d1..01e541a3ab3 100644 --- a/metricbeat/mb/module/factory.go +++ b/metricbeat/mb/module/factory.go @@ -8,19 +8,19 @@ import ( "github.com/elastic/beats/libbeat/cfgfile" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/cfgwarn" - "github.com/elastic/beats/libbeat/publisher/bc/publisher" + "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/metricbeat/mb" ) // Factory creates new Runner instances from configuration objects. // It is used to register and reload modules. type Factory struct { - pipeline publisher.Publisher + pipeline beat.Pipeline maxStartDelay time.Duration } // NewFactory creates new Reloader instance for the given config -func NewFactory(maxStartDelay time.Duration, p publisher.Publisher) *Factory { +func NewFactory(maxStartDelay time.Duration, p beat.Pipeline) *Factory { return &Factory{ pipeline: p, maxStartDelay: maxStartDelay, diff --git a/packetbeat/beater/packetbeat.go b/packetbeat/beater/packetbeat.go index 797ab398a6d..42669f12c3f 100644 --- a/packetbeat/beater/packetbeat.go +++ b/packetbeat/beater/packetbeat.go @@ -14,7 +14,6 @@ import ( "github.com/elastic/beats/libbeat/common/droppriv" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/bc/publisher" pub "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/libbeat/service" "github.com/elastic/beats/packetbeat/config" @@ -36,7 +35,7 @@ type packetbeat struct { sniff *sniffer.SnifferSetup // publisher/pipeline - pipeline publisher.Publisher + pipeline pub.Pipeline transPub *publish.TransactionPublisher services []interface { @@ -104,6 +103,7 @@ func (pb *packetbeat) init(b *beat.Beat) error { pb.pipeline = b.Publisher pb.transPub, err = publish.NewTransactionPublisher( + b.Info.Name, b.Publisher, pb.config.IgnoreOutgoing, pb.config.Interfaces.File == "", @@ -220,7 +220,7 @@ func (pb *packetbeat) createWorker(dl layers.LinkType) (sniffer.Worker, error) { return nil, err } - client, err := pb.pipeline.ConnectX(pub.ClientConfig{ + client, err := pb.pipeline.ConnectWith(pub.ClientConfig{ EventMetadata: config.Flows.EventMetadata, Processor: processors, }) diff --git a/packetbeat/publish/publish.go b/packetbeat/publish/publish.go index f06aeff7c29..024c5e089b1 100644 --- a/packetbeat/publish/publish.go +++ b/packetbeat/publish/publish.go @@ -6,13 +6,12 @@ import ( "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/bc/publisher" "github.com/elastic/beats/libbeat/publisher/beat" ) type TransactionPublisher struct { done chan struct{} - pipeline publisher.Publisher + pipeline beat.Pipeline canDrop bool processor transProcessor } @@ -26,7 +25,8 @@ type transProcessor struct { var debugf = logp.MakeDebug("publish") func NewTransactionPublisher( - pipeline publisher.Publisher, + name string, + pipeline beat.Pipeline, ignoreOutgoing bool, canDrop bool, ) (*TransactionPublisher, error) { @@ -35,7 +35,6 @@ func NewTransactionPublisher( return nil, err } - name := pipeline.(*publisher.BeatPublisher).GetName() p := &TransactionPublisher{ done: make(chan struct{}), pipeline: pipeline, @@ -79,7 +78,7 @@ func (p *TransactionPublisher) CreateReporter( clientConfig.PublishMode = beat.DropIfFull } - client, err := p.pipeline.ConnectX(clientConfig) + client, err := p.pipeline.ConnectWith(clientConfig) if err != nil { return nil, err } diff --git a/packetbeat/publish/publish_test.go b/packetbeat/publish/publish_test.go index 19fed683089..a91d098aee0 100644 --- a/packetbeat/publish/publish_test.go +++ b/packetbeat/publish/publish_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/bc/publisher" "github.com/elastic/beats/libbeat/publisher/beat" ) @@ -142,11 +141,6 @@ func TestDirectionIn(t *testing.T) { assert.True(t, event.Fields["direction"] == "in") } -func newTestPublisher() *publisher.BeatPublisher { - p := &publisher.BeatPublisher{} - return p -} - func TestNoDirection(t *testing.T) { processor := transProcessor{ localIPs: []string{"192.145.2.6"}, diff --git a/winlogbeat/beater/eventlogger.go b/winlogbeat/beater/eventlogger.go index e68068a88ee..5c53d5f7065 100644 --- a/winlogbeat/beater/eventlogger.go +++ b/winlogbeat/beater/eventlogger.go @@ -6,7 +6,6 @@ import ( "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/bc/publisher" "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/winlogbeat/checkpoint" "github.com/elastic/beats/winlogbeat/eventlog" @@ -44,9 +43,9 @@ func newEventLogger( }, nil } -func (e *eventLogger) connect(pipeline publisher.Publisher) (beat.Client, error) { +func (e *eventLogger) connect(pipeline beat.Pipeline) (beat.Client, error) { api := e.source.Name() - return pipeline.ConnectX(beat.ClientConfig{ + return pipeline.ConnectWith(beat.ClientConfig{ PublishMode: beat.GuaranteedSend, EventMetadata: e.eventMeta, Meta: nil, // TODO: configure modules/ES ingest pipeline? @@ -60,7 +59,7 @@ func (e *eventLogger) connect(pipeline publisher.Publisher) (beat.Client, error) func (e *eventLogger) run( done <-chan struct{}, - pipeline publisher.Publisher, + pipeline beat.Pipeline, state checkpoint.EventLogState, ) { api := e.source diff --git a/winlogbeat/beater/winlogbeat.go b/winlogbeat/beater/winlogbeat.go index 8ab5f7abd06..32c9ba95e08 100644 --- a/winlogbeat/beater/winlogbeat.go +++ b/winlogbeat/beater/winlogbeat.go @@ -14,7 +14,6 @@ import ( "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/paths" - "github.com/elastic/beats/libbeat/publisher/bc/publisher" pub "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/winlogbeat/checkpoint" @@ -40,7 +39,7 @@ type Winlogbeat struct { config *config.Settings // Configuration settings. eventLogs []*eventLogger // List of all event logs being monitored. done chan struct{} // Channel to initiate shutdown of main event loop. - pipeline publisher.Publisher // Interface to publish event. + pipeline pub.Pipeline // Interface to publish event. checkpoint *checkpoint.Checkpoint // Persists event log state to disk. } From 5dec5111e371d72beb038f2ceae1ae8c3f633087 Mon Sep 17 00:00:00 2001 From: Monica Sarbu Date: Mon, 31 Jul 2017 23:24:57 +0300 Subject: [PATCH 023/139] Add more info for each option under setup.template.settings (#4792) * Add more info for each option under setup.template.settings * Fix link --- auditbeat/auditbeat.reference.yml | 15 ++++++++++++--- filebeat/filebeat.reference.yml | 15 ++++++++++++--- heartbeat/heartbeat.reference.yml | 15 ++++++++++++--- libbeat/_meta/config.reference.yml | 15 ++++++++++++--- metricbeat/metricbeat.reference.yml | 15 ++++++++++++--- packetbeat/packetbeat.reference.yml | 15 ++++++++++++--- winlogbeat/winlogbeat.reference.yml | 15 ++++++++++++--- 7 files changed, 84 insertions(+), 21 deletions(-) diff --git a/auditbeat/auditbeat.reference.yml b/auditbeat/auditbeat.reference.yml index ee584fd7add..958d772c80a 100644 --- a/auditbeat/auditbeat.reference.yml +++ b/auditbeat/auditbeat.reference.yml @@ -686,9 +686,18 @@ output.elasticsearch: # Elasticsearch template settings setup.template.settings: - index.number_of_shards: 1 - index.codec: best_compression - #_source.enabled: false + + # A dictionary of settings to place into the settings.index dictionary + # of the Elasticsearch template. For more details, please check + # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html + #index: + #number_of_shards: 1 + #codec: best_compression + + # A dictionary of settings for the _source field. For more details, please check + # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-source-field.html + #_source: + #enabled: false #============================== Kibana ===================================== diff --git a/filebeat/filebeat.reference.yml b/filebeat/filebeat.reference.yml index 23a8cbe7006..20ee62930e2 100644 --- a/filebeat/filebeat.reference.yml +++ b/filebeat/filebeat.reference.yml @@ -1078,9 +1078,18 @@ output.elasticsearch: # Elasticsearch template settings setup.template.settings: - index.number_of_shards: 1 - index.codec: best_compression - #_source.enabled: false + + # A dictionary of settings to place into the settings.index dictionary + # of the Elasticsearch template. For more details, please check + # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html + #index: + #number_of_shards: 1 + #codec: best_compression + + # A dictionary of settings for the _source field. For more details, please check + # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-source-field.html + #_source: + #enabled: false #============================== Kibana ===================================== diff --git a/heartbeat/heartbeat.reference.yml b/heartbeat/heartbeat.reference.yml index 3ee8cc9b94f..ba14c3841bf 100644 --- a/heartbeat/heartbeat.reference.yml +++ b/heartbeat/heartbeat.reference.yml @@ -836,9 +836,18 @@ output.elasticsearch: # Elasticsearch template settings setup.template.settings: - index.number_of_shards: 1 - index.codec: best_compression - #_source.enabled: false + + # A dictionary of settings to place into the settings.index dictionary + # of the Elasticsearch template. For more details, please check + # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html + #index: + #number_of_shards: 1 + #codec: best_compression + + # A dictionary of settings for the _source field. For more details, please check + # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-source-field.html + #_source: + #enabled: false #============================== Kibana ===================================== diff --git a/libbeat/_meta/config.reference.yml b/libbeat/_meta/config.reference.yml index 420a1d6de13..294c3b93039 100644 --- a/libbeat/_meta/config.reference.yml +++ b/libbeat/_meta/config.reference.yml @@ -622,9 +622,18 @@ output.elasticsearch: # Elasticsearch template settings setup.template.settings: - index.number_of_shards: 1 - index.codec: best_compression - #_source.enabled: false + + # A dictionary of settings to place into the settings.index dictionary + # of the Elasticsearch template. For more details, please check + # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html + #index: + #number_of_shards: 1 + #codec: best_compression + + # A dictionary of settings for the _source field. For more details, please check + # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-source-field.html + #_source: + #enabled: false #============================== Kibana ===================================== diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index 9361ab4b73c..5dae6b22064 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -1045,9 +1045,18 @@ output.elasticsearch: # Elasticsearch template settings setup.template.settings: - index.number_of_shards: 1 - index.codec: best_compression - #_source.enabled: false + + # A dictionary of settings to place into the settings.index dictionary + # of the Elasticsearch template. For more details, please check + # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html + #index: + #number_of_shards: 1 + #codec: best_compression + + # A dictionary of settings for the _source field. For more details, please check + # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-source-field.html + #_source: + #enabled: false #============================== Kibana ===================================== diff --git a/packetbeat/packetbeat.reference.yml b/packetbeat/packetbeat.reference.yml index 1a4a4de64fc..f2e44f01ba2 100644 --- a/packetbeat/packetbeat.reference.yml +++ b/packetbeat/packetbeat.reference.yml @@ -1074,9 +1074,18 @@ output.elasticsearch: # Elasticsearch template settings setup.template.settings: - index.number_of_shards: 1 - index.codec: best_compression - #_source.enabled: false + + # A dictionary of settings to place into the settings.index dictionary + # of the Elasticsearch template. For more details, please check + # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html + #index: + #number_of_shards: 1 + #codec: best_compression + + # A dictionary of settings for the _source field. For more details, please check + # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-source-field.html + #_source: + #enabled: false #============================== Kibana ===================================== diff --git a/winlogbeat/winlogbeat.reference.yml b/winlogbeat/winlogbeat.reference.yml index 4b629eb98dd..6c3bfac90cc 100644 --- a/winlogbeat/winlogbeat.reference.yml +++ b/winlogbeat/winlogbeat.reference.yml @@ -651,9 +651,18 @@ output.elasticsearch: # Elasticsearch template settings setup.template.settings: - index.number_of_shards: 1 - index.codec: best_compression - #_source.enabled: false + + # A dictionary of settings to place into the settings.index dictionary + # of the Elasticsearch template. For more details, please check + # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html + #index: + #number_of_shards: 1 + #codec: best_compression + + # A dictionary of settings for the _source field. For more details, please check + # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-source-field.html + #_source: + #enabled: false #============================== Kibana ===================================== From b7dbf033cce81dff47fe7054e5490424bb357018 Mon Sep 17 00:00:00 2001 From: Vijay Samuel Date: Tue, 1 Aug 2017 02:14:46 -0700 Subject: [PATCH 024/139] Fix go plugins not loaded when beat starts (#4799) --- CHANGELOG.asciidoc | 2 +- libbeat/cmd/root.go | 3 +++ libbeat/plugin/cli.go | 8 ++++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 8d52e5b23a9..367dbd48633 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -29,7 +29,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di ==== Bugfixes *Affecting all Beats* - +- Fix go plugins not loaded when beat starts {pull}4799[4799] *Filebeat* - Fix issue where the `fileset.module` could have the wrong value. {issue}4761[4761] diff --git a/libbeat/cmd/root.go b/libbeat/cmd/root.go index 0651f30f3f3..4d23c582c97 100644 --- a/libbeat/cmd/root.go +++ b/libbeat/cmd/root.go @@ -68,6 +68,9 @@ func GenRootCmdWithRunFlags(name, version string, beatCreator beat.Creator, runF rootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.logs")) rootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.home")) rootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("strict.perms")) + if f := flag.CommandLine.Lookup("plugin"); f != nil { + rootCmd.PersistentFlags().AddGoFlag(f) + } // Inherit root flags from run command // TODO deprecate when root command no longer executes run (7.0) diff --git a/libbeat/plugin/cli.go b/libbeat/plugin/cli.go index 5849c48e923..0df4589ef2b 100644 --- a/libbeat/plugin/cli.go +++ b/libbeat/plugin/cli.go @@ -18,8 +18,12 @@ func (p *pluginList) String() string { } func (p *pluginList) Set(v string) error { - // TODO: check file exists - + for _, path := range p.paths { + if path == v { + logp.Warn("%s is already a registered plugin") + return nil + } + } p.paths = append(p.paths, v) return nil } From eb92974e443648e8ff8e500cb42e34f1a830017b Mon Sep 17 00:00:00 2001 From: Vijay Samuel Date: Tue, 1 Aug 2017 02:28:18 -0700 Subject: [PATCH 025/139] Implementing graphite protocol metricbeat module (#4734) (#4770) * Implementing graphite protocol metricbeat module --- CHANGELOG.asciidoc | 1 + metricbeat/_meta/beat.full.yml | 447 ++++++++++++++++++ metricbeat/docs/fields.asciidoc | 6 + metricbeat/docs/modules/http.asciidoc | 15 + metricbeat/docs/modules/http/server.asciidoc | 19 + metricbeat/helper/server/http/config.go | 13 + metricbeat/helper/server/http/http.go | 117 +++++ metricbeat/helper/server/http/http_test.go | 74 +++ metricbeat/include/list.go | 1 + metricbeat/metricbeat.reference.yml | 11 + metricbeat/module/http/_meta/config.yml | 11 + metricbeat/module/http/server/_meta/data.json | 19 + .../module/http/server/_meta/docs.asciidoc | 3 + .../module/http/server/_meta/fields.yml | 5 + metricbeat/module/http/server/config.go | 39 ++ metricbeat/module/http/server/data.go | 96 ++++ metricbeat/module/http/server/data_test.go | 79 ++++ metricbeat/module/http/server/server.go | 72 +++ metricbeat/modules.d/http.yml.disabled | 11 + 19 files changed, 1039 insertions(+) create mode 100644 metricbeat/_meta/beat.full.yml create mode 100644 metricbeat/docs/modules/http/server.asciidoc create mode 100644 metricbeat/helper/server/http/config.go create mode 100644 metricbeat/helper/server/http/http.go create mode 100644 metricbeat/helper/server/http/http_test.go create mode 100644 metricbeat/module/http/server/_meta/data.json create mode 100644 metricbeat/module/http/server/_meta/docs.asciidoc create mode 100644 metricbeat/module/http/server/_meta/fields.yml create mode 100644 metricbeat/module/http/server/config.go create mode 100644 metricbeat/module/http/server/data.go create mode 100644 metricbeat/module/http/server/data_test.go create mode 100644 metricbeat/module/http/server/server.go diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 367dbd48633..4cc56434703 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -56,6 +56,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Add support to exclude labels from kubernetes pod metadata. {pull}4757[4757] - Add graphite protocol metricbeat module. {pull}4734[4734] +- Add http server metricset to support push metrics via http. {pull}4770[4770] *Packetbeat* diff --git a/metricbeat/_meta/beat.full.yml b/metricbeat/_meta/beat.full.yml new file mode 100644 index 00000000000..46b7f45f983 --- /dev/null +++ b/metricbeat/_meta/beat.full.yml @@ -0,0 +1,447 @@ +########################## Metricbeat Configuration ########################### + +# This file is a full configuration example documenting all non-deprecated +# options in comments. For a shorter configuration example, that contains only +# the most common options, please see metricbeat.yml in the same directory. +# +# You can find the full configuration reference here: +# https://www.elastic.co/guide/en/beats/metricbeat/index.html + +#============================ Config Reloading =============================== + +# Config reloading allows to dynamically load modules. Each file which is +# monitored must contain one or multiple modules as a list. +metricbeat.config.modules: + + # Glob pattern for configuration reloading + path: ${path.config}/conf.d/*.yml + + # Period on which files under path should be checked for changes + reload.period: 10s + + # Set to true to enable config reloading + reload.enabled: false + +#========================== Modules configuration ============================ +metricbeat.modules: + +#------------------------------- System Module ------------------------------- +- module: system + metricsets: + # CPU stats + - cpu + + # System Load stats + - load + + # Per CPU core stats + #- core + + # IO stats + #- diskio + + # Per filesystem stats + - filesystem + + # File system summary stats + - fsstat + + # Memory stats + - memory + + # Network stats + - network + + # Processes summary + - process_summary + + # Per process stats + - process + + # Sockets and connection info (linux only) + #- socket + enabled: true + period: 10s + processes: ['.*'] + + # if true, exports the CPU usage in ticks, together with the percentage values + #cpu_ticks: false + + # These options allow you to filter out all processes that are not + # in the top N by CPU or memory, in order to reduce the number of documents created. + # If both the `by_cpu` and `by_memory` options are used, the union of the two sets + # is included. + #process.include_top_n: + # + # Set to false to disable this feature and include all processes + #enabled: true + + # How many processes to include from the top by CPU. The processes are sorted + # by the `system.process.cpu.total.pct` field. + #by_cpu: 0 + + # How many processes to include from the top by memory. The processes are sorted + # by the `system.process.memory.rss.bytes` field. + #by_memory: 0 + + # If false, cmdline of a process is not cached. + #process.cmdline.cache.enabled: true + + # Enable collection of cgroup metrics from processes on Linux. + #process.cgroups.enabled: true + + # A list of regular expressions used to whitelist environment variables + # reported with the process metricset's events. Defaults to empty. + #process.env.whitelist: [] + + # Configure reverse DNS lookup on remote IP addresses in the socket metricset. + #socket.reverse_lookup.enabled: false + #socket.reverse_lookup.success_ttl: 60s + #socket.reverse_lookup.failure_ttl: 60s + +#------------------------------- Apache Module ------------------------------- +- module: apache + metricsets: ["status"] + enabled: false + period: 10s + + # Apache hosts + hosts: ["http://127.0.0.1"] + + # Path to server status. Default server-status + #server_status_path: "server-status" + + # Username of hosts. Empty by default + #username: username + + # Password of hosts. Empty by default + #password: password + +#-------------------------------- Audit Module ------------------------------- +- module: audit + enabled: false + metricsets: ["kernel"] + kernel.resolve_ids: true + kernel.backlog_limit: 8196 + kernel.rate_limit: 0 + kernel.include_raw_message: false + kernel.include_warnings: false + +#-------------------------------- ceph Module -------------------------------- +- module: ceph + metricsets: ["cluster_disk", "cluster_health", "monitor_health", "pool_disk"] + enabled: false + period: 10s + hosts: ["localhost:5000"] + +#------------------------------ Couchbase Module ----------------------------- +- module: couchbase + metricsets: ["bucket", "cluster", "node"] + enabled: false + period: 10s + hosts: ["localhost:8091"] + +#------------------------------- Docker Module ------------------------------- +- module: docker + metricsets: ["container", "cpu", "diskio", "healthcheck", "info", "memory", "network"] + hosts: ["unix:///var/run/docker.sock"] + enabled: false + period: 10s + + # To connect to Docker over TLS you must specify a client and CA certificate. + #ssl: + #certificate_authority: "/etc/pki/root/ca.pem" + #certificate: "/etc/pki/client/cert.pem" + #key: "/etc/pki/client/cert.key" + +#----------------------------- Dropwizard Module ----------------------------- +- module: dropwizard + metricsets: ["collector"] + enabled: false + period: 10s + hosts: ["localhost:8080"] + metrics_path: /metrics/metrics + namespace: example + +#---------------------------- elasticsearch Module --------------------------- +- module: elasticsearch + metricsets: ["node", "node_stats"] + enabled: false + period: 10s + hosts: ["localhost:9200"] + + + +#------------------------------- golang Module ------------------------------- +- module: golang + metricsets: ["expvar","heap"] + enabled: false + period: 10s + hosts: ["localhost:6060"] + heap.path: "/debug/vars" + expvar: + namespace: "example" + path: "/debug/vars" + +#------------------------------- HAProxy Module ------------------------------ +- module: haproxy + metricsets: ["info", "stat"] + enabled: false + period: 10s + hosts: ["tcp://127.0.0.1:14567"] + +#-------------------------------- HTTP Module -------------------------------- +- module: http + metricsets: ["json"] + enabled: false + period: 10s + hosts: ["localhost:80"] + namespace: "json_namespace" + path: "/" + #body: "" + #method: "GET" + #request.enabled: false + #response.enabled: false + +#------------------------------- Jolokia Module ------------------------------ +- module: jolokia + metricsets: ["jmx"] + enabled: false + period: 10s + hosts: ["localhost"] + namespace: "metrics" + path: "/jolokia/?ignoreErrors=true&canonicalNaming=false" + jmx.mapping: + jmx.application: + jmx.instance: + +#-------------------------------- kafka Module ------------------------------- +- module: kafka + metricsets: ["partition"] + enabled: false + period: 10s + hosts: ["localhost:9092"] + + #client_id: metricbeat + #retries: 3 + #backoff: 250ms + + # List of Topics to query metadata for. If empty, all topics will be queried. + #topics: [] + + # Optional SSL. By default is off. + # List of root certificates for HTTPS server verifications + #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] + + # Certificate for SSL client authentication + #ssl.certificate: "/etc/pki/client/cert.pem" + + # Client Certificate Key + #ssl.key: "/etc/pki/client/cert.key" + + # SASL authentication + #username: "" + #password: "" + +#------------------------------- kibana Module ------------------------------- +- module: kibana + metricsets: ["status"] + enabled: false + period: 10s + hosts: ["localhost:5601"] + +#----------------------------- kubernetes Module ----------------------------- +# Node metrics, from kubelet: +- module: kubernetes + enabled: false + metricsets: + - node + - system + - pod + - container + - volume + period: 10s + hosts: ["localhost:10255"] + +# State metrics from kube-state-metrics service: +- module: kubernetes + enabled: false + metricsets: + - state_node + - state_deployment + - state_replicaset + - state_pod + - state_container + period: 10s + hosts: ["kube-state-metrics:8080"] + +# Kubernetes events +- module: kubernetes + metricsets: + - event + kube_config: ${HOME}/.kube/config + in_cluster: false + +#------------------------------ memcached Module ----------------------------- +- module: memcached + metricsets: ["stats"] + enabled: false + period: 10s + hosts: ["localhost:11211"] + + +#------------------------------- MongoDB Module ------------------------------ +- module: mongodb + metricsets: ["dbstats", "status"] + enabled: false + period: 10s + + # The hosts must be passed as MongoDB URLs in the format: + # [mongodb://][user:pass@]host[:port]. + # The username and password can also be set using the respective configuration + # options. The credentials in the URL take precedence over the username and + # password configuration options. + hosts: ["localhost:27017"] + + # Username to use when connecting to MongoDB. Empty by default. + #username: user + + # Password to use when connecting to MongoDB. Empty by default. + #password: pass + +#-------------------------------- MySQL Module ------------------------------- +- module: mysql + metricsets: ["status"] + enabled: false + period: 10s + + # Host DSN should be defined as "user:pass@tcp(127.0.0.1:3306)/" + # The username and password can either be set in the DSN or using the username + # and password config options. Those specified in the DSN take precedence. + hosts: ["root:secret@tcp(127.0.0.1:3306)/"] + + # Username of hosts. Empty by default. + #username: root + + # Password of hosts. Empty by default. + #password: secret + + # By setting raw to true, all raw fields from the status metricset will be added to the event. + #raw: false + +#-------------------------------- Nginx Module ------------------------------- +#- module: nginx + #metricsets: ["stubstatus"] + #enabled: true + #period: 10s + + # Nginx hosts + #hosts: ["http://127.0.0.1"] + + # Path to server status. Default server-status + #server_status_path: "server-status" + +#------------------------------- php_fpm Module ------------------------------ +- module: php_fpm + metricsets: ["pool"] + enabled: false + period: 10s + status_path: "/status" + hosts: ["localhost:8080"] + +#----------------------------- PostgreSQL Module ----------------------------- +- module: postgresql + metricsets: + # Stats about every PostgreSQL database + - database + + # Stats about the background writer process's activity + - bgwriter + + # Stats about every PostgreSQL process + - activity + + enabled: false + period: 10s + + # The host must be passed as PostgreSQL URL. Example: + # postgres://localhost:5432?sslmode=disable + # The available parameters are documented here: + # https://godoc.org/github.com/lib/pq#hdr-Connection_String_Parameters + hosts: ["postgres://localhost:5432"] + + # Username to use when connecting to PostgreSQL. Empty by default. + #username: user + + # Password to use when connecting to PostgreSQL. Empty by default. + #password: pass + + +#----------------------------- Prometheus Module ----------------------------- +- module: prometheus + metricsets: ["stats"] + enabled: false + period: 10s + hosts: ["localhost:9090"] + metrics_path: /metrics + #namespace: example + +#-------------------------------- Redis Module ------------------------------- +- module: redis + metricsets: ["info", "keyspace"] + enabled: false + period: 10s + + # Redis hosts + hosts: ["127.0.0.1:6379"] + + # Timeout after which time a metricset should return an error + # Timeout is by default defined as period, as a fetch of a metricset + # should never take longer then period, as otherwise calls can pile up. + #timeout: 1s + + # Optional fields to be added to each event + #fields: + # datacenter: west + + # Network type to be used for redis connection. Default: tcp + #network: tcp + + # Max number of concurrent connections. Default: 10 + #maxconn: 10 + + # Filters can be used to reduce the number of fields sent. + #filters: + # - include_fields: + # fields: ["stats"] + + # Redis AUTH password. Empty by default. + #password: foobared + +#------------------------------- vsphere Module ------------------------------ +- module: vsphere + metricsets: ["datastore, host, virtualmachine"] + enabled: false + period: 10s + hosts: ["https://localhost/sdk"] + + username: "user" + password: "password" + # If insecure is true, don't verify the server's certificate chain + insecure: false + +#------------------------------- Windows Module ------------------------------ +- module: windows + metricsets: ["perfmon"] + enabled: false + period: 10s + perfmon.counters: + +#------------------------------ ZooKeeper Module ----------------------------- +- module: zookeeper + metricsets: ["mntr"] + enabled: false + period: 10s + hosts: ["localhost:2181"] + + diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index ca75ffbf3f3..278733e95c2 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -3874,6 +3874,12 @@ The HTTP payload received json metricset +[float] +== server fields + +server + + [[exported-fields-jolokia]] == Jolokia fields diff --git a/metricbeat/docs/modules/http.asciidoc b/metricbeat/docs/modules/http.asciidoc index 5c6bef9e3e5..46cd1f66aaa 100644 --- a/metricbeat/docs/modules/http.asciidoc +++ b/metricbeat/docs/modules/http.asciidoc @@ -33,6 +33,17 @@ metricbeat.modules: #method: "GET" #request.enabled: false #response.enabled: false + +- module: http + metricsets: ["server"] + host: "localhost" + port: "8080" + enabled: false +# paths: +# - path: "/foo" +# namespace: "foo" +# fields: # added to the the response in root. overwrites existing fields +# key: "value" ---- [float] @@ -42,5 +53,9 @@ The following metricsets are available: * <> +* <> + include::http/json.asciidoc[] +include::http/server.asciidoc[] + diff --git a/metricbeat/docs/modules/http/server.asciidoc b/metricbeat/docs/modules/http/server.asciidoc new file mode 100644 index 00000000000..995d469120d --- /dev/null +++ b/metricbeat/docs/modules/http/server.asciidoc @@ -0,0 +1,19 @@ +//// +This file is generated! See scripts/docs_collector.py +//// + +[[metricbeat-metricset-http-server]] +include::../../../module/http/server/_meta/docs.asciidoc[] + + +==== Fields + +For a description of each field in the metricset, see the +<> section. + +Here is an example document generated by this metricset: + +[source,json] +---- +include::../../../module/http/server/_meta/data.json[] +---- diff --git a/metricbeat/helper/server/http/config.go b/metricbeat/helper/server/http/config.go new file mode 100644 index 00000000000..115c747aa3e --- /dev/null +++ b/metricbeat/helper/server/http/config.go @@ -0,0 +1,13 @@ +package http + +type HttpConfig struct { + Host string `config:"host"` + Port int `config:"port"` +} + +func defaultHttpConfig() HttpConfig { + return HttpConfig{ + Host: "localhost", + Port: 8080, + } +} diff --git a/metricbeat/helper/server/http/http.go b/metricbeat/helper/server/http/http.go new file mode 100644 index 00000000000..9346d4e473b --- /dev/null +++ b/metricbeat/helper/server/http/http.go @@ -0,0 +1,117 @@ +package http + +import ( + "context" + "fmt" + "io/ioutil" + "net/http" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/metricbeat/helper/server" + "github.com/elastic/beats/metricbeat/mb" +) + +type HttpServer struct { + server *http.Server + ctx context.Context + stop context.CancelFunc + done chan struct{} + eventQueue chan server.Event +} + +type HttpEvent struct { + event common.MapStr + meta server.Meta +} + +func (h *HttpEvent) GetEvent() common.MapStr { + return h.event +} + +func (h *HttpEvent) GetMeta() server.Meta { + return h.meta +} + +func NewHttpServer(mb mb.BaseMetricSet) (server.Server, error) { + config := defaultHttpConfig() + err := mb.Module().UnpackConfig(&config) + if err != nil { + return nil, err + } + + ctx, cancel := context.WithCancel(context.Background()) + h := &HttpServer{ + done: make(chan struct{}), + eventQueue: make(chan server.Event), + ctx: ctx, + stop: cancel, + } + + httpServer := &http.Server{ + Addr: fmt.Sprintf("%s:%d", config.Host, config.Port), + Handler: http.HandlerFunc(h.handleFunc), + } + h.server = httpServer + + return h, nil +} + +func (h *HttpServer) Start() { + go func() { + + logp.Info("Starting http server on %s", h.server.Addr) + err := h.server.ListenAndServe() + if err != nil { + logp.Critical("Unable to start HTTP server due to error: %v", err) + } + }() + +} + +func (h *HttpServer) Stop() { + close(h.done) + h.stop() + h.server.Shutdown(h.ctx) + close(h.eventQueue) +} + +func (h *HttpServer) GetEvents() chan server.Event { + return h.eventQueue +} + +func (h *HttpServer) handleFunc(writer http.ResponseWriter, req *http.Request) { + switch req.Method { + case "POST": + meta := server.Meta{ + "path": req.URL.String(), + } + + contentType := req.Header.Get("Content-Type") + if contentType != "" { + meta["Content-Type"] = contentType + } + + body, err := ioutil.ReadAll(req.Body) + if err != nil { + logp.Err("Error reading body: %v", err) + http.Error(writer, "Unexpected error reading request payload", http.StatusBadRequest) + return + } + + payload := common.MapStr{ + server.EventDataKey: body, + } + + event := &HttpEvent{ + event: payload, + meta: meta, + } + h.eventQueue <- event + writer.WriteHeader(http.StatusAccepted) + + case "GET": + writer.WriteHeader(http.StatusOK) + writer.Write([]byte("HTTP Server accepts data via POST")) + } +} diff --git a/metricbeat/helper/server/http/http_test.go b/metricbeat/helper/server/http/http_test.go new file mode 100644 index 00000000000..15bbfe1b36b --- /dev/null +++ b/metricbeat/helper/server/http/http_test.go @@ -0,0 +1,74 @@ +// +build !integration + +package http + +import ( + "bytes" + "context" + "fmt" + "net/http" + "testing" + "time" + + "github.com/elastic/beats/metricbeat/helper/server" + + "github.com/stretchr/testify/assert" +) + +func GetHttpServer(host string, port int) (server.Server, error) { + ctx, cancel := context.WithCancel(context.Background()) + h := &HttpServer{ + done: make(chan struct{}), + eventQueue: make(chan server.Event, 1), + ctx: ctx, + stop: cancel, + } + + httpServer := &http.Server{ + Addr: fmt.Sprintf("%s:%d", host, port), + Handler: http.HandlerFunc(h.handleFunc), + } + h.server = httpServer + + return h, nil +} + +func TestHttpServer(t *testing.T) { + host := "127.0.0.1" + port := 40050 + svc, err := GetHttpServer(host, port) + if err != nil { + t.Error(err) + t.FailNow() + } + + svc.Start() + defer svc.Stop() + // make sure server is up before writing data into it. + time.Sleep(2 * time.Second) + writeToServer(t, "test1", host, port) + msg := <-svc.GetEvents() + + assert.True(t, msg.GetEvent() != nil) + ok, _ := msg.GetEvent().HasKey("data") + assert.True(t, ok) + bytes, _ := msg.GetEvent()["data"].([]byte) + assert.True(t, string(bytes) == "test1") + +} + +func writeToServer(t *testing.T, message, host string, port int) { + url := fmt.Sprintf("http://%s:%d/", host, port) + var str = []byte(message) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(str)) + req.Header.Set("Content-Type", "text/plain") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + t.Error(err) + t.FailNow() + } + defer resp.Body.Close() + +} diff --git a/metricbeat/include/list.go b/metricbeat/include/list.go index 1d02db49827..fa77791b829 100644 --- a/metricbeat/include/list.go +++ b/metricbeat/include/list.go @@ -45,6 +45,7 @@ import ( _ "github.com/elastic/beats/metricbeat/module/haproxy/stat" _ "github.com/elastic/beats/metricbeat/module/http" _ "github.com/elastic/beats/metricbeat/module/http/json" + _ "github.com/elastic/beats/metricbeat/module/http/server" _ "github.com/elastic/beats/metricbeat/module/jolokia" _ "github.com/elastic/beats/metricbeat/module/jolokia/jmx" _ "github.com/elastic/beats/metricbeat/module/kafka" diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index 5dae6b22064..ef8404cba83 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -185,6 +185,17 @@ metricbeat.modules: #request.enabled: false #response.enabled: false +- module: http + metricsets: ["server"] + host: "localhost" + port: "8080" + enabled: false +# paths: +# - path: "/foo" +# namespace: "foo" +# fields: # added to the the response in root. overwrites existing fields +# key: "value" + #------------------------------- Jolokia Module ------------------------------ - module: jolokia metricsets: ["jmx"] diff --git a/metricbeat/module/http/_meta/config.yml b/metricbeat/module/http/_meta/config.yml index aa40cfb7cc1..32be789a932 100644 --- a/metricbeat/module/http/_meta/config.yml +++ b/metricbeat/module/http/_meta/config.yml @@ -8,3 +8,14 @@ #method: "GET" #request.enabled: false #response.enabled: false + +- module: http + metricsets: ["server"] + host: "localhost" + port: "8080" + enabled: false +# paths: +# - path: "/foo" +# namespace: "foo" +# fields: # added to the the response in root. overwrites existing fields +# key: "value" diff --git a/metricbeat/module/http/server/_meta/data.json b/metricbeat/module/http/server/_meta/data.json new file mode 100644 index 00000000000..26af4a231cf --- /dev/null +++ b/metricbeat/module/http/server/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"http", + "name":"server", + "rtt":44269 + }, + "http":{ + "server":{ + "test_metric": 5, + } + }, + "type":"metricsets" +} diff --git a/metricbeat/module/http/server/_meta/docs.asciidoc b/metricbeat/module/http/server/_meta/docs.asciidoc new file mode 100644 index 00000000000..5656331c2ca --- /dev/null +++ b/metricbeat/module/http/server/_meta/docs.asciidoc @@ -0,0 +1,3 @@ +=== http server MetricSet + +This is the server metricset of the module http. diff --git a/metricbeat/module/http/server/_meta/fields.yml b/metricbeat/module/http/server/_meta/fields.yml new file mode 100644 index 00000000000..43c3f8aa322 --- /dev/null +++ b/metricbeat/module/http/server/_meta/fields.yml @@ -0,0 +1,5 @@ +- name: server + type: group + description: > + server + fields: diff --git a/metricbeat/module/http/server/config.go b/metricbeat/module/http/server/config.go new file mode 100644 index 00000000000..2a7d9355dc4 --- /dev/null +++ b/metricbeat/module/http/server/config.go @@ -0,0 +1,39 @@ +package server + +import ( + "errors" + + "github.com/elastic/beats/libbeat/common" +) + +type httpServerConfig struct { + Paths []pathConfig `config:"paths"` + DefaultPath pathConfig `config:"default_path"` +} + +type pathConfig struct { + Path string `config:"path"` + Fields common.MapStr `config:"fields"` + Namespace string `config:"namespace"` +} + +func defaultHttpServerConfig() httpServerConfig { + return httpServerConfig{ + DefaultPath: pathConfig{ + Path: "/", + Namespace: "http", + }, + } +} + +func (p pathConfig) Validate() error { + if p.Namespace == "" { + return errors.New("`namespace` can not be empty in path configuration") + } + + if p.Path == "" { + return errors.New("`path` can not be empty in path configuration") + } + + return nil +} diff --git a/metricbeat/module/http/server/data.go b/metricbeat/module/http/server/data.go new file mode 100644 index 00000000000..22057248326 --- /dev/null +++ b/metricbeat/module/http/server/data.go @@ -0,0 +1,96 @@ +package server + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + "sync" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/metricbeat/helper/server" + "github.com/elastic/beats/metricbeat/mb" +) + +type metricProcessor struct { + paths map[string]pathConfig + defaultPath pathConfig + sync.RWMutex +} + +func NewMetricProcessor(paths []pathConfig, defaultPath pathConfig) *metricProcessor { + pathMap := map[string]pathConfig{} + for _, path := range paths { + pathMap[path.Path] = path + } + + return &metricProcessor{ + paths: pathMap, + defaultPath: defaultPath, + } +} + +func (m *metricProcessor) AddPath(path pathConfig) { + m.Lock() + m.paths[path.Path] = path + m.Unlock() +} + +func (m *metricProcessor) RemovePath(path pathConfig) { + m.Lock() + delete(m.paths, path.Path) + m.Unlock() +} + +func (p *metricProcessor) Process(event server.Event) (common.MapStr, error) { + urlRaw, ok := event.GetMeta()["path"] + if !ok { + return nil, errors.New("Malformed HTTP event. Path missing.") + } + url, _ := urlRaw.(string) + + typeRaw, ok := event.GetMeta()["Content-Type"] + if !ok { + return nil, errors.New("Unable to get Content-Type of request") + } + contentType := typeRaw.(string) + pathConf := p.findPath(url) + + bytesRaw, ok := event.GetEvent()[server.EventDataKey] + if !ok { + return nil, errors.New("Unable to retrieve response bytes") + } + + bytes, _ := bytesRaw.([]byte) + if len(bytes) == 0 { + return nil, errors.New("Request has no data") + } + + out := common.MapStr{} + switch contentType { + case "application/json": + err := json.Unmarshal(bytes, &out) + if err != nil { + return nil, err + } + default: + return nil, errors.New(fmt.Sprintf("Unsupported Content-Type: %s", contentType)) + } + + out[mb.NamespaceKey] = pathConf.Namespace + if len(pathConf.Fields) != 0 { + // Overwrite any keys that are present in the incoming payload + common.MergeFields(out, pathConf.Fields, true) + } + return out, nil +} + +func (p *metricProcessor) findPath(url string) *pathConfig { + for path, conf := range p.paths { + if strings.Index(url, path) == 0 { + return &conf + } + } + + return &p.defaultPath +} diff --git a/metricbeat/module/http/server/data_test.go b/metricbeat/module/http/server/data_test.go new file mode 100644 index 00000000000..cbd0a58d7c1 --- /dev/null +++ b/metricbeat/module/http/server/data_test.go @@ -0,0 +1,79 @@ +package server + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/libbeat/common" +) + +func GetMetricProcessor() *metricProcessor { + paths := []pathConfig{ + { + Namespace: "foo", + Path: "/foo", + Fields: common.MapStr{ + "a": "b", + }, + }, + { + Namespace: "bar", + Path: "/bar", + }, + } + + defaultPath := defaultHttpServerConfig().DefaultPath + return NewMetricProcessor(paths, defaultPath) +} + +func TestMetricProcessorAddPath(t *testing.T) { + processor := GetMetricProcessor() + temp := pathConfig{ + Namespace: "xyz", + Path: "/abc", + } + processor.AddPath(temp) + out, _ := processor.paths[temp.Path] + assert.NotNil(t, out) + assert.Equal(t, out.Namespace, temp.Namespace) +} + +func TestMetricProcessorDeletePath(t *testing.T) { + processor := GetMetricProcessor() + processor.RemovePath(processor.paths["bar"]) + _, ok := processor.paths["bar"] + assert.Equal(t, ok, false) +} + +func TestFindPath(t *testing.T) { + processor := GetMetricProcessor() + tests := []struct { + a string + expected pathConfig + }{ + { + a: "/foo/bar", + expected: processor.paths["/foo"], + }, + { + a: "/", + expected: processor.defaultPath, + }, + { + a: "/abc", + expected: processor.defaultPath, + }, + } + + for i, test := range tests { + a, expected := test.a, test.expected + name := fmt.Sprintf("%v: %v = %v", i, a, expected) + + t.Run(name, func(t *testing.T) { + b := processor.findPath(a) + assert.Equal(t, expected, *b) + }) + } +} diff --git a/metricbeat/module/http/server/server.go b/metricbeat/module/http/server/server.go new file mode 100644 index 00000000000..562908d484a --- /dev/null +++ b/metricbeat/module/http/server/server.go @@ -0,0 +1,72 @@ +package server + +import ( + "github.com/elastic/beats/libbeat/common/cfgwarn" + serverhelper "github.com/elastic/beats/metricbeat/helper/server" + "github.com/elastic/beats/metricbeat/helper/server/http" + "github.com/elastic/beats/metricbeat/mb" +) + +// init registers the MetricSet with the central registry. +// The New method will be called after the setup of the module and before starting to fetch data +func init() { + if err := mb.Registry.AddMetricSet("http", "server", New); err != nil { + panic(err) + } +} + +// MetricSet type defines all fields of the MetricSet +// As a minimum it must inherit the mb.BaseMetricSet fields, but can be extended with +// additional entries. These variables can be used to persist data or configuration between +// multiple fetch calls. +type MetricSet struct { + mb.BaseMetricSet + server serverhelper.Server + processor *metricProcessor +} + +// New create a new instance of the MetricSet +// Part of new is also setting up the configuration by processing additional +// configuration entries if needed. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Experimental("EXPERIMENTAL: The http server metricset is experimental") + + config := defaultHttpServerConfig() + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + + svc, err := http.NewHttpServer(base) + if err != nil { + return nil, err + } + + processor := NewMetricProcessor(config.Paths, config.DefaultPath) + return &MetricSet{ + BaseMetricSet: base, + server: svc, + processor: processor, + }, nil +} + +// Run method provides the Graphite server with a reporter with which events can be reported. +func (m *MetricSet) Run(reporter mb.PushReporter) { + // Start event watcher + m.server.Start() + + for { + select { + case <-reporter.Done(): + m.server.Stop() + return + case msg := <-m.server.GetEvents(): + event, err := m.processor.Process(msg) + if err != nil { + reporter.Error(err) + } else { + reporter.Event(event) + } + + } + } +} diff --git a/metricbeat/modules.d/http.yml.disabled b/metricbeat/modules.d/http.yml.disabled index aa40cfb7cc1..32be789a932 100644 --- a/metricbeat/modules.d/http.yml.disabled +++ b/metricbeat/modules.d/http.yml.disabled @@ -8,3 +8,14 @@ #method: "GET" #request.enabled: false #response.enabled: false + +- module: http + metricsets: ["server"] + host: "localhost" + port: "8080" + enabled: false +# paths: +# - path: "/foo" +# namespace: "foo" +# fields: # added to the the response in root. overwrites existing fields +# key: "value" From 07170c66b8aeb4e3d265dcc006507be0ff3cf41b Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Tue, 1 Aug 2017 10:48:11 -0400 Subject: [PATCH 026/139] Enhancements to auditbeat file metricset (#4796) Modify `file.paths` to be a list instead of a dictionary. Added `file.hash_types` config option for controlling the hash types. Added new hash types. Fixed `file.max_file_size` config option. It was missing the "file." prefix when reading the option. Added the ability to specify byte unit suffixes to `file.max_file_size`. Added documentation for the audit file metricset. --- CHANGELOG.asciidoc | 14 ++++ auditbeat/auditbeat.reference.yml | 23 ++--- auditbeat/auditbeat.yml | 12 ++- .../docs/auditbeat-modules-config.asciidoc | 12 ++- auditbeat/docs/getting-started.asciidoc | 12 ++- auditbeat/docs/modules/audit.asciidoc | 12 ++- auditbeat/module/audit/_meta/config.yml.tpl | 46 +++++----- auditbeat/module/audit/file/_meta/data.json | 62 +++++++------- .../module/audit/file/_meta/docs.asciidoc | 61 ++++++++++---- auditbeat/module/audit/file/config.go | 42 ++++++++++ auditbeat/module/audit/file/config_test.go | 46 ++++++++++ auditbeat/module/audit/file/event.go | 83 +++++++++++++------ .../module/audit/file/eventreader_fsnotify.go | 20 ++--- auditbeat/module/audit/file/metricset.go | 9 -- auditbeat/module/audit/file/metricset_test.go | 32 +++++-- .../module/audit/kernel/_meta/docs.asciidoc | 22 ++--- 16 files changed, 335 insertions(+), 173 deletions(-) create mode 100644 auditbeat/module/audit/file/config.go create mode 100644 auditbeat/module/audit/file/config_test.go diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 4cc56434703..aaf69a8550e 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -16,6 +16,10 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - The log directory (`path.log`) for Windows services is now set to `C:\ProgramData\[beatname]\logs`. {issue}4764[4764] +*Auditbeat* + +- Changed file metricset config to make `file.paths` a list instead of a dictionary. {pull}4796[4796] + *Filebeat* *Heartbeat* @@ -30,6 +34,11 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Affecting all Beats* - Fix go plugins not loaded when beat starts {pull}4799[4799] + +*Auditbeat* + +- Fix `file.max_file_size` config option for the audit file metricset. {pull}4796[4796] + *Filebeat* - Fix issue where the `fileset.module` could have the wrong value. {issue}4761[4761] @@ -48,6 +57,11 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Affecting all Beats* +*Auditbeat* + +- Added `file.hash_types` config option for controlling the hash types. {pull}4796[4796] +- Added the ability to specify byte unit suffixes to `file.max_file_size`. {pull}4796[4796] + *Filebeat* *Heartbeat* diff --git a/auditbeat/auditbeat.reference.yml b/auditbeat/auditbeat.reference.yml index 958d772c80a..ef9441b418a 100644 --- a/auditbeat/auditbeat.reference.yml +++ b/auditbeat/auditbeat.reference.yml @@ -46,21 +46,22 @@ auditbeat.modules: #-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -k access # The file integrity metricset sends events when files are changed (created, -# updated, deleted). The events contain file metadata and hashes (MD5, SHA1, and -# SHA256). +# updated, deleted). The events contain file metadata and hashes. - module: audit metricsets: [file] file.paths: - binaries: - - /bin - - /usr/bin - - /sbin - - /usr/sbin - conf: - - /etc + - /bin + - /usr/bin + - /sbin + - /usr/sbin + - /etc - # Limit in bytes on the size of files that will be hashed. - file.max_file_size: 1073741824 # 1 GiB + # Limit on the size of files that will be hashed. Default is 100 MiB. + file.max_file_size: 100 MiB + + # Hash types to compute when the file changes. Supported types are md5, sha1, + # sha224, sha256, sha384, sha512, sha512_224, and sha512_256. Default is sha1. + file.hash_types: [sha1] #================================ General ====================================== diff --git a/auditbeat/auditbeat.yml b/auditbeat/auditbeat.yml index 9fa11f48ba5..35fd3d040ee 100644 --- a/auditbeat/auditbeat.yml +++ b/auditbeat/auditbeat.yml @@ -21,13 +21,11 @@ auditbeat.modules: - module: audit metricsets: [file] file.paths: - binaries: - - /bin - - /usr/bin - - /sbin - - /usr/sbin - conf: - - /etc + - /bin + - /usr/bin + - /sbin + - /usr/sbin + - /etc diff --git a/auditbeat/docs/auditbeat-modules-config.asciidoc b/auditbeat/docs/auditbeat-modules-config.asciidoc index cdec30f6114..d0d81ae32dc 100644 --- a/auditbeat/docs/auditbeat-modules-config.asciidoc +++ b/auditbeat/docs/auditbeat-modules-config.asciidoc @@ -21,13 +21,11 @@ auditbeat.modules: - module: audit metricsets: [file] file.paths: - binaries: - - /bin - - /usr/bin - - /sbin - - /usr/sbin - conf: - - /etc + - /bin + - /usr/bin + - /sbin + - /usr/sbin + - /etc ---- The configuration details vary by module. See the diff --git a/auditbeat/docs/getting-started.asciidoc b/auditbeat/docs/getting-started.asciidoc index 72ec51d8906..9074b9e9518 100644 --- a/auditbeat/docs/getting-started.asciidoc +++ b/auditbeat/docs/getting-started.asciidoc @@ -152,13 +152,11 @@ auditbeat.modules: - module: audit metricsets: [file] file.paths: - binaries: - - /bin - - /usr/bin - - /sbin - - /usr/sbin - conf: - - /etc + - /bin + - /usr/bin + - /sbin + - /usr/sbin + - /etc ------------------------------------- + If you accept the default configuration without specifying additional modules, diff --git a/auditbeat/docs/modules/audit.asciidoc b/auditbeat/docs/modules/audit.asciidoc index 33fc6e11d20..1ea09d4fa6a 100644 --- a/auditbeat/docs/modules/audit.asciidoc +++ b/auditbeat/docs/modules/audit.asciidoc @@ -32,13 +32,11 @@ auditbeat.modules: - module: audit metricsets: [file] file.paths: - binaries: - - /bin - - /usr/bin - - /sbin - - /usr/sbin - conf: - - /etc + - /bin + - /usr/bin + - /sbin + - /usr/sbin + - /etc ---- diff --git a/auditbeat/module/audit/_meta/config.yml.tpl b/auditbeat/module/audit/_meta/config.yml.tpl index 0459a8f8dfd..1753ddee824 100644 --- a/auditbeat/module/audit/_meta/config.yml.tpl +++ b/auditbeat/module/audit/_meta/config.yml.tpl @@ -23,39 +23,37 @@ {{ if .reference -}} # The file integrity metricset sends events when files are changed (created, -# updated, deleted). The events contain file metadata and hashes (MD5, SHA1, and -# SHA256). +# updated, deleted). The events contain file metadata and hashes. {{ end -}} - module: audit metricsets: [file] {{ if eq .goos "darwin" -}} file.paths: - binaries: - - /bin - - /usr/bin - - /usr/local/bin - - /sbin - - /usr/sbin - - /usr/local/sbin + - /bin + - /usr/bin + - /usr/local/bin + - /sbin + - /usr/sbin + - /usr/local/sbin {{ else if eq .goos "windows" -}} file.paths: - windows: - - C:/windows - - C:/windows/system32 - programs: - - C:/Program Files - - C:/Program Files (x86) + - C:/windows + - C:/windows/system32 + - C:/Program Files + - C:/Program Files (x86) {{ else -}} file.paths: - binaries: - - /bin - - /usr/bin - - /sbin - - /usr/sbin - conf: - - /etc + - /bin + - /usr/bin + - /sbin + - /usr/sbin + - /etc {{ end -}} {{ if .reference }} - # Limit in bytes on the size of files that will be hashed. - file.max_file_size: 1073741824 # 1 GiB + # Limit on the size of files that will be hashed. Default is 100 MiB. + file.max_file_size: 100 MiB + + # Hash types to compute when the file changes. Supported types are md5, sha1, + # sha224, sha256, sha384, sha512, sha512_224, and sha512_256. Default is sha1. + file.hash_types: [sha1] {{- end }} diff --git a/auditbeat/module/audit/file/_meta/data.json b/auditbeat/module/audit/file/_meta/data.json index 670ce721274..78946a6fbb9 100644 --- a/auditbeat/module/audit/file/_meta/data.json +++ b/auditbeat/module/audit/file/_meta/data.json @@ -1,33 +1,35 @@ { - "@timestamp": "2017-07-10T18:13:08.197Z", - "audit": { - "file": { - "action": "created", - "atime": "2017-07-10T18:13:08Z", - "ctime": "2017-07-10T18:13:08Z", - "gid": 20, - "group": "staff", - "hashed": true, - "inode": "11706872", - "md5": "5eb63bbbe01eeed093cb22bb8f5acdc3", - "mode": "0600", - "mtime": "2017-07-10T18:13:08Z", - "owner": "akroh", - "path": "/var/folders/8x/rnyk6yxn6w97lddn3bs02gf00000gn/T/audit-file232876074/file.data", - "sha1": "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed", - "sha256": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9", - "size": 11, - "type": "file", - "uid": 501 - } - }, - "beat": { - "hostname": "host.example.com", - "name": "host.example.com" - }, - "metricset": { - "module": "audit", - "name": "file", - "rtt": 115 + "@timestamp": "2017-07-31T14:40:28.173Z", + "@metadata": { + "beat": "noindex", + "type": "doc" + }, + "audit": { + "file": { + "hashed": true, + "group": "staff", + "path": "/var/folders/8x/rnyk6yxn6w97lddn3bs02gf00000gn/T/audit-file927187403/file.data", + "inode": "12512120", + "size": 11, + "ctime": "2017-07-31T14:40:28.000Z", + "mode": "0600", + "owner": "akroh", + "atime": "2017-07-31T14:40:28.000Z", + "sha1": "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed", + "action": "created", + "mtime": "2017-07-31T14:40:28.000Z", + "type": "file", + "uid": 501, + "gid": 20 } + }, + "metricset": { + "module": "audit", + "name": "file", + "rtt": 115 + }, + "beat": { + "name": "host.example.com", + "hostname": "host.example.com" + } } \ No newline at end of file diff --git a/auditbeat/module/audit/file/_meta/docs.asciidoc b/auditbeat/module/audit/file/_meta/docs.asciidoc index 5b21d1b8eed..0591f5717f3 100644 --- a/auditbeat/module/audit/file/_meta/docs.asciidoc +++ b/auditbeat/module/audit/file/_meta/docs.asciidoc @@ -1,36 +1,67 @@ === Audit file metricset The `file` metricset sends events when a file is changed (created, updated, or -deleted) on disk. The events contain file metadata and hashes (MD5, SHA1, and -SHA256). +deleted) on disk. The events contain file metadata and hashes. + +The metricset is implemented for Linux, macOS (Darwin), and Windows. -//// [float] === How it works -This metricset... -//// +This metricset uses features of the operating system to monitor file changes in +realtime. When the metricset starts it creates a subscription with the OS to +receive notifications of changes to the specified files or directories. Upon +receiving notification of a change the metricset will read the file's metadata +and the compute a hash of the file's contents. + +This metricset does not perform an initial scan of the given paths to generate +events for the files as they existed at start time. It is strictly driven by +change notifications from the OS. + +The operating system features that power this feature are as follows. + +* Linux - `inotify` is used, and therefore the kernel must have inotify support. +Inotify was initially merged into the 2.6.13 Linux kernel. +* macOS (Darwin) - `kqueue` is used. It requires one file descriptor for each +file so please check the `ulimit` values used with {beatname_uc}. The FSEvents +API was considered for the implementation, but FSEvents coalesces multiple +notifications into a single event which is inconsistent with the metricset's +behavior on other operating systems. +* Windows - `ReadDirectoryChangesW` is used. + +The file metricset should not be used to monitor paths on network file systems. [float] === Configuration options This metricset has some configuration options for tuning its behavior. The -following example shows all configuration options with their default values. +following example shows all configuration options with their default values for +Linux. [source,yaml] ---- - module: audit metricsets: [file] file.paths: - binaries: - - /bin - - /usr/bin - - /sbin - - /usr/sbin - conf: - - /etc + - /bin + - /usr/bin + - /sbin + - /usr/sbin + - /etc + file.max_file_size: 100 MiB + file.hash_types: [sha1] ---- +*`file.paths`*:: A list of paths (directories or files) to watch. The watches +are non-recursive and globs are not supported. The specified paths should exist +when the metricset is started. + +*`file.max_file_size`*:: The maximum size of a file in bytes for which +{beatname_uc} will compute hashes. Files larger than this size will not be +hashed. The default value is 100 MiB. For convenience units can be specified as +a suffix to the value. The supported units are `b`, `kib`, `kb`, `mib`, `mb`, +`gib`, `gb`, `tib`, `tb`, `pib`, `pb`, `eib`, and `eb`. -*`file.paths`*:: A dictionary of arbitrary names (strings) to a list of paths -(directories or files). +*`file.hash_types`*:: A list of hash types to compute when the file changes. +The supported hash types are md5, sha1, sha224, sha256, sha384, sha512, +sha512_224, and sha512_256. The default value is sha1. diff --git a/auditbeat/module/audit/file/config.go b/auditbeat/module/audit/file/config.go new file mode 100644 index 00000000000..895434c1113 --- /dev/null +++ b/auditbeat/module/audit/file/config.go @@ -0,0 +1,42 @@ +package file + +import ( + "strings" + + "github.com/dustin/go-humanize" + "github.com/joeshaw/multierror" + "github.com/pkg/errors" +) + +type Config struct { + Paths []string `config:"file.paths" validate:"required"` + HashTypes []string `config:"file.hash_types"` + MaxFileSize string `config:"file.max_file_size"` + MaxFileSizeBytes uint64 `config:",ignore"` +} + +func (c *Config) Validate() error { + var errs multierror.Errors + var err error + + c.MaxFileSizeBytes, err = humanize.ParseBytes(c.MaxFileSize) + if err != nil { + errs = append(errs, errors.Wrap(err, "invalid file.max_file_size value")) + } + + for _, ht := range c.HashTypes { + switch strings.ToLower(ht) { + case "md5", "sha1", "sha224", "sha256", "sha384", "sha512", "sha512_224", "sha512_256": + default: + errs = append(errs, errors.Errorf("invalid hash type '%v'", ht)) + } + } + + return errs.Err() +} + +var defaultConfig = Config{ + MaxFileSize: "100 MiB", + MaxFileSizeBytes: 100 * 1024 * 1024, + HashTypes: []string{"sha1"}, +} diff --git a/auditbeat/module/audit/file/config_test.go b/auditbeat/module/audit/file/config_test.go new file mode 100644 index 00000000000..74f9600da31 --- /dev/null +++ b/auditbeat/module/audit/file/config_test.go @@ -0,0 +1,46 @@ +package file + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/libbeat/common" +) + +func TestConfig(t *testing.T) { + config, err := common.NewConfigFrom(map[string]interface{}{ + "file.paths": []string{"/usr/bin"}, + "file.hash_types": []string{"md5", "sha256"}, + "file.max_file_size": "1 GiB", + }) + if err != nil { + t.Fatal(err) + } + + c := defaultConfig + if err := config.Unpack(&c); err != nil { + t.Fatal(err) + } + + assert.Equal(t, []string{"md5", "sha256"}, c.HashTypes) + assert.EqualValues(t, 1024*1024*1024, c.MaxFileSizeBytes) +} + +func TestInvalidConfig(t *testing.T) { + config, err := common.NewConfigFrom(map[string]interface{}{ + "file.hash_types": []string{"crc32", "sha256"}, + "file.max_file_size": "32 Hz", + }) + if err != nil { + t.Fatal(err) + } + + c := defaultConfig + if err := config.Unpack(&c); err != nil { + assert.Error(t, err) + return + } + + t.Fatal("expected error") +} diff --git a/auditbeat/module/audit/file/event.go b/auditbeat/module/audit/file/event.go index c4abb92fc62..42093a7f159 100644 --- a/auditbeat/module/audit/file/event.go +++ b/auditbeat/module/audit/file/event.go @@ -4,8 +4,10 @@ import ( "crypto/md5" "crypto/sha1" "crypto/sha256" + "crypto/sha512" "encoding/hex" "fmt" + "hash" "io" "os" "runtime" @@ -47,15 +49,12 @@ var actionNames = map[Action]string{ // Event describe the filesystem change and includes metadata about the file. type Event struct { - Timestamp time.Time // Time of event. - Path string // The path associated with the event. - TargetPath string // Target path for symlinks. - Action string // Action (like created, updated). - Info *Metadata // File metadata (if the file exists). - Hashed bool // True if hashed. - MD5 string - SHA1 string - SHA256 string + Timestamp time.Time // Time of event. + Path string // The path associated with the event. + TargetPath string // Target path for symlinks. + Action string // Action (like created, updated). + Info *Metadata // File metadata (if the file exists). + Hashes map[string]string // File hashes. errors []error } @@ -81,7 +80,7 @@ func buildMapStr(e *Event) common.MapStr { "@timestamp": e.Timestamp, "path": e.Path, "action": e.Action, - "hashed": e.Hashed, + "hashed": len(e.Hashes) > 0, } if e.TargetPath != "" { @@ -118,33 +117,65 @@ func buildMapStr(e *Event) common.MapStr { } } - if e.Hashed { - m["md5"] = e.MD5 - m["sha1"] = e.SHA1 - m["sha256"] = e.SHA256 + for name, hash := range e.Hashes { + m[name] = hash } return m } -func hashFile(name string) (md5sum, sha1sum, sha256sum string, err error) { +func hashFile(name string, hashType ...string) (map[string]string, error) { + if len(hashType) == 0 { + return nil, nil + } + + var hashes []hash.Hash + for _, name := range hashType { + switch name { + case "md5": + hashes = append(hashes, md5.New()) + case "sha1": + hashes = append(hashes, sha1.New()) + case "sha224": + hashes = append(hashes, sha256.New224()) + case "sha256": + hashes = append(hashes, sha256.New()) + case "sha384": + hashes = append(hashes, sha512.New384()) + case "sha512": + hashes = append(hashes, sha512.New()) + case "sha512_224": + hashes = append(hashes, sha512.New512_224()) + case "sha512_256": + hashes = append(hashes, sha512.New512_256()) + default: + return nil, errors.Errorf("unknown hash type '%v'", name) + } + } + f, err := os.Open(name) if err != nil { - return "", "", "", errors.Wrap(err, "failed to open file for hashing") + return nil, errors.Wrap(err, "failed to open file for hashing") } defer f.Close() - m5 := md5.New() - s1 := sha1.New() - s256 := sha256.New() - - hashWriter := io.MultiWriter(m5, s1, s256) + hashWriter := multiWriter(hashes) if _, err := io.Copy(hashWriter, f); err != nil { - return "", "", "", errors.Wrap(err, "failed to calculate file hashes") + return nil, errors.Wrap(err, "failed to calculate file hashes") } - return hex.EncodeToString(m5.Sum(nil)), - hex.EncodeToString(s1.Sum(nil)), - hex.EncodeToString(s256.Sum(nil)), - nil + nameToHash := make(map[string]string, len(hashes)) + for i, h := range hashes { + nameToHash[hashType[i]] = hex.EncodeToString(h.Sum(nil)) + } + + return nameToHash, nil +} + +func multiWriter(hash []hash.Hash) io.Writer { + writers := make([]io.Writer, 0, len(hash)) + for _, h := range hash { + writers = append(writers, h) + } + return io.MultiWriter(writers...) } diff --git a/auditbeat/module/audit/file/eventreader_fsnotify.go b/auditbeat/module/audit/file/eventreader_fsnotify.go index ccf92bb82c8..d0fec988730 100644 --- a/auditbeat/module/audit/file/eventreader_fsnotify.go +++ b/auditbeat/module/audit/file/eventreader_fsnotify.go @@ -30,12 +30,7 @@ type reader struct { } func (r *reader) Start(done <-chan struct{}) (<-chan Event, error) { - var paths []string - for _, filePaths := range r.config.Paths { - paths = append(paths, filePaths...) - } - - for _, p := range paths { + for _, p := range r.config.Paths { if err := r.watcher.Add(p); err != nil { if err == syscall.EMFILE { logp.Warn("%v Failed to watch %v: %v (check the max number of "+ @@ -56,7 +51,7 @@ func (r *reader) Start(done <-chan struct{}) (<-chan Event, error) { if event.Name == "" { continue } - r.outC <- convertToFileEvent(event, r.config.MaxFileSize) + r.outC <- convertToFileEvent(event, r.config.MaxFileSizeBytes, r.config.HashTypes) case err := <-r.watcher.Errors: r.errC <- err } @@ -66,7 +61,7 @@ func (r *reader) Start(done <-chan struct{}) (<-chan Event, error) { return r.outC, nil } -func convertToFileEvent(e fsnotify.Event, maxFileSize int64) Event { +func convertToFileEvent(e fsnotify.Event, maxFileSize uint64, hashTypes []string) Event { event := Event{ Timestamp: time.Now().UTC(), Path: e.Name, @@ -84,15 +79,12 @@ func convertToFileEvent(e fsnotify.Event, maxFileSize int64) Event { switch event.Info.Type { case "file": - if event.Info.Size <= maxFileSize { - md5sum, sha1sum, sha256sum, err := hashFile(event.Path) + if uint64(event.Info.Size) <= maxFileSize { + hashes, err := hashFile(event.Path, hashTypes...) if err != nil { event.errors = append(event.errors, err) } else { - event.MD5 = md5sum - event.SHA1 = sha1sum - event.SHA256 = sha256sum - event.Hashed = true + event.Hashes = hashes } } case "symlink": diff --git a/auditbeat/module/audit/file/metricset.go b/auditbeat/module/audit/file/metricset.go index 67cf3b3d4f3..27a3e827096 100644 --- a/auditbeat/module/audit/file/metricset.go +++ b/auditbeat/module/audit/file/metricset.go @@ -26,15 +26,6 @@ func init() { } } -type Config struct { - Paths map[string][]string `config:"file.paths"` - MaxFileSize int64 `config:"max_file_size"` -} - -var defaultConfig = Config{ - MaxFileSize: 1 << 30, // 1 Gibibyte -} - type EventReader interface { Start(done <-chan struct{}) (<-chan Event, error) } diff --git a/auditbeat/module/audit/file/metricset_test.go b/auditbeat/module/audit/file/metricset_test.go index 96b42e44467..82c6a4263ac 100644 --- a/auditbeat/module/audit/file/metricset_test.go +++ b/auditbeat/module/audit/file/metricset_test.go @@ -47,9 +47,7 @@ func getConfig(path string) map[string]interface{} { return map[string]interface{}{ "module": "audit", "metricsets": []string{"file"}, - "file.paths": map[string][]string{ - "binaries": {path}, - }, + "file.paths": []string{path}, } } @@ -63,9 +61,7 @@ func TestEventReader(t *testing.T) { // Create a new EventReader. config := defaultConfig - config.Paths = map[string][]string{ - "testdir": {dir}, - } + config.Paths = []string{dir} r, err := NewEventReader(config) if err != nil { t.Fatal(err) @@ -353,3 +349,27 @@ func rename(t *testing.T, oldPath, newPath string) { t.Fatal(err) } } + +func BenchmarkHashFile(b *testing.B) { + f, err := ioutil.TempFile("", "hash") + if err != nil { + b.Fatal(err) + } + defer os.Remove(f.Name()) + + zeros := make([]byte, 100) + for i := 0; i < 1024*1024; i++ { + if _, err = f.Write(zeros); err != nil { + b.Fatal(err) + } + } + f.Close() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _, err = hashFile(f.Name(), "sha256") + if err != nil { + b.Fatal(err) + } + } +} diff --git a/auditbeat/module/audit/kernel/_meta/docs.asciidoc b/auditbeat/module/audit/kernel/_meta/docs.asciidoc index 651400f7e15..3b4dd92283b 100644 --- a/auditbeat/module/audit/kernel/_meta/docs.asciidoc +++ b/auditbeat/module/audit/kernel/_meta/docs.asciidoc @@ -8,7 +8,7 @@ This metricset is available only for Linux. [float] === How it works -This metricset establishes a subscription to the `kernel` to receive the events +This metricset establishes a subscription to the kernel to receive the events as they occur. So unlike most other metricsets, the `period` configuration option is unused because it is not implemented using polling. @@ -16,8 +16,8 @@ The Linux kernel only supports a single subscriber to the audit events so this metricset cannot be used simultaneously with a service like `auditd`. `auditd` should be disabled if this metricset is being used. If you wish to continue to use `auditd` instead of this metricset to receive audit messages from the kernel -then consider using {filebeat}/filebeat-module-auditd.html[Filebeat] to collect the daemon's -log files. +then consider using {filebeat}/filebeat-module-auditd.html[Filebeat] to collect +the daemon's log files. The Linux Audit Framework can send multiple messages for a single auditable event. For example, a `rename` syscall causes the kernel to send eight separate @@ -73,10 +73,12 @@ include each of the raw messages that contributed to the event in the document as a field called `messages`. The default value is false. This setting is primarily used for development and debugging purposes. -*`kernel.include_warnings`*:: This boolean setting causes {beatname_uc} to include -as warnings any issues that were encountered while parsing the raw messages. -The default value is false. This setting is primarily used for development and -debugging purposes. +*`kernel.include_warnings`*:: This boolean setting causes {beatname_uc} to +include as warnings any issues that were encountered while parsing the raw +messages. The default value is false. When this setting is enabled the raw +messages will be included in the event regardless of the +`kernel.include_raw_message` config setting. This setting is primarily used for +development and debugging purposes. *`kernel.audit_rules`*:: A string containing the audit rules that should be installed to the kernel. There should be one rule per line. Comments can be @@ -102,9 +104,9 @@ the most active rules first in order to speed up evaluation. You can assign keys to each rule for better identification of the rule that triggered an event and easier filtering later in Elasticsearch. -Defining any audit rules in the config causes {beatname_uc} to purge all existing -audit rules prior to adding the rules specified in the config. Therefore it is -unnecessary and unsupported to include a `-D` (delete all) rule. +Defining any audit rules in the config causes {beatname_uc} to purge all +existing audit rules prior to adding the rules specified in the config. +Therefore it is unnecessary and unsupported to include a `-D` (delete all) rule. ["source","sh",subs="attributes"] ---- From 20320b3475427aac685537fdf3ee155a7ab0a135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20P=C3=A9rez-Aradros=20Herce?= Date: Tue, 1 Aug 2017 16:52:10 +0200 Subject: [PATCH 027/139] Use the right `modules.d` folder on Windows build (#4806) Fixes #4805 --- dev-tools/packer/platforms/windows/run.sh.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/packer/platforms/windows/run.sh.j2 b/dev-tools/packer/platforms/windows/run.sh.j2 index dee7a536ae7..208f026c43e 100644 --- a/dev-tools/packer/platforms/windows/run.sh.j2 +++ b/dev-tools/packer/platforms/windows/run.sh.j2 @@ -17,7 +17,7 @@ unix2dos {{.beat_name}}-win.yml cp {{.beat_name}}-win.yml /{{.beat_name}}-${VERSION}-windows-{{.win_arch}}/{{.beat_name}}.yml cp {{.beat_name}}-win.reference.yml /{{.beat_name}}-${VERSION}-windows-{{.win_arch}}/{{.beat_name}}.reference.yml cp fields.yml /{{.beat_name}}-${VERSION}-windows-{{.win_arch}}/ -cp -a modules.d-darwin/ /{{.beat_name}}-${VERSION}-windows-{{.win_arch}}/modules.d || true +cp -a modules.d-win/ /{{.beat_name}}-${VERSION}-windows-{{.win_arch}}/modules.d || true cp install-service-{{.beat_name}}.ps1 /{{.beat_name}}-${VERSION}-windows-{{.win_arch}}/ cp uninstall-service-{{.beat_name}}.ps1 /{{.beat_name}}-${VERSION}-windows-{{.win_arch}}/ From e912cc1b58d6cf7a822f1b1793986f32a7cf5831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20P=C3=A9rez-Aradros=20Herce?= Date: Wed, 2 Aug 2017 10:17:18 +0200 Subject: [PATCH 028/139] Remove spurious beat.full.yml (#4803) --- metricbeat/_meta/beat.full.yml | 447 --------------------------------- 1 file changed, 447 deletions(-) delete mode 100644 metricbeat/_meta/beat.full.yml diff --git a/metricbeat/_meta/beat.full.yml b/metricbeat/_meta/beat.full.yml deleted file mode 100644 index 46b7f45f983..00000000000 --- a/metricbeat/_meta/beat.full.yml +++ /dev/null @@ -1,447 +0,0 @@ -########################## Metricbeat Configuration ########################### - -# This file is a full configuration example documenting all non-deprecated -# options in comments. For a shorter configuration example, that contains only -# the most common options, please see metricbeat.yml in the same directory. -# -# You can find the full configuration reference here: -# https://www.elastic.co/guide/en/beats/metricbeat/index.html - -#============================ Config Reloading =============================== - -# Config reloading allows to dynamically load modules. Each file which is -# monitored must contain one or multiple modules as a list. -metricbeat.config.modules: - - # Glob pattern for configuration reloading - path: ${path.config}/conf.d/*.yml - - # Period on which files under path should be checked for changes - reload.period: 10s - - # Set to true to enable config reloading - reload.enabled: false - -#========================== Modules configuration ============================ -metricbeat.modules: - -#------------------------------- System Module ------------------------------- -- module: system - metricsets: - # CPU stats - - cpu - - # System Load stats - - load - - # Per CPU core stats - #- core - - # IO stats - #- diskio - - # Per filesystem stats - - filesystem - - # File system summary stats - - fsstat - - # Memory stats - - memory - - # Network stats - - network - - # Processes summary - - process_summary - - # Per process stats - - process - - # Sockets and connection info (linux only) - #- socket - enabled: true - period: 10s - processes: ['.*'] - - # if true, exports the CPU usage in ticks, together with the percentage values - #cpu_ticks: false - - # These options allow you to filter out all processes that are not - # in the top N by CPU or memory, in order to reduce the number of documents created. - # If both the `by_cpu` and `by_memory` options are used, the union of the two sets - # is included. - #process.include_top_n: - # - # Set to false to disable this feature and include all processes - #enabled: true - - # How many processes to include from the top by CPU. The processes are sorted - # by the `system.process.cpu.total.pct` field. - #by_cpu: 0 - - # How many processes to include from the top by memory. The processes are sorted - # by the `system.process.memory.rss.bytes` field. - #by_memory: 0 - - # If false, cmdline of a process is not cached. - #process.cmdline.cache.enabled: true - - # Enable collection of cgroup metrics from processes on Linux. - #process.cgroups.enabled: true - - # A list of regular expressions used to whitelist environment variables - # reported with the process metricset's events. Defaults to empty. - #process.env.whitelist: [] - - # Configure reverse DNS lookup on remote IP addresses in the socket metricset. - #socket.reverse_lookup.enabled: false - #socket.reverse_lookup.success_ttl: 60s - #socket.reverse_lookup.failure_ttl: 60s - -#------------------------------- Apache Module ------------------------------- -- module: apache - metricsets: ["status"] - enabled: false - period: 10s - - # Apache hosts - hosts: ["http://127.0.0.1"] - - # Path to server status. Default server-status - #server_status_path: "server-status" - - # Username of hosts. Empty by default - #username: username - - # Password of hosts. Empty by default - #password: password - -#-------------------------------- Audit Module ------------------------------- -- module: audit - enabled: false - metricsets: ["kernel"] - kernel.resolve_ids: true - kernel.backlog_limit: 8196 - kernel.rate_limit: 0 - kernel.include_raw_message: false - kernel.include_warnings: false - -#-------------------------------- ceph Module -------------------------------- -- module: ceph - metricsets: ["cluster_disk", "cluster_health", "monitor_health", "pool_disk"] - enabled: false - period: 10s - hosts: ["localhost:5000"] - -#------------------------------ Couchbase Module ----------------------------- -- module: couchbase - metricsets: ["bucket", "cluster", "node"] - enabled: false - period: 10s - hosts: ["localhost:8091"] - -#------------------------------- Docker Module ------------------------------- -- module: docker - metricsets: ["container", "cpu", "diskio", "healthcheck", "info", "memory", "network"] - hosts: ["unix:///var/run/docker.sock"] - enabled: false - period: 10s - - # To connect to Docker over TLS you must specify a client and CA certificate. - #ssl: - #certificate_authority: "/etc/pki/root/ca.pem" - #certificate: "/etc/pki/client/cert.pem" - #key: "/etc/pki/client/cert.key" - -#----------------------------- Dropwizard Module ----------------------------- -- module: dropwizard - metricsets: ["collector"] - enabled: false - period: 10s - hosts: ["localhost:8080"] - metrics_path: /metrics/metrics - namespace: example - -#---------------------------- elasticsearch Module --------------------------- -- module: elasticsearch - metricsets: ["node", "node_stats"] - enabled: false - period: 10s - hosts: ["localhost:9200"] - - - -#------------------------------- golang Module ------------------------------- -- module: golang - metricsets: ["expvar","heap"] - enabled: false - period: 10s - hosts: ["localhost:6060"] - heap.path: "/debug/vars" - expvar: - namespace: "example" - path: "/debug/vars" - -#------------------------------- HAProxy Module ------------------------------ -- module: haproxy - metricsets: ["info", "stat"] - enabled: false - period: 10s - hosts: ["tcp://127.0.0.1:14567"] - -#-------------------------------- HTTP Module -------------------------------- -- module: http - metricsets: ["json"] - enabled: false - period: 10s - hosts: ["localhost:80"] - namespace: "json_namespace" - path: "/" - #body: "" - #method: "GET" - #request.enabled: false - #response.enabled: false - -#------------------------------- Jolokia Module ------------------------------ -- module: jolokia - metricsets: ["jmx"] - enabled: false - period: 10s - hosts: ["localhost"] - namespace: "metrics" - path: "/jolokia/?ignoreErrors=true&canonicalNaming=false" - jmx.mapping: - jmx.application: - jmx.instance: - -#-------------------------------- kafka Module ------------------------------- -- module: kafka - metricsets: ["partition"] - enabled: false - period: 10s - hosts: ["localhost:9092"] - - #client_id: metricbeat - #retries: 3 - #backoff: 250ms - - # List of Topics to query metadata for. If empty, all topics will be queried. - #topics: [] - - # Optional SSL. By default is off. - # List of root certificates for HTTPS server verifications - #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - - # Certificate for SSL client authentication - #ssl.certificate: "/etc/pki/client/cert.pem" - - # Client Certificate Key - #ssl.key: "/etc/pki/client/cert.key" - - # SASL authentication - #username: "" - #password: "" - -#------------------------------- kibana Module ------------------------------- -- module: kibana - metricsets: ["status"] - enabled: false - period: 10s - hosts: ["localhost:5601"] - -#----------------------------- kubernetes Module ----------------------------- -# Node metrics, from kubelet: -- module: kubernetes - enabled: false - metricsets: - - node - - system - - pod - - container - - volume - period: 10s - hosts: ["localhost:10255"] - -# State metrics from kube-state-metrics service: -- module: kubernetes - enabled: false - metricsets: - - state_node - - state_deployment - - state_replicaset - - state_pod - - state_container - period: 10s - hosts: ["kube-state-metrics:8080"] - -# Kubernetes events -- module: kubernetes - metricsets: - - event - kube_config: ${HOME}/.kube/config - in_cluster: false - -#------------------------------ memcached Module ----------------------------- -- module: memcached - metricsets: ["stats"] - enabled: false - period: 10s - hosts: ["localhost:11211"] - - -#------------------------------- MongoDB Module ------------------------------ -- module: mongodb - metricsets: ["dbstats", "status"] - enabled: false - period: 10s - - # The hosts must be passed as MongoDB URLs in the format: - # [mongodb://][user:pass@]host[:port]. - # The username and password can also be set using the respective configuration - # options. The credentials in the URL take precedence over the username and - # password configuration options. - hosts: ["localhost:27017"] - - # Username to use when connecting to MongoDB. Empty by default. - #username: user - - # Password to use when connecting to MongoDB. Empty by default. - #password: pass - -#-------------------------------- MySQL Module ------------------------------- -- module: mysql - metricsets: ["status"] - enabled: false - period: 10s - - # Host DSN should be defined as "user:pass@tcp(127.0.0.1:3306)/" - # The username and password can either be set in the DSN or using the username - # and password config options. Those specified in the DSN take precedence. - hosts: ["root:secret@tcp(127.0.0.1:3306)/"] - - # Username of hosts. Empty by default. - #username: root - - # Password of hosts. Empty by default. - #password: secret - - # By setting raw to true, all raw fields from the status metricset will be added to the event. - #raw: false - -#-------------------------------- Nginx Module ------------------------------- -#- module: nginx - #metricsets: ["stubstatus"] - #enabled: true - #period: 10s - - # Nginx hosts - #hosts: ["http://127.0.0.1"] - - # Path to server status. Default server-status - #server_status_path: "server-status" - -#------------------------------- php_fpm Module ------------------------------ -- module: php_fpm - metricsets: ["pool"] - enabled: false - period: 10s - status_path: "/status" - hosts: ["localhost:8080"] - -#----------------------------- PostgreSQL Module ----------------------------- -- module: postgresql - metricsets: - # Stats about every PostgreSQL database - - database - - # Stats about the background writer process's activity - - bgwriter - - # Stats about every PostgreSQL process - - activity - - enabled: false - period: 10s - - # The host must be passed as PostgreSQL URL. Example: - # postgres://localhost:5432?sslmode=disable - # The available parameters are documented here: - # https://godoc.org/github.com/lib/pq#hdr-Connection_String_Parameters - hosts: ["postgres://localhost:5432"] - - # Username to use when connecting to PostgreSQL. Empty by default. - #username: user - - # Password to use when connecting to PostgreSQL. Empty by default. - #password: pass - - -#----------------------------- Prometheus Module ----------------------------- -- module: prometheus - metricsets: ["stats"] - enabled: false - period: 10s - hosts: ["localhost:9090"] - metrics_path: /metrics - #namespace: example - -#-------------------------------- Redis Module ------------------------------- -- module: redis - metricsets: ["info", "keyspace"] - enabled: false - period: 10s - - # Redis hosts - hosts: ["127.0.0.1:6379"] - - # Timeout after which time a metricset should return an error - # Timeout is by default defined as period, as a fetch of a metricset - # should never take longer then period, as otherwise calls can pile up. - #timeout: 1s - - # Optional fields to be added to each event - #fields: - # datacenter: west - - # Network type to be used for redis connection. Default: tcp - #network: tcp - - # Max number of concurrent connections. Default: 10 - #maxconn: 10 - - # Filters can be used to reduce the number of fields sent. - #filters: - # - include_fields: - # fields: ["stats"] - - # Redis AUTH password. Empty by default. - #password: foobared - -#------------------------------- vsphere Module ------------------------------ -- module: vsphere - metricsets: ["datastore, host, virtualmachine"] - enabled: false - period: 10s - hosts: ["https://localhost/sdk"] - - username: "user" - password: "password" - # If insecure is true, don't verify the server's certificate chain - insecure: false - -#------------------------------- Windows Module ------------------------------ -- module: windows - metricsets: ["perfmon"] - enabled: false - period: 10s - perfmon.counters: - -#------------------------------ ZooKeeper Module ----------------------------- -- module: zookeeper - metricsets: ["mntr"] - enabled: false - period: 10s - hosts: ["localhost:2181"] - - From ecf58b5d66160dc760e9aa77548bedd283b6417c Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Wed, 2 Aug 2017 04:30:21 -0400 Subject: [PATCH 029/139] Update init scripts to use "test config" subcommand (#4797) Using "-configtest" is deprecated and the "[beat] test config" subcommand should be used instead. Fixes #4600 --- CHANGELOG.asciidoc | 2 ++ dev-tools/packer/platforms/centos/init.j2 | 2 +- dev-tools/packer/platforms/debian/init.j2 | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index aaf69a8550e..1d5a27a1c1d 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -57,6 +57,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Affecting all Beats* +- Update init scripts to use the `test config` subcommand instead of the deprecated `-configtest` flag. {issue}4600[4600] + *Auditbeat* - Added `file.hash_types` config option for controlling the hash types. {pull}4796[4796] diff --git a/dev-tools/packer/platforms/centos/init.j2 b/dev-tools/packer/platforms/centos/init.j2 index ea5d58c6f90..f713575539e 100755 --- a/dev-tools/packer/platforms/centos/init.j2 +++ b/dev-tools/packer/platforms/centos/init.j2 @@ -26,7 +26,7 @@ export PATH pidfile=${PIDFILE-/var/run/{{.beat_pkg_name}}.pid} agent=${BEATS_AGENT-/usr/share/{{.beat_name}}/bin/{{.beat_name}}} args="-c /etc/{{.beat_name}}/{{.beat_name}}.yml -path.home /usr/share/{{.beat_name}} -path.config /etc/{{.beat_name}} -path.data /var/lib/{{.beat_name}} -path.logs /var/log/{{.beat_name}}" -test_args="-e -configtest" +test_args="-e test config" beat_user="${BEAT_USER:-root}" wrapper="/usr/share/{{.beat_name}}/bin/{{.beat_name}}-god" wrapperopts="-r / -n -p $pidfile" diff --git a/dev-tools/packer/platforms/debian/init.j2 b/dev-tools/packer/platforms/debian/init.j2 index 5ffab16d9c2..04c24242d81 100755 --- a/dev-tools/packer/platforms/debian/init.j2 +++ b/dev-tools/packer/platforms/debian/init.j2 @@ -18,7 +18,7 @@ DESC="{{.beat_description}}" NAME="{{.beat_name}}" DAEMON=/usr/share/{{.beat_name}}/bin/$NAME DAEMON_ARGS="-c /etc/{{.beat_name}}/{{.beat_name}}.yml -path.home /usr/share/{{.beat_name}} -path.config /etc/{{.beat_name}} -path.data /var/lib/{{.beat_name}} -path.logs /var/log/{{.beat_name}}" -TEST_ARGS="-e -configtest" +TEST_ARGS="-e test config" PIDFILE=/var/run/{{.beat_pkg_name}}.pid WRAPPER="/usr/share/{{.beat_name}}/bin/{{.beat_name}}-god" BEAT_USER="root" From 29f05c5f763fb28b5df0b60ff46108a8eda9753a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20P=C3=A9rez-Aradros=20Herce?= Date: Wed, 2 Aug 2017 10:34:05 +0200 Subject: [PATCH 030/139] Add breaking change message about using Beats from Windows GUI (#4794) --- CHANGELOG.asciidoc | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 1d5a27a1c1d..2d2790eb20b 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -117,6 +117,7 @@ https://github.com/elastic/beats/compare/v6.0.0-alpha2...v6.0.0-beta1[View commi - Remove setting `queue_size` and `bulk_queue_size`. {pull}4650[4650] - Remove setting `dashboard.snapshot` and `dashboard.snapshot_url`. They are no longer needed because the dashboards are included in the packages by default. {pull}4675[4675] +- Beats can no longer be launched from Windows Explorer (GUI), command line is required. {pull}4420[4420] *Heartbeat* From 747cfd936bc685cc965161c2447300a434bb586f Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Wed, 2 Aug 2017 11:39:40 +0300 Subject: [PATCH 031/139] Metricbeat tests: split proxy_dep in 3 (#4801) * Metricbeat tests: split proxy_dep in 3 This is just a test, my hope is that by splitting the dependences in three groups, docker-compose will start the three groups in sequence, reducing the maximum load. * New attempt on staging startign containers * Lower heap size for the ES from the metricbeat tests --- metricbeat/docker-compose.yml | 47 +++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/metricbeat/docker-compose.yml b/metricbeat/docker-compose.yml index 8e54628ceed..add5a447292 100644 --- a/metricbeat/docker-compose.yml +++ b/metricbeat/docker-compose.yml @@ -13,7 +13,9 @@ services: # Wait for all services to be up and healthy. depends_on: - - proxy_dep + - proxy_dep1 + - proxy_dep2 + - proxy_dep3 env_file: - ${PWD}/module/aerospike/_meta/env @@ -41,7 +43,7 @@ services: # This is a proxy used to block beats until all services are healthy. # See: https://github.com/docker/compose/issues/4369 - proxy_dep: + proxy_dep1: image: busybox depends_on: aerospike: { condition: service_healthy } @@ -52,6 +54,11 @@ services: elasticsearch: { condition: service_healthy } haproxy: { condition: service_healthy } http: { condition: service_healthy } + + + proxy_dep2: + image: busybox + depends_on: jolokia: { condition: service_healthy } kafka: { condition: service_healthy } kibana: { condition: service_healthy } @@ -59,6 +66,10 @@ services: kube-state: { condition: service_started } memcached: { condition: service_healthy } mongodb: { condition: service_healthy } + + proxy_dep3: + image: busybox + depends_on: mysql: { condition: service_healthy } nginx: { condition: service_healthy } phpfpm: { condition: service_healthy } @@ -88,6 +99,8 @@ services: extends: file: ${ES_BEATS}/testing/environments/${TESTING_ENVIRONMENT}.yml service: elasticsearch + environment: + - "ES_JAVA_OPTS=-Xms90m -Xmx90m" haproxy: build: ${PWD}/module/haproxy/_meta @@ -97,14 +110,20 @@ services: jolokia: build: ${PWD}/module/jolokia/_meta + depends_on: + - proxy_dep1 kafka: build: ${PWD}/module/kafka/_meta + depends_on: + - proxy_dep1 kibana: extends: file: ${ES_BEATS}/testing/environments/${TESTING_ENVIRONMENT}.yml service: kibana + depends_on: + - proxy_dep1 kubernetes: build: ${PWD}/module/kubernetes/_meta @@ -116,38 +135,62 @@ services: - /sys:/sys - /var/lib/docker:/var/lib/docker - /var/run:/var/run + depends_on: + - proxy_dep1 kube-state: build: context: ${PWD}/module/kubernetes/_meta/ dockerfile: Dockerfile.kube-state + depends_on: + - proxy_dep1 memcached: build: ${PWD}/module/memcached/_meta + depends_on: + - proxy_dep1 mongodb: build: ${PWD}/module/mongodb/_meta + depends_on: + - proxy_dep1 mysql: build: ${PWD}/module/mysql/_meta + depends_on: + - proxy_dep2 nginx: build: ${PWD}/module/nginx/_meta + depends_on: + - proxy_dep2 phpfpm: build: ${PWD}/module/php_fpm/_meta + depends_on: + - proxy_dep2 postgresql: build: ${PWD}/module/postgresql/_meta + depends_on: + - proxy_dep2 prometheus: build: ${PWD}/module/prometheus/_meta + depends_on: + - proxy_dep2 rabbitmq: build: ${PWD}/module/rabbitmq/_meta + depends_on: + - proxy_dep2 redis: build: ${PWD}/module/redis/_meta + depends_on: + - proxy_dep2 zookeeper: build: ${PWD}/module/zookeeper/_meta + depends_on: + - proxy_dep2 From 44d6f9dfec14b68809128a9e5a2abb90112b6d87 Mon Sep 17 00:00:00 2001 From: Vova Date: Wed, 2 Aug 2017 17:45:43 +0300 Subject: [PATCH 032/139] Added required alias property to documentation (#4800) Trying to start metricbeat for capturing performance counters with default configuration form documentation fails complaining on absent "alias" field in counters definitions. --- metricbeat/module/windows/perfmon/_meta/docs.asciidoc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/metricbeat/module/windows/perfmon/_meta/docs.asciidoc b/metricbeat/module/windows/perfmon/_meta/docs.asciidoc index 68fcee1c362..d5297645ec3 100644 --- a/metricbeat/module/windows/perfmon/_meta/docs.asciidoc +++ b/metricbeat/module/windows/perfmon/_meta/docs.asciidoc @@ -22,11 +22,13 @@ For wildcard queries this setting has no effect. metricsets: ["perfmon"] period: 10s perfmon.counters: - - instance_label: "processor.name" + - alias: "procesor.name.stats" + instance_label: "processor.name" instance_name: "Total" measurement_label: "processor.time.total.pct" query: '\Processor Information(_Total)\% Processor Time' - - instance_label: "diskio.name" + - alias: "diskio.name.stats" + instance_label: "diskio.name" measurement_label: "diskio.write.bytes" query: '\PhysicalDisk(*)\Disk Writes/sec' format: "long" From 1946fe0863ffad33f0ad1a6a234c0ef921c72194 Mon Sep 17 00:00:00 2001 From: DeDe Morton Date: Wed, 2 Aug 2017 10:40:04 -0700 Subject: [PATCH 033/139] Update info about loading dashboards and index templates (#4778) Update Auditbeat docs with changes from testing --- auditbeat/docs/configuring-howto.asciidoc | 6 + auditbeat/docs/faq-ulimit.asciidoc | 29 ++++ auditbeat/docs/faq.asciidoc | 3 + auditbeat/docs/getting-started.asciidoc | 72 ++++---- .../docs/images/kibana-created-indexes.png | Bin 65800 -> 92195 bytes .../docs/images/kibana-navigation-vis.png | Bin 39103 -> 49311 bytes auditbeat/docs/index.asciidoc | 2 - auditbeat/docs/reload-configuration.asciidoc | 4 + filebeat/docs/configuring-howto.asciidoc | 6 + filebeat/docs/getting-started.asciidoc | 80 +++++---- .../docs/images/kibana-created-indexes.png | Bin 0 -> 74992 bytes .../docs/images/kibana-navigation-vis.png | Bin 0 -> 74326 bytes filebeat/docs/index.asciidoc | 1 + filebeat/docs/migration.asciidoc | 2 +- heartbeat/docs/configuring-howto.asciidoc | 6 + heartbeat/docs/getting-started.asciidoc | 61 ++++--- heartbeat/docs/heartbeat-options.asciidoc | 4 +- .../docs/images/kibana-created-indexes.png | Bin 65800 -> 70819 bytes .../docs/images/kibana-navigation-vis.png | Bin 39103 -> 35453 bytes heartbeat/docs/index.asciidoc | 1 + libbeat/docs/dashboards.asciidoc | 51 +++--- libbeat/docs/dashboardsconfig.asciidoc | 47 +++-- libbeat/docs/opendashboards.asciidoc | 23 +++ libbeat/docs/outputconfig.asciidoc | 154 +---------------- libbeat/docs/shared-kibana-config.asciidoc | 104 +++++++++++ libbeat/docs/shared-logstash-config.asciidoc | 8 +- libbeat/docs/shared-ssl-config.asciidoc | 161 ++++++++++++++++++ .../docs/shared-ssl-logstash-config.asciidoc | 2 +- libbeat/docs/shared-template-load.asciidoc | 61 ++----- .../step-configure-kibana-endpoint.asciidoc | 20 +++ libbeat/docs/step-look-at-config.asciidoc | 2 + libbeat/docs/step-test-config.asciidoc | 25 +++ libbeat/docs/template-config.asciidoc | 13 +- metricbeat/docs/configuring-howto.asciidoc | 10 +- metricbeat/docs/gettingstarted.asciidoc | 59 ++++--- .../docs/images/kibana-created-indexes.png | Bin 59691 -> 74532 bytes .../docs/images/kibana-navigation-vis.png | Bin 92059 -> 58209 bytes metricbeat/docs/index.asciidoc | 1 + packetbeat/docs/configuring-howto.asciidoc | 8 +- packetbeat/docs/gettingstarted.asciidoc | 72 ++++---- .../docs/images/kibana-created-indexes.png | Bin 58659 -> 72907 bytes .../docs/images/kibana-navigation-vis.png | Bin 77206 -> 70009 bytes packetbeat/docs/index.asciidoc | 1 + packetbeat/docs/packetbeat-geoip.asciidoc | 2 +- .../docs/visualizing-data-packetbeat.asciidoc | 4 +- winlogbeat/docs/configuring-howto.asciidoc | 6 + winlogbeat/docs/getting-started.asciidoc | 42 +++-- winlogbeat/docs/index.asciidoc | 1 + 48 files changed, 715 insertions(+), 439 deletions(-) create mode 100644 auditbeat/docs/faq-ulimit.asciidoc create mode 100644 filebeat/docs/images/kibana-created-indexes.png create mode 100644 filebeat/docs/images/kibana-navigation-vis.png create mode 100644 libbeat/docs/opendashboards.asciidoc create mode 100644 libbeat/docs/shared-kibana-config.asciidoc create mode 100644 libbeat/docs/shared-ssl-config.asciidoc create mode 100644 libbeat/docs/step-configure-kibana-endpoint.asciidoc create mode 100644 libbeat/docs/step-look-at-config.asciidoc create mode 100644 libbeat/docs/step-test-config.asciidoc diff --git a/auditbeat/docs/configuring-howto.asciidoc b/auditbeat/docs/configuring-howto.asciidoc index cdda8c0e21b..54a63e86ce4 100644 --- a/auditbeat/docs/configuring-howto.asciidoc +++ b/auditbeat/docs/configuring-howto.asciidoc @@ -23,9 +23,11 @@ The following topics describe how to configure {beatname_uc}: * <> * <<{beatname_lc}-configuration-reloading>> * <> +* <> * <> * <> * <> +* <> * <> * <> * <> @@ -46,12 +48,16 @@ include::./reload-configuration.asciidoc[] :allplatforms: include::../../libbeat/docs/outputconfig.asciidoc[] +include::../../libbeat/docs/shared-ssl-config.asciidoc[] + include::./auditbeat-filtering.asciidoc[] include::../../libbeat/docs/shared-config-ingest.asciidoc[] include::../../libbeat/docs/shared-path-config.asciidoc[] +include::../../libbeat/docs/shared-kibana-config.asciidoc[] + include::../../libbeat/docs/setup-config.asciidoc[] include::../../libbeat/docs/loggingconfig.asciidoc[] diff --git a/auditbeat/docs/faq-ulimit.asciidoc b/auditbeat/docs/faq-ulimit.asciidoc new file mode 100644 index 00000000000..6aa7420f374 --- /dev/null +++ b/auditbeat/docs/faq-ulimit.asciidoc @@ -0,0 +1,29 @@ +[float] +[[ulimit]] +=== {beatname_uc} fails to watch folders because too many files are open? + +Because of the way file monitoring is implemented on macOS, you may see a +warning similar to the following: + +[source,shell] +---- +eventreader_fsnotify.go:42: WARN [audit.file] Failed to watch /usr/bin: too many +open files (check the max number of open files allowed with 'ulimit -a') +---- + +To resolve this issue, run {beatname_uc} with the `ulimit` set to a larger +value, for example: + +["source","sh",subs="attributes"] +---- +sudo sh -c 'ulimit -n 8192 && ./{beatname_uc} -e +---- + +Or: + +["source","sh",subs="attributes"] +---- +sudo su +ulimit -n 8192 +./{beatname_lc} -e +---- diff --git a/auditbeat/docs/faq.asciidoc b/auditbeat/docs/faq.asciidoc index 54b9bca4e85..a9b525eab65 100644 --- a/auditbeat/docs/faq.asciidoc +++ b/auditbeat/docs/faq.asciidoc @@ -5,5 +5,8 @@ This section contains frequently asked questions about {beatname_uc}. Also check out the https://discuss.elastic.co/c/beats/{beatname_lc}[{beatname_uc} discussion forum]. +include::./faq-ulimit.asciidoc[] + include::../../libbeat/docs/faq-limit-bandwidth.asciidoc[] + include::../../libbeat/docs/shared-faq.asciidoc[] diff --git a/auditbeat/docs/getting-started.asciidoc b/auditbeat/docs/getting-started.asciidoc index 9074b9e9518..5abc893f51e 100644 --- a/auditbeat/docs/getting-started.asciidoc +++ b/auditbeat/docs/getting-started.asciidoc @@ -1,8 +1,6 @@ [id="{beatname_lc}-getting-started"] == Getting started with {beatname_uc} -//TODO: The getting started content needs to be changed to reflect changes in command-line syntax, dashboard loading, etc. - To get started with your own {beatname_uc} setup, install and configure these related products: @@ -19,8 +17,9 @@ install, configure, and run {beatname_uc}: * <<{beatname_lc}-installation>> * <<{beatname_lc}-configuration>> * <<{beatname_lc}-template>> +* <> * <<{beatname_lc}-starting>> -* <<{beatname_lc}-sample-dashboards>> +* <> * <> * <> @@ -160,44 +159,28 @@ auditbeat.modules: ------------------------------------- + If you accept the default configuration without specifying additional modules, -{beatname_uc} uses a default configuration that's tailored to the operating system -where {beatname_uc} is running. +{beatname_uc} uses a configuration that's tailored to the operating system where +{beatname_uc} is running. + See <> for more details about configuring modules. -. If you are sending output to Elasticsearch, set the IP address and port where -{beatname_uc} can find the Elasticsearch installation: +. If you are sending output to Elasticsearch (and not using Logstash), set the +IP address and port where {beatname_uc} can find the Elasticsearch installation: + [source,yaml] ---------------------------------------------------------------------- output.elasticsearch: - hosts: ["192.168.1.42:9200"] + hosts: ["127.0.0.1:9200"] ---------------------------------------------------------------------- + -If you are sending output to Logstash, see +If you are sending output to Logstash, make sure you <> instead. -. If you plan to use the sample Kibana dashboards provided with {beatname_uc}, -configure the Kibana endpoint: -+ -[source,yaml] ----------------------------------------------------------------------- -setup.kibana: - host: "localhost:5601" ----------------------------------------------------------------------- -+ --- -Where `host` is the hostname and port of the machine where Kibana is running, -for example, `localhost:5601`. - -TIP: If you specify a path after the port number, you need to include -the scheme and port: `http://localhost:5601/path`. +include::../../libbeat/docs/step-configure-kibana-endpoint.asciidoc[] --- +include::../../libbeat/docs/step-test-config.asciidoc[] -//TODO: Add link that mentions security settings and points to docs about setup.kibana for more info. - -//REVIEWERS: Wondering if I should protocol, username, and password in the example. We tend to leave that out, but not sure if that's the best thing to do. +include::../../libbeat/docs/step-look-at-config.asciidoc[] [id="{beatname_lc}-template"] === Step 3: Load the index template in Elasticsearch @@ -205,8 +188,14 @@ the scheme and port: `http://localhost:5601/path`. :allplatforms: include::../../libbeat/docs/shared-template-load.asciidoc[] +[[load-kibana-dashboards]] +=== Step 4: Set up the Kibana dashboards + +:allplatforms: +include::../../libbeat/docs/dashboards.asciidoc[] + [id="{beatname_lc}-starting"] -=== Step 4: Start {beatname_uc} +=== Step 5: Start {beatname_uc} Run {beatname_uc} by issuing the appropriate command for your platform. @@ -218,14 +207,14 @@ start {beatname_uc} in the foreground. ["source","sh",subs="attributes"] ---------------------------------------------------------------------- -sudo /etc/init.d/{beatname_lc} start +sudo service {beatname_lc} start ---------------------------------------------------------------------- *rpm:* ["source","sh",subs="attributes"] ---------------------------------------------------------------------- -sudo /etc/init.d/{beatname_lc} start +sudo service {beatname_lc} start ---------------------------------------------------------------------- *mac:* @@ -236,9 +225,13 @@ sudo chown root {beatname_lc}.yml <1> sudo ./{beatname_lc} -e -c {beatname_lc}.yml -d "publish" ---------------------------------------------------------------------- <1> To monitor system files, you'll be running {beatname_uc} as root, so you -need to change ownership of the configuration file (see +need to change ownership of the configuration file, or run {beatname_uc} with +`-strict.perms=false` specified. See {libbeat}/config-file-permissions.html[Config File Ownership and Permissions] -in the _Beats Platform Reference_). +in the _Beats Platform Reference_. + +If you see a warning about too many open files, you need to increase the +`ulimit`. See the <> for more details. *win:* @@ -265,15 +258,18 @@ Elasticsearch instance. On Windows, if you don't have cURL installed, simply point your browser to the URL. -[id="{beatname_lc}-sample-dashboards"] -=== Step 5: Load sample Kibana dashboards +[[view-kibana-dashboards]] +=== Step 6: View the sample Kibana dashboards To make it easier for you to start auditing the activities of users and -processes on your system, we have created sample {beatname_uc} dashboards. +processes on your system, we have created example {beatname_uc} dashboards. +You loaded the dashboards earlier when you ran the `setup` command. + +include::../../libbeat/docs/opendashboards.asciidoc[] + The dashboards are provided as examples. We recommend that you {kibana-ref}/dashboard.html[customize] them to meet your needs. image:./images/auditbeat-file-integrity-dashboard.png[Auditbeat File Integrity Dashboard] -:allplatforms: -include::../../libbeat/docs/dashboards.asciidoc[] + diff --git a/auditbeat/docs/images/kibana-created-indexes.png b/auditbeat/docs/images/kibana-created-indexes.png index 8f6379f552804e75b1b64b5018b4367229afb589..af8ad91a502eea295dcf037a18356e1e97b22572 100644 GIT binary patch literal 92195 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 z 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 nc+FbE5+imKcjxRTy#q!y) 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 Du_-F= literal 65800 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�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

m3SxiDM5C~ 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

{_;_d@&7tz7myWQSw<(w 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

S^ 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 S`5n;#Kwd^!x>V96@c#j*a|^Ek literal 39103 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%0AK2`$~3ju+W4QXcsOD9FtRg! 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 * <> * <> +* <> * <> * <> * <> +* <> * <> * <> * <> @@ -50,6 +52,8 @@ include::./reload-configuration.asciidoc[] :allplatforms: include::../../libbeat/docs/outputconfig.asciidoc[] +include::../../libbeat/docs/shared-ssl-config.asciidoc[] + include::./load-balancing.asciidoc[] include::./filebeat-filtering.asciidoc[] @@ -58,6 +62,8 @@ include::../../libbeat/docs/shared-config-ingest.asciidoc[] include::../../libbeat/docs/shared-path-config.asciidoc[] +include::../../libbeat/docs/shared-kibana-config.asciidoc[] + include::../../libbeat/docs/setup-config.asciidoc[] include::../../libbeat/docs/loggingconfig.asciidoc[] diff --git a/filebeat/docs/getting-started.asciidoc b/filebeat/docs/getting-started.asciidoc index a2135c71aef..5a18fe63fa7 100644 --- a/filebeat/docs/getting-started.asciidoc +++ b/filebeat/docs/getting-started.asciidoc @@ -15,8 +15,9 @@ After installing the Elastic Stack, read the following topics to learn how to in * <> * <> * <> +* <> * <> -* <> +* <> * <> * <> * <> @@ -157,6 +158,7 @@ default values for most configuration options. ------------------------------------------------------------------------------------- filebeat.prospectors: - type: log + enabled: true paths: - /var/log/*.log #- c:\programdata\elasticsearch\logs\* @@ -172,6 +174,7 @@ For the most basic Filebeat configuration, you can define a single prospector wi ------------------------------------------------------------------------------------- filebeat.prospectors: - type: log + enabled: true paths: - /var/log/*.log ------------------------------------------------------------------------------------- @@ -185,7 +188,8 @@ To fetch all files from a predefined level of subdirectories, the following patt fetch log files from the `/var/log` folder itself. Currently it is not possible to recursively fetch all files in all subdirectories of a directory. -. If you are sending output to Elasticsearch, set the IP address and port where Filebeat can find the Elasticsearch installation: +. If you are sending output directly to Elasticsearch (and not using Logstash), +set the IP address and port where Filebeat can find the Elasticsearch installation: + [source,yaml] ---------------------------------------------------------------------- @@ -193,18 +197,14 @@ output.elasticsearch: hosts: ["192.168.1.42:9200"] ---------------------------------------------------------------------- + -If you are sending output to Logstash, see <> instead. +If you are sending output to Logstash, make sure you +configure the Logstash output in <>. -TIP: To test your configuration file, change to the directory where the Filebeat -binary is installed, and run Filebeat in the foreground with the following -options specified: +./filebeat -configtest -e+. Make sure your config files are -in the path expected by Filebeat (see <>). If you -installed from DEB or RPM packages, run +./filebeat.sh -configtest -e+. +include::../../libbeat/docs/step-configure-kibana-endpoint.asciidoc[] -Before starting Filebeat, you should look at the configuration options in the -configuration file, for example `C:\Program Files\Filebeat\filebeat.yml` or -`/etc/filebeat/filebeat.yml`. For more information about these options, -see <>. +include::../../libbeat/docs/step-test-config.asciidoc[] + +include::../../libbeat/docs/step-look-at-config.asciidoc[] [[config-filebeat-logstash]] === Step 3: Configure Filebeat to use Logstash @@ -218,8 +218,14 @@ include::../../libbeat/docs/shared-logstash-config.asciidoc[] :allplatforms: include::../../libbeat/docs/shared-template-load.asciidoc[] +[[load-kibana-dashboards]] +=== Step 5: Set up the Kibana dashboards + +:allplatforms: +include::../../libbeat/docs/dashboards.asciidoc[] + [[filebeat-starting]] -=== Step 5: Start Filebeat +=== Step 6: Start Filebeat Start Filebeat by issuing the appropriate command for your platform. @@ -229,16 +235,16 @@ start Filebeat in the foreground. *deb:* -[source,shell] +["source","sh",subs="attributes"] ---------------------------------------------------------------------- -sudo /etc/init.d/filebeat start +sudo service {beatname_lc} start ---------------------------------------------------------------------- *rpm:* -[source,shell] +["source","sh",subs="attributes"] ---------------------------------------------------------------------- -sudo /etc/init.d/filebeat start +sudo service {beatname_lc} start ---------------------------------------------------------------------- *docker:* @@ -256,9 +262,10 @@ sudo chown root filebeat.yml <1> sudo ./filebeat -e -c filebeat.yml -d "publish" ---------------------------------------------------------------------- <1> You'll be running Filebeat as root, so you need to change ownership -of the configuration file (see +of the configuration file, or run Filebeat with `-strict.perms=false` +specified. See {libbeat}/config-file-permissions.html[Config File Ownership and Permissions] -in the _Beats Platform Reference_). +in the _Beats Platform Reference_. *win:* @@ -267,28 +274,33 @@ in the _Beats Platform Reference_). PS C:\Program Files\Filebeat> Start-Service filebeat ---------------------------------------------------------------------- + By default, Windows log files are stored in `C:\ProgramData\filebeat\Logs`. Filebeat is now ready to send log files to your defined output. -[[filebeat-index-pattern]] -=== Step 6: Load the Kibana index pattern +[[view-kibana-dashboards]] +=== Step 7: View the sample Kibana dashboards -We don't offer prebuilt dashboards for visualizing Filebeat data. However, to make it easier for you to explore Filebeat -data in Kibana, we've created a Filebeat index pattern: `filebeat-*`. To load this pattern, you can use the script -that's provided for importing dashboards: +To make it easier for you to explore Filebeat data in Kibana, we've created +example {beatname_uc} dashboards. You loaded the dashboards earlier when you +ran the `setup` command. -[source,shell] ----------------------------------------------------------------------- -./scripts/import_dashboards -only-index ----------------------------------------------------------------------- +include::../../libbeat/docs/opendashboards.asciidoc[] -For more information about running the script, see -{beatsdevguide}/import-dashboards.html[Importing Existing Beat Dashboards] in the _Beats Platform Reference_. +These dashboards are designed to work out-of-the box when you use +<>. However, you can also use them +as examples and {kibana-ref}/dashboard.html[customize] them to meet your needs +even if you aren't using Filebeat modules. -After you've created the index pattern, you can select the `filebeat-*` index pattern in Kibana to explore -Filebeat data. +To populate the example dashboards with data, you need to either +<> or use Logstash to +parse the data into the fields expected by the dashboards. If you are using +Logstash, see the +{logstashdoc}/logstash-config-for-filebeat-modules.html[configuration examples] +in the Logstash documentation for help parsing the log formats supported +by the dashboards. -image:./images/filebeat-discover-tab.png[] +Here is an example of the Filebeat system dashboard: -TIP: If you don't see `filebeat-*` in the list of available index patterns, try refreshing the page in your browser. +image:./images/kibana-system.png[] diff --git a/filebeat/docs/images/kibana-created-indexes.png b/filebeat/docs/images/kibana-created-indexes.png new file mode 100644 index 0000000000000000000000000000000000000000..b2ee79d94c181d91b298a48fd414b92193b4e1ea GIT binary patch literal 74992 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
    EG{C$5@1`**} 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

    $rFrtsy9x{M$gET>K%FY-~# z9pkqC<2`&O2|&$P9OXrkWL?}x28$|?Fm`Fv@mL|JE^j)vbBiU?$m?8U0@_G zepMtm3e%JSzSO8|>GKNLajDeCPG_U7KtHQ(AsMOVGY z)wg?qAEqqmp9mU0TwEDJX?vEa6`tw7GPel2ZAAnny=+gyuBkA2e&gi?m2Kpt^E1nY{h5a`&S(x@153MS*tG5C`QJ#1AnY)#}aZlLoZJ>J;cEPaqF!?mRE?M%Tv9nRM!t zb2HMEOI$yq5nefV2C)aRofqaW(W(CU2_<{OqiYV>L5r^~dzAk>?Q}~)(VrctNYA^7 z3c9@c|niF5CE; z^&E79xiHF3F;^Ib=qibE_&uuDLWa@ovk91Jj_2cjdZI-gnsKr^@8;&1S0X#^fjiRzsji~9{xGnthM%vRvBEfM9#U~QF_B9=X|3Ir z6Dk>WWgqu~Pk{*t>q4=bv=xj7X9r5hFEBg+6Fp-IbZg44H4P#>>)$2ei^<>%2(U2$ zA_Lk2zR7>Ou$-b>4HHPM-ik3Wi6Tv@Z55smmSRZ zj?bZ;8|#+6gb9<5Ka6D`4+G}O0rO|v#P+vPfsN)@@Hl}nqrtf=qBwOSrJ2VeFJp2| zYv&FiuC;dcIB<$X*29)w13S7>gm61?!fS9xP$wQIJ*D4TZibsHgu6#@!CUwmSJk4W za(^eI0EiGsgluD#VIO8dXR6+5u!fG!ibb;SKsi6LEgj^^ISQD9h#a;3H>g%4&A!d? zx$K)Ys4ut{z!?mU^`YEi-%^4^w$D!j5c@F}#wvNI20_qKflaT9iO7JJR1477^tBRWs z>0<;TCy$96!Tq)ouhjbtp($S%K8lO7G#PU7gs{-<~`WtA;`TNk0=% z^ut>+h!rvyj}kG%IP|CRNBMltK!ponESEh;C_fK3n~*_uMoMy21+m<$>Tqf-)f4<> zg)&CdbM!~^!unnIGCV{lRDyk)LcG074xTF38Bh<( z!YCtGmyOi!oLk?!_)Sz@+E}XHy-AxR25{&i_=80eV1xD>WUHMl9eNBJMP8Ix7AELZ z+sEvnmg##qv35svZs)_EXfTB}>2&e73f}R~oM-7=x{#P(=EZ;F^Mj?nB2RftXs#OA zPZ$L>nn4BLb!&SHNY(7ep&sw@J zXHdmEAp$beqx%ZsiGWHxlfBO{0$&jd&G~kh%1N-5KQ}}Dw~C_}1J#HFGU^_)MX*d% z+M{V6@h=g(F)KpPhx;xB*u+4$iZe{Uhs|$Os+h%{3RV#^IE6IoV3VGh7sB4h3bQ@{ zoJ`yUpKO>l2=lIopoSI#o$PL*;H{ybBNZ{*Z#d}6IU*gvGCy9g?d$XGLqtYXxvxo^ z@3@d#>zBo_Cyuybqa@)Atd3V>5*a%;+Or@RQm1t$Cd;wFn+EYRR{#OhoHsWBkenU7 zs>5+Ir2JHM0p-FMr~LZkO&9aLCnu74j){apl7HBHX!uR+U(5;>x?VWK9gzu4>oNE* zPh>En(<=emiONm?gB5=b8zmz*jL(V`lSRgGBxpT_?(CX|JgAM4Up(#6>Ne6ias((# z{*K}LNmrZcbNO_DGz}VE&eqansCy}MaM*g<%kcza5#lHo`X2(IMXQdw-weas_YA~A zvU)^3IU3$3-IS~>y7Cs$UX55#XS(vzAqVW>B^;k#^?6u~+pn8C9$&GHI>tHg05`i< z$8A~~d7|>HDHOi!Hti?~fxi(N*Lm=)kP*Jw*7|u#rg8FzA@~LYUqc}BPJyB~04oXF zcyugM*+2!ALKy_&gO1|r&%!{!XeJMAj|Mxyh%vra1H}v~-+cm}b;erb-l4FM2#B&% z(O9`in#Oj#1D|y!XxeYym|+WgUx_);Y7G{6*SP-B6<08X?&gT


    rz7Dh4hj;ic& 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%0Dm@~oUP~5D`d@JDU!quN7cb(r_rl5JWFx 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 literal 0 HcmV?d00001 diff --git a/filebeat/docs/images/kibana-navigation-vis.png b/filebeat/docs/images/kibana-navigation-vis.png new file mode 100644 index 0000000000000000000000000000000000000000..6b7158775c7d3245b8d3de01a394b0599978dda9 GIT binary patch literal 74326 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 ^_RbG|i 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æG>LxKNCVFO-iEB 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 i(*B?JiLGzExFPb3!&l?H(SNY-wAN~(Tw=i!2 literal 0 HcmV?d00001 diff --git a/filebeat/docs/index.asciidoc b/filebeat/docs/index.asciidoc index 17701f9d677..659e843c9de 100644 --- a/filebeat/docs/index.asciidoc +++ b/filebeat/docs/index.asciidoc @@ -3,6 +3,7 @@ include::../../libbeat/docs/version.asciidoc[] :libbeat: http://www.elastic.co/guide/en/beats/libbeat/{doc-branch} +:kibana-ref: https://www.elastic.co/guide/en/kibana/{doc-branch} :beatsdevguide: http://www.elastic.co/guide/en/beats/devguide/{doc-branch} :packetbeat: http://www.elastic.co/guide/en/beats/packetbeat/{doc-branch} :metricbeat: http://www.elastic.co/guide/en/beats/metricbeat/{doc-branch} diff --git a/filebeat/docs/migration.asciidoc b/filebeat/docs/migration.asciidoc index 06f10932c8d..aa268542b8d 100644 --- a/filebeat/docs/migration.asciidoc +++ b/filebeat/docs/migration.asciidoc @@ -220,7 +220,7 @@ output.logstash: <> configuration option. <2> Note that if the `ssl` settings are missing, then SSL is disabled. SSL is automatically enabled when you add any of the `ssl` options. For more information about - specific configuration options, see <>. + specific configuration options, see <>. [[changed-configuration-options]] diff --git a/heartbeat/docs/configuring-howto.asciidoc b/heartbeat/docs/configuring-howto.asciidoc index 12731b11a7e..a46909a50f9 100644 --- a/heartbeat/docs/configuring-howto.asciidoc +++ b/heartbeat/docs/configuring-howto.asciidoc @@ -24,9 +24,11 @@ The following topics describe how to configure Heartbeat: * <> * <> * <> +* <> * <> * <> * <> +* <> * <> * <> * <> @@ -43,12 +45,16 @@ include::./heartbeat-general-options.asciidoc[] :allplatforms: include::../../libbeat/docs/outputconfig.asciidoc[] +include::../../libbeat/docs/shared-ssl-config.asciidoc[] + include::./heartbeat-filtering.asciidoc[] include::../../libbeat/docs/shared-config-ingest.asciidoc[] include::../../libbeat/docs/shared-path-config.asciidoc[] +include::../../libbeat/docs/shared-kibana-config.asciidoc[] + include::../../libbeat/docs/setup-config.asciidoc[] include::../../libbeat/docs/loggingconfig.asciidoc[] diff --git a/heartbeat/docs/getting-started.asciidoc b/heartbeat/docs/getting-started.asciidoc index 26c2fe82e1f..d47a6dcdb4e 100644 --- a/heartbeat/docs/getting-started.asciidoc +++ b/heartbeat/docs/getting-started.asciidoc @@ -17,7 +17,9 @@ install, configure, and run Heartbeat: * <> * <> * <> +* <> * <> +* <> * <> * <> @@ -171,7 +173,7 @@ heartbeat.monitors: schedule: '*/5 * * * * * *' hosts: ["myhost"] output.elasticsearch: - hosts: ["myhost:9200"] + hosts: ["myEShost:9200"] ---------------------------------------------------------------------- To configure Heartbeat: @@ -203,8 +205,9 @@ was started. Heartbeat adds the `@every` keyword to the syntax provided by the See <> for a full description of each configuration option. -. If you are sending output to Elasticsearch, set the IP address and port where -Heartbeat can find the Elasticsearch installation: +. If you are sending output directly to Elasticsearch (and not using Logstash), +set the IP address and port where Heartbeat can find the Elasticsearch +installation: + [source,yaml] ---------------------------------------------------------------------- @@ -212,14 +215,14 @@ output.elasticsearch: hosts: ["192.168.1.42:9200"] ---------------------------------------------------------------------- + -If you are sending output to Logstash, see <> instead. +If you are sending output to Logstash, make sure you +<> instead. -TIP: To test your configuration file, change to the directory where the -Heartbeat binary is installed, and run Heartbeat in the foreground with -the following options specified: +./heartbeat -configtest -e+. Make sure -your config files are in the path expected by Heartbeat -(see <>). If you installed from DEB or RPM packages, run -+./heartbeat.sh -configtest -e+. +include::../../libbeat/docs/step-configure-kibana-endpoint.asciidoc[] + +include::../../libbeat/docs/step-test-config.asciidoc[] + +include::../../libbeat/docs/step-look-at-config.asciidoc[] [[heartbeat-template]] === Step 3: Load the index template in Elasticsearch @@ -227,8 +230,14 @@ your config files are in the path expected by Heartbeat :allplatforms: include::../../libbeat/docs/shared-template-load.asciidoc[] +[[load-kibana-dashboards]] +=== Step 4: Set up the Kibana dashboards + +:allplatforms: +include::../../libbeat/docs/dashboards.asciidoc[] + [[heartbeat-starting]] -=== Step 4: Start Heartbeat +=== Step 5: Start Heartbeat Start Heartbeat by issuing the appropriate command for your platform. @@ -236,18 +245,20 @@ NOTE: If you use an init.d script to start Heartbeat on deb or rpm, you can't specify command line flags (see <>). To specify flags, start Heartbeat in the foreground. +//REVIEWERS: Should the deb and rpm examples say start or run? + *deb:* ["source","sh",subs="attributes"] ---------------------------------------------------------------------- -sudo /etc/init.d/heartbeat-elastic start +sudo service {beatname_lc}-elastic start ---------------------------------------------------------------------- *rpm:* ["source","sh",subs="attributes"] ---------------------------------------------------------------------- -sudo /etc/init.d/heartbeat-elastic start +sudo service {beatname_lc}-elastic start ---------------------------------------------------------------------- *mac:* @@ -257,10 +268,10 @@ sudo /etc/init.d/heartbeat-elastic start sudo chown root heartbeat.yml <1> sudo ./heartbeat -e -c heartbeat.yml -d "publish" ---------------------------------------------------------------------- -<1> You'll be running Heartbeat as root, so you need to change ownership -of the configuration file (see +<1> You'll be running Heartbeat as root, so you need to change ownership of the +configuration file, or run Heartbeat with `-strict.perms=false` specified. See {libbeat}/config-file-permissions.html[Config File Ownership and Permissions] -in the _Beats Platform Reference_). +in the _Beats Platform Reference_. *win:* @@ -274,16 +285,16 @@ By default, Windows log files are stored in +C:\ProgramData\heartbeat\Logs+. Heartbeat is now ready to check the status of your services and send events to your defined output. -[[heartbeat-sample-dashboards]] -=== Step 5: Load sample Kibana dashboards +[[view-kibana-dashboards]] +=== Step 6: View the sample Kibana dashboards To make it easier for you to visualize the status of your services, we have -created sample Heartbeat dashboards. The dashboards are provided as -examples. We recommend that you -http://www.elastic.co/guide/en/kibana/current/dashboard.html[customize] them -to meet your needs. +created example {beatname_uc} dashboards. You loaded the dashboards earlier when +you ran the `setup` command. -image:./images/heartbeat-statistics.png[Heartbeat statistics] +include::../../libbeat/docs/opendashboards.asciidoc[] -:allplatforms: -include::../../libbeat/docs/dashboards.asciidoc[] +The dashboards are provided as examples. We recommend that you +{kibana-ref}/dashboard.html[customize] them to meet your needs. + +image:./images/heartbeat-statistics.png[Heartbeat statistics] diff --git a/heartbeat/docs/heartbeat-options.asciidoc b/heartbeat/docs/heartbeat-options.asciidoc index aab178bbf22..afd22133914 100644 --- a/heartbeat/docs/heartbeat-options.asciidoc +++ b/heartbeat/docs/heartbeat-options.asciidoc @@ -256,7 +256,7 @@ monitor is configured to use SSL, Heartbeat establishes an SSL/TLS-based connection. Otherwise, it establishes a plain TCP connection. * A hostname and port, such as `localhost:12345`. Heartbeat connects to the port on the specified host. If the monitor is -<>, Heartbeat establishes an +<>, Heartbeat establishes an SSL/TLS-based connection. Otherwise, it establishes a TCP connection. * A full URL using the syntax `scheme://:[port]`, where: ** `scheme` is one of `tcp`, `plain`, `ssl` or `tls`. If `tcp` or `plain` is @@ -341,7 +341,7 @@ that name resolution occurs on the proxy server. ==== `ssl` The TLS/SSL connection settings. If the monitor is -<>, it will attempt an 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. diff --git a/heartbeat/docs/images/kibana-created-indexes.png b/heartbeat/docs/images/kibana-created-indexes.png index 8f6379f552804e75b1b64b5018b4367229afb589..606ba267d68d8bc6984ce764e2212f84d348dccd 100644 GIT binary patch literal 70819 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⋘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
    9C@ntuFqi^OK5!UvT`0)XkN8_1)^w}q8%OvNv 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 F|35mHfBgUe literal 65800 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�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

    m3SxiDM5C~ zE0FLx_}F&#+;jfI424$13H>_6=*$Iq3S0#l7sMrvjn7hwpX7PU<{c;2y z?JT~_MS{Zag(;cye8z8vn564rt7BRs7YX>%eTFK^Pf;JQNLH&vG%hY0Yml4iCCmaD=L_YP`oAxRHu4a>iyYgoG*XQZPNm)`{@^+jzYaLU3!81@!c3#O7e2M#-+J zsD*O9(}IH(Gk5t~8$?nL8Y}3x#7jfdwYDi(Yd|ZP`WDwsK<@+AdbG51W2nsFUsLinjCBa-%DZE71@nO_Y|KUB7&*5=$P$H*Bz>b zss|0&-twNC=~qT?kIl4vu}YlLe^sMWh0)N&U=kD9H5T3cqam4M+Tqu~4@?C=Piqdy zkhzn6Pq%il`>7EaG1OOvA=7ie<{YlbA|y0Id?-d$M%KC=9Y8Jvv=KeKaE$qe8k^Z_ zdRX=i=XwZj&MDgRuNekB&lI_|vUl1Bg1nwzk(92X2#kJ8M=(_*=V`MAch!^@V;oWC z&a%{+M8feQ>HRjK0)!ZYR2xsAySx^oM~In;`6*y-(P|Q_fP#PFLY!f<+-tJZ>7VMJ z+kR&?i3)!AmwX+_VuHDeL{~nvc|3pX>RK5yK}1OStN-EeKKO1)xi#tjPondWZLb0k zc;gvtz-3O~j9knlWa`YbWb`LOY#?e$g^%&A0xC2Yz;TUt{OP856WcTd#qCl)eI&b| zu-j_s>!mYfIO)v86*D{oIUR^RSd4dcgY%D+%ewoS_A95Qy!j+%K_(|Tx4M(&mwgtm zQ{CE>?kB&I=C@I{=)dsDec_j%N@ZRnkw>DYdz-z2jHKiY@i629AVX+#{EU_(3B;sAq! zsf}dI?(%!KCJT<{`QpUHhJZ$`RzQC|aVpTI7)K>|(RYLK3}~&&@!-Lj>52s8EQU`7 zlY>3x9s_v*7Eu;-B#i+2X5tIa@!RIfpj81EIF6b(5zol#09zvpzB!1V(2_Sf-UvQ;Gm@=(odZ4Ty;WpshA$-|2jskRKq~br z+)nfK(t_V5Suk9*tUr@sqVg=U(4+hE+bwPx`I;&@9tgKjjpfp}J| zuyy!0H1jllq|K?_G;}^)7YBGFy00yHYbCe?qyE^IxxAVv54aW@7u(jDE+B3ON-Y5f z9yPvLv7}GLKeEi5*3WUk>T%4uJ?c2@MeYLv`oEQ<&7~B6FHWVV-cFMXY?9Rif0aBr zNvGF#E`_E}7=Iw*c=}OB3X=)WHKJatXk(XATpyK(O(0 z@o%>dTOoWV^8I?co97|zA=hkkjm<9j==0^{z9{;mLW0AF7YwqRHk}_^fjq^%OdoqP z?$mud9%@Bk?!Y@aFW@QufdR^Y8#!fUw$FX9{keSfr`fD|fQOHE+zA^q{>y>%-<6#g z!B^xVB!4PF{rMV-m)F?;HfH(XU*qcjk@SC*u>SP_S%MW9ZnCt)h@I&*{&pCD4DIqE z2>$;=08{+`XX0ORmaD5qm3fnn&0_gcfwzy%7R}U*=^=E%-_iuZbjHQ5wQjvy|3svL z_`hEOyUMwS1Zetc$ZMC(Zld!kf(Zpk8y6$B;2kBa!_|-1(;nwSvS}Fp^T6`wg=YIS zcLpCVL5bj{<4|cVH`LbWQS+wlmlAO|Q*)-7XP)JJ`Yy0__ewka*BfhDzf2Ba_Ip7k z1OC0Z{(9w*FrswM_C2O~Xgik1+6&8VJE0Aw%uGR>+ z1I8$5o^6YZNXtTr0H-!Mh;1v|2=B`EypHZ?B~q zw6*oQatgL2MiS*2VQN46oYD>#J`wYkMnojw7^v@&(H8bk%virzxu1MlWd0htc-Yr@ za@hIWY2dZx()d-6+aX|(F-JySK?a`Q2xjgp0TDypH#Ms@wmb6Q1BuR3_{}(@k_A&_ zIXUC!*>$+Ggf#;K0;C4_$QYIW{1OzdgiP^W4rurX^os}zPK2q+yjE3dfp))!nd6s6aOi|96)S1Z9u2{~Ukx;5i!EeedmKepT#(00UX-@ad6T@}( zW;o!^G`RkW^80~$vXrNj96QvMKopjMEcT!vs;yZ!zNu#GZr=F*5roBQaH+UPhFq*g67IC=H`H3DXc0K_KdQz=4E2$L#ZCRHr#&78SHB>^nc$UVl;HFQt=jgIp_g3ebU(=57GOi0b zmyINgapmGroLk7-m{O5*?u@%=xK~QA7MDhB_R8uCv?*Pz-T9TyD}6yT>kWg8!i~Nt zz1N3_#U`ArQqRjv`#*1S#fg+_wHW`B)qaC+?J?sms4$Oh5eAhEj;rpipF(1{*h1e0 z4$A48DSdDln&;F_+4!jOY;}b%mMMon^pPhQsK9dlRzDnO-Fvsb^!5X;g|3S(g6osf({dmTe(y6Edd$!sAf?9q{JlhJgGrg!=GjjgFb((a(2nuJhhM~RG5>8)f9nX;HYf-#`FK!v4b*d!91ZR!j`>pKfb?_#wX!iB1E063T(}Bu*oDYVHH)~Zv5qo=ku!l zD_+o09@wgwbV_WYPG`>6`SVPBd<3!AsSI0Hh?PlH9~EAksVI4Q4I`al9+YeB{itS8xbXz% z@hJK_WqEwf{F}b-`|*f8?2X@h$;m(E6^PT^p{Zg-XncGQ9?>V|(&g&w=!)uZ(u?Cl z;tEw{A2|!UZ!4V*oOY0MQRVOot@`)vDRT{+>Bv2QRrRw}SDSO8nXtd2yZo>vvEQ=< z`BcfWBKjJtI+Q}~qmrL;I-FB^Ag6vOx$r1}<4Zy;$7XKS9iOKId?}?nkH+S4vDdFB zn~N;v?(&jd6%8CW7n(SwJn=5As(OxSInwMK8UmzqzDjT2yrHOl20f!61p&6j1-ZEj znv!cb88(q9`HIYE^yWeW3(`KT-&=;m9}fv&0W(0YMIeEds{Lr|@7e4xPjT`JK{wXa zKlqCNCSkgo`9hdRmFtndq(x`skSFQ(U%p#-gcMJ64e`-U4duG)HmiM4MASgz)W5wF zh|jVPOC&XIE^sZ?y)%~9M|+icSh;X^U_~9A3_ouiBRmb&a4{aJhLt7Q>=te_$7*fz zVeH-Da}5oKMcxRM-C^BaDY`Y>pqIN^y~32Ps`M~rLvxo^m8*B#^qTi>d=%YoRYrfa zX9Ad*q^~Gn+t(>DSY5OukcTI}dflN+u7G!5<~0?cY;#Xn+#>>*Dj@ziez%iSv-) z@k0-C$>;EjfZCeSsYYBDp_tXG$Uw`gv=5NW3bE9Xz!mG~h=78QKmk)uu3MS~9Fu*~ z@yYNf%Suv?0)Q_c*H=y3xECLMqQH^@_9=$!?L4N9Rdv(+6nA$xE1QO{(;Lh4>xZQo zqN$OZQ#p}luU@WRL%?~cvub2H4_EY$OeboD+y^v*VY__@%ur5iVH z?C_reMZ%w}yU1JQPWFCx7v!u5ZyU7I=i^RSVs}f=0RtkfI%k;R(Z)y$Ko!gg7v!}B zyc308m!B}8CoBxgjd`f4spC^qH@|mbLggg)S7PO7SG@KX1pp{I5r$ru5T8ceE$n!r zk#hvNZO(dq2oE3Vp)=$E{Q2`R>&fEDtQ4Oad};(hWRpp0xJ2m_e_4nU#l8BaLGV@HpEX-6U~vlYJnC-(lw z!9^jQs))u(u0~E;1eNtdR@0Gw6*s>Mh2B_(ThNV7_IO-~-B*K2LW>8AzZNX2gxSAr zeO`wcOgMaxIGk_4zhy)Fdx(esGqbRoeOaWmkX3^E%Vc&QE{ukyOK_&#eMPK@aKE^o zJ$1s0{A5rG_H}(@AT;(v529ozd3GKn6;}cI68RJ>S01h&z02Qm%c^QBU;LHPa~u8o z$e9h=oj|Ea@ETI}K|)8=6D}Q%hDGe`#2CtcJM$8>0klqz6c+$e4%D^H_@js$A?MqC zz5r(6sJ&1*9^AH`Bm}q!<6#(_TXYryhgkn;;&PylV&(h$16^j<+R=!7N>0#u-$^SX z9B@5-l?}rB&eS<(Fp7?LgaTOejHd?qthKduKj6J?1puM(&hKhw%K<}7RD4pBUcJ@uH(qO_r2PF4PCG1Eo0UdDny)t&s&lXNY5h=`rw0NVtR?JY<8zK9;+?0QKxX z0HosNkbS>16F zVI^I+zs-aMmd5U&=@X$>Fk@T>0Soaut4zMj?U z`NUl>{;t`m>)tB|yYWS1pTEpc+(F4Q*Ou*T<|CS-K~%Nk>ArStX_|n&^$t9Nkc%(w zh0>3{T!kZ1#Sp`X-iqH^l}8k1*Us9TL=G4t7BhN4Bw_k}cXtzb+N@&;`}0UQcf7KS z!PRrk-g{0qL-1&iteA4VAd?1tg8lR#m&$tN8>ueiP(+h$`S39akRfr3i%&6uLrwr= zTrI$7{~pxXJ!ausu`@Es8+R$8EfW&0k%Gkws$T#;sWZ7P#GP4RI@|-_D5$-C`<;={ zXC+2r^;?FM8-;5tZoiAtD|dOy$T^8d^I?Y*)X%eG8EOVf0y+aUee#sE%@I8&d0g& z{ZI%2AmrSMFrEtR?WG?SXX=9&zcy^%-m-kINWL>M=jmeWQn9I~2JU9J)Z6xhwjt54 z52|inNY{GKdHH&sXOx$ldTyQFn6TP|CE1fO|4lYbd-JmDl;JpehV)Fvrg80Ixy7oH zweo6%@5&93QRS1hzUw}yFB_ZhT3*$ZuL}lonV&-yO$z!6&1uwGWQ(mUXA(6G#mh9T z6bsaai|zf6KPC4`w^*vjx~RISjk#lbnZ`#3x6Iy5QT1-$B&)wkvvtRz;@B!>FX=@EDah9D#*|81#A{evz#Wdc2XRSJ}w_$0Ys}D@zGi;Q6;SiRe{Gd5QRKn zw>Kx}FYb&(AhJG%jg)hPG)%37*Rk#CHLAe=Fb`7NU5#+()}TuJr787T;xF$#cY)Lg z2u5ypv$~A5a}$EVwXhBojiqMoaeHe7&QcDykiXsd9Tcq;(6hSaozn^{Tfe(d>}hK< zWWbxRy)py9$m*z8-!?K0sf@IeaZ5ihPX*7Z^L zEsKNamsb3jxA@_=)($P+e&ZJ@+#}CJ>?&bwZu4?ZSdQNLB|F=4+yErs0%}a(4bjNo zXNET<1(k`FKJ>?|7jTM5XfeHX7-vkgM_2GYAO5t>Z$n;+c2jMLz(W3ITdH0dB$z8zN#}vRL_|xIo zREtlp1>Ixjb;K1y5VRYE0yN}`Nuquz6rps4lqlF_=>opnmJ_E9%wW7g)EAi8)4iMI zpWsVfK+X7f`W9kmLQ0JB6NU0-^f>{Klo}2Ie<}(e7OOX5baIOyVrw9h$?3IP^ALMo{&Vg;^vCfcZ)G47|f zL*`HG?iBfYuhSvlTUk?Wj*E=cK)4Gt@JjiQq@`Ejk}(ETo&I$;yK!goXpWz;cexgp zzmp8rkcvREg__;m)}nQ_;w$2|xv5??*cns&<!``AN8TL4x zqab*!k+EV>*4Un039K=n7kO;}x1Czn7$69 z?6VdC6WI+wjs&IfYK0T_`$!)_9<5v7Y~BuV=#cUqJSjU5y%5jIbaX=wZto_&QYorm zbr7fsB`BW&z}Pa_4y_Hy%e0LjtXlH*XG@K3XiM%!dTNlDVcwkF1PM5x(a*Xo5DgvI z5MIdiu8|aaer;&tie^rhw*lGdC?Vbu4>-hq$ZBuU3Chy+E&h_|kr{Np<<%^h3RL@H zv%kcpL`-dt;p!gb`SvcLB*X4wfOeB|*(c{)Jir{lTG*f^@<_$AV(K1G>}3LaRWAia za9-o?LKN}biJ#`!h*Xp*9n2Gk*nwg<+3M2edRsU7FBGb;+CNr;j|HZ)6(X)YUa;SE z^^5){G+szJk7}lT@(}78aH2|tS`Nx~f|^6t*Pw-0MSF2T_F&)<6AHpzz?SpxyUFK_ zOyXw^wX6GReB@rJ3f$17(`YlSFtS0BWcaV!1bMFv>Qa{#uV&!QdNPQsjZ;U~;-iVI z^OlC}w$`^&1MtyhTVZ3g|EeMWyOOjY5&RRV$Q)r8PMTNWt=`+RI6Q#3KCdF3c23b+ z7(Z#KH=Z~IV0!Kb@P_!_P9Um8V)w|czCCb3q~$2e62U6xu=M@w=hG&8h~^wvcSo+d z4BI9ZK6U@W-i(G|#l!jvDHA+rDKO(gOi$(Cj=qeb3Ye z!weYGi#tX$6_Rx$weK00Zi>I>sg~ zn=X4lCJoBf?0yy07V6UMIk!PBZ&bT2P!^&6G2J%9gPcI4pc?We#6R%6BFQrk1*MBp zE6n-HR0ZPfe6^d1&Y0zrqZP{S2f4Zr)tkLAvDv}x9|><|{L*C`a=@;>e`46?7h{>> zp^ouG)^r5Q`l%_0IcUP_P~BZwZ0ST3T6N%FXjS5RXDkQC0!O0Yutve>5sVWF*30{9(vQFX>Jw^ z5MbQPg9=$jXNi*e4c`z9q=ywcjRhQmTMj>FnSeW7vx>{3`r1yWjF8${GkZ4|3PrXy zhB9pEW&@9gBpk2heEYUJ<|o<gdVNZ8B`N10k zw6Mr%>otsfIaj7c!uU(W1`U*a7LbudvREJ~Es|?T|7tInYs__I1T3{>0T$I_<(?)z zGqfY1h*R5vI3PJ)=~LIE#}2_T*oZ-pv~T>)47{S?bo7N^XF559<-+>*@v~aqhu6)H zgFr_ZHlAYN@9gaE;hQB+TN(4!2(C8vzhWznrk8bv@BfFctB#9m-P$w)0tSsRD$*q_ z9g1{Iw@66}4Bd!GDxs3}eJ-<1 z4Cly!%yWrXWL+R~;{W9s04lAFgx#seF*8s?9j=uu9%zJUJDi?x3}+a( z_@dj*fuU37{D9Go5SM#99U{N4bZ=E2oS+&syHz)p=y2M*x>AA&n_!*F4 zT$OX7DI0wxCcEllH09XJ<8 z)jQg>(3KxP-7LW+oNI*8;?K?$bqWDV(ND<`F)YR1VLq_I57IHg&SeYOsYIeYLePFj5tf<30l+5CnwHsAFJTPFsBjVv06n$i z4sM{Oq3Hp{Ii{v17T$s{s$JQJ00MRf90IS{($gl6OX9YQCx~}n=8F{W%TymWq5~n4*d04Dz?&rfeZQ1+PqSqSL&KW5TKEAQTFO=7j+>>3-z#Ui!>H zJwjc|0nd4IVmi*U6Vrs2bRQF3fB#hndh+@Q|~4WC*K|J zZ5LF0v!_+~;xF?pK^(kYb?{NC^?erU`y!82-QU^4W}iFdlHRu>WNjtCepw{3cyxiI zrC@YA{6Lp>aZ_E7N5S$9r}LN+D*XPUjpC=!-@aq$8~UC7s?|D)nP1FpVRHwwwr-1u zaM_FRO(`id+3D$}6HZV(q2EvfBor$hZzM1BCLc}^qE|#-`JHQBo^H{r47|X7@Z0et zlKS$Fv(sn25vgClit!G2I=UWRNCemM4K)Ys58bQdVr^1;K%6z;0;edfHu*A&KpWYe^A@r-QL8T zk=&vU@??l_G*y=mYjX(9uS&uFZMu4kXcO&Q_lD-|{`IRDD8{R+KW`Z3%Orx%V#frs zEhiJ#9(C~lVOXruVp|rht*I#xDiprr=33kY1foig{vzG2>h)O(DxxF)yR~Koh@mWS z3UmDHebG*%qH2Yp*Y_5Mfn`#W^|gTR z-4n5GYQ1$t`k%k|7J(B2@&Hd5v*1g_2SP+ly}UNRPU>=7N=E|b6d5VaymQB`XH?;o zvxav!=ze=O2LV8!Kmki0HA0M}F1GvWs*Yykd%2>-p#2k@g^!_ELzYjtp@GT&rtc`GSFC-^s>teCcR2!Z0umZ>U(p)O;(>%y5_q# zr_Sn|4}X0c&2e>Qnv&KbII?#@cxD{#)o`6=w(oT`Va1+m!wPl$(mf3cQNfW;)_HT+K=H zr|^zvd5Rb*&KMD3hL1Ekl@{t%=>?rdbxnlq7R!W^uuJ}E71Ld~_}}3KK2uJN9FB1g z*#uFo(@IExhJ^P@_+9KRfCD@M!hEQaWrxrh^=7YggBJ#{jKu1uHCs!lC|2T+X=x>{ z`hO<-_>6M|%}Cdo)1p}EF3xs8T!EgDudYXpE32u|h_2b}=OSM}%aah(hLP?5HYmtw zWC#$)%Pb}p!|wuDZ^|me4N$YG<0GNfP%O2CtNO6>PU-vhGGwL7SF|+FN5myC>&LwA z0ywXp!Gh7%QTIVp>*BvTZsMGta!b}YPCC6$>O?&r1&&bj`}#9MB8G-(Oxl&Q>>M1% zfWWMBDlIK-1gNmdyOo>KRwu8w?{Q)QB+EMl1ZaRl{_5>EnSk?mptR}h^o$I0!J_

    {_;_d@&7tz7myWQSw<(w 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%0AK2`$~3ju+W4QXcsOD9FtRg! z@JS%crUv#99dhstpoLi+9KU(WT~nZw7 zF`c5+dhw^B0ck=|M9E|eR6SY$TH+`A!i^%?t38b4ym)bZr#`_+N3r9AbAh7<39m2; zo)u+UpDd#doi|}(Ume2~xipgVb~a0_~f7L+I|06n+)()DQfv^El zHcismhnN;vRM|qSCEeoWnOQJ3#eE3|Njy3xfyGCtk2=@*kX`Ce9lEmejmj)XITh)) z?d_c#$?jHn)n1P6PJ1W(YFRfy-j_8c)J5~{O**flG^l$z3ET%`CMhWBf?$&5xNTy>2P7nt4}Vbf zn^fejV{p8z*|5#Vb+u8HuUv*9aEFsHpH~|ZgI|@USHJp9-(IARt5f#;3ud>9s{3fB zD~J>kt~@OnE`2Sn&q~|B<*7m5l0TE;&t@ianV241L-kFlzVSr8rab^6HgM4o@kTYg z`!d3mDE(0y%E;K1lDu151>ju|YfK;`dHLg}W%hmA7s}zRO051HBd_dKW(#r-yIVa4#x(buw`Tk)U8ZZ5|0n-GmFHu1UK!f%a|X27$F1b(%3klEE?%^3Pb^ zP3IJM<%;iVvL1|P3Bn9b|?(QB@QIYN(knZjp z1f;t=oB@WEj)9r8dEWn9kMMpv*ZFk#z%?`1%-;K6cdYuY-#YT=xqz(0)liQh)5CSx zojT)af3M;Wi}$qn-&inoDkb?RW-F}|Dhg5hN#kHwLZHasE>lXhL3BbFW3it2(kgUv z+KUqr`yujYcZ2_!i@v_GF}U36pravySgQ;-`po4;vB6`(Dv(~xb?(k7FEyjXM8xi_ z`-xIiGTU-9a?aT6)Z<7=CqO$c<^g&)&Um+}XBcJaN)^6c?_@|8G=Go7lI-|vwQO9#KX{zAWJh*nmqa(I5w2j>@yH4+Ux1YUbn z#+$WXMH0XE9C)CGSnC17W6~=dWyS}k*GoaHgPKdGo2h&Nw7#{h$SN#1Cb%o}69;ow zcUTBV0;gqBvH`sK(?nfe`q6##-1Fv7vs#++wv|>cgvEz+QiS+a$GnL1?DJ~$uayqM zdz0b6)}l8hDUCe?e4*m99a$xaeIXbVH1^JgE>O@@ z)R&Ia2oVLTR5{@$-YVgLbl6bbY9*WBS=fD~c`S+)RT1?(q^gmN*+3x5lhe_IRGWcX zsNEGphqeeocsD0?xCKwjR)W$YbvPyMJUx$ZgJfk~*kLKKeh2tlNFc0?2~W^SrT$j! zK@~5G_$h{xoM{RuC)?V=0Gj|$3is^0Q&SJ)LtJ%>F^n|}?gTvayTF;_Gnx~hplwB8 zy^OI945Z_{r&9dn*|F2L2cz-AB%uK>u5#|dj~PkE;QqR6)1qRgSlYISB)@0h9?O-1 zf3Nf(91Wi}N_QKrQwTr8(cSAME9}ofXgC~wEdy}+(n=bUjAf^MGv1a!^>esj;iIe> z{pis+cbg2av(Fv(_PR2WI&ipqUtb6vL4nieqA(_UWPXu2X?zBOQa1 z&DP@lvTSHyxIxW3lX&xK(SchNalVtobhJX8l7%%(REQ~iS%JN;@Siu5TDaV5pdL?O z{mVG{Tik}+`(kIF9q6Zxl)Ff4sOEa@{a|q~JB_4z+#b&tp90-9iCCN_Rj3Hw_Fflu zpSI$)%Ifqs-dA4-s)b@|GbGx#l*?dWOF7>w`0kj4!-mTSS?G0AzAE-dO=${hUB z#+{7Oa#b8_H~k}p2yfm@9ICR3LCW+;DX7FctQJXI*x1qw6yDa%}VK{s$3m~7F@=65)NGSZ38a$mOI)iZnlc7IR;hB`a>KH_PBj^ zb~4=SAhk)vT6`y$6yd%D`%06Rb za((7$(b3>x^cKy@;wjc{Yw}#sCoJ1HfR(O+Qws~t3~(LkAeQyHjd|;$c=Ohn-CGOv zixlUb5b>ukb1u<;pY{HE3(1CuJMV19X-3AOenf|8UsjWjDyL_u@g|ejCd6j(#wIvy zPbhCsH(wK$6cf95HOT<}%U3`k7-KUR7ng4|xzq$>l?F@TxT*9z)B|Vk>(&Fim`>VB zZ){90IQhRqLw{f4;GK&CM?da0P*bB51RQk_hyrj8_mFgye{kim?4;TAKq%TK@3i&J zULBGm@dkee@QTwV{#b{P{{xuvhxY<}@xv;=^#7<~1(6VdvwQA-ZVMWG1O%0IF+7h> z20iiisV*A;`1k^U^%vk%Uz-33j)bfuSC;<_dVxzgpf6HOke@U}m|PCazx@S+zwDpb zTOhXfGAiNcKY}BFI|TlE`#A{+6irMHb6=$au3^3bXlF@OY$z`C_y2K8kP8rfGcZ-? z{zF3lioU&60b;*zYs{~vt_4qA2V%cT!vCX)oJ0kjz7c+w%_n7u-})B%i!`L0VT&fq zt+uXpcGg^Xmd;~i?Th)i*`?A2B>uVl8V?Q~yX@6uDEO^k0C_w;p1MAT zT%dl!ZkquteBQ{z&c&91jG7wv0TTxY2cxb?<_rE<0BwyQUo{L5BMVLrSAjnZPlnO* z6l^yO4 z;3@BN*lh^ukdupCwuy1uf8?J&LLZRN)EzceX)`%DF__TuKq)qwe%MioLG(!@ni+{0 z)3lF8`B*o%f?QpfvjntlPDE{~qGW;wNAJ0t>OOe#M<^T`OZs^`Eb_5jfA0f7XxxpB z`6fM}EQ3w6T&lFJtQVSh-<>dA$fUd`BSYc>HQ(Knz|Seg5vG=#0Qc0&HFoitLR)U@ zF8pFy{}6&^JnE+JEvVs@o62;3O)!KxdXEX`rFh#tSL4C{T+Xlg+1(O@JhdY0uuSKm1y8Fr3+qTvU4!Gk z2XWf$^q2iEOcu2AJV)=T_X8%bThhUQFU?i>_v^IxpjySBg?%DB>@L-qbm)$MjTq5?PncdON(wrLpAaNrRq{Ivg5S3j zRUoWBW{P7(nt8u&=w@(jWqGIGZV<4yu@x$^H*tf}= zrD5=Ie;pt5;a^4QVV};?<|C~GX*X6rd~}_+oWuN*y1Twxoop~?Y$4juEXuCWIHa^}*R%I`hPuzmy6!)&Yh=S8uBS=y=0-K ziB2cYbt~P4(KIJveInVTW|ywCT-Fjdoc^V>6SLDpG> zVbxp~XM>vF#Oa)Tsk>9)mMd1 zP-RI$yR-sKmRP0t1fZuL$}wJV@J`U)v(GhBnZL40q5^}ccf%MDpJr7yqgw>b8r2+s zYaxcjSA+{hI!9612Z(dohB@>ghBnfEYJ;%zrzWI+rdo!^ZCj~xC=CAPu)EMO?{N6F ze_`6dR9^G9{I@HP<$7Dg+hNEJcee!VTh^-ngyC9WDmm*J&!%b1S-K>Z@)w zXBBhvwOhK(JyKD0gi5hUB(0~ikB?6f8*2wC!D)SNGd?3zx;5trhCAg1`h2?Apo|># zq6trxO-Hc;SFBL|ZT`_~EGf-Tb6Nz^+9xA4jO09e>r*wGLTJZy9iO9QhQ5ZNL+@wb zn;+&OH^TUyHPCCJUSlcS2qSGK8`K3@W#+6l!)PrQI+bqf6oFZX8Px{v%iRBv)1+N;YT5CXa&48c931~uF?v^clwC4 zmZsTv+cu2xNm8#w{0hn!k$=te`D}7|)o#xsUyU^6$9%qj1?k;lCka)ynFS)=X;VtB z#)U;{2bUZ*vU`PYAapvjMu9SWw?xob-x8gnzFM#+Ef5)>$*5MD+!mEo7~SAvG;{98JyH) zDwO((!R-4HO=|pWJ$}>s=4d2`I;;n~_=7UDhpUf0icUi_6fu*P=S28%vv>CN{P+6s z(fz(}!8aSm4|!4NWE=vEbDCLJxZt)YY=i?0ql<0to2m{z-+6mFc=)hS%qM?4kZ^zc z$%hC%gwpqb_9h@mUBdr-A|m3&`os!) zr2L-fm^jBp+MjC_Qw}9k0_iZoItYWeefq6D5$ymEi8p8;I#m~-WepNouxLY#X?Rdl zf@}uMpHRn(&SPGSrg&89rHz-m+38qS9k^91e%-aMz#_D$40o;wYsRL=;>7A?c3MuJ zvXY(Vd~Hy|zTntE$a{NZM2|GR7}S+qN#i;U%}Z(?T4^ntn5=z5V%M1_m^93X5UaXJ zd4~Fon!b}aVNa{2&0UQAQG+9|xS&i?ZtrQ1U7RQ}UB{Bo+ zE8B}E&M+k1JUS@8T0G1vX;U#gZmZ|4*mG>;j-3g?+w3GQ(scnMRW`qcOeu$>9iTk* zZ%U6x5>zM-=6UUqhI{SR(pMVZ&!~|VsTB%)Una@9CNAar2J!2Rub=vS$hetfYaX6; z_R(RT`PuGNu%>(VEH$@)uI=}2%#ZhWkvxvD{-TYrZC-cSP?V#QT(Ppv^qjz;vZD|t zJ`grT1)|}nAC)qgjp@3F<1v@>IH{fZChhF}iO!}M)rmQABpPIx{QoS ztFjfy8^x`RzI_oNo-Kjb$F37`Piy=^srrpatXtncb$AbM6%7U@yLKZpu>A?y{(Kp=>W?o15v=nrEhutY-4$%h}B5#oXYUd4Q#n2TAzW_19L`WoR$>o$~EYo1=;b;+G>Lced{*FNOMmJzn1 zktYOrxW6R@a;OclcDC;9g&hRUt)NQ0+6PGmDw|JJ+map|@Vv;Mc&u_qHX^bJjjMSL zI+pyIZOj#tY5aAgu7cuz&*yyFlex7hlXev2+*Iu=vXIKjTj+fAqI`9Im|kDv3Y*oY z)dJbymoI*g6nNqx?yqWXt&U3y3y`01G1$g; zj3P%`+F^C(Ne2DbTye`_ck)c6HPiyUj^t)DDNrI!LY~zCAkergZ<-fGLUR=Nq40yU z!sjd*pRzP*3#U0u46wBRawNX&d%tsyrv*>7XvWSqqNm!%h{-j*&O=;$U*YMp!@or_ z5?2u209Ci&q)x2N`dOfEgG$YKVft(m6Iw}Lcu#9}EbCy;DO0)r6kZ82KXD8%p7`E9 znEWF|O>HwbW_1{SXgd{HYx1LpqPk)zYf~i8{G-)xuV|G2;26Z9i}r-PNtx%6bDVE? z&IEDooK1MevRwc#W4KHroYHA=X|KZDmDGQjnBU`8UEHms3H}Xc9psOpH^MHR02xBS zE#l0J&Orb2#Q%CFYYDE##i5y;7vgeT%JtG5zi-#A<^=wk0~e|mD*&*JzrWYi$MX&7UyGN2SjlEK9Vu*PNTScJk^Z{&-jF?@h0-2r>2L~;;c)} zdLj(kY?;jPSEdSD7RYp@c0BXPwQo#E+e~^q zi;9B)%0=9I8iq|WP1!JxjV_Pg}8ED z@aXVYpeeC%?*|dBq76aAxUebSj(z)cks6I~HsSDIt9NqX>$e=a{yv$~?E1e%ly$90 z4AKn(2^A!sJzflBr;1}SMj(coY|`C$lry+QC8Le;j4ZvYM(~s}Oyq04jD3RLyk<*J zVilg}ARM-alurDDDnD==x8T&u1GtE_=~^R8Ey!JuhF!RGJ6Zm>`pW0j*PMoh*wmHS z^)zBxjVatFH0PN;>x7h^)G7KP)wWU;a}Q;v$3L=nw{j*_h~oLHW=U;n(g?~a8+q1C z>Sy8u)#oP;7+(CSF@8%Aj%xOnCqEe4|k_$Wor!(d6Ell>d#Y)mj|essR7E?EwuuiPOm1 z46lrx84)5AM0 zQT0qnYmlI(JZiBo;?~LMbGv)a5J4`R(ViVWXVL^5(+!%Lv#tldoAZniO{Jxq3tH46 znP*>|lg7q3P?jCvVs~z>&-s}7q-qxs&}y+T)m6D#XhLKOZ~7uPEHpC8l=53o8*gq( z=6kphX+``vJ*(||K9MTU#>%&su8h_x9Czksv-53>@Z?qZF%WCX>EZk%aS?lnnf#<_ zp0o4e>Pu!6 z)sAN%46uaX(Gp17^V!dr*zGj1KlCljau_&i%3TrV%+Q%TYB!m*8}tH3ciRWKs++|w zc$~L_KqaOK9j*xPo*SOXL-L&7EpZCDOC7GFQmSNWgiNE$X$prA9~ly2uiQ5I$(clb zdnj?ESwx3^Y&#;QNz(T$p6sP4-l@?vVNCzG^~6tVZ?q`;ENyg(^7E-i?`=#PqH$J# zlo=Z@jY6mG+AuK>4i4m_BmzkZ)tq~fR$QZB370f2;yN5;@xld>nA}=;Q)Nk$qG3Sp z%NDClvi9svNJX0|dy{v?a#%xPXnVvVjB;>sZ z#ICl)POJ0ugx4nWnK52940lLv9HJ^!oK79NC3+I`prs@OY`u556rj3(wsZ^EqH5z>UiNO%w19L@?ijxqF z_Wphn`>ebelrO#9a?YHY#MRZ8U6&+w2lE21^CEz#Gn!p1y=?E;H)N1w#snV-DhE>E z*)~uZYiDVzU9~IuwyjXW&P8dd@5YPJc{IhjE-3McA*#>rs8Un;Sk|N@MJxoB5S59} z%y=amvO4(oO@M%B614rSzH_t1NSAiyj}#Ml5hv5CwVkxRT;e0G&;WOFrXL(iQwuGg zo^44wOgD14Yg(-U$-XHX;Z?6t;<1XLMHX%EOZ#UYJ`>R<5A}{l&=ajCHQG%D{AyUF z#$<$C)a*?tqj!9E(Xa^ESA|Cyfx<;a9b_`D2U~b3x+n20Ia;PkR9lc82lx-V&Y|y-*HbDt7Ns9BkBLjd!WCqor2K6Cgn`u$-3kn2e&*d$@vX zy}xZ{+To?m6pcKq!G)QJS}eNuo>ginG0 zIjv51=ibAv%-Tw@pIEDj>9nO}9gO1~UwQn76)XASqUioFI6i&r6ALTPe#+PEAUx&LTf=Ed1}6<-KNr7_gL!*nJt}mbQQS8Km0jdbwBK1t$r0jmcREuHs$)MF zZ!mhod@bt|Hcb#1b4#7%mzc8eoh1=vXalzA6k5$QxC<|rz_=Rcqp1ZK)OliPWEAak z69Yr=x$<>kQ-)wg?D^XOsG-@ou5(;RvY9En{neSvEH!$JJN z&qA*ONZ;#XS^p&D`A25szw&Lj9{~A@TWjV2gOCjqNQBT|OM3M8?fCDjNqvAuvhgN< zCPlDS3)) z1CaE|oJ%CVC8ke~fqG1i8=&*&u%S0^6{lPSgIi~0O>WTt#c}jsL;a61W9$WcfU>;2 z|DRX+r!47T0og8t8S{IWrTPB)49t9i;D^I_{|D==0k*o?)5lxofBNu$-C3G#V0xMr zEGG6mbs+L+=+};vg+*?9R#wQwp%Y@|GuiWx%s^vGF5?m2E4I|IcuH0l3qRFLDfCQ6?FC8*CKE zu%K&|k7}LTqTwGc>KudQG@=kAG~!@{Q`PGK+E^EWdki6>zvnytJ-hk>7Xf2=*TBZB zQ^H&rz?|QK{!;wIF#Fd+&Wr%^c~?ISV~LolY1Xk+~DS`|wwke)B*|JwIbTnxecxh?rn7{RYgeEYTO7k=Vm$u=7j$Hrn{6Woj zBN7%SNfQQeU!61)`+$Iob;C6=YwLmw`WDyZ)h5*Gx-mfEVkqEaX1qS!?{mmwZfzX} z&?E&KU~P8CaMEh_o=|O9rtxui1%(0UWou!}_EE_0YG;m#IJiS(W3FM^{4*2^b7NfB zxO4k%c8_!nD=BHWyW?)g^LbH^6bYM2?S%YS`vjNmHt>B;eT87(b*=eue>`G=@%We+ z{$&kJU!a2}JWKQ(;iux^aSBC#sV|AcB-3?EP4qsTe5}BuVcl+J7fTH&IMs^UTFuuo zG6Bylc3m?vGCIHBV@;eS;Jed$0}SqTRj4G*^pXP~+;iXUJ|KX9m1x7p4&R&>^Zkz# z<6o00uL;J&Bl?^{cse!SxGXfgO+*nw+M4{q7ihH#|Hji73iLLdeAZJL^ftebr(ftH zPzzBv>^7@L7PRc)U(0?K{$7*0tkHy zR>@O+X6|8CeB6XuZ~8fNOUqNg{12`PMyP6gv z0QM8ys&2VXG~V)f5y%~B6v04vM|hfee4T67ggT3icR&E``a!A+SP$K>Q;&) z#XGrQKsO_h6s%nO!C$m*PHxf`MKE$1i(@1(C>E~c(aUJ4snEl3hZ1du@(W7{@CJ;v z;B6|O$rx$*_Z4owb`25I9v3#-a}&weeyrE1aVv6L*j_A|2KoN?FY|E2OXr^sECvDz z3kw^#BOV3{Q$r#mc$N?FHmEK-BdUXzz6WwpJcZZ0@4@Q#`XT^8`kcnw3DTbxAb;db zq?iOSSc?2+V9X~gv*Gvk9Le7-Fe=o)8d7X$pP zlW~&Y_ON02$1WOo0lk#%fi|n-YHISjico<&1CU0Jldbgvx=ETG z<~W9xNO(u-Gx)Bf_j~l6qE=?mqInFVuLxbYqr{mvO$~rS%q@Mk`4=OB-@ z6N7TJ-zlG`TYS>evV8)?fBsa;V)fWS>B{y^8%YjD%azJFOyHo@?o|h+mXz##Fq{=X zNG-c9pB-yNncp=0fQy6`q^PZ(X!PC5lp8yfjp?^Z_ZMb|xi{gg5FI|x0cZDN<%>=3 zkZ!pfP<7tmz3ZmzS$#gmcVcfAeFj@{$cfjXSNj+brwLSCi$Kjkt$I7=rkv!_OHJ)? zl-V-m_PWBWj73g&1{FP{J5Aep6W&oZ-WwL*NOaP%Cy86QUXZEkp2vJ<52ve}OW6<@ z;bZDmNcsNOr=DKV!htsJNUG z=&QXTHoPrEY1HPhCyF}$rKG9J0zlrE_D)_sRd(2vKZF8wG_cb~`tSUFn8FMh4OQqj zho8s#m^#B0I60~J4KXlSi)c2#Wj~X!6)teFZP25Xi2(Zej`@jYT2<=@-yzAiT@Np? z_EyS%)6ZFy7djrY|C;HE+*ltc^{V##%ySKM|I=ELX7$$tS}aEp-4qOru!eSlilmg` zK4&tOPQ>~BU=ioB=O@#pvV;wX9m}US=3_6#^YXgkh4(ZVc`J5DZq%edec|C8KeYVQ zW-`y0pMWQe4dwXUcj7Xem#YEWN`J1)jO-@O_NYc^GcL-u@x;U((4I#9$-);3^)Ktf&n)fHZ4%YHIU&Y^Yko=q+|*5+3Z^4uZGGRwKXNou+G{ z98(QCr4!`!`yE03<%AfPljc+7BVX$_3u5|Tk z)EQfjb8AFwM-hLZfImoLv$L)^m!yg8^$cFKL~nrKXdkF#!2*r7rz_XxPIl+)5|_X8 zkaiIoPdXgrXgKtuyntdV1V$rA%?9GdBG0EAPO2~B*s|H8hO4N_N4^$t>Kp476pqaK zHj3XnzDyc^P%ccMAN5e`eV$Ltr?ktV;&r8^KZr|-zbS zql=aes^5Fd@uJoAN*NB}%pRez$dqZ-mXx)mAYbzI4AhVChn4_+S-C{i9gUu`(*=$x zD@%M55-Aw9wCr>Q&D~-@sLo1HjF21w@6_%r|601sjUhaV_5P)qw}UG?68oZ|x%GAs znQj&s_^7(VdO(DV`Mf_(L_<00!L}fS4$Y}da6U&d7%5-VV7?ES5SAL5qeq<)wul-e z@p%g%he|euq2Zw?{%_*T{OnpD>!6|R$)uB`1%V8n!b;0jn_DFAwW*RKMc^Ri7>)?M zWh89$l(fd$v$do>ZuXUG&;D@^{iN#ot~7i(~S+dCxkJ6Hf7s5mzey2KX!m zb6axr^5DUOTcL%89H!py>+9>qoAD{No7M~KUO98*@kUoldJoyFI$>eexo$`A?(Tlz zT(T6us7w;%;Wp_{mJ`!YJaVq3<;xKVm*8SsQG6{hONkVxbop~Jiz#!kw z-KeKp>w?}xB>PXX_7*KLCV^zufnDH;T1?mbaD$w|1+l0PFhxU0bX?|^v03T&ky?S1 zgcj=E(Xv1zXZy_j0${+ecVRzGiAyq}BeSHMm({$J`-{m3FOMaI+c2^CNFZ!&r)59| zsS$$cT*?ocj)U`w0AJlBB|%pRbnh90n~`70*u>G$6!SgC`E?|6(K43>zRf150A=K) z+3hHK{~I+I{m^0fF!jausZ^6l0s8f{RSmDGnoXiD555N+!Oz<}F!AVyRD;6wPGc{wCU|(k|ZBx>r0L#do^}Iv}|ILP@KcW2WvPa zy8^m{E#&M_KP10^Im{UGz}&{l`Lv`@end}|J&qLu*$gWPqAo2Gl*{GLR~FwP4zjGq z`+bFD2+-{+;kODiaS3B$Vj#+mF^0-uGc}763L7@AE>4|>)5KlETf_Uwsx=mtnKNbI z6)n1M>@%Jv{a%0HB)3=$bPhT&0DOJCVRYqRGmB(8@FFksz8v)l>8&BUXyrsoI>{El&_S0`I* z%i@z-zOs$;BEg>}U|-y?W;8Fr5wi4Yvi^;KfX!j*fsOss6`XbNV1;*mGm<^xX|<20 zMDkr}h>-F)bwyfpJyi`zR3d(ADquSxlT1L5jIt7_U-GZO*6vkQd=B=*MtU&7j-&_X z(?or4A*og)togOK#$e80aRA(45~=lL&?Q6yp-kYdtyO>ld@ZCRA!$?O%(I?sI0Mq| zDRfM2DDE$uxvQ*gdSj+I_xWM@DJ)Bn0>;xV1E*$K1UqTH0BI=U29deSD664UBar3i z(Y2^2SO!kK84WVY_PO5%h(i>x2pY*v-|<{xto&ubKs%YZzH0NQnU;Y3aIkenrV#a0 zVLT5&Tpkz}mzu{w7?D(J@Idkpzk0U1@2=aXS&WyaDgFmuF8v~G?93K5zboqT{a67) zX_n>`cBy!(w$nQWvN1ld)&-|;vyzM#k5k)@d|{|K8GN>vG>%B-W-6)rG4;;vM%%=fFhH$hvmt;BrN#ZSIekU-M1 zWJG^CRwOdeVA{*k-VGtLC%W2=CyAv3T>Xe&T^g4U?!p_F5&*s;?JBcMa@7n1dB}&* z`2V|%ej*Ums`w=o-g22wKq9735AOFH0|CZB;ImPtntjGH8O3llKAhtF@X zUXC1==7h?E)0-rmNG{P@|A-}kkMRMhb;v{0D~lq;KnMUBNq^4%{eMKcS}*uKyr`ZL zTrCCZi{45I+gsF^Rm}dwEe45PFmC_q(70SUf63e9Lf*cCtDvjzv~y9lKr7h?5Lo`l z>HeR`zSs~zE+TcR^%C#unf(m#Re+D5I*?wyK*Du_Q4h`23H*=9o!15YyFIMzKX3ov z&lS24j5-`eIw*eiot7SQ0nTv$9t!9mBKpX9H!B* zu8dKfzD6y*0_yA*%Bvrh29*Y+;@n8$MV0O#VUPI$?5g2o$Qw ze085(5SRUh8g?62#yeos6oazB%!QF(*xc{?i%M<Yg< z7o4|<8dsR{e(ue8)gbXfp&OVHx9_?c`IaT-<$!-GZ_PVe2?Ydg#wsRjyRTX0goips zr+4yj658;rvPZ1TCo#m`j+C2a-}Rt=1HR)o`a92bx${t`VplOTrR(~^FbYhUjF7cc%mhloq(EI^L03>)Xr6xi#3`2Y8xO3hukx=u*nfAmr5ct# zHkd(Ubvrx(iQSh^v9(D}PaG^(YRD)u;-^43Lk*RJ zi=Qk!^9b-Z>Jkz`KTZT%7VZ!w>Q+95Ko5^6LT5m>yn$EPW&Z;?4x+b*~S^5#BH20t^~r#s7aIAnsZW5t{nbm z=Ot$xH&e~4XTe?J0AivR*U5O+_OKzTzyZD&bUT|Vik1^{Z?0%XB-=cs&fZSH*OSG(-Ou_bx3$@brNmIbf9Rgv z;=#qWa`*r5t@f`;qfZliEhKnQ^094qp-l!Cz%!m$fAZ_4A=k7@*bHQw9|M7tegR1I zu!LWLc`AJ9>LlY0eb~+N6|Zl;u2|7R$=R==#8W?^;rd;7;{u{;WZk*IbgHBPy_~9Q ze>CSZVxfW5Rx|hR@=8aS)u5rEv2B1<>NqRPv3D~_2 z*16sM8%jq{Z?Qxn6{^l3Oj@pN?MjVq(4Cyz$LXsH99C*gh-0w4F_eB7yGd-Jw`=TA zqs%Zh@6jN?Y1^B4yC#EsW?mtwLXl(G&o3)al8<&zS}Fv+fOxX&+PC$VxkEOJBB}Sy znD1G$esynMv?UjGoRzR)agW#a)X3Hp!V9SmE+6Lq6L|Yi0n&$v0d|gdRj$xl)Z{lm z^|qnwI!e?uGcM~BKU&9&azphRMqxJbiQ_4Hcndu67i~3t3#g+5>7yc5%_R^-$OS|X zNpP&699b4P88CFlqV$OAiD4wmlrB``Cu|kO++Fx7y!$Xj*c!qtTJP34lK$aKfS^dI zDkzHLv)R)b5Wn?xh*gVcbQg=a2l|j-5SC^dBOO*?`}+dU;Op&ANVbLw*C-Vk`R@6{ zc)E}u-tGCMFAYE>IP6dn;_r7fiImL8YAqrbGZ>{X$37C<+_}e0;{YI0$dJ86Ox>v&|>6TQ<-jgvMAX6C7ZU zVeP9RG?{8lr$rLG;%fFJJ%Q`f#wLRzh2&yCzk4Af;`7uaDPqTIIM)rRw+G)!MAv77 zMAdvP6+v%7#uW4e5l`_rJIW*6j5c4(jg}2f(myb5`YfEX?Z|h~*;iHW1DmMtCzIDP zl63u;=;7l{8=KaA)4R80rweOa14gxp>Iy{>S>mSmMcXif^pQ$ab?M?aaK|)bvvPv+ z(}{00)GxRiU->+($J*{Ei3K;}D9+ zYqY;DH9>@ro>pL%+A6*j8-7UmMdRrxozF?#S*c9f9rMiZc7twWFFYZQ#J=nT&Y753 zGLY#nUjQ|K|Dq-|5TzY~UIZ$Mm^3^+V&W7;H{=k+}El<;zCL!880#ZdwiCe4w42r%MQN5g1jC0TlWk zZV`iG77unNHz;&)elf_lvU}7RM?gkwcypYV_M2-FV?~aZCcQ!zHxE2MS7T|I@su;p za_`zJx4TVf?6hYh7c!W5MQXByMw8mp?5IfQ0e$?D5qIap2` zn-)ou-d#PtmXqXgKro1VFqZa}cYp|3D&|EjN@k*u`?~yQ;ge!R;4DI&)XHZJ`gi(1?8_80b{y4;v2b_*}ds zB%S&MH>XQDkMM}-j@pjAp`DA{#GfFsRr|sTf+h%%I|LxU!DatMWaFs``)DXpdngvI z?P3u<9F<7~Ij(QNgZ)wY?B*66T6rs&m^8X8UfYvJl-{^zQBmTR#n%y7%(_9d&&f=1 zi-W0ng|?um%$O=!=M>5$UhBsm0dAE*t-}12)61`Y>=98X?z{Y_cR0LDEh80Bw%%!S zM5;Z}xl3LrA5d0nHeusPGI1Im;_NGT8-RDe0Dp}^WFGm*p%eOUJXKT13d*v|wTz+E z6XHsK!FV34uN$nLV(*tZCqFqP!t220uvZe?w3FE8kjl^0^BT|a8c9hAq#JW|87f^}NPJ$U)&a8-MlEXa_=h+_Kcx5x>E_Yw<)jTovYTT^F+@#Sg)cfPiD(g__aXVFBP{- zlb?T`jL>YHM-1MI`D3)TZk^C?7zq!4gM(~;=6dW}6B~CSW0pH-_U}p);~J}ZrwPsR zHr~I^NIOSf7`rcS2>s4-xq05hdm$|n0z?=VyTfSdWS@iGeR> in the ++{beatname_lc}.yml+ config file. NOTE: Starting with Beats 6.0.0, the dashboards are loaded via the Kibana API. This requires a Kibana endpoint configuration. You should have configured the -endpoint earlier. If you didn't, configure it now. +endpoint earlier when you +<<{beatname_lc}-configuration,configured {beatname_uc}>>. If you didn't, +configure it now. + +Make sure Kibana is running before you perform this step. To set up the Kibana dashboards for {beatname_uc}: @@ -33,16 +36,23 @@ From the directory where you installed {beatname_uc}, run: ["source","sh",subs="attributes,callouts"] ---------------------------------------------------------------------- -./{beatname_lc} setup +./{beatname_lc} setup --dashboards ---------------------------------------------------------------------- +ifeval::["{requires-sudo}"=="yes"] + +If you changed ownership of the config file to root, you'll need preface this +command with `sudo`. + +endif::[] + ifeval::["{beatname_lc}"!="auditbeat"] *docker:* ["source","sh",subs="attributes"] ---------------------------------------------------------------------- -docker run {dockerimage} setup +docker run {dockerimage} setup --dashboards ---------------------------------------------------------------------- endif::[] @@ -60,24 +70,5 @@ and run: ["source","sh",subs="attributes,callouts"] ---------------------------------------------------------------------- -PS > {beatname_lc} setup +PS > {beatname_lc} setup --dashboards ---------------------------------------------------------------------- - - -[[view-kibana-dashboards]] -==== Open the dashboards in Kibana - -After loading the dashboards, launch the Kibana web interface by pointing your browser -to port 5601. For example, http://127.0.0.1:5601[http://127.0.0.1:5601]. - -On the *Discover* page, make sure that the predefined +{beatname_lc}-*+ index -pattern is selected to see {beatname_uc} data. - -image:./images/kibana-created-indexes.png[Discover tab with index selected] - -To open the loaded dashboards, go to the *Dashboard* page and select the -dashboard that you want to open. - -image:./images/kibana-navigation-vis.png[Navigation widget in Kibana] - - diff --git a/libbeat/docs/dashboardsconfig.asciidoc b/libbeat/docs/dashboardsconfig.asciidoc index 2eb4c8fb1ce..da3e89129b8 100644 --- a/libbeat/docs/dashboardsconfig.asciidoc +++ b/libbeat/docs/dashboardsconfig.asciidoc @@ -7,60 +7,59 @@ //// resolve Beat names: beatname_uc and beatname_lc //// Use the following include to pull this content into a doc file: //// include::../../libbeat/docs/dashboardsconfig.asciidoc[] -//// Make sure this content appears below a level 2 heading. ////////////////////////////////////////////////////////////////////////// [[configuration-dashboards]] -== Load Kibana dashboards +== Load the Kibana dashboards beta[] -The `dashboards` section of the +{beatname_lc}.yml+ config file contains options -for automatically loading the sample Beats dashboards. Automatic dashboard -loading is disabled by default, but can be enabled either from the configuration -file or by using the `-setup` CLI flag. +{beatname_uc} comes packaged with example Kibana dashboards, visualizations, +and searches for visualizing {beatname_uc} data in Kibana. -If dashboard loading is enabled, {beatname_uc} attempts to configure Kibana by -writing directly in the Elasticsearch index for the Kibana configuration (by -default, `.kibana`). To connect to Elasticsearch, {beatname_uc} uses the -settings defined in the Elasticsearch output. If the Elasticsearch output is -not configured or not enabled, {beatname_uc} will stop with an error. Dashboard -loading is only attempted at Beat startup. If Elasticsearch is not available when -the Beat starts, {beatname_uc} will stop with an error. +To load the dashboards, you can either enable dashboard loading in the +`setup.dashboards` section of the +{beatname_lc}.yml+ config file, or you can +run the `setup` command. Dashboard loading is disabled by default. -Here is an example configuration: +When dashboard loading is enabled, {beatname_uc} uses the Kibana API to load the +sample dashboards. Dashboard loading is only attempted at Beat startup. +If Kibana is not available at startup, {beatname_uc} will stop with an error. + +To enable dashboard loading, add the following setting to the config file: [source,yaml] ------------------------------------------------------------------------------ -dashboards.enabled: true +setup.dashboards.enabled: true ------------------------------------------------------------------------------ [float] === Configuration options -You can specify the following options in the `dashboards` section of the +You can specify the following options in the `setup.dashboards` section of the +{beatname_lc}.yml+ config file: [float] -==== `enabled` +==== `setup.dashboards.enabled` If this option is set to true, {beatname_uc} loads the sample Kibana dashboards automatically on startup. If no other options are set, the dashboard are loaded from the local `kibana` directory in the home path of the installation. To load dashboards from a different location, you can configure one of the -following options: <>, or <>. +following options: <>, +<>, or +<>. [float] [[directory-option]] -==== `directory` +==== `setup.dashboards.directory` The directory that contains the dashboards to load. The default is the `kibana` folder in the home path. [float] [[url-option]] -==== `url` +==== `setup.dashboards.url` The URL to use for downloading the dashboard archive. If this option is set, {beatname_uc} downloads the dashboard archive from the specified URL @@ -68,14 +67,14 @@ instead of using the local directory. [float] [[file-option]] -==== `file` +==== `setup.dashboards.file` The file archive (zip file) that contains the dashboards to load. If this option is set, {beatname_uc} looks for a dashboard archive in the specified path instead of using the local directory. [float] -==== `beat` +==== `setup.dashboards.beat` In case the archive contains the dashboards for multiple Beats, this setting lets you select the Beat for which you want to load dashboards. To load all the @@ -83,14 +82,14 @@ dashboards in the archive, set this option to an empty string. The default is +"{beatname_lc}"+. [float] -==== `kibana_index` +==== `setup.dashboards.kibana_index` The name of the Kibana index to use for setting the configuration. The default is `".kibana"` [float] -==== `index` +==== `setup.dashboards.index` The Elasticsearch index name. This setting overwrites the index name defined in the dashboards and index pattern. Example: `"testbeat-*"` diff --git a/libbeat/docs/opendashboards.asciidoc b/libbeat/docs/opendashboards.asciidoc new file mode 100644 index 00000000000..93d6dbe725d --- /dev/null +++ b/libbeat/docs/opendashboards.asciidoc @@ -0,0 +1,23 @@ +////////////////////////////////////////////////////////////////////////// +//// This content is shared by all Elastic Beats. Make sure you keep the +//// descriptions here generic enough to work for all Beats that include +//// this file. When using cross references, make sure that the cross +//// references resolve correctly for any files that include this one. +//// Use the appropriate variables defined in the index.asciidoc file to +//// resolve Beat names: beatname_uc and beatname_lc. +//// Use the following include to pull this content into a doc file: +//// include::../../libbeat/docs/opendashboards.asciidoc[] +////////////////////////////////////////////////////////////////////////// + +To open the dashboards, launch the Kibana web interface by pointing your browser +to port 5601. For example, http://127.0.0.1:5601[http://127.0.0.1:5601]. + +On the *Discover* page, make sure that the predefined +{beatname_lc}-*+ index +pattern is selected to see {beatname_uc} data. + +image:./images/kibana-created-indexes.png[Discover tab with index selected] + +Go to the *Dashboard* page and select the dashboard that you want to open. + +image:./images/kibana-navigation-vis.png[Navigation widget in Kibana] + diff --git a/libbeat/docs/outputconfig.asciidoc b/libbeat/docs/outputconfig.asciidoc index 19a78151438..751dd55650a 100644 --- a/libbeat/docs/outputconfig.asciidoc +++ b/libbeat/docs/outputconfig.asciidoc @@ -301,10 +301,10 @@ requests are made. ===== `ssl` Configuration options for SSL parameters like the certificate authority to use -for HTTPS-based connections. If the `tls` section is missing, the host CAs are used for HTTPS connections to +for HTTPS-based connections. If the `ssl` section is missing, the host CAs are used for HTTPS connections to Elasticsearch. -See <> for more information. +See <> for more information. [[logstash-output]] @@ -502,7 +502,7 @@ For example "{beatname_lc}" generates "[{beatname_lc}-]YYYY.MM.DD" indexes (for ===== `ssl` Configuration options for SSL parameters like the root CA for Logstash connections. See -<> for more information. To use SSL, you must also configure the +<> for more information. To use SSL, you must also configure the https://www.elastic.co/guide/en/logstash/current/plugins-inputs-beats.html[Beats input plugin for Logstash] to use SSL/TLS. ===== `timeout` @@ -738,7 +738,7 @@ The number of seconds to wait for new events between two producer API calls. ===== `ssl` Configuration options for SSL parameters like the root CA for Kafka connections. See -<> for more information. +<> for more information. [[redis-output]] === Configure the Redis output @@ -944,7 +944,7 @@ size. Configuration options for SSL parameters like the root CA for Redis connections guarded by SSL proxies (for example https://www.stunnel.org[stunnel]). See -<> for more information. +<> for more information. ===== `proxy_url` @@ -1070,149 +1070,6 @@ setting does not affect how events are published. Setting `bulk_max_size` to 0 disables buffering in libbeat. -[[configuration-output-ssl]] - -=== Configure SSL options - -++++ -SSL options -++++ - -You can specify SSL options for any output that supports SSL. - -Example configuration: - -[source,yaml] ------------------------------------------------------------------------------- -output.elasticsearch: - hosts: ["192.168.1.42:9200"] - ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - ssl.certificate: "/etc/pki/client/cert.pem" - ssl.key: "/etc/pki/client/cert.key" ------------------------------------------------------------------------------- - -Also see <>. - -==== Configuration options - -You can specify the following options in the `ssl` section of the +{beatname_lc}.yml+ config file: - -===== `enabled` - -The `enabled` setting can be used to disable the ssl configuration by setting -it to `false`. The default value is `true`. - -Note: SSL settings are disabled if either `enabled` is set to `false` or the -`ssl` section is missing. - -===== `certificate_authorities` - -The list of root certificates for server verifications. If `certificate_authorities` is empty or not set, the trusted certificate authorities of the host system are used. - -[[certificate]] - -===== `certificate: "/etc/pki/client/cert.pem"` - -The path to the certificate for SSL client authentication. If the certificate -is not specified, client authentication is not available. The connection -might fail if the server requests client authentication. If the SSL server does not -require client authentication, the certificate will be loaded, but not requested or used -by the server. - -When this option is configured, the <> option is also required. - -[[certificate_key]] -===== `key: "/etc/pki/client/cert.key"` - -The client certificate key used for client authentication. This option is required if <> is specified. - -===== `key_passphrase` - -The passphrase used to decrypt an encrypted key stored in the configured `key` file. - -===== `supported_protocols` - -List of allowed SSL/TLS versions. If SSL/TLS server decides for protocol versions -not configured, the connection will be dropped during or after the handshake. The -setting is a list of allowed protocol versions: -`SSLv3`, `TLSv1` for TLS version 1.0, `TLSv1.0`, `TLSv1.1` and `TLSv1.2`. - -The default value is `[TLSv1.0, TLSv1.1, TLSv1.2]`. - -===== `verification_mode` - -This option controls whether the client verifies server certificates and host -names. The values `none` and `full` can be used. If `verification_mode` is set -to `none`, all server host names and certificates are accepted. In this mode, -TLS-based connections are susceptible to man-in-the-middle attacks. Use this -option for testing only. - -The default is `full`. - -===== `cipher_suites` - -The list of cipher suites to use. The first entry has the highest priority. -If this option is omitted, the Go crypto library's default -suites are used (recommended). - -The following cipher suites are available: - -* RSA-RC4-128-SHA (disabled by default - RC4 not recommended) -* RSA-3DES-CBC3-SHA -* RSA-AES-128-CBC-SHA -* RSA-AES-256-CBC-SHA -* ECDHE-ECDSA-RC4-128-SHA (disabled by default - RC4 not recommended) -* ECDHE-ECDSA-AES-128-CBC-SHA -* ECDHE-ECDSA-AES-256-CBC-SHA -* ECDHE-RSA-RC4-128-SHA (disabled by default- RC4 not recommended) -* ECDHE-RSA-3DES-CBC3-SHA -* ECDHE-RSA-AES-128-CBC-SHA -* ECDHE-RSA-AES-256-CBC-SHA -* ECDHE-RSA-AES-128-GCM-SHA256 (TLS 1.2 only) -* ECDHE-ECDSA-AES-128-GCM-SHA256 (TLS 1.2 only) -* ECDHE-RSA-AES-256-GCM-SHA384 (TLS 1.2 only) -* ECDHE-ECDSA-AES-256-GCM-SHA384 (TLS 1.2 only) - -Here is a list of acronyms used in defining the cipher suites: - -* 3DES: - Cipher suites using triple DES - -* AES-128/256: - Cipher suites using AES with 128/256-bit keys. - -* CBC: - Cipher using Cipher Block Chaining as block cipher mode. - -* ECDHE: - Cipher suites using Elliptic Curve Diffie-Hellman (DH) ephemeral key exchange. - -* ECDSA: - Cipher suites using Elliptic Curve Digital Signature Algorithm for authentication. - -* GCM: - Galois/Counter mode is used for symmetric key cryptography. - -* RC4: - Cipher suites using RC4. - -* RSA: - Cipher suites using RSA. - -* SHA, SHA256, SHA384: - Cipher suites using SHA-1, SHA-256 or SHA-384. - - -===== `curve_types` - -The list of curve types for ECDHE (Elliptic Curve Diffie-Hellman ephemeral key exchange). - -The following elliptic curve types are available: - -* P-256 -* P-384 -* P-521 - [[configuration-output-codec]] === Configure the ouput codec @@ -1245,3 +1102,4 @@ output.console: codec.format: string: '%{[@timestamp]} %{[message]}' ------------------------------------------------------------------------------ + diff --git a/libbeat/docs/shared-kibana-config.asciidoc b/libbeat/docs/shared-kibana-config.asciidoc new file mode 100644 index 00000000000..4fbfce4cd40 --- /dev/null +++ b/libbeat/docs/shared-kibana-config.asciidoc @@ -0,0 +1,104 @@ +////////////////////////////////////////////////////////////////////////// +//// This content is shared by all Elastic Beats. Make sure you keep the +//// descriptions here generic enough to work for all Beats that include +//// this file. When using cross references, make sure that the cross +//// references resolve correctly for any files that include this one. +//// Use the appropriate variables defined in the index.asciidoc file to +//// resolve Beat names: beatname_uc and beatname_lc. +//// Use the following include to pull this content into a doc file: +//// include::../../libbeat/docs/shared-kibana-config.asciidoc[] +////////////////////////////////////////////////////////////////////////// + +[[setup-kibana-endpoint]] +== Set up the Kibana endpoint + +Starting with Beats 6.0.0, the Kibana dashboards are loaded into Kibana +via the Kibana API. This requires a Kibana endpoint configuration. + +You configure the endpoint in the `setup.kibana` section of the ++{beatname_lc}.yml+ config file. + +Here is an example configuration: + +[source,yaml] +---- +setup.kibana.host: "localhost:5601" +---- + +[float] +=== Configuration options + +You can specify the following options in the `setup.kibana` section of the ++{beatname_lc}.yml+ config file: + +[float] +==== `setup.kibana.host` + +The Kibana host where the dashboards will be loaded. The default is +`127.0.0.1:5601`. The value of `host` can be a `URL` or `IP:PORT`. For example: `http://192.15.3.2`, `192:15.3.2:5601` or `http://192.15.3.2:6701/path`. If no +port is specified, `5601` is used. + +NOTE: When a node is defined as an `IP:PORT`, the _scheme_ and _path_ are taken +from the <> and +<> config options. + +IPv6 addresses must be defined using the following format: +`https://[2001:db8::1]:5601`. + +[float] +[[kibana-protocol-option]] +==== `setup.kibana.protocol` + +The name of the protocol Kibana is reachable on. The options are: `http` or +`https`. The default is `http`. However, if you specify a URL for host, the +value of `protocol` is overridden by whatever scheme you specify in the URL. + +Example config: + +[source,yaml] +---- +setup.kibana.host: "192.0.2.255:5601" +setup.kibana.protocol: "https" +setup.kibana.path: /kibana +---- + + +[float] +==== `setup.kibana.username` + +The basic authentication username for connecting to Kibana. + +[float] +==== `setup.kibana.password` + +The basic authentication password for connecting to Elasticsearch. + +[float] +[[kibana-path-option]] +==== `setup.kibana.path` + +An HTTP path prefix that is prepended to the HTTP API calls. This is useful for +the cases where Kibana listens behind an HTTP reverse proxy that exports the API +under a custom prefix. + +[float] +==== `setup.kibana.ssl.enabled` + +Enables {beatname_uc} to use SSL settings when connecting to Kibana via HTTPS. +If you configure the Beat to connect over HTTPS, this setting defaults to +`true` and {beatname_uc} uses the default SSL settings. + +Example configuration: + +[source,yaml] +---- +setup.kibana.host: "192.0.2.255:5601" +setup.kibana.protocol: "https" +setup.kibana.ssl.enabled: true +setup.kibana.ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] +setup.kibana.ssl.certificate: "/etc/pki/client/cert.pem" +setup.kibana.ssl.key: "/etc/pki/client/cert.key +---- + +See <> for more information. + diff --git a/libbeat/docs/shared-logstash-config.asciidoc b/libbeat/docs/shared-logstash-config.asciidoc index 071b51e2bd1..4b3c176a794 100644 --- a/libbeat/docs/shared-logstash-config.asciidoc +++ b/libbeat/docs/shared-logstash-config.asciidoc @@ -37,11 +37,7 @@ because the options for auto loading the template are only available for the Ela ifdef::allplatforms[] -TIP: To test your configuration file, change to the directory where the {beatname_uc} -binary is installed, and run {beatname_uc} in the foreground with the following -options specified: +./{beatname_lc} -configtest -e+. Make sure your config files are -in the path expected by {beatname_uc} (see <>). If you -installed from DEB or RPM packages, run +./{beatname_lc}.sh -configtest -e+. +include::../../libbeat/docs/step-test-config.asciidoc[] endif::allplatforms[] @@ -49,7 +45,7 @@ ifdef::win[] TIP: To test your configuration file, change to the directory where the {beatname_uc} binary is installed, and run {beatname_uc} in the foreground with the following -options specified: +.\winlogbeat.exe -c .\winlogbeat.yml -configtest -e+. +options specified: +.\winlogbeat.exe test config -c .\winlogbeat.yml -e+. endif::win[] diff --git a/libbeat/docs/shared-ssl-config.asciidoc b/libbeat/docs/shared-ssl-config.asciidoc new file mode 100644 index 00000000000..61fe8c7f416 --- /dev/null +++ b/libbeat/docs/shared-ssl-config.asciidoc @@ -0,0 +1,161 @@ +[[configuration-ssl]] +== Specify SSL settings + +You can specify SSL options for any <> that supports +SSL. You can also specify SSL options when you +<>. + +Example output config with SSL enabled: + +[source,yaml] +---- +output.elasticsearch.hosts: ["192.168.1.42:9200"] +output.elasticsearch.ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] +output.elasticsearch.ssl.certificate: "/etc/pki/client/cert.pem" +output.elasticsearch.ssl.key: "/etc/pki/client/cert.key" +---- + +Also see <>. + +Example Kibana endpoint config with SSL enabled: + +[source,yaml] +---- +setup.kibana.host: "192.0.2.255:5601" +setup.kibana.protocol: "https" +setup.kibana.ssl.enabled: true +setup.kibana.ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] +setup.kibana.ssl.certificate: "/etc/pki/client/cert.pem" +setup.kibana.ssl.key: "/etc/pki/client/cert.key +---- + +[float] +=== Configuration options + +You can specify the following options in the `ssl` section of the +{beatname_lc}.yml+ config file: + +[float] +==== `enabled` + +The `enabled` setting can be used to disable the ssl configuration by setting +it to `false`. The default value is `true`. + +NOTE: SSL settings are disabled if either `enabled` is set to `false` or the +`ssl` section is missing. + +[float] +==== `certificate_authorities` + +The list of root certificates for server verifications. If `certificate_authorities` is empty or not set, the trusted certificate authorities of the host system are used. + +[float] +[[certificate]] +==== `certificate: "/etc/pki/client/cert.pem"` + +The path to the certificate for SSL client authentication. If the certificate +is not specified, client authentication is not available. The connection +might fail if the server requests client authentication. If the SSL server does not +require client authentication, the certificate will be loaded, but not requested or used +by the server. + +When this option is configured, the <> option is also required. + +[float] +[[certificate_key]] +==== `key: "/etc/pki/client/cert.key"` + +The client certificate key used for client authentication. This option is required if <> is specified. + +[float] +==== `key_passphrase` + +The passphrase used to decrypt an encrypted key stored in the configured `key` file. + +[float] +==== `supported_protocols` + +//REVIEWERS: This description is kind of garbled. Can we fix the language, but maybe without going into details about how the client and server negotiate which version to use? + +List of allowed SSL/TLS versions. If SSL/TLS server decides for protocol versions +not configured, the connection will be dropped during or after the handshake. The +setting is a list of allowed protocol versions: +`SSLv3`, `TLSv1` for TLS version 1.0, `TLSv1.0`, `TLSv1.1` and `TLSv1.2`. + +The default value is `[TLSv1.0, TLSv1.1, TLSv1.2]`. + +[float] +==== `verification_mode` + +This option controls whether the client verifies server certificates and host +names. Valid values are `none` and `full`. If `verification_mode` is set +to `none`, all server host names and certificates are accepted. In this mode, +TLS-based connections are susceptible to man-in-the-middle attacks. Use this +option for testing only. + +The default is `full`. + +[float] +==== `cipher_suites` + +The list of cipher suites to use. The first entry has the highest priority. +If this option is omitted, the Go crypto library's default +suites are used (recommended). + +The following cipher suites are available: + +* RSA-RC4-128-SHA (disabled by default - RC4 not recommended) +* RSA-3DES-CBC3-SHA +* RSA-AES-128-CBC-SHA +* RSA-AES-256-CBC-SHA +* ECDHE-ECDSA-RC4-128-SHA (disabled by default - RC4 not recommended) +* ECDHE-ECDSA-AES-128-CBC-SHA +* ECDHE-ECDSA-AES-256-CBC-SHA +* ECDHE-RSA-RC4-128-SHA (disabled by default- RC4 not recommended) +* ECDHE-RSA-3DES-CBC3-SHA +* ECDHE-RSA-AES-128-CBC-SHA +* ECDHE-RSA-AES-256-CBC-SHA +* ECDHE-RSA-AES-128-GCM-SHA256 (TLS 1.2 only) +* ECDHE-ECDSA-AES-128-GCM-SHA256 (TLS 1.2 only) +* ECDHE-RSA-AES-256-GCM-SHA384 (TLS 1.2 only) +* ECDHE-ECDSA-AES-256-GCM-SHA384 (TLS 1.2 only) + +Here is a list of acronyms used in defining the cipher suites: + +* 3DES: + Cipher suites using triple DES + +* AES-128/256: + Cipher suites using AES with 128/256-bit keys. + +* CBC: + Cipher using Cipher Block Chaining as block cipher mode. + +* ECDHE: + Cipher suites using Elliptic Curve Diffie-Hellman (DH) ephemeral key exchange. + +* ECDSA: + Cipher suites using Elliptic Curve Digital Signature Algorithm for authentication. + +* GCM: + Galois/Counter mode is used for symmetric key cryptography. + +* RC4: + Cipher suites using RC4. + +* RSA: + Cipher suites using RSA. + +* SHA, SHA256, SHA384: + Cipher suites using SHA-1, SHA-256 or SHA-384. + +[float] +==== `curve_types` + +The list of curve types for ECDHE (Elliptic Curve Diffie-Hellman ephemeral key exchange). + +The following elliptic curve types are available: + +* P-256 +* P-384 +* P-521 + diff --git a/libbeat/docs/shared-ssl-logstash-config.asciidoc b/libbeat/docs/shared-ssl-logstash-config.asciidoc index e902c150ca4..8e55dc0c15d 100644 --- a/libbeat/docs/shared-ssl-logstash-config.asciidoc +++ b/libbeat/docs/shared-ssl-logstash-config.asciidoc @@ -42,7 +42,7 @@ output.logstash: ssl.key: "/etc/client.key" ------------------------------------------------------------------------------ + -For more information about these configuration options, see <>. +For more information about these configuration options, see <>. . Configure Logstash to use SSL. In the Logstash config file, specify the following settings for the https://www.elastic.co/guide/en/logstash/current/plugins-inputs-beats.html[Beats input plugin for Logstash]: + diff --git a/libbeat/docs/shared-template-load.asciidoc b/libbeat/docs/shared-template-load.asciidoc index 02af4f54698..ab6a8a3583a 100644 --- a/libbeat/docs/shared-template-load.asciidoc +++ b/libbeat/docs/shared-template-load.asciidoc @@ -37,21 +37,20 @@ For more information, see: By default, {beatname_uc} automatically loads the recommended template file, +fields.yml+, if Elasticsearch output is enabled. You can configure {beatname_lc} to load a different template -by adjusting the `template.name` and `template.fields` options in +{beatname_lc}.yml+ file: +by adjusting the `setup.template.name` and `setup.template.fields` options in ++{beatname_lc}.yml+ file: ["source","yaml",subs="attributes,callouts"] ---------------------------------------------------------------------- -output.elasticsearch: - hosts: ["localhost:9200"] - template.name: "{beatname_lc}" - template.fields: "fields.yml" - template.overwrite: false +setup.template.name: "{beatname_lc}" +setup.template.fields: "path/to/fields.yml" +setup.template.overwrite: false ---------------------------------------------------------------------- By default, if a template already exists in the index, it is not overwritten. To overwrite an existing -template, set `template.overwrite: true` in the configuration file. +template, set `setup.template.overwrite: true` in the configuration file. -To disable automatic template loading, comment out the template part under the Elasticsearch output. +To disable automatic template loading, set `setup.template.enabled: false`. The options for auto loading the template are not supported if you are using the Logstash output. @@ -59,53 +58,27 @@ Logstash output. [[load-template-manually]] ==== Load the template manually -If you disable automatic template loading, you need to run the following command to load the template: +If you disable automatic template loading, you can run the `setup` command to +load the template manually. -ifdef::allplatforms[] +["source","sh",subs="attributes"] +---- +./{beatname_lc} setup --template +---- -*deb or rpm:* +ifeval::["{requires-sudo}"=="yes"] -["source","sh",subs="attributes,callouts"] ----------------------------------------------------------------------- -curl -H 'Content-Type: application/json' -XPUT 'http://localhost:9200/_template/{beatname_lc}' -d@/etc/{beatname_lc}/{beatname_lc}.template.json ----------------------------------------------------------------------- - -*mac:* - -["source","sh",subs="attributes,callouts"] ----------------------------------------------------------------------- -cd {beatname_lc}-{version}-darwin-x86_64 -curl -H 'Content-Type: application/json' -XPUT 'http://localhost:9200/_template/{beatname_lc}' -d@{beatname_lc}.template.json ----------------------------------------------------------------------- - -ifeval::["{beatname_lc}"!="auditbeat"] - -*docker:* - -["source", "sh", subs="attributes"] ----------------------------------------------------------------------- -docker run --rm {dockerimage} curl -H 'Content-Type: application/json' -XPUT 'http://localhost:9200/_template/{beatname_lc}' -d@{beatname_lc}.template.json ----------------------------------------------------------------------- +If you changed ownership of the config file to root, you'll need preface this +command with `sudo`. endif::[] -*win:* - -endif::allplatforms[] - -["source","sh",subs="attributes,callouts"] ----------------------------------------------------------------------- -PS C:\Program Files{backslash}{beatname_uc}> Invoke-WebRequest -Method Put -InFile {beatname_lc}.template.json -Uri http://localhost:9200/_template/{beatname_lc}?pretty -ContentType application/json ----------------------------------------------------------------------- - -where `localhost:9200` is the IP and port where Elasticsearch is listening. - NOTE: If you've already used {beatname_uc} to index data into Elasticsearch, the index may contain old documents. After you load the index template, you can delete the old documents from {beatname_lc}-* to force Kibana to look at the newest documents. Use this command: -["source","sh",subs="attributes,callouts"] +["source","sh",subs="attributes"] ---------------------------------------------------------------------- curl -XDELETE 'http://localhost:9200/{beatname_lc}-*' ---------------------------------------------------------------------- diff --git a/libbeat/docs/step-configure-kibana-endpoint.asciidoc b/libbeat/docs/step-configure-kibana-endpoint.asciidoc new file mode 100644 index 00000000000..00fe1397703 --- /dev/null +++ b/libbeat/docs/step-configure-kibana-endpoint.asciidoc @@ -0,0 +1,20 @@ +. If you plan to use the sample Kibana dashboards provided with {beatname_uc}, +configure the Kibana endpoint: ++ +[source,yaml] +---------------------------------------------------------------------- +setup.kibana: + host: "localhost:5601" +---------------------------------------------------------------------- ++ +-- +Where `host` is the hostname and port of the machine where Kibana is running, +for example, `localhost:5601`. + +NOTE: If you specify a path after the port number, you need to include +the scheme and port: `http://localhost:5601/path`. + +Also see the security-related options in <> if you are +connecting to a secured instance of Kibana. + +-- diff --git a/libbeat/docs/step-look-at-config.asciidoc b/libbeat/docs/step-look-at-config.asciidoc new file mode 100644 index 00000000000..66d9bd9d1e6 --- /dev/null +++ b/libbeat/docs/step-look-at-config.asciidoc @@ -0,0 +1,2 @@ +Before starting {beatname_lc}, you should look at the configuration options in the +configuration file. For more information about these options, see <>. diff --git a/libbeat/docs/step-test-config.asciidoc b/libbeat/docs/step-test-config.asciidoc new file mode 100644 index 00000000000..9cb57683386 --- /dev/null +++ b/libbeat/docs/step-test-config.asciidoc @@ -0,0 +1,25 @@ +ifeval::["{requires-sudo}"!="yes"] + +TIP: To test your configuration file, change to the directory where the +{beatname_uc} binary is installed, and run {beatname_uc} in the foreground with +the following options specified: +./{beatname_lc} test config -e+. Make sure your +config files are in the path expected by {beatname_uc} (see <>), +or use the `-c` flag to specify the path to the config file. + +//REVIEWERS: I'm assuming that the test command works the same on all platforms + +endif::[] + +ifeval::["{requires-sudo}"=="yes"] + +TIP: To test your configuration file, change to the directory where the +{beatname_uc} binary is installed, and run {beatname_uc} in the foreground with +the following options specified: +sudo ./{beatname_lc} test config -e+. Make sure +your config files are in the path expected by {beatname_uc} (see +<>), or use the `-c` flag to specify the path to the config +file. Depending on your OS, you might run into file ownership issues when you +run this test. See +{libbeat}/config-file-permissions.html[Config File Ownership and Permissions] +in the _Beats Platform Reference_ for more information. + +endif::[] diff --git a/libbeat/docs/template-config.asciidoc b/libbeat/docs/template-config.asciidoc index f6ee654d563..cb49e62efbe 100644 --- a/libbeat/docs/template-config.asciidoc +++ b/libbeat/docs/template-config.asciidoc @@ -8,19 +8,20 @@ Elasticsearch. You can adjust the following settings to load your own template or overwrite an existing one: -*`enabled`*:: Set to false to disable template loading. If set this to false, +*`setup.template.enabled`*:: Set to false to disable template loading. If set this to false, you must <>. -*`name`*:: The name of the template. The default is +{beatname_lc}+. +*`setup.template.name`*:: The name of the template. The default is +{beatname_lc}+. The version of the Beat will always be appended to the given name +so the final name is `filebeat-%{[beat.version]}` -*`fields`*:: The path to the YAML file describing the fields. The default is +fields.yml+. If a +*`setup.template.fields`*:: The path to the YAML file describing the fields. The default is +fields.yml+. If a relative path is set, it is considered relative to the config path. See the <> section for details. -*`overwrite`*:: A boolean that specifies whether to overwrite the existing template. The default +*`setup.template.overwrite`*:: A boolean that specifies whether to overwrite the existing template. The default is false. -*`settings.index`*:: A dictionary of settings to place into the `settings.index` dictionary of the +*`setup.template.settings`*:: A dictionary of settings to place into the `settings.index` dictionary of the Elasticsearch template. For more details about the available Elasticsearch mapping options, please see the Elasticsearch {elasticsearch}/mapping.html[mapping reference]. + @@ -36,7 +37,7 @@ setup.template.settings: index.number_of_replicas: 1 ---------------------------------------------------------------------- -*`settings._source`*:: A dictionary of settings for the `_source` field. For the available settings, +*`setup.template.settings._source`*:: A dictionary of settings for the `_source` field. For the available settings, please see the Elasticsearch {elasticsearch}/mapping-source-field.html[reference]. + Example: diff --git a/metricbeat/docs/configuring-howto.asciidoc b/metricbeat/docs/configuring-howto.asciidoc index 1eb0666418c..27fdf740058 100644 --- a/metricbeat/docs/configuring-howto.asciidoc +++ b/metricbeat/docs/configuring-howto.asciidoc @@ -23,9 +23,11 @@ The following topics describe how to configure Metricbeat: * <> * <> * <> +* <> * <> * <> * <> +* <> * <> * <> * <> @@ -33,10 +35,6 @@ The following topics describe how to configure Metricbeat: * <> * <> -//REVIEWERS: I removed the "basic configuration" section because we were duplicating content, and it was getting out of sync - -//REVIEWERS: Moved section about config combinations because it seems premature to talk about detailed config settings in an overview. I think users will expect to see this info under the section called "Specify which modules to run". - -- include::./metricbeat-options.asciidoc[] @@ -48,12 +46,16 @@ include::./reload-configuration.asciidoc[] :allplatforms: include::../../libbeat/docs/outputconfig.asciidoc[] +include::../../libbeat/docs/shared-ssl-config.asciidoc[] + include::./metricbeat-filtering.asciidoc[] include::../../libbeat/docs/shared-config-ingest.asciidoc[] include::../../libbeat/docs/shared-path-config.asciidoc[] +include::../../libbeat/docs/shared-kibana-config.asciidoc[] + include::../../libbeat/docs/setup-config.asciidoc[] include::../../libbeat/docs/loggingconfig.asciidoc[] diff --git a/metricbeat/docs/gettingstarted.asciidoc b/metricbeat/docs/gettingstarted.asciidoc index b534fb51690..b7ce54c8b02 100644 --- a/metricbeat/docs/gettingstarted.asciidoc +++ b/metricbeat/docs/gettingstarted.asciidoc @@ -18,8 +18,9 @@ After installing the Elastic Stack, read the following topics to learn how to in * <> * <> * <> +* <> * <> -* <> +* <> * <> * <> @@ -214,8 +215,8 @@ more details about configuring modules. If you accept the default configuration without specifying additional modules, Metricbeat will collect system metrics only. -. If you are sending output to Elasticsearch, set the IP address and port where -Metricbeat can find the Elasticsearch installation: +. If you are sending output directly to Elasticsearch (and not using Logstash), +set the IP address and port where Metricbeat can find the Elasticsearch installation: + [source,yaml] ---------------------------------------------------------------------- @@ -223,8 +224,14 @@ output.elasticsearch: hosts: ["192.168.1.42:9200"] ---------------------------------------------------------------------- + -If you are sending output to Logstash, see <> -instead. +If you are sending output to Logstash, make sure you +<> instead. + +include::../../libbeat/docs/step-configure-kibana-endpoint.asciidoc[] + +include::../../libbeat/docs/step-test-config.asciidoc[] + +include::../../libbeat/docs/step-look-at-config.asciidoc[] [[metricbeat-template]] === Step 3: Load the index template in Elasticsearch @@ -232,8 +239,14 @@ instead. :allplatforms: include::../../libbeat/docs/shared-template-load.asciidoc[] +[[load-kibana-dashboards]] +=== Step 4: Set up the Kibana dashboards + +:allplatforms: +include::../../libbeat/docs/dashboards.asciidoc[] + [[metricbeat-starting]] -=== Step 4: Start Metricbeat +=== Step 5: Start Metricbeat Run Metricbeat by issuing the appropriate command for your platform. @@ -243,16 +256,16 @@ start Metricbeat in the foreground. *deb:* -[source,shell] +["source","sh",subs="attributes"] ---------------------------------------------------------------------- -sudo /etc/init.d/metricbeat start +sudo service {beatname_lc} start ---------------------------------------------------------------------- *rpm:* -[source,shell] +["source","sh",subs="attributes"] ---------------------------------------------------------------------- -sudo /etc/init.d/metricbeat start +sudo service {beatname_lc} start ---------------------------------------------------------------------- *docker:* @@ -267,12 +280,14 @@ docker run {dockerimage} [source,shell] ---------------------------------------------------------------------- sudo chown root metricbeat.yml <1> +sudo chown root modules.d/system.yml <1> sudo ./metricbeat -e -c metricbeat.yml -d "publish" ---------------------------------------------------------------------- -<1> You'll be running Metricbeat as root, so you need to change ownership -of the configuration file (see +<1> You'll be running Metricbeat as root, so you need to change ownership of the +configuration file and any configurations enabled in the `modules.d` directory, +or run Metricbeat with `-strict.perms=false` specified. See {libbeat}/config-file-permissions.html[Config File Ownership and Permissions] -in the _Beats Platform Reference_). +in the _Beats Platform Reference_. *win:* @@ -302,16 +317,16 @@ Elasticsearch instance. On Windows, if you don't have cURL installed, simply point your browser to the URL. -[[metricbeat-sample-dashboards]] -=== Step 5: Load sample Kibana dashboards +[[view-kibana-dashboards]] +=== Step 6: View the sample Kibana dashboards To make it easier for you to start monitoring your servers in Kibana, -we have created sample Metricbeat dashboards. The dashboards are provided as -examples. We recommend that you -http://www.elastic.co/guide/en/kibana/current/dashboard.html[customize] them -to meet your needs. +we have created example {beatname_uc} dashboards. You loaded the dashboards +earlier when you ran the `setup` command. -image:./images/metricbeat_system_dashboard.png[Metricbeat Dashboard] +include::../../libbeat/docs/opendashboards.asciidoc[] -:allplatforms: -include::../../libbeat/docs/dashboards.asciidoc[] +The dashboards are provided as examples. We recommend that you +{kibana-ref}/dashboard.html[customize] them to meet your needs. + +image:./images/metricbeat_system_dashboard.png[Metricbeat Dashboard] diff --git a/metricbeat/docs/images/kibana-created-indexes.png b/metricbeat/docs/images/kibana-created-indexes.png index 7035e59011ad020330e8663fff7fa305bce8fe50..ad9c65ae1c7fc3282c14162ff9c59b91d192a809 100644 GIT binary patch literal 74532 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

    |7^xmyG)EF8rj~D4dxzF$v38$!pK5 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%0DyELzMmT%`%Tcg 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

    g>7f>^D; z6(g@yX^c7gqaF2l6;#FicFpZ@ni%zF3_4MRkiJuGAOgyhfWCM{najvkeQBJ7_urg? z1lg*@)YxynIUgyOv^kagt=s5pU`pK$4Wcz_r7JR5cU-tb!m05HSVg_h1(Q^2Z(45W zI{F(oa>$y!dM$N~63UR+Wul^uPK&*1p|xkhHsjT9!5EXxPmT*u)j*`B4U6uZJ@W?V zHMWoCXS7D{I#ri~43OCa!L6+hoa*!_I0Og?KR z2U#oOoz0-z&-XAUt2GPz!ce{DnrQjPpq9O!g$W_@q19gdtLMu1;@t|L4rE1WKE+Y{ z`?GC6NMTAIK78l}H^Ps)l-T;rb&1>Xw8wRHn6)Jh0CdUIdu|M;C|l8$3nMsZWST$H z1elY)L)!#QhUG^SLB9=+S^$^@{nI7tM)~@x#rmnO?R2iC56>k;mQGn!6lZ4c&-x>rD!d^zCU2wp%+;e#V z9?zSK;fssjo|nVNK8G^IS%1iXj?j5gR`NP9OYz9=r#i&J&MLjc;c!CS5NEzWZ8(R~ q10AjdwFNf}{;$8rnygQ*{lx*u)0l}`0@3!d9)l|;dbv6dVgCRL`z}BL literal 59691 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∓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 sE0Itc0bJ1VN6!%NA9xWN^o#UG;nYTmH=ef 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%0AEi`#7bjz=z3;S{eYCNP>FShJN5O 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⪙pkRyHN;1_an49ER(rh0JWX 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 C#y&^@ diff --git a/metricbeat/docs/index.asciidoc b/metricbeat/docs/index.asciidoc index 9e3c0af9c60..60f650132d3 100644 --- a/metricbeat/docs/index.asciidoc +++ b/metricbeat/docs/index.asciidoc @@ -3,6 +3,7 @@ include::../../libbeat/docs/version.asciidoc[] :libbeat: http://www.elastic.co/guide/en/beats/libbeat/{doc-branch} +:kibana-ref: https://www.elastic.co/guide/en/kibana/{doc-branch} :beatsdevguide: http://www.elastic.co/guide/en/beats/devguide/{doc-branch} :filebeat: http://www.elastic.co/guide/en/beats/filebeat/{doc-branch} :logstashdoc: https://www.elastic.co/guide/en/logstash/{doc-branch} diff --git a/packetbeat/docs/configuring-howto.asciidoc b/packetbeat/docs/configuring-howto.asciidoc index eebfef0989b..a324997beab 100644 --- a/packetbeat/docs/configuring-howto.asciidoc +++ b/packetbeat/docs/configuring-howto.asciidoc @@ -4,7 +4,7 @@ [partintro] -- Before modifying configuration settings, make sure you've completed the -<> in the Getting Started. +<> in the Getting Started. This section describes some common use cases for changing configuration options. To configure {beatname_uc}, you edit the configuration file. For rpm and deb, @@ -25,10 +25,12 @@ The following topics describe how to configure Packetbeat: * <> * <> * <> +* <> * <> * <> * <> * <> +* <> * <> * <> * <> @@ -45,6 +47,8 @@ include::./packetbeat-general-options.asciidoc[] :allplatforms: include::../../libbeat/docs/outputconfig.asciidoc[] +include::../../libbeat/docs/shared-ssl-config.asciidoc[] + include::./packetbeat-filtering.asciidoc[] include::../../libbeat/docs/shared-config-ingest.asciidoc[] @@ -53,6 +57,8 @@ include::./packetbeat-geoip.asciidoc[] include::../../libbeat/docs/shared-path-config.asciidoc[] +include::../../libbeat/docs/shared-kibana-config.asciidoc[] + include::../../libbeat/docs/setup-config.asciidoc[] include::../../libbeat/docs/loggingconfig.asciidoc[] diff --git a/packetbeat/docs/gettingstarted.asciidoc b/packetbeat/docs/gettingstarted.asciidoc index 4ac40e1f80b..86c55b99e61 100644 --- a/packetbeat/docs/gettingstarted.asciidoc +++ b/packetbeat/docs/gettingstarted.asciidoc @@ -15,10 +15,11 @@ See {libbeat}/getting-started.html[Getting Started with Beats and the Elastic St After installing the Elastic Stack, read the following topics to learn how to install, configure, and run Packetbeat: * <> -* <> +* <> * <> +* <> * <> -* <> +* <> * <> * <> @@ -144,7 +145,7 @@ Before starting Packetbeat, you should look at the configuration options in the configuration file, for example `C:\Program Files\Packetbeat\packetbeat.yml` or `/etc/packetbeat/packetbeat.yml`. For more information about these options, see <>. -[[configuring-packetbeat]] +[[packetbeat-configuration]] === Step 2: Configure Packetbeat include::../../libbeat/docs/shared-configuring.asciidoc[] @@ -226,7 +227,8 @@ packetbeat.protocols: ---------------------------------------------------------------------- + -. Set the IP address and port where Packetbeat can find the Elasticsearch +. If you are sending output directly to Elasticsearch (and not using Logstash), +set the IP address and port where Packetbeat can find the Elasticsearch installation: + [source,yaml] @@ -236,26 +238,32 @@ output.elasticsearch: hosts: ["192.168.1.42:9200"] ---------------------------------------------------------------------- + -If you are sending output to Logstash, see +If you are sending output to Logstash, make sure you <> instead. -TIP: To test your configuration file, change to the directory where the Packetbeat -binary is installed, and run Packetbeat in the foreground with the following -options specified: +sudo ./packetbeat -configtest -e+. Make sure your config files are -in the path expected by Packetbeat (see <>). If you -installed from DEB or RPM packages, run +sudo ./packetbeat.sh -configtest -e+. -Depending on your OS, you might run into file ownership issues when you run this -test. See {libbeat}/config-file-permissions.html[Config File Ownership and Permissions] -in the _Beats Platform Reference_ for more information. +include::../../libbeat/docs/step-configure-kibana-endpoint.asciidoc[] + +:requires-sudo: yes +include::../../libbeat/docs/step-test-config.asciidoc[] + +include::../../libbeat/docs/step-look-at-config.asciidoc[] [[packetbeat-template]] === Step 3: Load the index template in Elasticsearch +:requires-sudo: yes :allplatforms: include::../../libbeat/docs/shared-template-load.asciidoc[] +[[load-kibana-dashboards]] +=== Step 4: Set up the Kibana dashboards + +:requires-sudo: yes +:allplatforms: +include::../../libbeat/docs/dashboards.asciidoc[] + [[packetbeat-starting]] -=== Step 4: Start Packetbeat +=== Step 5: Start Packetbeat Run Packetbeat by issuing the command that is appropriate for your platform. @@ -265,21 +273,21 @@ start Packetbeat in the foreground. *deb:* -[source,shell] +["source","sh",subs="attributes"] ---------------------------------------------------------------------- -sudo /etc/init.d/packetbeat start +sudo service {beatname_lc} start ---------------------------------------------------------------------- *rpm:* -[source,shell] +["source","sh",subs="attributes"] ---------------------------------------------------------------------- -sudo /etc/init.d/packetbeat start +sudo service {beatname_lc} start ---------------------------------------------------------------------- *docker:* -["source", "shell", subs="attributes"] +["source","sh",subs="attributes"] ---------------------------------------------------------------------- docker run {dockerimage} ---------------------------------------------------------------------- @@ -291,10 +299,10 @@ docker run {dockerimage} sudo chown root packetbeat.yml <1> sudo ./packetbeat -e -c packetbeat.yml -d "publish" ---------------------------------------------------------------------- -<1> You'll be running Packetbeat as root, so you need to change ownership -of the configuration file (see -{libbeat}/config-file-permissions.html[Config File Ownership and Permissions] -in the _Beats Platform Reference_). +<1> You'll be running Packetbeat as root, so you need to change ownership of the +configuration file, or run Packetbeat with `-strict.perms=false` specified. See +{libbeat}/config-file-permissions.html[Config File Ownership and Permissions]in +the _Beats Platform Reference_. *win:* @@ -326,16 +334,16 @@ curl -XGET 'http://localhost:9200/packetbeat-*/_search?pretty' Make sure that you replace `localhost:9200` with the address of your Elasticsearch instance. The command should return data about the HTTP transaction you just created. -[[packetbeat-sample-dashboards]] -=== Step 5: Load sample Kibana dashboards +[[view-kibana-dashboards]] +=== Step 6: View the sample Kibana dashboards To make it easier for you to get application performance insights -from packet data, we have created sample Packetbeat dashboards. The dashboards are provided as -examples. We recommend that you -http://www.elastic.co/guide/en/kibana/current/dashboard.html[customize] them -to meet your needs. +from packet data, we have created example {beatname_uc} dashboards. You loaded +the dashboards earlier when you ran the `setup` command. -image:./images/packetbeat-statistics.png[Packetbeat statistics] +include::../../libbeat/docs/opendashboards.asciidoc[] -:allplatforms: -include::../../libbeat/docs/dashboards.asciidoc[] +The dashboards are provided as examples. We recommend that you +{kibana-ref}/dashboard.html[customize] them to meet your needs. + +image:./images/packetbeat-statistics.png[Packetbeat statistics] diff --git a/packetbeat/docs/images/kibana-created-indexes.png b/packetbeat/docs/images/kibana-created-indexes.png index 343675b05e325675a58bb184496b2695cc48590f..efed361d5ac2c599c5c21b296d240c72359045a3 100644 GIT binary patch literal 72907 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

    H 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

    w%1+13@^`1eQ&Ot^(Y#t{Gh)S(vCF>#MwaY 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 diff --git a/packetbeat/docs/index.asciidoc b/packetbeat/docs/index.asciidoc index b28432202b4..9c6f55d1a79 100644 --- a/packetbeat/docs/index.asciidoc +++ b/packetbeat/docs/index.asciidoc @@ -3,6 +3,7 @@ include::../../libbeat/docs/version.asciidoc[] :libbeat: http://www.elastic.co/guide/en/beats/libbeat/{doc-branch} +:kibana-ref: https://www.elastic.co/guide/en/kibana/{doc-branch} :beatsdevguide: http://www.elastic.co/guide/en/beats/devguide/{doc-branch} :packetbeat: http://www.elastic.co/guide/en/beats/packetbeat/{doc-branch} :metricbeat: http://www.elastic.co/guide/en/beats/metricbeat/{doc-branch} diff --git a/packetbeat/docs/packetbeat-geoip.asciidoc b/packetbeat/docs/packetbeat-geoip.asciidoc index fba9da7b0b0..be84a4bab1c 100644 --- a/packetbeat/docs/packetbeat-geoip.asciidoc +++ b/packetbeat/docs/packetbeat-geoip.asciidoc @@ -89,7 +89,7 @@ The event that's sent to Elasticsearch should now include a === Visualizing the location of your Packetbeat clients To visualize the location of your Packetbeat clients, you can either -<> (if +<> (if you haven't already), or create a new {kibanadoc}/tilemap.html[Tile map] in Kibana and use the `client_geoip.location` field as the Geohash. diff --git a/packetbeat/docs/visualizing-data-packetbeat.asciidoc b/packetbeat/docs/visualizing-data-packetbeat.asciidoc index 698093b4974..eca103a2149 100644 --- a/packetbeat/docs/visualizing-data-packetbeat.asciidoc +++ b/packetbeat/docs/visualizing-data-packetbeat.asciidoc @@ -4,7 +4,7 @@ [partintro] -- -Before trying to visualize Packetbeat data in Kibana, we recommend that you <>. Then read the topics in this +Before trying to visualize Packetbeat data in Kibana, we recommend that you <>. Then read the topics in this section to learn how to work with Packetbeat data in Kibana: * <> @@ -27,7 +27,7 @@ Use the *Packetbeat Flows Search* to display the most important information for image:./images/discovery-packetbeat-flows.png[Packetbeat Flows Search] These searches are not default views on the *Discover* page. To use these searches, make sure you've -<> in Kibana. Then go to the *Discover* page and click +<>. Then go to the *Discover* page and click *Open*. You can type `Packetbeat` in the Search field to filter the list of searches. diff --git a/winlogbeat/docs/configuring-howto.asciidoc b/winlogbeat/docs/configuring-howto.asciidoc index 503dae7a6af..8a6fa05ebce 100644 --- a/winlogbeat/docs/configuring-howto.asciidoc +++ b/winlogbeat/docs/configuring-howto.asciidoc @@ -20,9 +20,11 @@ The following topics describe how to configure Winlogbeat: * <> * <> * <> +* <> * <> * <> * <> +* <> * <> * <> * <> @@ -38,12 +40,16 @@ include::./winlogbeat-general-options.asciidoc[] :win: include::../../libbeat/docs/outputconfig.asciidoc[] +include::../../libbeat/docs/shared-ssl-config.asciidoc[] + include::./winlogbeat-filtering.asciidoc[] include::../../libbeat/docs/shared-config-ingest.asciidoc[] include::../../libbeat/docs/shared-path-config.asciidoc[] +include::../../libbeat/docs/shared-kibana-config.asciidoc[] + include::../../libbeat/docs/setup-config.asciidoc[] include::../../libbeat/docs/loggingconfig.asciidoc[] diff --git a/winlogbeat/docs/getting-started.asciidoc b/winlogbeat/docs/getting-started.asciidoc index 3d7f1648deb..927c985333a 100644 --- a/winlogbeat/docs/getting-started.asciidoc +++ b/winlogbeat/docs/getting-started.asciidoc @@ -17,8 +17,9 @@ After installing the Elastic Stack, read the following topics to learn how to in * <> * <> * <> +* <> * <> -* <> +* <> * <> * <> @@ -104,8 +105,9 @@ To obtain a list of available event logs, run `Get-EventLog *` in PowerShell. For more information about this command, see the configuration details for <>. -. If you are sending output to Elasticsearch, set the IP address and port where -Winlogbeat can find the Elasticsearch installation: +. If you are sending output directly to Elasticsearch (and not using Logstash), +set the IP address and port where Winlogbeat can find the Elasticsearch +installation: + [source,yaml] ---------------------------------------------------------------------- @@ -114,13 +116,16 @@ output.elasticsearch: - localhost:9200 ---------------------------------------------------------------------- + -If you are sending output to Logstash, see <> instead. +If you are sending output to Logstash, make sure you +<> instead. + +include::../../libbeat/docs/step-configure-kibana-endpoint.asciidoc[] . After you save your configuration file, test it with the following command. + [source,shell] ---------------------------------------------------------------------- -PS C:\Program Files\Winlogbeat> .\winlogbeat.exe -c .\winlogbeat.yml -configtest -e +PS C:\Program Files\Winlogbeat> .\winlogbeat.exe test config -c .\winlogbeat.yml -e ---------------------------------------------------------------------- [[config-winlogbeat-logstash]] @@ -134,8 +139,14 @@ include::../../libbeat/docs/shared-logstash-config.asciidoc[] include::../../libbeat/docs/shared-template-load.asciidoc[] +[[load-kibana-dashboards]] +=== Step 5: Set up the Kibana dashboards + +:win: +include::../../libbeat/docs/dashboards.asciidoc[] + [[winlogbeat-starting]] -=== Step 5: Start Winlogbeat +=== Step 6: Start Winlogbeat Start the Winlogbeat service with the following command: @@ -165,17 +176,16 @@ Stop the Winlogbeat service with the following command: PS C:\Program Files\Winlogbeat> Stop-Service winlogbeat ---------------------------------------------------------------------- -[[winlogbeat-sample-dashboards]] -=== Step 6: Load sample Kibana dashboards +[[view-kibana-dashboards]] +=== Step 7: View the sample Kibana dashboards -To make it easier for you to start monitoring your servers in Kibana, -we have created sample Winlogbeat dashboards. The dashboards are provided as -examples. We recommend that you -http://www.elastic.co/guide/en/kibana/current/dashboard.html[customize] them -to meet your needs. +To make it easier for you to start monitoring your servers in Kibana, we have +created example {beatname_uc} dashboards. You loaded the dashboards earlier +when you ran the `setup` command. -image:./images/winlogbeat-dashboard.png[Winlogbeat statistics] - -include::../../libbeat/docs/dashboards.asciidoc[] +include::../../libbeat/docs/opendashboards.asciidoc[] +The dashboards are provided as examples. We recommend that you +{kibana-ref}/dashboard.html[customize] them to meet your needs. +image:./images/winlogbeat-dashboard.png[Winlogbeat statistics] diff --git a/winlogbeat/docs/index.asciidoc b/winlogbeat/docs/index.asciidoc index d221fb65fa2..fc24f8382b9 100644 --- a/winlogbeat/docs/index.asciidoc +++ b/winlogbeat/docs/index.asciidoc @@ -3,6 +3,7 @@ include::../../libbeat/docs/version.asciidoc[] :libbeat: http://www.elastic.co/guide/en/beats/libbeat/{doc-branch} +:kibana-ref: https://www.elastic.co/guide/en/kibana/{doc-branch} :beatsdevguide: http://www.elastic.co/guide/en/beats/devguide/{doc-branch} :packetbeat: http://www.elastic.co/guide/en/beats/packetbeat/{doc-branch} :metricbeat: http://www.elastic.co/guide/en/beats/metricbeat/{doc-branch} From 94a197bd06d54c0e97c6ce3ef76a49c3dea34fae Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Wed, 2 Aug 2017 17:17:39 -0300 Subject: [PATCH 034/139] Adds a "type" field to the filesystem beat (#4717) (#4717) Its value is copied from sigar.FileSystem.SysTypeName (on Windows, sigar.FileSystem.TypeName) and passed through so that it becomes possible to filter out `overlay`, `tmpfs` or otherwise uninteresting filesystems. Fixes #3459. --- CHANGELOG.asciidoc | 1 + metricbeat/docs/fields.asciidoc | 8 +++ .../module/system/filesystem/_meta/data.json | 28 +++++----- .../system/filesystem/_meta/docs.asciidoc | 4 +- .../module/system/filesystem/_meta/fields.yml | 4 ++ metricbeat/module/system/filesystem/doc.go | 52 +++++++++++-------- metricbeat/module/system/filesystem/helper.go | 12 +++++ .../module/system/filesystem/helper_test.go | 4 ++ metricbeat/tests/system/test_system.py | 2 +- 9 files changed, 78 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 2d2790eb20b..ac9b420f2ca 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -130,6 +130,7 @@ https://github.com/elastic/beats/compare/v6.0.0-alpha2...v6.0.0-beta1[View commi with the system process metricset. The documentation for these metrics already stated that on multi-core systems the percentages could be greater than 100%. {pull}4544[4544] - Remove filters setting from metricbeat modules. {pull}4699[4699] +- Added `type` field to filesystem metrics. {pull}4717[4717] *Packetbeat* diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 278733e95c2..08191e8c8ac 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -8797,6 +8797,14 @@ type: keyword The disk name. For example: `/dev/disk1` +[float] +=== `system.filesystem.type` + +type: keyword + +The disk type. For example: `ext4` + + [float] === `system.filesystem.mount_point` diff --git a/metricbeat/module/system/filesystem/_meta/data.json b/metricbeat/module/system/filesystem/_meta/data.json index 225428eda98..3009b911ff0 100644 --- a/metricbeat/module/system/filesystem/_meta/data.json +++ b/metricbeat/module/system/filesystem/_meta/data.json @@ -4,6 +4,10 @@ "hostname": "host.example.com", "name": "host.example.com" }, + "@metadata": { + "beat": "noindex", + "type": "doc" + }, "metricset": { "module": "system", "name": "filesystem", @@ -11,18 +15,18 @@ }, "system": { "filesystem": { - "available": 38688276480, - "device_name": "none", - "files": 3940352, - "free": 41930997760, - "free_files": 3276976, + "available": 105569656832, + "device_name": "/dev/disk1", + "type": "hfs", + "files": 4294967279 + "free": 105831800832, + "free_files": 4292793781, "mount_point": "/", - "total": 63371726848, + "total": 249779191808, "used": { - "bytes": 21440729088, - "pct": 0.3383 - } + "bytes": 143947390976, + "pct": 0.5763 + }, } - }, - "type": "metricsets" -} \ No newline at end of file + } +} diff --git a/metricbeat/module/system/filesystem/_meta/docs.asciidoc b/metricbeat/module/system/filesystem/_meta/docs.asciidoc index ee216a01ffd..e3aa78f585f 100644 --- a/metricbeat/module/system/filesystem/_meta/docs.asciidoc +++ b/metricbeat/module/system/filesystem/_meta/docs.asciidoc @@ -16,7 +16,9 @@ This metricset is available on: Often there are mounted filesystems that you do not want Metricbeat to report metrics on. A simple strategy to deal with these filesystems is to configure a -drop_event filter that matches the `mount_point` using a regular expression. +drop_event filter that matches the `mount_point` or `type` using a regular +expression. + Below is an example. [source,yaml] diff --git a/metricbeat/module/system/filesystem/_meta/fields.yml b/metricbeat/module/system/filesystem/_meta/fields.yml index 4948bcf1323..c4a180aa630 100644 --- a/metricbeat/module/system/filesystem/_meta/fields.yml +++ b/metricbeat/module/system/filesystem/_meta/fields.yml @@ -12,6 +12,10 @@ type: keyword description: > The disk name. For example: `/dev/disk1` + - name: type + type: keyword + description: > + The disk type. For example: `ext4` - name: mount_point type: keyword description: > diff --git a/metricbeat/module/system/filesystem/doc.go b/metricbeat/module/system/filesystem/doc.go index d344acd22dd..69e2c7b2bcc 100644 --- a/metricbeat/module/system/filesystem/doc.go +++ b/metricbeat/module/system/filesystem/doc.go @@ -5,30 +5,36 @@ for each of the mounted file systems. An example event looks as following: { - "@timestamp": "2016-05-25T20:51:36.813Z", - "beat": { - "hostname": "host.example.com", - "name": "host.example.com" - }, - "metricset": { - "module": "system", - "name": "filesystem", - "rtt": 55 - }, - "system": { - "filesystem": { - "avail": 13838553088, - "device_name": "/dev/disk1", - "files": 60981246, - "free": 14100697088, - "free_files": 3378553, - "mount_point": "/", - "total": 249779191808, - "used": 235678494720, - "used_p": 0.9435 + "@timestamp": "2016-05-23T08:05:34.853Z", + "beat": { + "hostname": "host.example.com", + "name": "host.example.com" + }, + "@metadata": { + "beat": "noindex", + "type": "doc" + }, + "metricset": { + "module": "system", + "name": "filesystem", + "rtt": 115 + }, + "system": { + "filesystem": { + "available": 105569656832, + "device_name": "/dev/disk1", + "type": "hfs", + "files": 4294967279 + "free": 105831800832, + "free_files": 4292793781, + "mount_point": "/", + "total": 249779191808, + "used": { + "bytes": 143947390976, + "pct": 0.5763 + }, + } } - }, - "type": "metricsets" } */ diff --git a/metricbeat/module/system/filesystem/helper.go b/metricbeat/module/system/filesystem/helper.go index c7f6159a27b..f5471f5df26 100644 --- a/metricbeat/module/system/filesystem/helper.go +++ b/metricbeat/module/system/filesystem/helper.go @@ -6,6 +6,8 @@ import ( "path/filepath" "time" + "runtime" + "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/metricbeat/module/system" sigar "github.com/elastic/gosigar" @@ -16,6 +18,7 @@ type FileSystemStat struct { DevName string `json:"device_name"` Mount string `json:"mount_point"` UsedPercent float64 `json:"used_p"` + SysTypeName string `json:"type"` ctime time.Time } @@ -46,10 +49,18 @@ func GetFileSystemStat(fs sigar.FileSystem) (*FileSystemStat, error) { return nil, err } + var t string + if runtime.GOOS == "windows" { + t = fs.TypeName + } else { + t = fs.SysTypeName + } + filesystem := FileSystemStat{ FileSystemUsage: stat, DevName: fs.DevName, Mount: fs.DirName, + SysTypeName: t, } return &filesystem, nil @@ -66,6 +77,7 @@ func AddFileSystemUsedPercentage(f *FileSystemStat) { func GetFilesystemEvent(fsStat *FileSystemStat) common.MapStr { return common.MapStr{ + "type": fsStat.SysTypeName, "device_name": fsStat.DevName, "mount_point": fsStat.Mount, "total": fsStat.Total, diff --git a/metricbeat/module/system/filesystem/helper_test.go b/metricbeat/module/system/filesystem/helper_test.go index 8c5e37228b2..c0e101b8c7a 100644 --- a/metricbeat/module/system/filesystem/helper_test.go +++ b/metricbeat/module/system/filesystem/helper_test.go @@ -37,6 +37,10 @@ func TestFileSystemList(t *testing.T) { assert.True(t, (stat.Free >= 0)) assert.True(t, (stat.Avail >= 0)) assert.True(t, (stat.Used >= 0)) + + if runtime.GOOS != "windows" { + assert.NotEqual(t, "", stat.SysTypeName) + } } } } diff --git a/metricbeat/tests/system/test_system.py b/metricbeat/tests/system/test_system.py index a339c19feaa..b0f2df4003e 100644 --- a/metricbeat/tests/system/test_system.py +++ b/metricbeat/tests/system/test_system.py @@ -27,7 +27,7 @@ SYSTEM_DISKIO_FIELDS = ["name", "read.count", "write.count", "read.bytes", "write.bytes", "read.time", "write.time", "io.time"] -SYSTEM_FILESYSTEM_FIELDS = ["available", "device_name", "files", "free", +SYSTEM_FILESYSTEM_FIELDS = ["available", "device_name", "type", "files", "free", "free_files", "mount_point", "total", "used.bytes", "used.pct"] From 61bd302bd42441b480f5143f6fd6aa6091698f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20Gr=C3=A9au?= Date: Thu, 3 Aug 2017 04:18:09 +0200 Subject: [PATCH 035/139] Fix HTTP 404 URLs in README (#4822) * fix Beats current developer guide URL * add https protocol on Elastic website URL --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4c1b3ef0256..98a5fb5a1ed 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Beat | Description [Winlogbeat](https://github.com/elastic/beats/tree/master/winlogbeat) | Fetches and ships Windows Event logs In addition to the above Beats, which are officially supported by -[Elastic](elastic.co), the +[Elastic](https://elastic.co), the community has created a set of other Beats that make use of libbeat but live outside of this Github repository. We maintain a list of community Beats [here](https://www.elastic.co/guide/en/beats/libbeat/master/community-beats.html). @@ -67,7 +67,7 @@ Please start by reading our [CONTRIBUTING](CONTRIBUTING.md) file. If you are creating a new Beat, you don't need to submit the code to this repository. You can simply start working in a new repository and make use of the libbeat packages, by following our [developer -guide](https://www.elastic.co/guide/en/beats/libbeat/master/new-beat.html). +guide](https://www.elastic.co/guide/en/beats/libbeat/current/new-beat.html). After you have a working prototype, open a pull request to add your Beat to the list of [community Beats](https://github.com/elastic/beats/blob/master/libbeat/docs/communitybeats.asciidoc). From 23d9fe69e8a4367fc31915553596129a2ca8267b Mon Sep 17 00:00:00 2001 From: Vijay Samuel Date: Thu, 3 Aug 2017 01:00:47 -0700 Subject: [PATCH 036/139] Make config object public for graphite and http server (#4820) --- CHANGELOG.asciidoc | 3 ++- metricbeat/module/graphite/server/config.go | 18 +++++++++--------- metricbeat/module/graphite/server/data.go | 8 ++++---- metricbeat/module/graphite/server/data_test.go | 8 ++++---- metricbeat/module/graphite/server/server.go | 2 +- metricbeat/module/http/server/config.go | 16 ++++++++-------- metricbeat/module/http/server/data.go | 14 +++++++------- metricbeat/module/http/server/data_test.go | 6 +++--- 8 files changed, 38 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index ac9b420f2ca..61910847ffe 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -73,7 +73,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Add support to exclude labels from kubernetes pod metadata. {pull}4757[4757] - Add graphite protocol metricbeat module. {pull}4734[4734] - Add http server metricset to support push metrics via http. {pull}4770[4770] - +- Make config object public for graphite and http server {pull}4820[4820] + *Packetbeat* *Winlogbeat* diff --git a/metricbeat/module/graphite/server/config.go b/metricbeat/module/graphite/server/config.go index c1419e87a35..982d1183abb 100644 --- a/metricbeat/module/graphite/server/config.go +++ b/metricbeat/module/graphite/server/config.go @@ -8,13 +8,13 @@ const ( defaultDelimiter = "." ) -type graphiteCollectorConfig struct { +type GraphiteServerConfig struct { Protocol string `config:"protocol"` - Templates []templateConfig `config:"templates"` - DefaultTemplate templateConfig `config:"default_template"` + Templates []TemplateConfig `config:"templates"` + DefaultTemplate TemplateConfig `config:"default_template"` } -type templateConfig struct { +type TemplateConfig struct { Filter string `config:"filter"` Template string `config:"template"` Namespace string `config:"namespace"` @@ -22,10 +22,10 @@ type templateConfig struct { Tags map[string]string `config:"tags"` } -func defaultGraphiteCollectorConfig() graphiteCollectorConfig { - return graphiteCollectorConfig{ +func DefaultGraphiteCollectorConfig() GraphiteServerConfig { + return GraphiteServerConfig{ Protocol: "udp", - DefaultTemplate: templateConfig{ + DefaultTemplate: TemplateConfig{ Filter: "*", Template: "metric*", Namespace: "graphite", @@ -34,14 +34,14 @@ func defaultGraphiteCollectorConfig() graphiteCollectorConfig { } } -func (c graphiteCollectorConfig) Validate() error { +func (c GraphiteServerConfig) Validate() error { if c.Protocol != "tcp" && c.Protocol != "udp" { return errors.New("`protocol` can only be tcp or udp") } return nil } -func (t *templateConfig) Validate() error { +func (t *TemplateConfig) Validate() error { if t.Namespace == "" { return errors.New("`namespace` can not be empty in template configuration") } diff --git a/metricbeat/module/graphite/server/data.go b/metricbeat/module/graphite/server/data.go index 2e6a8b6ae27..7527225f912 100644 --- a/metricbeat/module/graphite/server/data.go +++ b/metricbeat/module/graphite/server/data.go @@ -25,7 +25,7 @@ type metricProcessor struct { sync.RWMutex } -func NewMetricProcessor(templates []templateConfig, defaultTemplate templateConfig) *metricProcessor { +func NewMetricProcessor(templates []TemplateConfig, defaultTemplate TemplateConfig) *metricProcessor { templateTree := NewTree(getTemplateFromConfig(defaultTemplate)) for _, t := range templates { templateTree.Insert(t.Filter, getTemplateFromConfig(t)) @@ -37,7 +37,7 @@ func NewMetricProcessor(templates []templateConfig, defaultTemplate templateConf } } -func getTemplateFromConfig(config templateConfig) template { +func getTemplateFromConfig(config TemplateConfig) template { return template{ Namespace: config.Namespace, Tags: config.Tags, @@ -46,14 +46,14 @@ func getTemplateFromConfig(config templateConfig) template { } } -func (m *metricProcessor) AddTemplate(t templateConfig) { +func (m *metricProcessor) AddTemplate(t TemplateConfig) { m.Lock() template := getTemplateFromConfig(t) m.templates.Insert(t.Filter, template) m.Unlock() } -func (m *metricProcessor) RemoveTemplate(template templateConfig) { +func (m *metricProcessor) RemoveTemplate(template TemplateConfig) { m.Lock() m.templates.Delete(template.Filter) m.Unlock() diff --git a/metricbeat/module/graphite/server/data_test.go b/metricbeat/module/graphite/server/data_test.go index cb93978e056..543c2e08d51 100644 --- a/metricbeat/module/graphite/server/data_test.go +++ b/metricbeat/module/graphite/server/data_test.go @@ -13,7 +13,7 @@ import ( ) func GetMetricProcessor() *metricProcessor { - templates := []templateConfig{ + templates := []TemplateConfig{ { Namespace: "foo", Filter: "test.localhost.*", @@ -31,13 +31,13 @@ func GetMetricProcessor() *metricProcessor { }, } - defaultTemplate := defaultGraphiteCollectorConfig().DefaultTemplate + defaultTemplate := DefaultGraphiteCollectorConfig().DefaultTemplate return NewMetricProcessor(templates, defaultTemplate) } func TestMetricProcessorAddTemplate(t *testing.T) { processor := GetMetricProcessor() - temp := templateConfig{ + temp := TemplateConfig{ Namespace: "xyz", Filter: "a.b.*", Template: ".host.shell.metric", @@ -51,7 +51,7 @@ func TestMetricProcessorAddTemplate(t *testing.T) { func TestMetricProcessorDeleteTemplate(t *testing.T) { processor := GetMetricProcessor() - temp := templateConfig{ + temp := TemplateConfig{ Namespace: "xyz", Filter: "a.b.*", Template: ".host.shell.metric", diff --git a/metricbeat/module/graphite/server/server.go b/metricbeat/module/graphite/server/server.go index 37e01fbd2dc..fac1154b507 100644 --- a/metricbeat/module/graphite/server/server.go +++ b/metricbeat/module/graphite/server/server.go @@ -32,7 +32,7 @@ type MetricSet struct { func New(base mb.BaseMetricSet) (mb.MetricSet, error) { cfgwarn.Experimental("The graphite server metricset is experimental") - config := defaultGraphiteCollectorConfig() + config := DefaultGraphiteCollectorConfig() if err := base.Module().UnpackConfig(&config); err != nil { return nil, err } diff --git a/metricbeat/module/http/server/config.go b/metricbeat/module/http/server/config.go index 2a7d9355dc4..627277584f0 100644 --- a/metricbeat/module/http/server/config.go +++ b/metricbeat/module/http/server/config.go @@ -6,27 +6,27 @@ import ( "github.com/elastic/beats/libbeat/common" ) -type httpServerConfig struct { - Paths []pathConfig `config:"paths"` - DefaultPath pathConfig `config:"default_path"` +type HttpServerConfig struct { + Paths []PathConfig `config:"paths"` + DefaultPath PathConfig `config:"default_path"` } -type pathConfig struct { +type PathConfig struct { Path string `config:"path"` Fields common.MapStr `config:"fields"` Namespace string `config:"namespace"` } -func defaultHttpServerConfig() httpServerConfig { - return httpServerConfig{ - DefaultPath: pathConfig{ +func defaultHttpServerConfig() HttpServerConfig { + return HttpServerConfig{ + DefaultPath: PathConfig{ Path: "/", Namespace: "http", }, } } -func (p pathConfig) Validate() error { +func (p PathConfig) Validate() error { if p.Namespace == "" { return errors.New("`namespace` can not be empty in path configuration") } diff --git a/metricbeat/module/http/server/data.go b/metricbeat/module/http/server/data.go index 22057248326..5f8e8311009 100644 --- a/metricbeat/module/http/server/data.go +++ b/metricbeat/module/http/server/data.go @@ -13,13 +13,13 @@ import ( ) type metricProcessor struct { - paths map[string]pathConfig - defaultPath pathConfig + paths map[string]PathConfig + defaultPath PathConfig sync.RWMutex } -func NewMetricProcessor(paths []pathConfig, defaultPath pathConfig) *metricProcessor { - pathMap := map[string]pathConfig{} +func NewMetricProcessor(paths []PathConfig, defaultPath PathConfig) *metricProcessor { + pathMap := map[string]PathConfig{} for _, path := range paths { pathMap[path.Path] = path } @@ -30,13 +30,13 @@ func NewMetricProcessor(paths []pathConfig, defaultPath pathConfig) *metricProce } } -func (m *metricProcessor) AddPath(path pathConfig) { +func (m *metricProcessor) AddPath(path PathConfig) { m.Lock() m.paths[path.Path] = path m.Unlock() } -func (m *metricProcessor) RemovePath(path pathConfig) { +func (m *metricProcessor) RemovePath(path PathConfig) { m.Lock() delete(m.paths, path.Path) m.Unlock() @@ -85,7 +85,7 @@ func (p *metricProcessor) Process(event server.Event) (common.MapStr, error) { return out, nil } -func (p *metricProcessor) findPath(url string) *pathConfig { +func (p *metricProcessor) findPath(url string) *PathConfig { for path, conf := range p.paths { if strings.Index(url, path) == 0 { return &conf diff --git a/metricbeat/module/http/server/data_test.go b/metricbeat/module/http/server/data_test.go index cbd0a58d7c1..4ab37e474c0 100644 --- a/metricbeat/module/http/server/data_test.go +++ b/metricbeat/module/http/server/data_test.go @@ -10,7 +10,7 @@ import ( ) func GetMetricProcessor() *metricProcessor { - paths := []pathConfig{ + paths := []PathConfig{ { Namespace: "foo", Path: "/foo", @@ -30,7 +30,7 @@ func GetMetricProcessor() *metricProcessor { func TestMetricProcessorAddPath(t *testing.T) { processor := GetMetricProcessor() - temp := pathConfig{ + temp := PathConfig{ Namespace: "xyz", Path: "/abc", } @@ -51,7 +51,7 @@ func TestFindPath(t *testing.T) { processor := GetMetricProcessor() tests := []struct { a string - expected pathConfig + expected PathConfig }{ { a: "/foo/bar", From 2caf75d04397e508118069e4e01c36f78630825e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Tue, 8 Aug 2017 08:51:15 +0200 Subject: [PATCH 037/139] Add PostgresSQL module for Filebeat (#4763) * filebeat: add PostgreSQL module This module includes a sample dashboard and two sample searches for Kibana. * filebeat: add PostgreSQL slowlog * system-tests: make it possible to test more than 10 logs Previously, only 10 logs could be in *.log and *-expected.json files, as it is the default page size of ES. However, to be more future proof the test was extended, so it can validate more than 10 logs and events. --- CHANGELOG.asciidoc | 2 + filebeat/docs/fields.asciidoc | 87 ++ .../images/filebeat-postgresql-overview.png | Bin 0 -> 44427 bytes .../filebeat-postgresql-slowlog-overview.png | Bin 0 -> 57254 bytes filebeat/docs/images/filebeat-postgresql.png | Bin 0 -> 71286 bytes filebeat/docs/modules/postgresql.asciidoc | 43 + filebeat/docs/modules_list.asciidoc | 2 + filebeat/filebeat.reference.yml | 14 + .../postgresql/_meta/config.reference.yml | 12 + filebeat/module/postgresql/_meta/config.yml | 8 + .../module/postgresql/_meta/docs.asciidoc | 30 + filebeat/module/postgresql/_meta/fields.yml | 11 + .../Filebeat-Postgresql-overview.json | 64 ++ .../Filebeat-Postgresql-slowlogs.json | 87 ++ .../module/postgresql/log/_meta/fields.yml | 40 + filebeat/module/postgresql/log/config/log.yml | 10 + .../postgresql/log/ingest/pipeline.json | 41 + filebeat/module/postgresql/log/manifest.yml | 13 + .../postgresql-9.6-debian-with-slowlog.log | 61 ++ ...-9.6-debian-with-slowlog.log-expected.json | 814 ++++++++++++++++++ .../log/test/postgresql-ubuntu-9.5.log | 78 ++ filebeat/modules.d/postgresql.yml.disabled | 8 + filebeat/tests/system/test_modules.py | 33 +- 23 files changed, 1446 insertions(+), 12 deletions(-) create mode 100644 filebeat/docs/images/filebeat-postgresql-overview.png create mode 100644 filebeat/docs/images/filebeat-postgresql-slowlog-overview.png create mode 100644 filebeat/docs/images/filebeat-postgresql.png create mode 100644 filebeat/docs/modules/postgresql.asciidoc create mode 100644 filebeat/module/postgresql/_meta/config.reference.yml create mode 100644 filebeat/module/postgresql/_meta/config.yml create mode 100644 filebeat/module/postgresql/_meta/docs.asciidoc create mode 100644 filebeat/module/postgresql/_meta/fields.yml create mode 100644 filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-overview.json create mode 100644 filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-slowlogs.json create mode 100644 filebeat/module/postgresql/log/_meta/fields.yml create mode 100644 filebeat/module/postgresql/log/config/log.yml create mode 100644 filebeat/module/postgresql/log/ingest/pipeline.json create mode 100644 filebeat/module/postgresql/log/manifest.yml create mode 100644 filebeat/module/postgresql/log/test/postgresql-9.6-debian-with-slowlog.log create mode 100644 filebeat/module/postgresql/log/test/postgresql-9.6-debian-with-slowlog.log-expected.json create mode 100644 filebeat/module/postgresql/log/test/postgresql-ubuntu-9.5.log create mode 100644 filebeat/modules.d/postgresql.yml.disabled diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 61910847ffe..82d8b24bed4 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -66,6 +66,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Filebeat* +- Add PostgreSQL module with slowlog support. {pull}4763[4763] + *Heartbeat* *Metricbeat* diff --git a/filebeat/docs/fields.asciidoc b/filebeat/docs/fields.asciidoc index 54ef5bc482d..4e1cf9673fc 100644 --- a/filebeat/docs/fields.asciidoc +++ b/filebeat/docs/fields.asciidoc @@ -22,6 +22,7 @@ grouped in the following categories: * <> * <> * <> +* <> * <> * <> @@ -1277,6 +1278,92 @@ type: text The error message +[[exported-fields-postgresql]] +== PostgreSQL fields + +Module for parsing the PostgreSQL log files. + + + +[float] +== postgresql fields + +Fields from PostgreSQL logs. + + + +[float] +== log fields + +Fields from the PostgreSQL log files. + + + +[float] +=== `postgresql.log.timestamp` + +The timestamp from the log line. + + +[float] +=== `postgresql.log.timezone` + +The timezone of timestamp. + + +[float] +=== `postgresql.log.thread_id` + +type: long + +Processs id + + +[float] +=== `postgresql.log.user` + +example: admin + +Name of user + +[float] +=== `postgresql.log.database` + +example: mydb + +Name of database + +[float] +=== `postgresql.log.level` + +example: FATAL + +The log level. + +[float] +=== `postgresql.log.duration` + +type: float + +example: 30.0 + +Duration of a query. + +[float] +=== `postgresql.log.query` + +example: SELECT * FROM users; + +Query statment. + +[float] +=== `postgresql.log.message` + +type: text + +The logged message. + + [[exported-fields-redis]] == Redis fields diff --git a/filebeat/docs/images/filebeat-postgresql-overview.png b/filebeat/docs/images/filebeat-postgresql-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..b4fc428c4d02dee831ecaaced31eb55ecc668bb3 GIT binary patch literal 44427 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 literal 0 HcmV?d00001 diff --git a/filebeat/docs/images/filebeat-postgresql-slowlog-overview.png b/filebeat/docs/images/filebeat-postgresql-slowlog-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..944a257785226e6e977007126373c9c60baf7dcb GIT binary patch literal 57254 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 f?Z2hOa6w$k_vM=L=gi!Uub_R> section. + diff --git a/filebeat/docs/modules_list.asciidoc b/filebeat/docs/modules_list.asciidoc index f8ce7354cdc..1dd62900250 100644 --- a/filebeat/docs/modules_list.asciidoc +++ b/filebeat/docs/modules_list.asciidoc @@ -8,6 +8,7 @@ This file is generated! See scripts/docs_collector.py * <> * <> * <> + * <> * <> * <> @@ -20,5 +21,6 @@ include::modules/auditd.asciidoc[] include::modules/icinga.asciidoc[] include::modules/mysql.asciidoc[] include::modules/nginx.asciidoc[] +include::modules/postgresql.asciidoc[] include::modules/redis.asciidoc[] include::modules/system.asciidoc[] diff --git a/filebeat/filebeat.reference.yml b/filebeat/filebeat.reference.yml index 20ee62930e2..dcd7d03653b 100644 --- a/filebeat/filebeat.reference.yml +++ b/filebeat/filebeat.reference.yml @@ -166,6 +166,20 @@ filebeat.modules: # can be added under this section. #prospector: +#----------------------------- PostgreSQL Module ----------------------------- +#- module: postgresql + # Logs + #log: + #enabled: true + + # Set custom paths for the log files. If left empty, + # Filebeat will choose the paths depending on your OS. + #var.paths: + + # Prospector configuration (advanced). Any prospector configuration option + # can be added under this section. + #prospector: + #-------------------------------- Redis Module ------------------------------- #- module: redis # Main logs diff --git a/filebeat/module/postgresql/_meta/config.reference.yml b/filebeat/module/postgresql/_meta/config.reference.yml new file mode 100644 index 00000000000..fa500fda4b2 --- /dev/null +++ b/filebeat/module/postgresql/_meta/config.reference.yml @@ -0,0 +1,12 @@ +#- module: postgresql + # Logs + #log: + #enabled: true + + # Set custom paths for the log files. If left empty, + # Filebeat will choose the paths depending on your OS. + #var.paths: + + # Prospector configuration (advanced). Any prospector configuration option + # can be added under this section. + #prospector: diff --git a/filebeat/module/postgresql/_meta/config.yml b/filebeat/module/postgresql/_meta/config.yml new file mode 100644 index 00000000000..c82734a9570 --- /dev/null +++ b/filebeat/module/postgresql/_meta/config.yml @@ -0,0 +1,8 @@ +- module: postgresql + # All logs + log: + enabled: true + + # Set custom paths for the log files. If left empty, + # Filebeat will choose the paths depending on your OS. + #var.paths: diff --git a/filebeat/module/postgresql/_meta/docs.asciidoc b/filebeat/module/postgresql/_meta/docs.asciidoc new file mode 100644 index 00000000000..c67350d08bc --- /dev/null +++ b/filebeat/module/postgresql/_meta/docs.asciidoc @@ -0,0 +1,30 @@ +== PostgreSQL module + +This module collects and parses the logs created by https://www.postgresql.org/[PostgreSQL]. + +[float] +=== Compatibility + +The PostgreSQL module was tested with logs from versions 9.5 on Ubuntu and 9.6 on Debian. + +[float] +=== Dashboard + +This module comes with two sample dashboards. + +The first dashboard is for regulars logs. + +image::./images/filebeat-postgresql-overview.png[] + +The second one shows the slowlogs of PostgreSQL. + +image::./images/filebeat-postgresql-postgresql-overview.png[] + +[float] +=== Logs fileset settings + +[float] +==== var.paths + +An array of paths where to look for the log files. If left empty, Filebeat +will choose the paths depending on your operating systems. diff --git a/filebeat/module/postgresql/_meta/fields.yml b/filebeat/module/postgresql/_meta/fields.yml new file mode 100644 index 00000000000..5c773288ab6 --- /dev/null +++ b/filebeat/module/postgresql/_meta/fields.yml @@ -0,0 +1,11 @@ +- key: postgresql + title: "PostgreSQL" + description: > + Module for parsing the PostgreSQL log files. + short_config: true + fields: + - name: postgresql + type: group + description: > + Fields from PostgreSQL logs. + fields: diff --git a/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-overview.json b/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-overview.json new file mode 100644 index 00000000000..c63dea005ff --- /dev/null +++ b/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-overview.json @@ -0,0 +1,64 @@ +{ + "objects": [ + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "ef9da9b0-776c-11e7-9e03-393c0d1aa325", + "title": "PostgreSQL Log Level Count", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "version": 1, + "visState": "{\"title\":\"PostgreSQL Log Level Count\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"postgresql.log.level\",\"size\":12,\"order\":\"desc\",\"orderBy\":\"1\"}}]}" + }, + "id": "28563b50-776d-11e7-9e03-393c0d1aa325", + "type": "visualization", + "version": 1 + }, + { + "attributes": { + "columns": [ + "postgresql.log.user", + "postgresql.log.database", + "postgresql.log.level", + "postgresql.log.message", + "postgresql.log.query" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"a0b887a0-763d-11e7-9e03-393c0d1aa325\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"postgresql.log.level:*\",\"language\":\"lucene\"},\"filter\":[]}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "PostgreSQL All Logs", + "version": 1 + }, + "id": "ef9da9b0-776c-11e7-9e03-393c0d1aa325", + "type": "search", + "version": 1 + }, + { + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" + }, + "optionsJSON": "{\"darkTheme\":false}", + "panelsJSON": "[{\"size_x\":6,\"size_y\":3,\"panelIndex\":1,\"type\":\"visualization\",\"id\":\"28563b50-776d-11e7-9e03-393c0d1aa325\",\"col\":1,\"row\":4},{\"size_x\":12,\"size_y\":3,\"panelIndex\":2,\"type\":\"search\",\"id\":\"ef9da9b0-776c-11e7-9e03-393c0d1aa325\",\"col\":1,\"row\":1,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.level\",\"postgresql.log.message\",\"postgresql.log.query\"],\"sort\":[\"@timestamp\",\"desc\"]}]", + "timeRestore": false, + "title": "PostgreSQL All Logs", + "uiStateJSON": "{\"P-1\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", + "version": 1 + }, + "id": "a21284c0-776e-11e7-9e03-393c0d1aa325", + "type": "dashboard", + "version": 1 + } + ], + "version": "6.0.0-beta1-SNAPSHOT" +} \ No newline at end of file diff --git a/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-slowlogs.json b/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-slowlogs.json new file mode 100644 index 00000000000..6268c9a5cc8 --- /dev/null +++ b/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-slowlogs.json @@ -0,0 +1,87 @@ +{ + "objects": [ + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\"}}" + }, + "savedSearchId": "d338f1e0-776b-11e7-9e03-393c0d1aa325", + "title": "PostgreSQL Query Count and Duration", + "uiStateJSON": "{\"vis\":{\"colors\":{\"Sum of query duration\":\"#6ED0E0\",\"Number of queries\":\"#0A437C\"},\"legendOpen\":true}}", + "version": 1, + "visState": "{\"title\":\"PostgreSQL Query Count and Duration\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{\"text\":\"@timestamp per minute\"}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"\"}}],\"seriesParams\":[{\"show\":true,\"mode\":\"normal\",\"type\":\"histogram\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"lineWidth\":2,\"data\":{\"id\":\"4\",\"label\":\"Number of queries\"},\"valueAxis\":\"ValueAxis-1\"},{\"show\":true,\"mode\":\"normal\",\"type\":\"histogram\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"lineWidth\":2,\"data\":{\"id\":\"2\",\"label\":\"Sum of query duration\"},\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"m\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Number of queries\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"sum\",\"schema\":\"metric\",\"params\":{\"field\":\"postgresql.log.duration\",\"customLabel\":\"Sum of query duration\"}}]}" + }, + "id": "63bb6bd0-776c-11e7-9e03-393c0d1aa325", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "columns": [ + "postgresql.log.user", + "postgresql.log.database", + "postgresql.log.duration", + "postgresql.log.query" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"a0b887a0-763d-11e7-9e03-393c0d1aa325\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"postgresql.log.duration:\u003e30\",\"language\":\"lucene\"},\"filter\":[]}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "Slow PostgreSQL Queries", + "version": 1 + }, + "id": "653bbfb0-776b-11e7-9e03-393c0d1aa325", + "type": "search", + "version": 3 + }, + { + "attributes": { + "columns": [ + "postgresql.log.user", + "postgresql.log.database", + "postgresql.log.duration", + "postgresql.log.query" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"a0b887a0-763d-11e7-9e03-393c0d1aa325\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"postgresql.log.duration:*\",\"language\":\"lucene\"},\"filter\":[]}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "PostgreSQL Query Durations", + "version": 1 + }, + "id": "d338f1e0-776b-11e7-9e03-393c0d1aa325", + "type": "search", + "version": 2 + }, + { + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"postgresql.log.query:*\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" + }, + "optionsJSON": "{\"darkTheme\":false}", + "panelsJSON": "[{\"col\":1,\"id\":\"63bb6bd0-776c-11e7-9e03-393c0d1aa325\",\"panelIndex\":1,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.duration\",\"postgresql.log.query\"],\"id\":\"653bbfb0-776b-11e7-9e03-393c0d1aa325\",\"panelIndex\":2,\"row\":1,\"size_x\":6,\"size_y\":3,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"size_x\":12,\"size_y\":3,\"panelIndex\":3,\"type\":\"search\",\"id\":\"d338f1e0-776b-11e7-9e03-393c0d1aa325\",\"col\":1,\"row\":4,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.duration\",\"postgresql.log.query\"],\"sort\":[\"@timestamp\",\"desc\"]}]", + "timeRestore": false, + "title": "PostgreSQL Query Duration Overview", + "uiStateJSON": "{}", + "version": 1 + }, + "id": "92370770-776d-11e7-9e03-393c0d1aa325", + "type": "dashboard", + "version": 1 + } + ], + "version": "6.0.0-beta1-SNAPSHOT" +} \ No newline at end of file diff --git a/filebeat/module/postgresql/log/_meta/fields.yml b/filebeat/module/postgresql/log/_meta/fields.yml new file mode 100644 index 00000000000..06e01ca7862 --- /dev/null +++ b/filebeat/module/postgresql/log/_meta/fields.yml @@ -0,0 +1,40 @@ +- name: log + type: group + description: > + Fields from the PostgreSQL log files. + fields: + - name: timestamp + description: > + The timestamp from the log line. + - name: timezone + description: > + The timezone of timestamp. + - name: thread_id + type: long + description: > + Processs id + - name: user + example: "admin" + description: + Name of user + - name: database + example: "mydb" + description: + Name of database + - name: level + example: "FATAL" + description: + The log level. + - name: duration + type: float + example: "30.0" + description: + Duration of a query. + - name: query + example: "SELECT * FROM users;" + description: + Query statment. + - name: message + type: text + description: > + The logged message. diff --git a/filebeat/module/postgresql/log/config/log.yml b/filebeat/module/postgresql/log/config/log.yml new file mode 100644 index 00000000000..5f236667e90 --- /dev/null +++ b/filebeat/module/postgresql/log/config/log.yml @@ -0,0 +1,10 @@ +type: log +paths: +{{ range $i, $path := .paths }} + - {{$path}} +{{ end }} +exclude_files: [".gz$"] +multiline: + pattern: '^[-0-9]* ' + negate: true + match: after diff --git a/filebeat/module/postgresql/log/ingest/pipeline.json b/filebeat/module/postgresql/log/ingest/pipeline.json new file mode 100644 index 00000000000..17e461d897e --- /dev/null +++ b/filebeat/module/postgresql/log/ingest/pipeline.json @@ -0,0 +1,41 @@ +{ + "description": "Pipeline for parsing PostgreSQL logs.", + "processors": [ + { + "grok": { + "field": "message", + "ignore_missing": true, + "patterns": [ + "%{LOCALDATETIME:postgresql.log.timestamp} %{WORD:postgresql.log.timezone} \\[%{NUMBER:postgresql.log.thread_id}\\] %{USERNAME:postgresql.log.user}@%{HOSTNAME:postgresql.log.database} %{WORD:postgresql.log.level}: duration: %{NUMBER:postgresql.log.duration} ms statement: %{MULTILINEQUERY:postgresql.log.query}", + "%{LOCALDATETIME:postgresql.log.timestamp} %{WORD:postgresql.log.timezone} \\[%{NUMBER:postgresql.log.thread_id}\\] \\[%{USERNAME:postgresql.log.user}\\]@\\[%{HOSTNAME:postgresql.log.database}\\] %{WORD:postgresql.log.level}: duration: %{NUMBER:postgresql.log.duration} ms statement: %{MULTILINEQUERY:postgresql.log.query}", + "%{LOCALDATETIME:postgresql.log.timestamp} %{WORD:postgresql.log.timezone} \\[%{NUMBER:postgresql.log.thread_id}\\] %{USERNAME:postgresql.log.user}@%{HOSTNAME:postgresql.log.database} %{WORD:postgresql.log.level}: ?%{GREEDYDATA:postgresql.log.message}", + "%{LOCALDATETIME:postgresql.log.timestamp} %{WORD:postgresql.log.timezone} \\[%{NUMBER:postgresql.log.thread_id}\\] \\[%{USERNAME:postgresql.log.user}\\]@\\[%{HOSTNAME:postgresql.log.database}\\] %{WORD:postgresql.log.level}: ?%{GREEDYDATA:postgresql.log.message}", + "%{LOCALDATETIME:postgresql.log.timestamp} %{WORD:postgresql.log.timezone} \\[%{NUMBER:postgresql.log.thread_id}\\] %{WORD:postgresql.log.level}: ?%{GREEDYDATA:postgresql.log.message}" + ], + "pattern_definitions": { + "LOCALDATETIME": "[-0-9]+ %{TIME}", + "GREEDYDATA": ".*", + "MULTILINEQUERY" : "(.|\n|\t)*?;$" + } + } + }, + { + "date": { + "field": "postgresql.log.timestamp", + "target_field": "@timestamp", + "formats": [ + "yyyy-MM-dd HH:mm:ss.SSS" + ], + "ignore_failure": true + } + } + ], + "on_failure": [ + { + "set": { + "field": "error.message", + "value": "{{ _ingest.on_failure_message }}" + } + } + ] +} diff --git a/filebeat/module/postgresql/log/manifest.yml b/filebeat/module/postgresql/log/manifest.yml new file mode 100644 index 00000000000..bd9631f945f --- /dev/null +++ b/filebeat/module/postgresql/log/manifest.yml @@ -0,0 +1,13 @@ +module_version: "1.0" + +var: + - name: paths + default: + - /var/log/postgresql/postgresql-*-*.log* + os.darwin: + - /usr/local/var/postgres/*.log* + os.windows: + - "c:/Program Files/PostgreSQL/*/logs/*.log*" + +ingest_pipeline: ingest/pipeline.json +prospector: config/log.yml diff --git a/filebeat/module/postgresql/log/test/postgresql-9.6-debian-with-slowlog.log b/filebeat/module/postgresql/log/test/postgresql-9.6-debian-with-slowlog.log new file mode 100644 index 00000000000..1903a2a16db --- /dev/null +++ b/filebeat/module/postgresql/log/test/postgresql-9.6-debian-with-slowlog.log @@ -0,0 +1,61 @@ +2017-07-31 13:36:42.585 CEST [4974] LOG: database system was shut down at 2017-06-17 16:58:04 CEST +2017-07-31 13:36:42.605 CEST [4974] LOG: MultiXact member wraparound protections are now enabled +2017-07-31 13:36:42.615 CEST [4978] LOG: autovacuum launcher started +2017-07-31 13:36:42.616 CEST [4973] LOG: database system is ready to accept connections +2017-07-31 13:36:42.956 CEST [4980] [unknown]@[unknown] LOG: incomplete startup packet +2017-07-31 13:36:43.557 CEST [4983] postgres@postgres LOG: duration: 37.118 ms statement: SELECT d.datname as "Name", + pg_catalog.pg_get_userbyid(d.datdba) as "Owner", + pg_catalog.pg_encoding_to_char(d.encoding) as "Encoding", + d.datcollate as "Collate", + d.datctype as "Ctype", + pg_catalog.array_to_string(d.datacl, E'\n') AS "Access privileges" + FROM pg_catalog.pg_database d + ORDER BY 1; +2017-07-31 13:36:44.104 CEST [4986] postgres@postgres LOG: duration: 2.895 ms statement: SELECT d.datname as "Name", + pg_catalog.pg_get_userbyid(d.datdba) as "Owner", + pg_catalog.pg_encoding_to_char(d.encoding) as "Encoding", + d.datcollate as "Collate", + d.datctype as "Ctype", + pg_catalog.array_to_string(d.datacl, E'\n') AS "Access privileges" + FROM pg_catalog.pg_database d + ORDER BY 1; +2017-07-31 13:36:44.642 CEST [4989] postgres@postgres LOG: duration: 2.809 ms statement: SELECT d.datname as "Name", + pg_catalog.pg_get_userbyid(d.datdba) as "Owner", + pg_catalog.pg_encoding_to_char(d.encoding) as "Encoding", + d.datcollate as "Collate", + d.datctype as "Ctype", + pg_catalog.array_to_string(d.datacl, E'\n') AS "Access privileges" + FROM pg_catalog.pg_database d + ORDER BY 1; +2017-07-31 13:39:16.249 CEST [5407] postgres@users FATAL: database "users" does not exist +2017-07-31 13:39:17.945 CEST [5500] postgres@user FATAL: database "user" does not exist +2017-07-31 13:39:21.025 CEST [5404] postgres@postgres LOG: duration: 37.598 ms statement: SELECT n.nspname as "Schema", + c.relname as "Name", + CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' END as "Type", + pg_catalog.pg_get_userbyid(c.relowner) as "Owner" + FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE c.relkind IN ('r','') + AND n.nspname <> 'pg_catalog' + AND n.nspname <> 'information_schema' + AND n.nspname !~ '^pg_toast' + AND pg_catalog.pg_table_is_visible(c.oid) + ORDER BY 1,2; +2017-07-31 13:39:31.619 CEST [5502] postgres@clients LOG: duration: 9.482 ms statement: select * from clients; +2017-07-31 13:39:40.147 CEST [5502] postgres@clients LOG: duration: 0.765 ms statement: select id from clients; +2017-07-31 13:40:54.310 CEST [5502] postgres@clients LOG: duration: 26.082 ms statement: SELECT n.nspname as "Schema", + c.relname as "Name", + CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' END as "Type", + pg_catalog.pg_get_userbyid(c.relowner) as "Owner" + FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE c.relkind IN ('r','') + AND n.nspname <> 'pg_catalog' + AND n.nspname <> 'information_schema' + AND n.nspname !~ '^pg_toast' + AND pg_catalog.pg_table_is_visible(c.oid) + ORDER BY 1,2; +2017-07-31 13:43:22.645 CEST [5502] postgres@clients LOG: duration: 36.162 ms statement: create table cats(name varchar(50) primary key, toy varchar (50) not null, born timestamp not null); +2017-07-31 13:46:02.670 CEST [5502] postgres@clients LOG: duration: 10.540 ms statement: insert into cats(name, toy, born) values('kate', 'ball', now()); +2017-07-31 13:46:23.016 CEST [5502] postgres@clients LOG: duration: 5.156 ms statement: insert into cats(name, toy, born) values('frida', 'horse', now()); +2017-07-31 13:46:55.637 CEST [5502] postgres@clients LOG: duration: 25.871 ms statement: create table dogs(name varchar(50) primary key, owner varchar (50) not null, born timestamp not null); diff --git a/filebeat/module/postgresql/log/test/postgresql-9.6-debian-with-slowlog.log-expected.json b/filebeat/module/postgresql/log/test/postgresql-9.6-debian-with-slowlog.log-expected.json new file mode 100644 index 00000000000..91f5e346834 --- /dev/null +++ b/filebeat/module/postgresql/log/test/postgresql-9.6-debian-with-slowlog.log-expected.json @@ -0,0 +1,814 @@ +[ + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "t8S2ml0BVlT2mTAm4zRv", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:36:42.585Z", + "offset": 100, + "postgresql": { + "log": { + "thread_id": "4974", + "level": "LOG", + "timezone": "CEST", + "message": "database system was shut down at 2017-06-17 16:58:04 CEST", + "timestamp": "2017-07-31 13:36:42.585" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "message": "2017-07-31 13:36:42.585 CEST [4974] LOG: database system was shut down at 2017-06-17 16:58:04 CEST", + "fileset": { + "module": "postgresql", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:36:42.585Z" + ] + }, + "sort": [ + 1501508202585 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "tcS2ml0BVlT2mTAm4jSf", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:36:42.605Z", + "offset": 198, + "postgresql": { + "log": { + "thread_id": "4974", + "level": "LOG", + "timezone": "CEST", + "message": "MultiXact member wraparound protections are now enabled", + "timestamp": "2017-07-31 13:36:42.605" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "message": "2017-07-31 13:36:42.605 CEST [4974] LOG: MultiXact member wraparound protections are now enabled", + "fileset": { + "module": "postgresql", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:36:42.605Z" + ] + }, + "sort": [ + 1501508202605 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "tsS2ml0BVlT2mTAm4jSf", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:36:42.615Z", + "offset": 268, + "postgresql": { + "log": { + "thread_id": "4978", + "level": "LOG", + "timezone": "CEST", + "message": "autovacuum launcher started", + "timestamp": "2017-07-31 13:36:42.615" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "message": "2017-07-31 13:36:42.615 CEST [4978] LOG: autovacuum launcher started", + "fileset": { + "module": "postgresql", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:36:42.615Z" + ] + }, + "sort": [ + 1501508202615 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "uMS2ml0BVlT2mTAm4zST", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:36:42.616Z", + "offset": 357, + "postgresql": { + "log": { + "thread_id": "4973", + "level": "LOG", + "timezone": "CEST", + "message": "database system is ready to accept connections", + "timestamp": "2017-07-31 13:36:42.616" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "message": "2017-07-31 13:36:42.616 CEST [4973] LOG: database system is ready to accept connections", + "fileset": { + "module": "postgresql", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:36:42.616Z" + ] + }, + "sort": [ + 1501508202616 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "ucS2ml0BVlT2mTAm4zST", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:36:42.956Z", + "offset": 445, + "postgresql": { + "log": { + "thread_id": "4980", + "database": "unknown", + "level": "LOG", + "timezone": "CEST", + "message": "incomplete startup packet", + "user": "unknown", + "timestamp": "2017-07-31 13:36:42.956" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "fileset": { + "module": "postgresql", + "name": "log" + }, + "message": "2017-07-31 13:36:42.956 CEST [4980] [unknown]@[unknown] LOG: incomplete startup packet" + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:36:42.956Z" + ] + }, + "sort": [ + 1501508202956 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "usS2ml0BVlT2mTAm4zST", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:36:43.557Z", + "offset": 873, + "postgresql": { + "log": { + "duration": "37.118", + "thread_id": "4983", + "database": "postgres", + "level": "LOG", + "timezone": "CEST", + "query": "SELECT d.datname as \"Name\",\n\t pg_catalog.pg_get_userbyid(d.datdba) as \"Owner\",\n\t pg_catalog.pg_encoding_to_char(d.encoding) as \"Encoding\",\n\t d.datcollate as \"Collate\",\n\t d.datctype as \"Ctype\",\n\t pg_catalog.array_to_string(d.datacl, E'\\n') AS \"Access privileges\"\n\tFROM pg_catalog.pg_database d\n\tORDER BY 1;", + "user": "postgres", + "timestamp": "2017-07-31 13:36:43.557" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "fileset": { + "module": "postgresql", + "name": "log" + }, + "message": "2017-07-31 13:36:43.557 CEST [4983] postgres@postgres LOG: duration: 37.118 ms statement: SELECT d.datname as \"Name\",\n\t pg_catalog.pg_get_userbyid(d.datdba) as \"Owner\",\n\t pg_catalog.pg_encoding_to_char(d.encoding) as \"Encoding\",\n\t d.datcollate as \"Collate\",\n\t d.datctype as \"Ctype\",\n\t pg_catalog.array_to_string(d.datacl, E'\\n') AS \"Access privileges\"\n\tFROM pg_catalog.pg_database d\n\tORDER BY 1;" + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:36:43.557Z" + ] + }, + "sort": [ + 1501508203557 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "u8S2ml0BVlT2mTAm4zST", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:36:44.104Z", + "offset": 1300, + "postgresql": { + "log": { + "duration": "2.895", + "thread_id": "4986", + "database": "postgres", + "level": "LOG", + "timezone": "CEST", + "query": "SELECT d.datname as \"Name\",\n\t pg_catalog.pg_get_userbyid(d.datdba) as \"Owner\",\n\t pg_catalog.pg_encoding_to_char(d.encoding) as \"Encoding\",\n\t d.datcollate as \"Collate\",\n\t d.datctype as \"Ctype\",\n\t pg_catalog.array_to_string(d.datacl, E'\\n') AS \"Access privileges\"\n\tFROM pg_catalog.pg_database d\n\tORDER BY 1;", + "user": "postgres", + "timestamp": "2017-07-31 13:36:44.104" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "message": "2017-07-31 13:36:44.104 CEST [4986] postgres@postgres LOG: duration: 2.895 ms statement: SELECT d.datname as \"Name\",\n\t pg_catalog.pg_get_userbyid(d.datdba) as \"Owner\",\n\t pg_catalog.pg_encoding_to_char(d.encoding) as \"Encoding\",\n\t d.datcollate as \"Collate\",\n\t d.datctype as \"Ctype\",\n\t pg_catalog.array_to_string(d.datacl, E'\\n') AS \"Access privileges\"\n\tFROM pg_catalog.pg_database d\n\tORDER BY 1;", + "fileset": { + "module": "postgresql", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:36:44.104Z" + ] + }, + "sort": [ + 1501508204104 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "vMS2ml0BVlT2mTAm4zST", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:36:44.642Z", + "offset": 1727, + "postgresql": { + "log": { + "duration": "2.809", + "thread_id": "4989", + "database": "postgres", + "level": "LOG", + "timezone": "CEST", + "query": "SELECT d.datname as \"Name\",\n\t pg_catalog.pg_get_userbyid(d.datdba) as \"Owner\",\n\t pg_catalog.pg_encoding_to_char(d.encoding) as \"Encoding\",\n\t d.datcollate as \"Collate\",\n\t d.datctype as \"Ctype\",\n\t pg_catalog.array_to_string(d.datacl, E'\\n') AS \"Access privileges\"\n\tFROM pg_catalog.pg_database d\n\tORDER BY 1;", + "user": "postgres", + "timestamp": "2017-07-31 13:36:44.642" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "fileset": { + "module": "postgresql", + "name": "log" + }, + "message": "2017-07-31 13:36:44.642 CEST [4989] postgres@postgres LOG: duration: 2.809 ms statement: SELECT d.datname as \"Name\",\n\t pg_catalog.pg_get_userbyid(d.datdba) as \"Owner\",\n\t pg_catalog.pg_encoding_to_char(d.encoding) as \"Encoding\",\n\t d.datcollate as \"Collate\",\n\t d.datctype as \"Ctype\",\n\t pg_catalog.array_to_string(d.datacl, E'\\n') AS \"Access privileges\"\n\tFROM pg_catalog.pg_database d\n\tORDER BY 1;" + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:36:44.642Z" + ] + }, + "sort": [ + 1501508204642 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "vcS2ml0BVlT2mTAm4zST", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:39:16.249Z", + "offset": 1818, + "postgresql": { + "log": { + "thread_id": "5407", + "database": "users", + "level": "FATAL", + "timezone": "CEST", + "message": "database \"users\" does not exist", + "user": "postgres", + "timestamp": "2017-07-31 13:39:16.249" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "message": "2017-07-31 13:39:16.249 CEST [5407] postgres@users FATAL: database \"users\" does not exist", + "fileset": { + "module": "postgresql", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:39:16.249Z" + ] + }, + "sort": [ + 1501508356249 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "vsS2ml0BVlT2mTAm4zST", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:39:17.945Z", + "offset": 1907, + "postgresql": { + "log": { + "thread_id": "5500", + "database": "user", + "level": "FATAL", + "timezone": "CEST", + "message": "database \"user\" does not exist", + "user": "postgres", + "timestamp": "2017-07-31 13:39:17.945" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "fileset": { + "module": "postgresql", + "name": "log" + }, + "message": "2017-07-31 13:39:17.945 CEST [5500] postgres@user FATAL: database \"user\" does not exist" + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:39:17.945Z" + ] + }, + "sort": [ + 1501508357945 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "v8S2ml0BVlT2mTAm4zST", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:39:21.025Z", + "offset": 2620, + "postgresql": { + "log": { + "duration": "37.598", + "thread_id": "5404", + "database": "postgres", + "level": "LOG", + "timezone": "CEST", + "query": "SELECT n.nspname as \"Schema\",\n\t c.relname as \"Name\",\n\t CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' END as \"Type\",\n\t pg_catalog.pg_get_userbyid(c.relowner) as \"Owner\"\n\tFROM pg_catalog.pg_class c\n\t LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n\tWHERE c.relkind IN ('r','')\n\t AND n.nspname <> 'pg_catalog'\n\t AND n.nspname <> 'information_schema'\n\t AND n.nspname !~ '^pg_toast'\n\t AND pg_catalog.pg_table_is_visible(c.oid)\n\tORDER BY 1,2;", + "user": "postgres", + "timestamp": "2017-07-31 13:39:21.025" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "message": "2017-07-31 13:39:21.025 CEST [5404] postgres@postgres LOG: duration: 37.598 ms statement: SELECT n.nspname as \"Schema\",\n\t c.relname as \"Name\",\n\t CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' END as \"Type\",\n\t pg_catalog.pg_get_userbyid(c.relowner) as \"Owner\"\n\tFROM pg_catalog.pg_class c\n\t LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n\tWHERE c.relkind IN ('r','')\n\t AND n.nspname <> 'pg_catalog'\n\t AND n.nspname <> 'information_schema'\n\t AND n.nspname !~ '^pg_toast'\n\t AND pg_catalog.pg_table_is_visible(c.oid)\n\tORDER BY 1,2;", + "fileset": { + "module": "postgresql", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:39:21.025Z" + ] + }, + "sort": [ + 1501508361025 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "wMS2ml0BVlT2mTAm4zST", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:39:31.619Z", + "offset": 2733, + "postgresql": { + "log": { + "duration": "9.482", + "thread_id": "5502", + "database": "clients", + "level": "LOG", + "timezone": "CEST", + "query": "select * from clients;", + "user": "postgres", + "timestamp": "2017-07-31 13:39:31.619" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "message": "2017-07-31 13:39:31.619 CEST [5502] postgres@clients LOG: duration: 9.482 ms statement: select * from clients;", + "fileset": { + "module": "postgresql", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:39:31.619Z" + ] + }, + "sort": [ + 1501508371619 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "wcS2ml0BVlT2mTAm4zST", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:39:40.147Z", + "offset": 2847, + "postgresql": { + "log": { + "duration": "0.765", + "thread_id": "5502", + "database": "clients", + "level": "LOG", + "timezone": "CEST", + "query": "select id from clients;", + "user": "postgres", + "timestamp": "2017-07-31 13:39:40.147" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "fileset": { + "module": "postgresql", + "name": "log" + }, + "message": "2017-07-31 13:39:40.147 CEST [5502] postgres@clients LOG: duration: 0.765 ms statement: select id from clients;" + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:39:40.147Z" + ] + }, + "sort": [ + 1501508380147 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "wsS2ml0BVlT2mTAm4zST", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:40:54.310Z", + "offset": 3559, + "postgresql": { + "log": { + "duration": "26.082", + "thread_id": "5502", + "database": "clients", + "level": "LOG", + "timezone": "CEST", + "query": "SELECT n.nspname as \"Schema\",\n\t c.relname as \"Name\",\n\t CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' END as \"Type\",\n\t pg_catalog.pg_get_userbyid(c.relowner) as \"Owner\"\n\tFROM pg_catalog.pg_class c\n\t LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n\tWHERE c.relkind IN ('r','')\n\t AND n.nspname <> 'pg_catalog'\n\t AND n.nspname <> 'information_schema'\n\t AND n.nspname !~ '^pg_toast'\n\t AND pg_catalog.pg_table_is_visible(c.oid)\n\tORDER BY 1,2;", + "user": "postgres", + "timestamp": "2017-07-31 13:40:54.310" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "message": "2017-07-31 13:40:54.310 CEST [5502] postgres@clients LOG: duration: 26.082 ms statement: SELECT n.nspname as \"Schema\",\n\t c.relname as \"Name\",\n\t CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' END as \"Type\",\n\t pg_catalog.pg_get_userbyid(c.relowner) as \"Owner\"\n\tFROM pg_catalog.pg_class c\n\t LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n\tWHERE c.relkind IN ('r','')\n\t AND n.nspname <> 'pg_catalog'\n\t AND n.nspname <> 'information_schema'\n\t AND n.nspname !~ '^pg_toast'\n\t AND pg_catalog.pg_table_is_visible(c.oid)\n\tORDER BY 1,2;", + "fileset": { + "module": "postgresql", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:40:54.310Z" + ] + }, + "sort": [ + 1501508454310 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "w8S2ml0BVlT2mTAm4zST", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:43:22.645Z", + "offset": 3751, + "postgresql": { + "log": { + "duration": "36.162", + "thread_id": "5502", + "database": "clients", + "level": "LOG", + "timezone": "CEST", + "query": "create table cats(name varchar(50) primary key, toy varchar (50) not null, born timestamp not null);", + "user": "postgres", + "timestamp": "2017-07-31 13:43:22.645" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "message": "2017-07-31 13:43:22.645 CEST [5502] postgres@clients LOG: duration: 36.162 ms statement: create table cats(name varchar(50) primary key, toy varchar (50) not null, born timestamp not null);", + "fileset": { + "module": "postgresql", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:43:22.645Z" + ] + }, + "sort": [ + 1501508602645 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "xMS2ml0BVlT2mTAm4zST", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:46:02.670Z", + "offset": 3907, + "postgresql": { + "log": { + "duration": "10.540", + "thread_id": "5502", + "database": "clients", + "level": "LOG", + "timezone": "CEST", + "query": "insert into cats(name, toy, born) values('kate', 'ball', now());", + "user": "postgres", + "timestamp": "2017-07-31 13:46:02.670" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "fileset": { + "module": "postgresql", + "name": "log" + }, + "message": "2017-07-31 13:46:02.670 CEST [5502] postgres@clients LOG: duration: 10.540 ms statement: insert into cats(name, toy, born) values('kate', 'ball', now());" + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:46:02.670Z" + ] + }, + "sort": [ + 1501508762670 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "xcS2ml0BVlT2mTAm4zST", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:46:23.016Z", + "offset": 4064, + "postgresql": { + "log": { + "duration": "5.156", + "thread_id": "5502", + "database": "clients", + "level": "LOG", + "timezone": "CEST", + "query": "insert into cats(name, toy, born) values('frida', 'horse', now());", + "user": "postgres", + "timestamp": "2017-07-31 13:46:23.016" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "message": "2017-07-31 13:46:23.016 CEST [5502] postgres@clients LOG: duration: 5.156 ms statement: insert into cats(name, toy, born) values('frida', 'horse', now());", + "fileset": { + "module": "postgresql", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:46:23.016Z" + ] + }, + "sort": [ + 1501508783016 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.01", + "_type": "doc", + "_id": "x8S2ml0BVlT2mTAm8zQ2", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-07-31T13:46:55.637Z", + "offset": 4258, + "postgresql": { + "log": { + "duration": "25.871", + "thread_id": "5502", + "database": "clients", + "level": "LOG", + "timezone": "CEST", + "query": "create table dogs(name varchar(50) primary key, owner varchar (50) not null, born timestamp not null);", + "user": "postgres", + "timestamp": "2017-07-31 13:46:55.637" + } + }, + "beat": { + "hostname": "baldur", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/postgresql/log/test/postgresql-9.6-debian.log", + "message": "2017-07-31 13:46:55.637 CEST [5502] postgres@clients LOG: duration: 25.871 ms statement: create table dogs(name varchar(50) primary key, owner varchar (50) not null, born timestamp not null);", + "fileset": { + "module": "postgresql", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-07-31T13:46:55.637Z" + ] + }, + "sort": [ + 1501508815637 + ] + } +] diff --git a/filebeat/module/postgresql/log/test/postgresql-ubuntu-9.5.log b/filebeat/module/postgresql/log/test/postgresql-ubuntu-9.5.log new file mode 100644 index 00000000000..5a3df37b16a --- /dev/null +++ b/filebeat/module/postgresql/log/test/postgresql-ubuntu-9.5.log @@ -0,0 +1,78 @@ +2017-04-03 22:32:14.322 CEST [31225] postgres@mydb LOG: could not receive data from client: Connection reset by peer +2017-04-03 22:32:14.322 CEST [31225] postgres@mydb LOG: unexpected EOF on client connection with an open transaction +2017-04-03 22:35:22.389 CEST [3474] postgres@mydb LOG: could not receive data from client: Connection reset by peer +2017-04-03 22:36:56.464 CEST [3525] postgres@mydb LOG: could not receive data from client: Connection reset by peer +2017-04-03 22:37:12.961 CEST [3570] postgres@mydb LOG: could not receive data from client: Connection reset by peer +2017-04-07 21:05:28.549 CEST [21483] postgres@mydb LOG: could not receive data from client: Connection reset by peer +2017-04-07 21:09:41.345 CEST [21597] postgres@mydb LOG: could not receive data from client: Connection reset by peer +2017-04-07 22:45:30.218 CEST [22603] postgres@mydb ERROR: operator does not exist: jsonb @> at character 49 +2017-04-07 22:45:30.218 CEST [22603] postgres@mydb HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +2017-04-07 22:45:30.218 CEST [22603] postgres@mydb STATEMENT: SELECT id, user FROM users WHERE NOT user @> %s +2017-04-07 22:46:09.751 CEST [22608] postgres@mydb ERROR: column "%s" does not exist at character 52 +2017-04-07 22:46:09.751 CEST [22608] postgres@mydb STATEMENT: SELECT id, user FROM users WHERE NOT user @> "%s" +2017-04-07 23:02:51.199 CEST [24341] postgres@mydb LOG: could not receive data from client: Connection reset by peer +2017-04-07 23:02:51.199 CEST [24341] postgres@mydb LOG: unexpected EOF on client connection with an open transaction +2017-04-07 23:04:36.087 CEST [20730] postgres@mydb ERROR: syntax error at or near "{" at character 49 +2017-04-07 23:04:36.087 CEST [20730] postgres@mydb STATEMENT: INSERT INTO users (id, user) VALUES (1, {"attr": "yes"}); +2017-04-07 23:04:51.462 CEST [20730] postgres@mydb ERROR: syntax error at or near "{" at character 49 +2017-04-07 23:04:51.462 CEST [20730] postgres@mydb STATEMENT: INSERT INTO users (id, user) VALUES (1, {attr: "yes"}); +2017-04-07 23:05:06.217 CEST [20730] postgres@mydb ERROR: column "a" does not exist at character 42 +2017-04-07 23:05:06.217 CEST [20730] postgres@mydb STATEMENT: INSERT INTO users (id, user) VALUES (1, '{"attr": "yes"}'); +2017-04-07 23:05:18.295 CEST [20730] postgres@mydb ERROR: column "attr" does not exist at character 42 +2017-04-07 23:05:18.295 CEST [20730] postgres@mydb STATEMENT: INSERT INTO users (id, user) VALUES ("1", '{"attr": "no"}'); +2017-04-07 23:13:47.505 CEST [24489] postgres@mydb LOG: could not receive data from client: Connection reset by peer +2017-04-07 23:13:47.505 CEST [24489] postgres@mydb LOG: unexpected EOF on client connection with an open transaction +2017-04-08 12:32:51.056 CEST [20730] postgres@mydb ERROR: duplicate key value violates unique constraint "users_pkey" +2017-04-08 12:32:51.056 CEST [20730] postgres@mydb DETAIL: Key (id)=(1) already exists. +2017-04-08 12:32:51.056 CEST [20730] postgres@mydb STATEMENT: INSERT INTO users (id, user) VALUES ('1', '{"attr": "yes"}'); +2017-04-08 21:54:37.443 CEST [30630] postgres@mydb LOG: could not receive data from client: Connection reset by peer +2017-04-08 21:54:37.468 CEST [30502] postgres@mydb LOG: could not receive data from client: Connection reset by peer +2017-04-08 21:54:37.618 CEST [20769] LOG: received fast shutdown request +2017-04-08 21:54:37.618 CEST [20769] LOG: aborting any active transactions +2017-04-08 21:54:37.618 CEST [20774] LOG: autovacuum launcher shutting down +2017-04-08 21:54:37.622 CEST [20771] LOG: shutting down +2017-04-08 21:54:37.644 CEST [20769] LOG: database system is shut down +2017-04-08 21:56:02.932 CEST [797] LOG: database system was shut down at 2017-04-08 21:54:37 CEST +2017-04-08 21:56:02.944 CEST [797] LOG: MultiXact member wraparound protections are now enabled +2017-04-08 21:56:02.946 CEST [780] LOG: database system is ready to accept connections +2017-04-08 21:56:02.947 CEST [802] LOG: autovacuum launcher started +2017-04-08 21:56:03.362 CEST [891] [unknown]@[unknown] LOG: incomplete startup packet +2017-05-27 14:07:53.007 UTC [32567] LOG: database system was shut down at 2017-05-27 14:07:52 UTC +2017-05-27 14:07:53.010 UTC [32567] LOG: MultiXact member wraparound protections are now enabled +2017-05-27 14:07:53.015 UTC [32566] LOG: database system is ready to accept connections +2017-05-27 14:07:53.016 UTC [32571] LOG: autovacuum launcher started +2017-05-27 14:07:53.463 UTC [32573] [unknown]@[unknown] LOG: incomplete startup packet +2017-05-27 14:08:13.661 UTC [1308] postgres@mydb FATAL: database "mydb" does not exist +2017-05-27 14:59:26.553 UTC [1994] postgres@mydb LOG: could not receive data from client: Connection reset by peer +2017-05-27 14:59:26.555 UTC [1989] postgres@mydb LOG: could not receive data from client: Connection reset by peer +2017-06-06 07:54:13.753 CEST [9110] LOG: received fast shutdown request +2017-06-06 07:54:13.753 CEST [9110] LOG: aborting any active transactions +2017-06-06 07:54:13.753 CEST [9115] LOG: autovacuum launcher shutting down +2017-06-06 07:54:13.755 CEST [9112] LOG: shutting down +2017-06-06 07:54:13.816 CEST [9110] LOG: database system is shut down +2017-06-06 07:55:39.725 CEST [12969] LOG: database system was shut down at 2017-06-06 07:54:13 CEST +2017-06-06 07:55:39.736 CEST [12969] LOG: MultiXact member wraparound protections are now enabled +2017-06-06 07:55:39.739 CEST [12968] LOG: database system is ready to accept connections +2017-06-06 07:55:39.739 CEST [12973] LOG: autovacuum launcher started +2017-06-06 07:55:40.155 CEST [12975] [unknown]@[unknown] LOG: incomplete startup packet +2017-06-06 07:55:40.156 CEST [12975] [unknown]@[unknown] LOG: incomplete startup packet +2017-06-10 19:37:30.681 CEST [17398] LOG: database system was shut down at 2017-06-10 19:37:29 CEST +2017-06-10 19:37:30.695 CEST [17398] LOG: MultiXact member wraparound protections are now enabled +2017-06-10 19:37:30.702 CEST [17397] LOG: database system is ready to accept connections +2017-06-10 19:37:30.702 CEST [17402] LOG: autovacuum launcher started +2017-06-10 19:37:31.104 CEST [17404] [unknown]@[unknown] LOG: incomplete startup packet +2017-06-10 20:27:55.911 CEST [17397] LOG: received fast shutdown request +2017-06-10 20:27:55.911 CEST [17397] LOG: aborting any active transactions +2017-06-10 20:27:55.911 CEST [17402] LOG: autovacuum launcher shutting down +2017-06-10 20:27:55.914 CEST [17399] LOG: shutting down +2017-06-10 20:27:55.973 CEST [17397] LOG: database system is shut down +2017-06-10 20:27:57.022 CEST [24490] LOG: database system was shut down at 2017-06-10 20:27:55 CEST +2017-06-10 20:27:57.032 CEST [24490] LOG: MultiXact member wraparound protections are now enabled +2017-06-10 20:27:57.035 CEST [24494] LOG: autovacuum launcher started +2017-06-10 20:27:57.035 CEST [24489] LOG: database system is ready to accept connections +2017-06-10 20:27:57.475 CEST [24496] [unknown]@[unknown] LOG: incomplete startup packet +2017-06-17 16:58:03.937 CEST [24489] LOG: received fast shutdown request +2017-06-17 16:58:03.937 CEST [24489] LOG: aborting any active transactions +2017-06-17 16:58:03.938 CEST [24494] LOG: autovacuum launcher shutting down +2017-06-17 16:58:03.940 CEST [24491] LOG: shutting down +2017-06-17 16:58:04.040 CEST [24489] LOG: database system is shut down diff --git a/filebeat/modules.d/postgresql.yml.disabled b/filebeat/modules.d/postgresql.yml.disabled new file mode 100644 index 00000000000..c82734a9570 --- /dev/null +++ b/filebeat/modules.d/postgresql.yml.disabled @@ -0,0 +1,8 @@ +- module: postgresql + # All logs + log: + enabled: true + + # Set custom paths for the log files. If left empty, + # Filebeat will choose the paths depending on your OS. + #var.paths: diff --git a/filebeat/tests/system/test_modules.py b/filebeat/tests/system/test_modules.py index a07fafab13f..4b0f79bc59d 100644 --- a/filebeat/tests/system/test_modules.py +++ b/filebeat/tests/system/test_modules.py @@ -64,6 +64,26 @@ def test_modules(self): test_file=test_file, cfgfile=cfgfile) + def _test_expected_events(self, module, test_file, res, objects): + with open(test_file + "-expected.json", "r") as f: + expected = json.load(f) + + if len(expected) > len(objects): + res = self.es.search(index=self.index_name, + body={"query": {"match_all": {}}, + "size": len(expected)}) + objects = [o["_source"] for o in res["hits"]["hits"]] + + assert len(expected) == res['hits']['total'], "expected {} but got {}".format(len(expected), len(objects)) + + for ev in expected: + found = False + for obj in objects: + if ev["_source"][module] == obj[module]: + found = True + break + assert found, "The following expected object was not found: {}".format(obj) + def run_on_file(self, module, fileset, test_file, cfgfile): print("Testing {}/{} on {}".format(module, fileset, test_file)) @@ -116,18 +136,7 @@ def run_on_file(self, module, fileset, test_file, cfgfile): self.assert_fields_are_documented(obj) if os.path.exists(test_file + "-expected.json"): - with open(test_file + "-expected.json", "r") as f: - expected = json.load(f) - assert len(expected) == len(objects), "expected {} but got {}".format(len(expected), len(objects)) - for ev in expected: - found = False - for obj in objects: - if ev["_source"][module] == obj[module]: - found = True - break - if not found: - raise Exception("The following expected object was" + - " not found: {}".format(obj)) + self._test_expected_events(module, test_file, res, objects) @unittest.skipIf(not INTEGRATION_TESTS or os.getenv("TESTING_ENVIRONMENT") == "2x", From fa77316a01d620078c0311dc4a607b0487e8e610 Mon Sep 17 00:00:00 2001 From: Silvia Mitter Date: Tue, 8 Aug 2017 09:04:16 +0200 Subject: [PATCH 038/139] Add SetValue method to libbeat common.MapStr (#4838) SetValue dereferences given values for *int, *string and *boolean, otherwise it just sets the value for the given key as long as the value is not nil or empty. --- libbeat/common/mapstr.go | 49 +++++++++++++++++++++++++++++++ libbeat/common/mapstr_test.go | 54 +++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/libbeat/common/mapstr.go b/libbeat/common/mapstr.go index c38977d10f2..d33b84bfd5a 100644 --- a/libbeat/common/mapstr.go +++ b/libbeat/common/mapstr.go @@ -138,6 +138,15 @@ func (m MapStr) Put(key string, value interface{}) (interface{}, error) { return walkMap(key, m, mapStrOperation{putOperation{value}, true}) } +// SetValue dereferences a value if it is a pointer. Sets the dereferenced value if not nil. +// If value is a MapStr or an array, the value is set if not empty. +// Supported data types so far: *string, *int, *boolean, common.MapStr, array[]int, array[]string. +// Values of unsupported types are set if they are not nil. +// Sets a value for a given key if the (dereferenced) value is not nil or empty. +func (m MapStr) SetValue(key string, value interface{}) { + walkMap(key, m, mapStrOperation{setValueOperation{value}, true}) +} + // StringToPrint returns the MapStr as pretty JSON. func (m MapStr) StringToPrint() string { json, err := json.MarshalIndent(m, "", " ") @@ -380,3 +389,43 @@ func (op putOperation) Do(key string, data MapStr) (interface{}, error) { data[key] = op.Value return existingValue, nil } + +type setValueOperation struct { + Value interface{} +} + +func (op setValueOperation) Do(key string, data MapStr) (interface{}, error) { + if op.Value == nil { + return data, nil + } + + switch op.Value.(type) { + case *bool: + if newVal := op.Value.(*bool); newVal != nil { + data[key] = *newVal + } + case *int: + if newVal := op.Value.(*int); newVal != nil { + data[key] = *newVal + } + case *string: + if newVal := op.Value.(*string); newVal != nil { + data[key] = *newVal + } + case MapStr: + if valMap := op.Value.(MapStr); len(valMap) > 0 { + data[key] = valMap + } + case []int: + if valArr := op.Value.([]int); len(valArr) > 0 { + data[key] = valArr + } + case []string: + if valArr := op.Value.([]string); len(valArr) > 0 { + data[key] = valArr + } + default: + data[key] = op.Value + } + return data, nil +} diff --git a/libbeat/common/mapstr_test.go b/libbeat/common/mapstr_test.go index 633032a8f8f..403b986fbbf 100644 --- a/libbeat/common/mapstr_test.go +++ b/libbeat/common/mapstr_test.go @@ -221,6 +221,60 @@ func TestMapStrPut(t *testing.T) { assert.Equal(t, MapStr{"subMap": MapStr{"newMap": MapStr{"a": 1}}}, m) } +func TestMapStrSet(t *testing.T) { + m := MapStr{ + "i1": 123, + "s1": "123", + "b1": false, + "x3": MapStr{ + "b41": "val.b41", + }, + } + type io struct { + Key string + Val interface{} + Fetch string + Expected interface{} + } + + mapVal := MapStr{"newKey": "newVal"} + arrStrVal := []string{"v1", "v2"} + arrIntVal := []int{1, 2, 3} + str := "strPtr" + var emptyStrPtr *string + i := 44 + var emptyIntPtr *int + b := false + var emptyBoolPtr *bool + tests := []io{ + {Key: "x3.b42", Val: "b42New", Fetch: "x3", Expected: MapStr{"b41": "val.b41", "b42": "b42New"}}, + {Key: "m1", Val: mapVal, Fetch: "m1", Expected: mapVal}, + {Key: "m2", Val: MapStr{}, Fetch: "m2", Expected: nil}, + {Key: "a1", Val: arrStrVal, Fetch: "a1", Expected: arrStrVal}, + {Key: "a2", Val: []string{}, Fetch: "a2", Expected: nil}, + {Key: "a3", Val: arrIntVal, Fetch: "a3", Expected: arrIntVal}, + {Key: "a4", Val: []int{}, Fetch: "a2", Expected: nil}, + {Key: "s1", Val: nil, Fetch: "s1", Expected: "123"}, + {Key: "s1", Val: "s1New", Fetch: "s1", Expected: "s1New"}, + {Key: "s2", Val: emptyStrPtr, Fetch: "s2", Expected: nil}, + {Key: "s3", Val: &str, Fetch: "s3", Expected: "strPtr"}, + {Key: "i1", Val: nil, Fetch: "i1", Expected: 123}, + {Key: "i1", Val: 456, Fetch: "i1", Expected: 456}, + {Key: "i2", Val: emptyIntPtr, Fetch: "i2", Expected: nil}, + {Key: "i3", Val: &i, Fetch: "i3", Expected: 44}, + {Key: "b1", Val: nil, Fetch: "b1", Expected: false}, + {Key: "b1", Val: true, Fetch: "b1", Expected: true}, + {Key: "b2", Val: emptyBoolPtr, Fetch: "b2", Expected: nil}, + {Key: "b3", Val: &b, Fetch: "b3", Expected: false}, + } + for idx, test := range tests { + m.SetValue(test.Key, test.Val) + fetched, _ := m.GetValue(test.Fetch) + errMsg := fmt.Sprintf("Failed for %v: Expected %v, Received %v", idx, test.Expected, fetched) + assert.Equal(t, test.Expected, fetched, errMsg) + } +} + func TestClone(t *testing.T) { assert := assert.New(t) From 38ebb36b6fdb76270286b2a93195c3dc43a9e450 Mon Sep 17 00:00:00 2001 From: Kyriakos Kentzoglanakis Date: Tue, 8 Aug 2017 10:15:16 +0300 Subject: [PATCH 039/139] add cloudwatchlogsbeat to community beats (#4829) --- libbeat/docs/communitybeats.asciidoc | 1 + 1 file changed, 1 insertion(+) diff --git a/libbeat/docs/communitybeats.asciidoc b/libbeat/docs/communitybeats.asciidoc index 6c96aa53a3b..e977a9c441d 100644 --- a/libbeat/docs/communitybeats.asciidoc +++ b/libbeat/docs/communitybeats.asciidoc @@ -26,6 +26,7 @@ https://github.com/goomzee/burrowbeat[burrowbeat]:: Monitors Kafka consumer lag https://github.com/goomzee/cassandrabeat[cassandrabeat]:: Uses Cassandra's nodetool cfstats utility to monitor Cassandra database nodes and lag. https://github.com/hartfordfive/cloudflarebeat[cloudflarebeat]:: Indexes log entries from the Cloudflare Enterprise Log Share API. https://github.com/aidan-/cloudtrailbeat[cloudtrailbeat]:: Reads events from Amazon Web Services' https://aws.amazon.com/cloudtrail/[CloudTrail]. +https://github.com/e-travel/cloudwatchlogsbeat[cloudwatchlogsbeat]:: Reads log events from Amazon Web Services' https://aws.amazon.com/cloudwatch/details/#log-monitoring[CloudWatch Logs]. https://github.com/raboof/connbeat[connbeat]:: Exposes metadata about TCP connections. https://github.com/Pravoru/consulbeat[consulbeat]:: Reads services health checks from consul and pushes them to Elastic. https://github.com/Ingensi/dockbeat[dockbeat]:: Reads Docker container From 7aabf7a01497c5ae598e62e1cc713afa84ca7031 Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Tue, 8 Aug 2017 11:31:47 +0300 Subject: [PATCH 040/139] Fix link to image in FBM Postgres docs (#4843) --- filebeat/docs/modules/postgresql.asciidoc | 2 +- filebeat/module/postgresql/_meta/docs.asciidoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/filebeat/docs/modules/postgresql.asciidoc b/filebeat/docs/modules/postgresql.asciidoc index d11930a3df5..8cbf7460f4a 100644 --- a/filebeat/docs/modules/postgresql.asciidoc +++ b/filebeat/docs/modules/postgresql.asciidoc @@ -23,7 +23,7 @@ image::./images/filebeat-postgresql-overview.png[] The second one shows the slowlogs of PostgreSQL. -image::./images/filebeat-postgresql-postgresql-overview.png[] +image::./images/filebeat-postgresql-slowlog-overview.png[] [float] === Logs fileset settings diff --git a/filebeat/module/postgresql/_meta/docs.asciidoc b/filebeat/module/postgresql/_meta/docs.asciidoc index c67350d08bc..3ee20d7fb52 100644 --- a/filebeat/module/postgresql/_meta/docs.asciidoc +++ b/filebeat/module/postgresql/_meta/docs.asciidoc @@ -18,7 +18,7 @@ image::./images/filebeat-postgresql-overview.png[] The second one shows the slowlogs of PostgreSQL. -image::./images/filebeat-postgresql-postgresql-overview.png[] +image::./images/filebeat-postgresql-slowlog-overview.png[] [float] === Logs fileset settings From 0008c722eba848c3e48be81c4a270e51b024ace2 Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Tue, 8 Aug 2017 11:57:48 +0200 Subject: [PATCH 041/139] Add support for dynamic param in fields (#4835) In fields.yml `dynamic: false` or `dynamic: strict` can now be used. For more details see https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic.html --- libbeat/template/field.go | 50 +++++++++++++++------ libbeat/template/field_test.go | 82 ++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 13 deletions(-) diff --git a/libbeat/template/field.go b/libbeat/template/field.go index fdf40151db6..f8f6dfcd5db 100644 --- a/libbeat/template/field.go +++ b/libbeat/template/field.go @@ -1,6 +1,7 @@ package template import ( + "fmt" "strings" "github.com/elastic/beats/libbeat/common" @@ -11,18 +12,19 @@ var ( ) type Field struct { - Name string `config:"name"` - Type string `config:"type"` - Description string `config:"description"` - Format string `config:"format"` - ScalingFactor int `config:"scaling_factor"` - Fields Fields `config:"fields"` - MultiFields Fields `config:"multi_fields"` - ObjectType string `config:"object_type"` - Enabled *bool `config:"enabled"` - Analyzer string `config:"analyzer"` - SearchAnalyzer string `config:"search_analyzer"` - Norms bool `config:"norms"` + Name string `config:"name"` + Type string `config:"type"` + Description string `config:"description"` + Format string `config:"format"` + ScalingFactor int `config:"scaling_factor"` + Fields Fields `config:"fields"` + MultiFields Fields `config:"multi_fields"` + ObjectType string `config:"object_type"` + Enabled *bool `config:"enabled"` + Analyzer string `config:"analyzer"` + SearchAnalyzer string `config:"search_analyzer"` + Norms bool `config:"norms"` + Dynamic dynamicType `config:"dynamic"` path string esVersion common.Version @@ -33,7 +35,9 @@ type Field struct { // long, geo_point, date, short, byte, float, double, boolean func (f *Field) other() common.MapStr { property := f.getDefaultProperties() - property["type"] = f.Type + if f.Type != "" { + property["type"] = f.Type + } return property } @@ -184,6 +188,10 @@ func (f *Field) getDefaultProperties() common.MapStr { property["enabled"] = *f.Enabled } + if f.Dynamic.value != nil { + property["dynamic"] = f.Dynamic.value + } + return property } @@ -196,3 +204,19 @@ func generateKey(key string) string { } return key } + +type dynamicType struct{ value interface{} } + +func (d *dynamicType) Unpack(s string) error { + switch s { + case "true": + d.value = true + case "false": + d.value = false + case "strict": + d.value = s + default: + return fmt.Errorf("'%v' is invalid dynamic setting", s) + } + return nil +} diff --git a/libbeat/template/field_test.go b/libbeat/template/field_test.go index 2ae8f7dc0c1..c8793b796e0 100644 --- a/libbeat/template/field_test.go +++ b/libbeat/template/field_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/go-ucfg/yaml" ) func TestField(t *testing.T) { @@ -132,6 +133,27 @@ func TestField(t *testing.T) { }, }, }, + { + field: Field{Dynamic: dynamicType{false}}, + method: func(f Field) common.MapStr { return f.other() }, + output: common.MapStr{ + "dynamic": false, + }, + }, + { + field: Field{Dynamic: dynamicType{true}}, + method: func(f Field) common.MapStr { return f.other() }, + output: common.MapStr{ + "dynamic": true, + }, + }, + { + field: Field{Dynamic: dynamicType{"strict"}}, + method: func(f Field) common.MapStr { return f.other() }, + output: common.MapStr{ + "dynamic": "strict", + }, + }, } for _, test := range tests { @@ -196,3 +218,63 @@ func TestDynamicTemplate(t *testing.T) { assert.Equal(t, test.output, dynamicTemplates[0]) } } + +func TestDynamicYaml(t *testing.T) { + tests := []struct { + input []byte + output Field + error bool + }{ + { + input: []byte(` +name: test +dynamic: true +`), + output: Field{ + Name: "test", + Dynamic: dynamicType{true}, + }, + }, + { + input: []byte(` +name: test +dynamic: "true" +`), + output: Field{ + Name: "test", + Dynamic: dynamicType{true}, + }, + }, + { + input: []byte(` +name: test +dynamic: "blue" +`), + error: true, + }, + { + input: []byte(` +name: test +dynamic: "strict" +`), + output: Field{ + Name: "test", + Dynamic: dynamicType{"strict"}, + }, + }, + } + + for _, test := range tests { + keys := Field{} + + cfg, err := yaml.NewConfig(test.input) + assert.NoError(t, err) + err = cfg.Unpack(&keys) + + if err != nil { + assert.True(t, test.error) + } else { + assert.Equal(t, test.output.Dynamic, keys.Dynamic) + } + } +} From d789a32bcd8a36674c97dea5af9d28c9bc67cc9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Tue, 8 Aug 2017 13:38:58 +0200 Subject: [PATCH 042/139] filebeat: remove unreferenced image from documentation (#4844) --- filebeat/docs/images/filebeat-postgresql.png | Bin 71286 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 filebeat/docs/images/filebeat-postgresql.png diff --git a/filebeat/docs/images/filebeat-postgresql.png b/filebeat/docs/images/filebeat-postgresql.png deleted file mode 100644 index 5772eb8bfa3df60bbb8a68144c4844ec48ddcb24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71286 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 f?Z2hOa6w$k_vM=L=gi!Uub_R Date: Tue, 8 Aug 2017 18:30:14 +0300 Subject: [PATCH 043/139] Increase api version for Beats monitoring (#4793) * Increase the api version to 6 for monitoring and add to the response body returned by Elasticsearch in case of an error Fix comment * Add requested change --- .../report/elasticsearch/elasticsearch.go | 2 +- libbeat/outputs/elasticsearch/client.go | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libbeat/monitoring/report/elasticsearch/elasticsearch.go b/libbeat/monitoring/report/elasticsearch/elasticsearch.go index 00adffa58e0..729c9c1bd02 100644 --- a/libbeat/monitoring/report/elasticsearch/elasticsearch.go +++ b/libbeat/monitoring/report/elasticsearch/elasticsearch.go @@ -45,7 +45,7 @@ var errNoMonitoring = errors.New("xpack monitoring not available") // default monitoring api parameters var defaultParams = map[string]string{ "system_id": "beats", - "system_api_version": "2", + "system_api_version": "6", } func init() { diff --git a/libbeat/outputs/elasticsearch/client.go b/libbeat/outputs/elasticsearch/client.go index b6c2709a818..990e7fcfea5 100644 --- a/libbeat/outputs/elasticsearch/client.go +++ b/libbeat/outputs/elasticsearch/client.go @@ -720,16 +720,17 @@ func (conn *Connection) execHTTPRequest(req *http.Request) (int, []byte, error) defer closing(resp.Body) status := resp.StatusCode - var retErr error - if status >= 300 { - retErr = fmt.Errorf("%v", resp.Status) - } - obj, err := ioutil.ReadAll(resp.Body) if err != nil { - return status, nil, retErr + return status, nil, err } - return status, obj, retErr + + if status >= 300 { + // add the response body with the error returned by Elasticsearch + err = fmt.Errorf("%v: %s", resp.Status, obj) + } + + return status, obj, err } func (conn *Connection) GetVersion() string { From 190edf03c9a35d9682bf7fa49094b10ac9a93b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Tue, 8 Aug 2017 18:09:05 +0200 Subject: [PATCH 044/139] Update Filebeat development guide && create _meta/kibana/default folder (#4787) * create_fileset: Create kibana/default folder kibana/default folder is created under _meta to be more consistent with the development guide. * filebeat: update development guide on dashboards The way dashboards are exported has changed, so it followed up in the development guide. It also includes the export of dashboards before 6.x. --- docs/devguide/modules-dev-guide.asciidoc | 19 +++++++++++++++++-- filebeat/scripts/create_fileset.py | 5 ++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/docs/devguide/modules-dev-guide.asciidoc b/docs/devguide/modules-dev-guide.asciidoc index 29f58b25661..9a91389f080 100644 --- a/docs/devguide/modules-dev-guide.asciidoc +++ b/docs/devguide/modules-dev-guide.asciidoc @@ -52,6 +52,8 @@ module/{module}/{fileset} │   └── pipeline.json ├── _meta │   └── fields.yml +│   └── kibana +│    └── default └── test ---- @@ -306,11 +308,24 @@ them, you can build them visually in Kibana and then run the following command: [source,shell] ---- -$ cd filebeat/module/{module}/ -python ../../../dev-tools/export_dashboards.py --regex {module} --dir _meta/kibana +$ cd dev-tools/cmd/dashboards +$ make # if export_dashboard is not built +$ ./export_dashboards -dashboard '{dashboard-id}' -output '../../../filebeat/module/{module}/_meta/kibana/default/dashboard' +---- + +New Filebeat modules might not be compatible with Kibana 5.x. To export dashboards that are compatible with 5.x, run the following command inside the developer virtualenv: + +[source,shell] +---- +$ cd filebeat +$ make python-env +$ cd module/{module}/ +$ python ../../../dev-tools/export_5x_dashboards.py --regex {module} --dir _meta/kibana/5.x ---- Where the `--regex` parameter should match the dashboard you want to export. +Please note that dashboards exported from Kibana 5.x are not compatible with Kibana 6.x. + You can find more details about the process of creating and exporting the Kibana dashboards by reading {beatsdevguide}/new-dashboards.html[this guide]. diff --git a/filebeat/scripts/create_fileset.py b/filebeat/scripts/create_fileset.py index 2f5b0dd6043..b41d27302fc 100644 --- a/filebeat/scripts/create_fileset.py +++ b/filebeat/scripts/create_fileset.py @@ -46,13 +46,16 @@ def generate_module(base_path, metricbeat_path, module, fileset): module_path = base_path + "/module/" + module meta_path = module_path + "/_meta" + kibana_default_path = meta_path + "/kibana/default" if os.path.isdir(module_path): print("Module already exists. Skipping creating module {}" .format(module)) return - os.makedirs(meta_path) + paths_to_create = [meta_path, kibana_default_path] + for path_to_create in paths_to_create: + os.makedirs(path_to_create) templates = metricbeat_path + "/scripts/module/" From 66d6929ca5f0b85b568c11059c3c387db9e79b93 Mon Sep 17 00:00:00 2001 From: urso Date: Tue, 1 Aug 2017 21:00:27 +0200 Subject: [PATCH 045/139] Move most functionality from libbeat/beat to libbeat/cmd package - only have commonly shared structs/interfaces in libbeat/beat - move libbeat/beat functionality to libbeat/cmd/instance package - update imports/dependencies - start hiding some exported symbols --- filebeat/cmd/modules.go | 5 +- libbeat/beat/beat.go | 609 +------------------- libbeat/beat/error.go | 6 + libbeat/cmd/export/config.go | 4 +- libbeat/cmd/export/template.go | 4 +- libbeat/cmd/instance/beat.go | 582 +++++++++++++++++++ libbeat/{beat => cmd/instance}/beat_test.go | 6 +- libbeat/cmd/instance/doc.go | 30 + libbeat/{beat => cmd/instance}/flags.go | 16 +- libbeat/{beat => cmd/instance}/metrics.go | 2 +- libbeat/{beat => cmd/instance}/setup.go | 2 +- libbeat/cmd/modules.go | 19 +- libbeat/cmd/run.go | 3 +- libbeat/cmd/setup.go | 3 +- libbeat/cmd/test/config.go | 3 +- libbeat/cmd/test/output.go | 4 +- libbeat/cmd/version.go | 4 +- metricbeat/cmd/modules.go | 5 +- metricbeat/cmd/test/modules.go | 12 +- packetbeat/beater/devices.go | 4 +- winlogbeat/beater/winlogbeat.go | 26 +- winlogbeat/config/config.go | 18 +- winlogbeat/eventlog/eventlogging.go | 7 +- winlogbeat/eventlog/wineventlog.go | 9 +- 24 files changed, 697 insertions(+), 686 deletions(-) create mode 100644 libbeat/beat/error.go create mode 100644 libbeat/cmd/instance/beat.go rename libbeat/{beat => cmd/instance}/beat_test.go (85%) create mode 100644 libbeat/cmd/instance/doc.go rename libbeat/{beat => cmd/instance}/flags.go (61%) rename libbeat/{beat => cmd/instance}/metrics.go (97%) rename libbeat/{beat => cmd/instance}/setup.go (94%) diff --git a/filebeat/cmd/modules.go b/filebeat/cmd/modules.go index a1e1969ae76..3677a3d7579 100644 --- a/filebeat/cmd/modules.go +++ b/filebeat/cmd/modules.go @@ -11,10 +11,7 @@ import ( ) func buildModulesManager(beat *beat.Beat) (cmd.ModulesManager, error) { - config, err := beat.BeatConfig() - if err != nil { - return nil, errors.Wrap(err, "initialization error") - } + config := beat.BeatConfig glob, err := config.String("config.modules.path", -1) if err != nil { diff --git a/libbeat/beat/beat.go b/libbeat/beat/beat.go index 59fade43459..f7ec9402da6 100644 --- a/libbeat/beat/beat.go +++ b/libbeat/beat/beat.go @@ -1,81 +1,17 @@ -/* -Package beat provides the functions required to manage the life-cycle of a Beat. -It provides the standard mechanism for launching a Beat. It manages -configuration, logging, and publisher initialization and registers a signal -handler to gracefully stop the process. - -Each Beat implementation must implement the `Beater` interface and a `Creator` -to create and initialize the Beater instance. See the `Beater` interface and `Creator` -documentation for more details. - -To use this package, create a simple main that invokes the Run() function. - - func main() { - if err := beat.Run("mybeat", myVersion, beater.New); err != nil { - os.Exit(1) - } - } - -In the example above, the beater package contains the implementation of the -Beater interface and the New method returns a new instance of Beater. The -Beater implementation is placed into its own package so that it can be reused -or combined with other Beats. - -Recommendations - - * Use the logp package for logging rather than writing to stdout or stderr. - * Do not call os.Exit in any of your code. Return an error instead. Or if your - code needs to exit without an error, return beat.GracefulExit. -*/ package beat import ( - cryptRand "crypto/rand" - "encoding/json" - "errors" - "flag" - "fmt" - "math" - "math/big" - "math/rand" - "os" - "runtime" - "strings" - "time" - - "github.com/satori/go.uuid" - - "github.com/elastic/beats/libbeat/api" - "github.com/elastic/beats/libbeat/cfgfile" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/common/cfgwarn" - "github.com/elastic/beats/libbeat/common/file" - "github.com/elastic/beats/libbeat/dashboards" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/monitoring/report" - "github.com/elastic/beats/libbeat/outputs/elasticsearch" "github.com/elastic/beats/libbeat/paths" - "github.com/elastic/beats/libbeat/plugin" "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/libbeat/publisher/pipeline" - svc "github.com/elastic/beats/libbeat/service" - "github.com/elastic/beats/libbeat/template" - "github.com/elastic/beats/libbeat/version" - - // Register publisher pipeline modules - _ "github.com/elastic/beats/libbeat/publisher/includes" - - // Register default processors. - _ "github.com/elastic/beats/libbeat/processors/actions" - _ "github.com/elastic/beats/libbeat/processors/add_cloud_metadata" - _ "github.com/elastic/beats/libbeat/processors/add_docker_metadata" - _ "github.com/elastic/beats/libbeat/processors/add_kubernetes_metadata" - _ "github.com/elastic/beats/libbeat/processors/add_locale" - - // Register default monitoring reporting - _ "github.com/elastic/beats/libbeat/monitoring/report/elasticsearch" ) +// Creator initializes and configures a new Beater instance used to execute +// the beat its run-loop. +type Creator func(*Beat, *common.Config) (Beater, error) + // Beater is the interface that must be implemented by every Beat. A Beater // provides the main Run-loop and a Stop method to break the Run-loop. // Instantiation and Configuration is normally provided by a Beat-`Creator`. @@ -97,24 +33,19 @@ type Beater interface { Stop() } -// Creator initializes and configures a new Beater instance used to execute -// the beat its run-loop. -type Creator func(*Beat, *common.Config) (Beater, error) - -// SetupMLCallback can be used by the Beat to register MachineLearning configurations -// for the enabled modules. -type SetupMLCallback func(*Beat) error - // Beat contains the basic beat data and the publisher client used to publish // events. type Beat struct { Info common.BeatInfo // beat metadata. - RawConfig *common.Config // Raw config that can be unpacked to get Beat specific config data. - Config BeatConfig // Common Beat configuration data. Publisher beat.Pipeline // Publisher pipeline SetupMLCallback SetupMLCallback // setup callback for ML job configs InSetupCmd bool // this is set to true when the `setup` command is called + + // XXX: remove Config from public interface + Config BeatConfig // Common Beat configuration data. + + BeatConfig *common.Config // The beats it's own configuration section } // BeatConfig struct contains the basic configuration of every beat @@ -139,522 +70,6 @@ type BeatConfig struct { Kibana *common.Config `config:"setup.kibana"` } -var ( - printVersion = flag.Bool("version", false, "Print the version and exit") - setup = flag.Bool("setup", false, "Load the sample Kibana dashboards") -) - -var debugf = logp.MakeDebug("beat") - -// GracefulExit is an error that signals to exit with a code of 0. -var GracefulExit = errors.New("graceful exit") - -func init() { - // Initialize runtime random number generator seed using global, shared - // cryptographically strong pseudo random number generator. - // - // On linux Reader might use getrandom(2) or /udev/random. On windows systems - // CryptGenRandom is used. - n, err := cryptRand.Int(cryptRand.Reader, big.NewInt(math.MaxInt64)) - var seed int64 - if err != nil { - // fallback to current timestamp on error - seed = time.Now().UnixNano() - } else { - seed = n.Int64() - } - - rand.Seed(seed) -} - -// Run initializes and runs a Beater implementation. name is the name of the -// Beat (e.g. packetbeat or metricbeat). version is version number of the Beater -// implementation. bt is the `Creator` callback for creating a new beater -// instance. -// XXX Move this as a *Beat method? -func Run(name, version string, bt Creator) error { - return handleError(func() error { - b, err := New(name, version) - if err != nil { - return err - } - return b.launch(bt) - }()) -} - -// New creates a new beat instance -func New(name, v string) (*Beat, error) { - if v == "" { - v = version.GetDefaultVersion() - } - - hostname, err := os.Hostname() - if err != nil { - return nil, err - } - - return &Beat{ - Info: common.BeatInfo{ - Beat: name, - Version: v, - Name: hostname, - Hostname: hostname, - UUID: uuid.NewV4(), - }, - }, nil -} - -// init does initialization of things common to all actions (read confs, flags) -func (b *Beat) Init() error { - err := b.handleFlags() - if err != nil { - return err - } - - if err := plugin.Initialize(); err != nil { - return err - } - - if err := b.configure(); err != nil { - return err - } - - return nil -} - -// BeatConfig returns config section for this beat -func (b *Beat) BeatConfig() (*common.Config, error) { - configName := strings.ToLower(b.Info.Beat) - if b.RawConfig.HasField(configName) { - sub, err := b.RawConfig.Child(configName, -1) - if err != nil { - return nil, err - } - - return sub, nil - } - - return common.NewConfig(), nil -} - -// create and return the beater, this method also initializes all needed items, -// including template registering, publisher, xpack monitoring -func (b *Beat) createBeater(bt Creator) (Beater, error) { - sub, err := b.BeatConfig() - if err != nil { - return nil, err - } - - logp.Info("Setup Beat: %s; Version: %s", b.Info.Beat, b.Info.Version) - - err = b.registerTemplateLoading() - if err != nil { - return nil, err - } - - debugf("Initializing output plugins") - pipeline, err := pipeline.Load(b.Info, b.Config.Pipeline, b.Config.Output) - if err != nil { - return nil, fmt.Errorf("error initializing publisher: %v", err) - } - - // TODO: some beats race on shutdown with publisher.Stop -> do not call Stop yet, - // but refine publisher to disconnect clients on stop automatically - // defer pipeline.Close() - - b.Publisher = pipeline - beater, err := bt(b, sub) - if err != nil { - return nil, err - } - - return beater, nil -} - -func (b *Beat) launch(bt Creator) error { - err := b.Init() - if err != nil { - return err - } - - svc.BeforeRun() - defer svc.Cleanup() - - beater, err := b.createBeater(bt) - if err != nil { - return err - } - - if b.Config.Monitoring.Enabled() { - reporter, err := report.New(b.Info, b.Config.Monitoring, b.Config.Output) - if err != nil { - return err - } - defer reporter.Stop() - } - - // If -configtest was specified, exit now prior to run. - if cfgfile.IsTestConfig() { - cfgwarn.Deprecate("6.0", "-configtest flag has been deprecated, use configtest subcommand") - fmt.Println("Config OK") - return GracefulExit - } - - svc.HandleSignals(beater.Stop) - - // TODO Deprecate this in favor of setup subcommand (7.0) - if *setup { - cfgwarn.Deprecate("6.0", "-setup flag has been deprectad, use setup subcommand") - } - err = b.loadDashboards(false) - if err != nil { - return err - } - if b.SetupMLCallback != nil && *setup { - err = b.SetupMLCallback(b) - if err != nil { - return err - } - } - - logp.Info("%s start running.", b.Info.Beat) - defer logp.Info("%s stopped.", b.Info.Beat) - defer logp.LogTotalExpvars(&b.Config.Logging) - - if b.Config.HTTP.Enabled() { - api.Start(b.Config.HTTP, b.Info) - } - - return beater.Run(b) -} - -// TestConfig check all settings are ok and the beat can be run -func (b *Beat) TestConfig(bt Creator) error { - return handleError(func() error { - err := b.Init() - if err != nil { - return err - } - - // Create beater to ensure all settings are OK - _, err = b.createBeater(bt) - if err != nil { - return err - } - - fmt.Println("Config OK") - return GracefulExit - }()) -} - -// Setup registers ES index template and kibana dashboards -func (b *Beat) Setup(bt Creator, template, dashboards, machineLearning bool) error { - return handleError(func() error { - err := b.Init() - if err != nil { - return err - } - - // Tell the beat that we're in the setup command - b.InSetupCmd = true - - // Create beater to give it the opportunity to set loading callbacks - _, err = b.createBeater(bt) - if err != nil { - return err - } - - if template { - if b.Config.Output.Name() != "elasticsearch" { - return fmt.Errorf("Template loading requested but the Elasticsearch output is not configured/enabled") - } - - esConfig := b.Config.Output.Config() - if b.Config.Template == nil || (b.Config.Template != nil && b.Config.Template.Enabled()) { - loadCallback, err := b.templateLoadingCallback() - if err != nil { - return err - } - - esClient, err := elasticsearch.NewConnectedClient(esConfig) - if err != nil { - return err - } - - // Load template - err = loadCallback(esClient) - if err != nil { - return err - } - } - - fmt.Println("Loaded index template") - } - - if dashboards { - err = b.loadDashboards(true) - if err != nil { - return err - } - - fmt.Println("Loaded dashboards") - } - - if machineLearning && b.SetupMLCallback != nil { - err = b.SetupMLCallback(b) - if err != nil { - return err - } - fmt.Println("Loaded machine learning job configurations") - } - - return nil - }()) -} - -// handleFlags parses the command line flags. It handles the '-version' flag -// and invokes the HandleFlags callback if implemented by the Beat. -func (b *Beat) handleFlags() error { - // Due to a dependence upon the beat name, the default config file path - // must be updated prior to CLI flag handling. - err := cfgfile.ChangeDefaultCfgfileFlag(b.Info.Beat) - if err != nil { - return fmt.Errorf("failed to set default config file path: %v", err) - } - flag.Parse() - - if *printVersion { - cfgwarn.Deprecate("6.0", "-version flag has been deprectad, use version subcommand") - fmt.Printf("%s version %s (%s), libbeat %s\n", - b.Info.Beat, b.Info.Version, runtime.GOARCH, version.GetDefaultVersion()) - return GracefulExit - } - - if err := logp.HandleFlags(b.Info.Beat); err != nil { - return err - } - if err := cfgfile.HandleFlags(); err != nil { - return err - } - - return handleFlags(b) -} - -// config reads the configuration file from disk, parses the common options -// defined in BeatConfig, initializes logging, and set GOMAXPROCS if defined -// in the config. Lastly it invokes the Config method implemented by the beat. -func (b *Beat) configure() error { - var err error - - cfg, err := cfgfile.Load("") - if err != nil { - return fmt.Errorf("error loading config file: %v", err) - } - - b.RawConfig = cfg - err = cfg.Unpack(&b.Config) - if err != nil { - return fmt.Errorf("error unpacking config data: %v", err) - } - - err = cfgwarn.CheckRemoved5xSettings(cfg, "queue_size", "bulk_queue_size") - if err != nil { - return err - } - - if name := b.Config.Name; name != "" { - b.Info.Name = name - } - - err = paths.InitPaths(&b.Config.Path) - if err != nil { - return fmt.Errorf("error setting default paths: %v", err) - } - - err = logp.Init(b.Info.Beat, &b.Config.Logging) - if err != nil { - return fmt.Errorf("error initializing logging: %v", err) - } - - // log paths values to help with troubleshooting - logp.Info(paths.Paths.String()) - - err = b.loadMeta() - if err != nil { - return err - } - - logp.Info("Beat UUID: %v", b.Info.UUID) - - if maxProcs := b.Config.MaxProcs; maxProcs > 0 { - runtime.GOMAXPROCS(maxProcs) - } - - return nil -} - -func (b *Beat) loadMeta() error { - type meta struct { - UUID uuid.UUID `json:"uuid"` - } - - metaPath := paths.Resolve(paths.Data, "meta.json") - logp.Info("Beat metadata path: %v", metaPath) - - f, err := openRegular(metaPath) - if err != nil && !os.IsNotExist(err) { - return fmt.Errorf("Beat meta file failed to open: %s", err) - } - - if err == nil { - m := meta{} - if err := json.NewDecoder(f).Decode(&m); err != nil { - f.Close() - return fmt.Errorf("Beat meta file reading error: %v", err) - } - - f.Close() - valid := !uuid.Equal(m.UUID, uuid.Nil) - if valid { - b.Info.UUID = m.UUID - return nil - } - } - - // file does not exist or UUID is invalid, let's create a new one - - // write temporary file first - tempFile := metaPath + ".new" - f, err = os.OpenFile(tempFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - return fmt.Errorf("Failed to create Beat meta file: %s", err) - } - - err = json.NewEncoder(f).Encode(meta{UUID: b.Info.UUID}) - f.Close() - if err != nil { - return fmt.Errorf("Beat meta file failed to write: %s", err) - } - - // move temporary file into final location - err = file.SafeFileRotate(metaPath, tempFile) - return err -} - -func openRegular(filename string) (*os.File, error) { - f, err := os.Open(filename) - if err != nil { - return f, err - } - - info, err := f.Stat() - if err != nil { - f.Close() - return nil, err - } - - if !info.Mode().IsRegular() { - f.Close() - if info.IsDir() { - return nil, fmt.Errorf("%s is a directory", filename) - } - return nil, fmt.Errorf("%s is not a regular file", filename) - } - - return f, nil -} - -func (b *Beat) loadDashboards(force bool) error { - if *setup || force { - // -setup implies dashboards.enabled=true - if b.Config.Dashboards == nil { - b.Config.Dashboards = common.NewConfig() - } - err := b.Config.Dashboards.SetBool("enabled", -1, true) - if err != nil { - return fmt.Errorf("Error setting dashboard.enabled=true: %v", err) - } - } - - if b.Config.Dashboards != nil && b.Config.Dashboards.Enabled() { - var esConfig *common.Config - - if b.Config.Output.Name() == "elasticsearch" { - esConfig = b.Config.Output.Config() - } - err := dashboards.ImportDashboards(b.Info.Beat, b.Info.Version, paths.Resolve(paths.Home, ""), - b.Config.Kibana, esConfig, b.Config.Dashboards, nil) - if err != nil { - return fmt.Errorf("Error importing Kibana dashboards: %v", err) - } - logp.Info("Kibana dashboards successfully loaded.") - } - - return nil -} - -// registerTemplateLoading registers the loading of the template as a callback with -// the elasticsearch output. It is important the the registration happens before -// the publisher is created. -func (b *Beat) registerTemplateLoading() error { - // Check if outputting to file is enabled, and output to file if it is - if b.Config.Template != nil && b.Config.Template.Enabled() { - var cfg template.TemplateConfig - err := b.Config.Template.Unpack(&cfg) - if err != nil { - return fmt.Errorf("unpacking template config fails: %v", err) - } - } - - // Loads template by default if esOutput is enabled - if b.Config.Output.Name() == "elasticsearch" { - if b.Config.Template == nil || (b.Config.Template != nil && b.Config.Template.Enabled()) { - // load template through callback to make sure it is also loaded - // on reconnecting - callback, err := b.templateLoadingCallback() - if err != nil { - return err - } - elasticsearch.RegisterConnectCallback(callback) - } - } - - return nil -} - -// Build and return a callback to load index template into ES -func (b *Beat) templateLoadingCallback() (func(esClient *elasticsearch.Client) error, error) { - callback := func(esClient *elasticsearch.Client) error { - if b.Config.Template == nil { - b.Config.Template = common.NewConfig() - } - - loader, err := template.NewLoader(b.Config.Template, esClient, b.Info) - if err != nil { - return fmt.Errorf("Error creating Elasticsearch template loader: %v", err) - } - - err = loader.Load() - if err != nil { - return fmt.Errorf("Error loading Elasticsearch template: %v", err) - } - - return nil - } - - return callback, nil -} - -// handleError handles the given error by logging it and then returning the -// error. If the err is nil or is a GracefulExit error then the method will -// return nil without logging anything. -func handleError(err error) error { - if err == nil || err == GracefulExit { - return nil - } - - // logp may not be initialized so log the err to stderr too. - logp.Critical("Exiting: %v", err) - fmt.Fprintf(os.Stderr, "Exiting: %v\n", err) - return err -} +// SetupMLCallback can be used by the Beat to register MachineLearning configurations +// for the enabled modules. +type SetupMLCallback func(*Beat) error diff --git a/libbeat/beat/error.go b/libbeat/beat/error.go new file mode 100644 index 00000000000..14a74ddd215 --- /dev/null +++ b/libbeat/beat/error.go @@ -0,0 +1,6 @@ +package beat + +import "errors" + +// GracefulExit is an error that signals to exit with a code of 0. +var GracefulExit = errors.New("graceful exit") diff --git a/libbeat/cmd/export/config.go b/libbeat/cmd/export/config.go index 7060a5dd2f9..f073455af9f 100644 --- a/libbeat/cmd/export/config.go +++ b/libbeat/cmd/export/config.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/cobra" "gopkg.in/yaml.v2" - "github.com/elastic/beats/libbeat/beat" + "github.com/elastic/beats/libbeat/cmd/instance" ) func GenExportConfigCmd(name, beatVersion string) *cobra.Command { @@ -15,7 +15,7 @@ func GenExportConfigCmd(name, beatVersion string) *cobra.Command { Use: "config", Short: "Export current config to stdout", Run: func(cmd *cobra.Command, args []string) { - b, err := beat.New(name, beatVersion) + b, err := instance.NewBeat(name, beatVersion) if err != nil { fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err) os.Exit(1) diff --git a/libbeat/cmd/export/template.go b/libbeat/cmd/export/template.go index b459638c42b..876690b6803 100644 --- a/libbeat/cmd/export/template.go +++ b/libbeat/cmd/export/template.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" - "github.com/elastic/beats/libbeat/beat" + "github.com/elastic/beats/libbeat/cmd/instance" "github.com/elastic/beats/libbeat/template" ) @@ -18,7 +18,7 @@ func GenTemplateConfigCmd(name, beatVersion string) *cobra.Command { version, _ := cmd.Flags().GetString("es.version") index, _ := cmd.Flags().GetString("index") - b, err := beat.New(name, beatVersion) + b, err := instance.NewBeat(name, beatVersion) if err != nil { fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err) os.Exit(1) diff --git a/libbeat/cmd/instance/beat.go b/libbeat/cmd/instance/beat.go new file mode 100644 index 00000000000..ac2eda7bb36 --- /dev/null +++ b/libbeat/cmd/instance/beat.go @@ -0,0 +1,582 @@ +package instance + +import ( + cryptRand "crypto/rand" + "encoding/json" + "flag" + "fmt" + "math" + "math/big" + "math/rand" + "os" + "runtime" + "strings" + "time" + + "github.com/satori/go.uuid" + + "github.com/elastic/beats/libbeat/api" + "github.com/elastic/beats/libbeat/beat" + "github.com/elastic/beats/libbeat/cfgfile" + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/common/cfgwarn" + "github.com/elastic/beats/libbeat/common/file" + "github.com/elastic/beats/libbeat/dashboards" + "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/libbeat/monitoring/report" + "github.com/elastic/beats/libbeat/outputs/elasticsearch" + "github.com/elastic/beats/libbeat/paths" + "github.com/elastic/beats/libbeat/plugin" + "github.com/elastic/beats/libbeat/publisher/pipeline" + svc "github.com/elastic/beats/libbeat/service" + "github.com/elastic/beats/libbeat/template" + "github.com/elastic/beats/libbeat/version" + + // Register publisher pipeline modules + _ "github.com/elastic/beats/libbeat/publisher/includes" + + // Register default processors. + _ "github.com/elastic/beats/libbeat/processors/actions" + _ "github.com/elastic/beats/libbeat/processors/add_cloud_metadata" + _ "github.com/elastic/beats/libbeat/processors/add_docker_metadata" + _ "github.com/elastic/beats/libbeat/processors/add_kubernetes_metadata" + _ "github.com/elastic/beats/libbeat/processors/add_locale" + + // Register default monitoring reporting + _ "github.com/elastic/beats/libbeat/monitoring/report/elasticsearch" +) + +type Beat struct { + beat.Beat + + RawConfig *common.Config // Raw config that can be unpacked to get Beat specific config data. +} + +var ( + printVersion bool + setup bool +) + +var debugf = logp.MakeDebug("beat") + +func init() { + initRand() + + flag.BoolVar(&printVersion, "version", false, "Print the version and exit") + flag.BoolVar(&setup, "setup", false, "Load the sample Kibana dashboards") +} + +// initRand initializes the runtime random number generator seed using +// global, shared cryptographically strong pseudo random number generator. +// +// On linux Reader might use getrandom(2) or /udev/random. On windows systems +// CryptGenRandom is used. +func initRand() { + n, err := cryptRand.Int(cryptRand.Reader, big.NewInt(math.MaxInt64)) + seed := n.Int64() + if err != nil { + // fallback to current timestamp + seed = time.Now().UnixNano() + } + + rand.Seed(seed) +} + +// Run initializes and runs a Beater implementation. name is the name of the +// Beat (e.g. packetbeat or metricbeat). version is version number of the Beater +// implementation. bt is the `Creator` callback for creating a new beater +// instance. +// XXX Move this as a *Beat method? +func Run(name, version string, bt beat.Creator) error { + return handleError(func() error { + b, err := NewBeat(name, version) + if err != nil { + return err + } + return b.launch(bt) + }()) +} + +// New creates a new beat instance +func NewBeat(name, v string) (*Beat, error) { + if v == "" { + v = version.GetDefaultVersion() + } + + hostname, err := os.Hostname() + if err != nil { + return nil, err + } + + b := beat.Beat{ + Info: common.BeatInfo{ + Beat: name, + Version: v, + Name: hostname, + Hostname: hostname, + UUID: uuid.NewV4(), + }, + } + + return &Beat{Beat: b}, nil +} + +// init does initialization of things common to all actions (read confs, flags) +func (b *Beat) Init() error { + err := b.handleFlags() + if err != nil { + return err + } + + if err := plugin.Initialize(); err != nil { + return err + } + + if err := b.configure(); err != nil { + return err + } + + return nil +} + +// BeatConfig returns config section for this beat +func (b *Beat) BeatConfig() (*common.Config, error) { + configName := strings.ToLower(b.Info.Beat) + if b.RawConfig.HasField(configName) { + sub, err := b.RawConfig.Child(configName, -1) + if err != nil { + return nil, err + } + + return sub, nil + } + + return common.NewConfig(), nil +} + +// create and return the beater, this method also initializes all needed items, +// including template registering, publisher, xpack monitoring +func (b *Beat) createBeater(bt beat.Creator) (beat.Beater, error) { + sub, err := b.BeatConfig() + if err != nil { + return nil, err + } + + logp.Info("Setup Beat: %s; Version: %s", b.Info.Beat, b.Info.Version) + + err = b.registerTemplateLoading() + if err != nil { + return nil, err + } + + debugf("Initializing output plugins") + pipeline, err := pipeline.Load(b.Info, b.Config.Pipeline, b.Config.Output) + if err != nil { + return nil, fmt.Errorf("error initializing publisher: %v", err) + } + + // TODO: some beats race on shutdown with publisher.Stop -> do not call Stop yet, + // but refine publisher to disconnect clients on stop automatically + // defer pipeline.Close() + + b.Publisher = pipeline + beater, err := bt(&b.Beat, sub) + if err != nil { + return nil, err + } + + return beater, nil +} + +func (b *Beat) launch(bt beat.Creator) error { + err := b.Init() + if err != nil { + return err + } + + svc.BeforeRun() + defer svc.Cleanup() + + beater, err := b.createBeater(bt) + if err != nil { + return err + } + + if b.Config.Monitoring.Enabled() { + reporter, err := report.New(b.Info, b.Config.Monitoring, b.Config.Output) + if err != nil { + return err + } + defer reporter.Stop() + } + + // If -configtest was specified, exit now prior to run. + if cfgfile.IsTestConfig() { + cfgwarn.Deprecate("6.0", "-configtest flag has been deprecated, use configtest subcommand") + fmt.Println("Config OK") + return beat.GracefulExit + } + + svc.HandleSignals(beater.Stop) + + // TODO Deprecate this in favor of setup subcommand (7.0) + if setup { + cfgwarn.Deprecate("6.0", "-setup flag has been deprectad, use setup subcommand") + } + err = b.loadDashboards(false) + if err != nil { + return err + } + if setup && b.SetupMLCallback != nil { + err = b.SetupMLCallback(&b.Beat) + if err != nil { + return err + } + } + + logp.Info("%s start running.", b.Info.Beat) + defer logp.Info("%s stopped.", b.Info.Beat) + defer logp.LogTotalExpvars(&b.Config.Logging) + + if b.Config.HTTP.Enabled() { + api.Start(b.Config.HTTP, b.Info) + } + + return beater.Run(&b.Beat) +} + +// TestConfig check all settings are ok and the beat can be run +func (b *Beat) TestConfig(bt beat.Creator) error { + return handleError(func() error { + err := b.Init() + if err != nil { + return err + } + + // Create beater to ensure all settings are OK + _, err = b.createBeater(bt) + if err != nil { + return err + } + + fmt.Println("Config OK") + return beat.GracefulExit + }()) +} + +// Setup registers ES index template and kibana dashboards +func (b *Beat) Setup(bt beat.Creator, template, dashboards, machineLearning bool) error { + return handleError(func() error { + err := b.Init() + if err != nil { + return err + } + + // Tell the beat that we're in the setup command + b.InSetupCmd = true + + // Create beater to give it the opportunity to set loading callbacks + _, err = b.createBeater(bt) + if err != nil { + return err + } + + if template { + if b.Config.Output.Name() != "elasticsearch" { + return fmt.Errorf("Template loading requested but the Elasticsearch output is not configured/enabled") + } + + esConfig := b.Config.Output.Config() + if b.Config.Template == nil || (b.Config.Template != nil && b.Config.Template.Enabled()) { + loadCallback, err := b.templateLoadingCallback() + if err != nil { + return err + } + + esClient, err := elasticsearch.NewConnectedClient(esConfig) + if err != nil { + return err + } + + // Load template + err = loadCallback(esClient) + if err != nil { + return err + } + } + + fmt.Println("Loaded index template") + } + + if dashboards { + err = b.loadDashboards(true) + if err != nil { + return err + } + + fmt.Println("Loaded dashboards") + } + + if machineLearning && b.SetupMLCallback != nil { + err = b.SetupMLCallback(&b.Beat) + if err != nil { + return err + } + fmt.Println("Loaded machine learning job configurations") + } + + return nil + }()) +} + +// handleFlags parses the command line flags. It handles the '-version' flag +// and invokes the HandleFlags callback if implemented by the Beat. +func (b *Beat) handleFlags() error { + // Due to a dependence upon the beat name, the default config file path + // must be updated prior to CLI flag handling. + err := cfgfile.ChangeDefaultCfgfileFlag(b.Info.Beat) + if err != nil { + return fmt.Errorf("failed to set default config file path: %v", err) + } + flag.Parse() + + if printVersion { + cfgwarn.Deprecate("6.0", "-version flag has been deprectad, use version subcommand") + fmt.Printf("%s version %s (%s), libbeat %s\n", + b.Info.Beat, b.Info.Version, runtime.GOARCH, version.GetDefaultVersion()) + return beat.GracefulExit + } + + if err := logp.HandleFlags(b.Info.Beat); err != nil { + return err + } + if err := cfgfile.HandleFlags(); err != nil { + return err + } + + return handleFlags(&b.Beat) +} + +// config reads the configuration file from disk, parses the common options +// defined in BeatConfig, initializes logging, and set GOMAXPROCS if defined +// in the config. Lastly it invokes the Config method implemented by the beat. +func (b *Beat) configure() error { + var err error + + cfg, err := cfgfile.Load("") + if err != nil { + return fmt.Errorf("error loading config file: %v", err) + } + + b.RawConfig = cfg + err = cfg.Unpack(&b.Config) + if err != nil { + return fmt.Errorf("error unpacking config data: %v", err) + } + + err = cfgwarn.CheckRemoved5xSettings(cfg, "queue_size", "bulk_queue_size") + if err != nil { + return err + } + + if name := b.Config.Name; name != "" { + b.Info.Name = name + } + + err = paths.InitPaths(&b.Config.Path) + if err != nil { + return fmt.Errorf("error setting default paths: %v", err) + } + + err = logp.Init(b.Info.Beat, &b.Config.Logging) + if err != nil { + return fmt.Errorf("error initializing logging: %v", err) + } + + // log paths values to help with troubleshooting + logp.Info(paths.Paths.String()) + + err = b.loadMeta() + if err != nil { + return err + } + + logp.Info("Beat UUID: %v", b.Info.UUID) + + if maxProcs := b.Config.MaxProcs; maxProcs > 0 { + runtime.GOMAXPROCS(maxProcs) + } + + b.Beat.BeatConfig, err = b.BeatConfig() + if err != nil { + return err + } + + return nil +} + +func (b *Beat) loadMeta() error { + type meta struct { + UUID uuid.UUID `json:"uuid"` + } + + metaPath := paths.Resolve(paths.Data, "meta.json") + logp.Info("Beat metadata path: %v", metaPath) + + f, err := openRegular(metaPath) + if err != nil && !os.IsNotExist(err) { + return fmt.Errorf("Beat meta file failed to open: %s", err) + } + + if err == nil { + m := meta{} + if err := json.NewDecoder(f).Decode(&m); err != nil { + f.Close() + return fmt.Errorf("Beat meta file reading error: %v", err) + } + + f.Close() + valid := !uuid.Equal(m.UUID, uuid.Nil) + if valid { + b.Info.UUID = m.UUID + return nil + } + } + + // file does not exist or UUID is invalid, let's create a new one + + // write temporary file first + tempFile := metaPath + ".new" + f, err = os.OpenFile(tempFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + return fmt.Errorf("Failed to create Beat meta file: %s", err) + } + + err = json.NewEncoder(f).Encode(meta{UUID: b.Info.UUID}) + f.Close() + if err != nil { + return fmt.Errorf("Beat meta file failed to write: %s", err) + } + + // move temporary file into final location + err = file.SafeFileRotate(metaPath, tempFile) + return err +} + +func openRegular(filename string) (*os.File, error) { + f, err := os.Open(filename) + if err != nil { + return f, err + } + + info, err := f.Stat() + if err != nil { + f.Close() + return nil, err + } + + if !info.Mode().IsRegular() { + f.Close() + if info.IsDir() { + return nil, fmt.Errorf("%s is a directory", filename) + } + return nil, fmt.Errorf("%s is not a regular file", filename) + } + + return f, nil +} + +func (b *Beat) loadDashboards(force bool) error { + if setup || force { + // -setup implies dashboards.enabled=true + if b.Config.Dashboards == nil { + b.Config.Dashboards = common.NewConfig() + } + err := b.Config.Dashboards.SetBool("enabled", -1, true) + if err != nil { + return fmt.Errorf("Error setting dashboard.enabled=true: %v", err) + } + } + + if b.Config.Dashboards != nil && b.Config.Dashboards.Enabled() { + var esConfig *common.Config + + if b.Config.Output.Name() == "elasticsearch" { + esConfig = b.Config.Output.Config() + } + err := dashboards.ImportDashboards(b.Info.Beat, b.Info.Version, paths.Resolve(paths.Home, ""), + b.Config.Kibana, esConfig, b.Config.Dashboards, nil) + if err != nil { + return fmt.Errorf("Error importing Kibana dashboards: %v", err) + } + logp.Info("Kibana dashboards successfully loaded.") + } + + return nil +} + +// registerTemplateLoading registers the loading of the template as a callback with +// the elasticsearch output. It is important the the registration happens before +// the publisher is created. +func (b *Beat) registerTemplateLoading() error { + // Check if outputting to file is enabled, and output to file if it is + if b.Config.Template != nil && b.Config.Template.Enabled() { + var cfg template.TemplateConfig + err := b.Config.Template.Unpack(&cfg) + if err != nil { + return fmt.Errorf("unpacking template config fails: %v", err) + } + } + + // Loads template by default if esOutput is enabled + if b.Config.Output.Name() == "elasticsearch" { + if b.Config.Template == nil || (b.Config.Template != nil && b.Config.Template.Enabled()) { + // load template through callback to make sure it is also loaded + // on reconnecting + callback, err := b.templateLoadingCallback() + if err != nil { + return err + } + elasticsearch.RegisterConnectCallback(callback) + } + } + + return nil +} + +// Build and return a callback to load index template into ES +func (b *Beat) templateLoadingCallback() (func(esClient *elasticsearch.Client) error, error) { + callback := func(esClient *elasticsearch.Client) error { + if b.Config.Template == nil { + b.Config.Template = common.NewConfig() + } + + loader, err := template.NewLoader(b.Config.Template, esClient, b.Info) + if err != nil { + return fmt.Errorf("Error creating Elasticsearch template loader: %v", err) + } + + err = loader.Load() + if err != nil { + return fmt.Errorf("Error loading Elasticsearch template: %v", err) + } + + return nil + } + + return callback, nil +} + +// handleError handles the given error by logging it and then returning the +// error. If the err is nil or is a GracefulExit error then the method will +// return nil without logging anything. +func handleError(err error) error { + if err == nil || err == beat.GracefulExit { + return nil + } + + // logp may not be initialized so log the err to stderr too. + logp.Critical("Exiting: %v", err) + fmt.Fprintf(os.Stderr, "Exiting: %v\n", err) + return err +} diff --git a/libbeat/beat/beat_test.go b/libbeat/cmd/instance/beat_test.go similarity index 85% rename from libbeat/beat/beat_test.go rename to libbeat/cmd/instance/beat_test.go index 2ef30b50617..a0c8eb96f41 100644 --- a/libbeat/beat/beat_test.go +++ b/libbeat/cmd/instance/beat_test.go @@ -1,6 +1,6 @@ // +build !integration -package beat +package instance import ( "testing" @@ -10,7 +10,7 @@ import ( ) func TestNewInstance(t *testing.T) { - b, err := New("testbeat", "0.9") + b, err := NewBeat("testbeat", "0.9") if err != nil { panic(err) } @@ -24,7 +24,7 @@ func TestNewInstance(t *testing.T) { } func TestNewInstanceUUID(t *testing.T) { - b, err := New("testbeat", "0.9") + b, err := NewBeat("testbeat", "0.9") if err != nil { panic(err) } diff --git a/libbeat/cmd/instance/doc.go b/libbeat/cmd/instance/doc.go new file mode 100644 index 00000000000..307fd232671 --- /dev/null +++ b/libbeat/cmd/instance/doc.go @@ -0,0 +1,30 @@ +/* +Package instance provides the functions required to manage the life-cycle of a Beat. +It provides the standard mechanism for launching a Beat. It manages +configuration, logging, and publisher initialization and registers a signal +handler to gracefully stop the process. + +Each Beat implementation must implement the `Beater` interface and a `Creator` +to create and initialize the Beater instance. See the `Beater` interface and `Creator` +documentation for more details. + +To use this package, create a simple main that invokes the Run() function. + + func main() { + if err := beat.Run("mybeat", myVersion, beater.New); err != nil { + os.Exit(1) + } + } + +In the example above, the beater package contains the implementation of the +Beater interface and the New method returns a new instance of Beater. The +Beater implementation is placed into its own package so that it can be reused +or combined with other Beats. + +Recommendations + + * Use the logp package for logging rather than writing to stdout or stderr. + * Do not call os.Exit in any of your code. Return an error instead. Or if your + code needs to exit without an error, return beat.GracefulExit. +*/ +package instance diff --git a/libbeat/beat/flags.go b/libbeat/cmd/instance/flags.go similarity index 61% rename from libbeat/beat/flags.go rename to libbeat/cmd/instance/flags.go index e8aaca794dc..5057f642ebb 100644 --- a/libbeat/beat/flags.go +++ b/libbeat/cmd/instance/flags.go @@ -1,4 +1,8 @@ -package beat +package instance + +import "github.com/elastic/beats/libbeat/beat" + +// XXX: With introduction of cmd package, the FlagsHandler should be deprecated. // FlagsHandler is an interface that can optionally be implemented by a Beat // if it needs to process command line flags on startup. If implemented, the @@ -6,10 +10,10 @@ package beat // and before any of the Beater interface methods are invoked. There will be // no callback when '-help' or '-version' are specified. type FlagsHandler interface { - HandleFlags(*Beat) error // Handle any custom command line arguments. + HandleFlags(*beat.Beat) error // Handle any custom command line arguments. } -type FlagsHandlerCallback func(*Beat) error +type FlagsHandlerCallback func(*beat.Beat) error var handlers []FlagsHandler @@ -17,11 +21,11 @@ func AddFlagsHandler(h FlagsHandler) { handlers = append(handlers, h) } -func AddFlagsCallback(cb func(*Beat) error) { +func AddFlagsCallback(cb func(*beat.Beat) error) { AddFlagsHandler(FlagsHandlerCallback(cb)) } -func handleFlags(b *Beat) error { +func handleFlags(b *beat.Beat) error { for _, h := range handlers { err := h.HandleFlags(b) if err != nil { @@ -31,6 +35,6 @@ func handleFlags(b *Beat) error { return nil } -func (cb FlagsHandlerCallback) HandleFlags(b *Beat) error { +func (cb FlagsHandlerCallback) HandleFlags(b *beat.Beat) error { return cb(b) } diff --git a/libbeat/beat/metrics.go b/libbeat/cmd/instance/metrics.go similarity index 97% rename from libbeat/beat/metrics.go rename to libbeat/cmd/instance/metrics.go index 4cdaae9fe87..6169d6a04e1 100644 --- a/libbeat/beat/metrics.go +++ b/libbeat/cmd/instance/metrics.go @@ -1,4 +1,4 @@ -package beat +package instance import ( "runtime" diff --git a/libbeat/beat/setup.go b/libbeat/cmd/instance/setup.go similarity index 94% rename from libbeat/beat/setup.go rename to libbeat/cmd/instance/setup.go index 1cb5c2d4a41..e1f19193b56 100644 --- a/libbeat/beat/setup.go +++ b/libbeat/cmd/instance/setup.go @@ -1,4 +1,4 @@ -package beat +package instance type TemplateConfig struct { Enabled bool `config:"enabled"` diff --git a/libbeat/cmd/modules.go b/libbeat/cmd/modules.go index 4e52ffb72d7..3ace488533b 100644 --- a/libbeat/cmd/modules.go +++ b/libbeat/cmd/modules.go @@ -8,6 +8,7 @@ import ( "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/cfgfile" + "github.com/elastic/beats/libbeat/cmd/instance" ) // ModulesManager interface provides all actions needed to implement modules command @@ -21,12 +22,12 @@ type ModulesManager interface { Disable(name string) error } -// ModulesManagerFactory builds and return a ModulesManager for the given Beat -type ModulesManagerFactory func(beat *beat.Beat) (ModulesManager, error) +// modulesManagerFactory builds and return a ModulesManager for the given Beat +type modulesManagerFactory func(beat *beat.Beat) (ModulesManager, error) // GenModulesCmd initializes a command to manage a modules.d folder, it offers // list, enable and siable actions -func GenModulesCmd(name, version string, modulesFactory ModulesManagerFactory) *cobra.Command { +func GenModulesCmd(name, version string, modulesFactory modulesManagerFactory) *cobra.Command { modulesCmd := cobra.Command{ Use: "modules", Short: "Manage configured modules", @@ -40,8 +41,8 @@ func GenModulesCmd(name, version string, modulesFactory ModulesManagerFactory) * } // Instantiate a modules manager or die trying -func getModules(name, version string, modulesFactory ModulesManagerFactory) ModulesManager { - b, err := beat.New(name, version) +func getModules(name, version string, modulesFactory modulesManagerFactory) ModulesManager { + b, err := instance.NewBeat(name, version) if err != nil { fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err) os.Exit(1) @@ -52,7 +53,7 @@ func getModules(name, version string, modulesFactory ModulesManagerFactory) Modu os.Exit(1) } - manager, err := modulesFactory(b) + manager, err := modulesFactory(&b.Beat) if err != nil { fmt.Fprintf(os.Stderr, "Error in modules manager: %s\n", err) os.Exit(1) @@ -61,7 +62,7 @@ func getModules(name, version string, modulesFactory ModulesManagerFactory) Modu return manager } -func genListModulesCmd(name, version string, modulesFactory ModulesManagerFactory) *cobra.Command { +func genListModulesCmd(name, version string, modulesFactory modulesManagerFactory) *cobra.Command { return &cobra.Command{ Use: "list", Short: "List modules", @@ -81,7 +82,7 @@ func genListModulesCmd(name, version string, modulesFactory ModulesManagerFactor } } -func genEnableModulesCmd(name, version string, modulesFactory ModulesManagerFactory) *cobra.Command { +func genEnableModulesCmd(name, version string, modulesFactory modulesManagerFactory) *cobra.Command { return &cobra.Command{ Use: "enable MODULE...", Short: "Enable one or more given modules", @@ -110,7 +111,7 @@ func genEnableModulesCmd(name, version string, modulesFactory ModulesManagerFact } } -func genDisableModulesCmd(name, version string, modulesFactory ModulesManagerFactory) *cobra.Command { +func genDisableModulesCmd(name, version string, modulesFactory modulesManagerFactory) *cobra.Command { return &cobra.Command{ Use: "disable MODULE...", Short: "Disable one or more given modules", diff --git a/libbeat/cmd/run.go b/libbeat/cmd/run.go index d68cd19fa3e..b68d08e3997 100644 --- a/libbeat/cmd/run.go +++ b/libbeat/cmd/run.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/pflag" "github.com/elastic/beats/libbeat/beat" + "github.com/elastic/beats/libbeat/cmd/instance" ) func genRunCmd(name, version string, beatCreator beat.Creator, runFlags *pflag.FlagSet) *cobra.Command { @@ -15,7 +16,7 @@ func genRunCmd(name, version string, beatCreator beat.Creator, runFlags *pflag.F Use: "run", Short: "Run " + name, Run: func(cmd *cobra.Command, args []string) { - err := beat.Run(name, version, beatCreator) + err := instance.Run(name, version, beatCreator) if err != nil { os.Exit(1) } diff --git a/libbeat/cmd/setup.go b/libbeat/cmd/setup.go index dafbc7385b0..ee13cdba91c 100644 --- a/libbeat/cmd/setup.go +++ b/libbeat/cmd/setup.go @@ -7,6 +7,7 @@ import ( "github.com/spf13/cobra" "github.com/elastic/beats/libbeat/beat" + "github.com/elastic/beats/libbeat/cmd/instance" ) func genSetupCmd(name, version string, beatCreator beat.Creator) *cobra.Command { @@ -20,7 +21,7 @@ func genSetupCmd(name, version string, beatCreator beat.Creator) *cobra.Command * ML jobs (where available). `, Run: func(cmd *cobra.Command, args []string) { - beat, err := beat.New(name, version) + beat, err := instance.NewBeat(name, version) if err != nil { fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err) os.Exit(1) diff --git a/libbeat/cmd/test/config.go b/libbeat/cmd/test/config.go index a6285991abf..c8cbc9cdb55 100644 --- a/libbeat/cmd/test/config.go +++ b/libbeat/cmd/test/config.go @@ -7,6 +7,7 @@ import ( "github.com/spf13/cobra" "github.com/elastic/beats/libbeat/beat" + "github.com/elastic/beats/libbeat/cmd/instance" ) func GenTestConfigCmd(name, version string, beatCreator beat.Creator) *cobra.Command { @@ -14,7 +15,7 @@ func GenTestConfigCmd(name, version string, beatCreator beat.Creator) *cobra.Com Use: "config", Short: "Test configuration settings", Run: func(cmd *cobra.Command, args []string) { - b, err := beat.New(name, version) + b, err := instance.NewBeat(name, version) if err != nil { fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err) os.Exit(1) diff --git a/libbeat/cmd/test/output.go b/libbeat/cmd/test/output.go index b39f0d41113..c3b059e1caf 100644 --- a/libbeat/cmd/test/output.go +++ b/libbeat/cmd/test/output.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" - "github.com/elastic/beats/libbeat/beat" + "github.com/elastic/beats/libbeat/cmd/instance" "github.com/elastic/beats/libbeat/outputs" "github.com/elastic/beats/libbeat/testing" ) @@ -16,7 +16,7 @@ func GenTestOutputCmd(name, beatVersion string) *cobra.Command { Use: "output", Short: "Test output works with current settings", Run: func(cmd *cobra.Command, args []string) { - b, err := beat.New(name, beatVersion) + b, err := instance.NewBeat(name, beatVersion) if err != nil { fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err) os.Exit(1) diff --git a/libbeat/cmd/version.go b/libbeat/cmd/version.go index dcb7b0c2278..b34f37cad36 100644 --- a/libbeat/cmd/version.go +++ b/libbeat/cmd/version.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/cobra" - "github.com/elastic/beats/libbeat/beat" + "github.com/elastic/beats/libbeat/cmd/instance" "github.com/elastic/beats/libbeat/version" ) @@ -16,7 +16,7 @@ func genVersionCmd(name, beatVersion string) *cobra.Command { Use: "version", Short: "Show current version info", Run: func(cmd *cobra.Command, args []string) { - beat, err := beat.New(name, beatVersion) + beat, err := instance.NewBeat(name, beatVersion) if err != nil { fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err) os.Exit(1) diff --git a/metricbeat/cmd/modules.go b/metricbeat/cmd/modules.go index f7a467e5154..c2baf2c2883 100644 --- a/metricbeat/cmd/modules.go +++ b/metricbeat/cmd/modules.go @@ -11,10 +11,7 @@ import ( ) func buildModulesManager(beat *beat.Beat) (cmd.ModulesManager, error) { - config, err := beat.BeatConfig() - if err != nil { - return nil, errors.Wrap(err, "initialization error") - } + config := beat.BeatConfig glob, err := config.String("config.modules.path", -1) if err != nil { diff --git a/metricbeat/cmd/test/modules.go b/metricbeat/cmd/test/modules.go index f7375752fe6..c977be61fb3 100644 --- a/metricbeat/cmd/test/modules.go +++ b/metricbeat/cmd/test/modules.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" - "github.com/elastic/beats/libbeat/beat" + "github.com/elastic/beats/libbeat/cmd/instance" "github.com/elastic/beats/libbeat/testing" "github.com/elastic/beats/metricbeat/beater" ) @@ -25,7 +25,7 @@ func GenTestModulesCmd(name, beatVersion string) *cobra.Command { filter_metricset = args[1] } - b, err := beat.New(name, beatVersion) + b, err := instance.NewBeat(name, beatVersion) if err != nil { fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err) os.Exit(1) @@ -37,13 +37,7 @@ func GenTestModulesCmd(name, beatVersion string) *cobra.Command { os.Exit(1) } - config, err := b.BeatConfig() - if err != nil { - fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err) - os.Exit(1) - } - - mb, err := beater.New(b, config) + mb, err := beater.New(&b.Beat, b.Beat.BeatConfig) if err != nil { fmt.Fprintf(os.Stderr, "Error initializing metricbeat: %s\n", err) os.Exit(1) diff --git a/packetbeat/beater/devices.go b/packetbeat/beater/devices.go index 59c280d1e84..cbad0804122 100644 --- a/packetbeat/beater/devices.go +++ b/packetbeat/beater/devices.go @@ -6,14 +6,14 @@ import ( "runtime" "github.com/elastic/beats/libbeat/beat" - + "github.com/elastic/beats/libbeat/cmd/instance" "github.com/elastic/beats/packetbeat/sniffer" ) func init() { printDevices := flag.Bool("devices", false, "Print the list of devices and exit") - beat.AddFlagsCallback(func(_ *beat.Beat) error { + instance.AddFlagsCallback(func(_ *beat.Beat) error { if *printDevices == false { return nil } diff --git a/winlogbeat/beater/winlogbeat.go b/winlogbeat/beater/winlogbeat.go index 32c9ba95e08..cd101bff71c 100644 --- a/winlogbeat/beater/winlogbeat.go +++ b/winlogbeat/beater/winlogbeat.go @@ -35,12 +35,12 @@ var startTime = time.Now().UTC() // Winlogbeat is used to conform to the beat interface type Winlogbeat struct { - beat *beat.Beat // Common beat information. - config *config.Settings // Configuration settings. - eventLogs []*eventLogger // List of all event logs being monitored. - done chan struct{} // Channel to initiate shutdown of main event loop. - pipeline pub.Pipeline // Interface to publish event. - checkpoint *checkpoint.Checkpoint // Persists event log state to disk. + beat *beat.Beat // Common beat information. + config config.WinlogbeatConfig // Configuration settings. + eventLogs []*eventLogger // List of all event logs being monitored. + done chan struct{} // Channel to initiate shutdown of main event loop. + pipeline pub.Pipeline // Interface to publish event. + checkpoint *checkpoint.Checkpoint // Persists event log state to disk. } // New returns a new Winlogbeat. @@ -49,21 +49,19 @@ func New(b *beat.Beat, _ *common.Config) (beat.Beater, error) { // XXX: winlogbeat validates top-level config -> ignore beater config and // parse complete top-level config config := config.DefaultSettings - rawConfig := b.RawConfig - err := rawConfig.Unpack(&config) + err := b.BeatConfig.Unpack(&config) if err != nil { return nil, fmt.Errorf("Error reading configuration file. %v", err) } // resolve registry file path - config.Winlogbeat.RegistryFile = paths.Resolve( - paths.Data, config.Winlogbeat.RegistryFile) + config.RegistryFile = paths.Resolve(paths.Data, config.RegistryFile) logp.Info("State will be read from and persisted to %s", - config.Winlogbeat.RegistryFile) + config.RegistryFile) eb := &Winlogbeat{ beat: b, - config: &config, + config: config, done: make(chan struct{}), } @@ -75,7 +73,7 @@ func New(b *beat.Beat, _ *common.Config) (beat.Beater, error) { } func (eb *Winlogbeat) init(b *beat.Beat) error { - config := &eb.config.Winlogbeat + config := &eb.config // Create the event logs. This will validate the event log specific // configuration. @@ -101,7 +99,7 @@ func (eb *Winlogbeat) init(b *beat.Beat) error { // Setup uses the loaded config and creates necessary markers and environment // settings to allow the beat to be used. func (eb *Winlogbeat) setup(b *beat.Beat) error { - config := &eb.config.Winlogbeat + config := &eb.config var err error eb.checkpoint, err = checkpoint.NewCheckpoint(config.RegistryFile, 10, 5*time.Second) diff --git a/winlogbeat/config/config.go b/winlogbeat/config/config.go index 42cf47528da..4b33b4ea8d0 100644 --- a/winlogbeat/config/config.go +++ b/winlogbeat/config/config.go @@ -23,26 +23,12 @@ type Validator interface { Validate() error } -// Settings is the root of the Winlogbeat configuration data hierarchy. -type Settings struct { - Winlogbeat WinlogbeatConfig `config:"winlogbeat"` - Raw map[string]interface{} `config:",inline"` -} - var ( - DefaultSettings = Settings{ - Winlogbeat: WinlogbeatConfig{ - RegistryFile: DefaultRegistryFile, - }, + DefaultSettings = WinlogbeatConfig{ + RegistryFile: DefaultRegistryFile, } ) -// Validate validates the Settings data and returns an error describing -// all problems or nil if there are none. -func (s Settings) Validate() error { - return s.Winlogbeat.Validate() -} - // WinlogbeatConfig contains all of Winlogbeat configuration data. type WinlogbeatConfig struct { EventLogs []*common.Config `config:"event_logs"` diff --git a/winlogbeat/eventlog/eventlogging.go b/winlogbeat/eventlog/eventlogging.go index f0848ff52a1..4401d9666f2 100644 --- a/winlogbeat/eventlog/eventlogging.go +++ b/winlogbeat/eventlog/eventlogging.go @@ -26,10 +26,9 @@ var eventLoggingConfigKeys = append(commonConfigKeys, "ignore_older", type eventLoggingConfig struct { ConfigCommon `config:",inline"` - IgnoreOlder time.Duration `config:"ignore_older"` - ReadBufferSize uint `config:"read_buffer_size" validate:"min=1"` - FormatBufferSize uint `config:"format_buffer_size" validate:"min=1"` - Raw map[string]interface{} `config:",inline"` + IgnoreOlder time.Duration `config:"ignore_older"` + ReadBufferSize uint `config:"read_buffer_size" validate:"min=1"` + FormatBufferSize uint `config:"format_buffer_size" validate:"min=1"` } // Validate validates the eventLoggingConfig data and returns an error diff --git a/winlogbeat/eventlog/wineventlog.go b/winlogbeat/eventlog/wineventlog.go index 2086294479b..1f7576a8a5b 100644 --- a/winlogbeat/eventlog/wineventlog.go +++ b/winlogbeat/eventlog/wineventlog.go @@ -32,11 +32,10 @@ var winEventLogConfigKeys = append(commonConfigKeys, "batch_read_size", type winEventLogConfig struct { ConfigCommon `config:",inline"` - BatchReadSize int `config:"batch_read_size"` // Maximum number of events that Read will return. - IncludeXML bool `config:"include_xml"` - Forwarded *bool `config:"forwarded"` - SimpleQuery query `config:",inline"` - Raw map[string]interface{} `config:",inline"` + BatchReadSize int `config:"batch_read_size"` // Maximum number of events that Read will return. + IncludeXML bool `config:"include_xml"` + Forwarded *bool `config:"forwarded"` + SimpleQuery query `config:",inline"` } // defaultWinEventLogConfig is the default configuration for new wineventlog readers. From 1f242a9afff3a1d4a126e39a13e069b4a9147187 Mon Sep 17 00:00:00 2001 From: urso Date: Tue, 1 Aug 2017 21:14:54 +0200 Subject: [PATCH 046/139] Add devices command to packetbeat --- packetbeat/cmd/devices.go | 41 +++++++++++++++++++++++++++++++++++++++ packetbeat/cmd/root.go | 1 + 2 files changed, 42 insertions(+) create mode 100644 packetbeat/cmd/devices.go diff --git a/packetbeat/cmd/devices.go b/packetbeat/cmd/devices.go new file mode 100644 index 00000000000..c4cbf4feaf0 --- /dev/null +++ b/packetbeat/cmd/devices.go @@ -0,0 +1,41 @@ +package cmd + +import ( + "fmt" + "log" + "runtime" + + "github.com/spf13/cobra" + + "github.com/elastic/beats/packetbeat/sniffer" +) + +func genDevicesCommand() *cobra.Command { + return &cobra.Command{ + Use: "devices", + Short: "List available devices", + Run: func(cmd *cobra.Command, args []string) { + printDevicesList() + }, + } +} + +func printDevicesList() { + lst, err := sniffer.ListDeviceNames(true, true) + if err != nil { + log.Fatalf("Error getting devices list: %v\n", err) + } + + if len(lst) == 0 { + fmt.Printf("No devices found.") + if runtime.GOOS != "windows" { + fmt.Println(" You might need sudo?") + } else { + fmt.Println("") + } + } + + for i, d := range lst { + fmt.Printf("%d: %s\n", i, d) + } +} diff --git a/packetbeat/cmd/root.go b/packetbeat/cmd/root.go index 42403d10356..3b6b0c71bf3 100644 --- a/packetbeat/cmd/root.go +++ b/packetbeat/cmd/root.go @@ -30,4 +30,5 @@ func init() { runFlags.AddGoFlag(flag.CommandLine.Lookup("devices")) RootCmd = cmd.GenRootCmdWithRunFlags(Name, "", beater.New, runFlags) + RootCmd.AddCommand(genDevicesCommand()) } From 1854f10f3e916b26b0731119f06057842e2aa2a7 Mon Sep 17 00:00:00 2001 From: urso Date: Tue, 1 Aug 2017 21:15:29 +0200 Subject: [PATCH 047/139] removes devices flag from packetbeat --- packetbeat/beater/devices.go | 39 ------------------------------------ 1 file changed, 39 deletions(-) delete mode 100644 packetbeat/beater/devices.go diff --git a/packetbeat/beater/devices.go b/packetbeat/beater/devices.go deleted file mode 100644 index cbad0804122..00000000000 --- a/packetbeat/beater/devices.go +++ /dev/null @@ -1,39 +0,0 @@ -package beater - -import ( - "flag" - "fmt" - "runtime" - - "github.com/elastic/beats/libbeat/beat" - "github.com/elastic/beats/libbeat/cmd/instance" - "github.com/elastic/beats/packetbeat/sniffer" -) - -func init() { - printDevices := flag.Bool("devices", false, "Print the list of devices and exit") - - instance.AddFlagsCallback(func(_ *beat.Beat) error { - if *printDevices == false { - return nil - } - - devs, err := sniffer.ListDeviceNames(true, true) - if err != nil { - return fmt.Errorf("Error getting devices list: %v\n", err) - } - if len(devs) == 0 { - fmt.Printf("No devices found.") - if runtime.GOOS != "windows" { - fmt.Printf(" You might need sudo?\n") - } else { - fmt.Printf("\n") - } - } - - for i, dev := range devs { - fmt.Printf("%d: %s\n", i, dev) - } - return beat.GracefulExit - }) -} From 353c15304a1bcfbc8d914a344097b3a023860e14 Mon Sep 17 00:00:00 2001 From: urso Date: Tue, 1 Aug 2017 21:17:59 +0200 Subject: [PATCH 048/139] Remove FlagHandler support --- libbeat/cmd/instance/beat.go | 8 +++---- libbeat/cmd/instance/flags.go | 40 ----------------------------------- 2 files changed, 3 insertions(+), 45 deletions(-) delete mode 100644 libbeat/cmd/instance/flags.go diff --git a/libbeat/cmd/instance/beat.go b/libbeat/cmd/instance/beat.go index ac2eda7bb36..af1cd695bfb 100644 --- a/libbeat/cmd/instance/beat.go +++ b/libbeat/cmd/instance/beat.go @@ -46,6 +46,7 @@ import ( _ "github.com/elastic/beats/libbeat/monitoring/report/elasticsearch" ) +// Beat provides the runnable and configurable instance of a beat. type Beat struct { beat.Beat @@ -97,7 +98,7 @@ func Run(name, version string, bt beat.Creator) error { }()) } -// New creates a new beat instance +// NewBeat creates a new beat instance func NewBeat(name, v string) (*Beat, error) { if v == "" { v = version.GetDefaultVersion() @@ -350,11 +351,8 @@ func (b *Beat) handleFlags() error { if err := logp.HandleFlags(b.Info.Beat); err != nil { return err } - if err := cfgfile.HandleFlags(); err != nil { - return err - } - return handleFlags(&b.Beat) + return cfgfile.HandleFlags() } // config reads the configuration file from disk, parses the common options diff --git a/libbeat/cmd/instance/flags.go b/libbeat/cmd/instance/flags.go deleted file mode 100644 index 5057f642ebb..00000000000 --- a/libbeat/cmd/instance/flags.go +++ /dev/null @@ -1,40 +0,0 @@ -package instance - -import "github.com/elastic/beats/libbeat/beat" - -// XXX: With introduction of cmd package, the FlagsHandler should be deprecated. - -// FlagsHandler is an interface that can optionally be implemented by a Beat -// if it needs to process command line flags on startup. If implemented, the -// HandleFlags method will be invoked after parsing the command line flags -// and before any of the Beater interface methods are invoked. There will be -// no callback when '-help' or '-version' are specified. -type FlagsHandler interface { - HandleFlags(*beat.Beat) error // Handle any custom command line arguments. -} - -type FlagsHandlerCallback func(*beat.Beat) error - -var handlers []FlagsHandler - -func AddFlagsHandler(h FlagsHandler) { - handlers = append(handlers, h) -} - -func AddFlagsCallback(cb func(*beat.Beat) error) { - AddFlagsHandler(FlagsHandlerCallback(cb)) -} - -func handleFlags(b *beat.Beat) error { - for _, h := range handlers { - err := h.HandleFlags(b) - if err != nil { - return err - } - } - return nil -} - -func (cb FlagsHandlerCallback) HandleFlags(b *beat.Beat) error { - return cb(b) -} From 5cf200935b619c1432a04c48df4f3aba7047f23e Mon Sep 17 00:00:00 2001 From: urso Date: Wed, 2 Aug 2017 22:38:45 +0200 Subject: [PATCH 049/139] Move definitions from libbeat/publisher/beat to libbeat/beat - move beat.Client, beat.Event, beat.Pipeline to libbeat/beat - move some shared config objects from beat.BeatConfig to private cmd/instance package where easily possible (fix import cycles) --- filebeat/beater/acker.go | 3 +- filebeat/beater/filebeat.go | 3 +- filebeat/channel/factory.go | 2 +- filebeat/channel/outlet.go | 2 +- filebeat/harvester/reader/json.go | 2 +- filebeat/prospector/log/harvester.go | 15 +++++----- filebeat/prospector/redis/harvester.go | 7 +++-- filebeat/prospector/udp/harvester.go | 7 +++-- filebeat/util/data.go | 5 ++-- heartbeat/beater/manager.go | 2 +- heartbeat/monitors/monitors.go | 2 +- heartbeat/monitors/util.go | 2 +- libbeat/beat/beat.go | 21 ++----------- libbeat/{publisher => }/beat/event.go | 0 libbeat/{publisher => }/beat/pipeline.go | 0 libbeat/cmd/instance/beat.go | 30 +++++++++++++++++-- libbeat/common/fmtstr/formatevents.go | 2 +- libbeat/common/fmtstr/formatevents_test.go | 2 +- libbeat/common/jsontransform/jsonhelper.go | 2 +- libbeat/mock/mockbeat.go | 5 ++-- .../report/elasticsearch/elasticsearch.go | 2 +- libbeat/outputs/codec/codec.go | 2 +- libbeat/outputs/codec/format/format.go | 2 +- libbeat/outputs/codec/format/format_test.go | 2 +- libbeat/outputs/codec/json/event.go | 2 +- libbeat/outputs/codec/json/json.go | 2 +- libbeat/outputs/codec/json/json_test.go | 2 +- libbeat/outputs/console/console_test.go | 2 +- libbeat/outputs/elasticsearch/client.go | 2 +- .../elasticsearch/client_integration_test.go | 2 +- libbeat/outputs/elasticsearch/client_test.go | 2 +- libbeat/outputs/elasticsearch/enc.go | 2 +- .../outputs/kafka/kafka_integration_test.go | 2 +- libbeat/outputs/kafka/partition_test.go | 2 +- libbeat/outputs/logstash/client_test.go | 2 +- libbeat/outputs/logstash/enc.go | 2 +- .../logstash/logstash_integration_test.go | 2 +- libbeat/outputs/logstash/logstash_test.go | 2 +- libbeat/outputs/outest/batch.go | 2 +- libbeat/outputs/outil/select.go | 2 +- libbeat/outputs/outil/select_test.go | 2 +- libbeat/outputs/redis/client.go | 2 +- .../outputs/redis/redis_integration_test.go | 2 +- .../processors/actions/decode_json_fields.go | 2 +- .../actions/decode_json_fields_test.go | 2 +- libbeat/processors/actions/drop_event.go | 2 +- libbeat/processors/actions/drop_fields.go | 2 +- libbeat/processors/actions/extract_field.go | 2 +- .../processors/actions/extract_field_test.go | 2 +- libbeat/processors/actions/include_fields.go | 2 +- .../add_cloud_metadata/add_cloud_metadata.go | 2 +- .../provider_alibaba_cloud_test.go | 2 +- .../provider_aws_ec2_test.go | 2 +- .../provider_digital_ocean_test.go | 2 +- .../provider_google_gce_test.go | 2 +- .../provider_tencent_cloud_test.go | 2 +- .../add_docker_metadata.go | 2 +- .../add_docker_metadata_test.go | 2 +- .../add_kubernetes_metadata/kubernetes.go | 2 +- libbeat/processors/add_locale/add_locale.go | 2 +- .../processors/add_locale/add_locale_test.go | 2 +- libbeat/processors/condition.go | 2 +- libbeat/processors/condition_test.go | 2 +- libbeat/processors/namespace_test.go | 2 +- libbeat/processors/processor.go | 2 +- libbeat/processors/processor_test.go | 3 +- libbeat/publisher/event.go | 2 +- libbeat/publisher/pipeline/acker.go | 2 +- libbeat/publisher/pipeline/client.go | 2 +- libbeat/publisher/pipeline/client_ack.go | 2 +- libbeat/publisher/pipeline/config.go | 2 +- libbeat/publisher/pipeline/pipeline.go | 5 ++-- libbeat/publisher/pipeline/pipeline_ack.go | 2 +- libbeat/publisher/pipeline/processor.go | 2 +- libbeat/publisher/queue/memqueue/produce.go | 2 +- libbeat/publisher/queue/queue.go | 2 +- libbeat/publisher/queue/queuetest/event.go | 2 +- libbeat/publisher/testing/testing.go | 2 +- libbeat/publisher/testing/testing_test.go | 2 +- metricbeat/mb/module/connector.go | 2 +- metricbeat/mb/module/event.go | 3 +- metricbeat/mb/module/example_test.go | 4 +-- metricbeat/mb/module/factory.go | 2 +- metricbeat/mb/module/publish.go | 2 +- metricbeat/mb/module/runner.go | 2 +- metricbeat/mb/module/runner_test.go | 2 +- metricbeat/mb/module/wrapper.go | 2 +- metricbeat/mb/testing/data_generator.go | 2 +- packetbeat/beater/packetbeat.go | 6 ++-- packetbeat/flows/flows.go | 2 +- packetbeat/flows/flows_test.go | 2 +- packetbeat/flows/util.go | 2 +- packetbeat/flows/worker.go | 2 +- packetbeat/protos/amqp/amqp.go | 3 +- packetbeat/protos/amqp/amqp_test.go | 3 +- packetbeat/protos/applayer/applayer.go | 2 +- packetbeat/protos/cassandra/pub.go | 3 +- packetbeat/protos/dns/dns.go | 2 +- packetbeat/protos/dns/dns_test.go | 3 +- packetbeat/protos/http/http.go | 2 +- packetbeat/protos/http/http_test.go | 2 +- packetbeat/protos/icmp/icmp.go | 2 +- packetbeat/protos/icmp/icmp_test.go | 2 +- packetbeat/protos/memcache/memcache.go | 2 +- packetbeat/protos/memcache/memcache_test.go | 2 +- packetbeat/protos/mongodb/mongodb.go | 2 +- packetbeat/protos/mongodb/mongodb_test.go | 2 +- packetbeat/protos/mysql/mysql.go | 2 +- packetbeat/protos/mysql/mysql_test.go | 2 +- packetbeat/protos/nfs/nfs.go | 2 +- packetbeat/protos/nfs/request_handler.go | 2 +- packetbeat/protos/pgsql/pgsql.go | 2 +- packetbeat/protos/pgsql/pgsql_test.go | 2 +- packetbeat/protos/protos.go | 2 +- packetbeat/protos/redis/redis.go | 2 +- packetbeat/protos/registry.go | 2 +- packetbeat/protos/thrift/thrift.go | 2 +- packetbeat/publish/publish.go | 2 +- packetbeat/publish/publish_test.go | 2 +- winlogbeat/beater/eventlogger.go | 3 +- winlogbeat/beater/winlogbeat.go | 7 ++--- winlogbeat/eventlog/eventlog.go | 3 +- 122 files changed, 179 insertions(+), 161 deletions(-) rename libbeat/{publisher => }/beat/event.go (100%) rename libbeat/{publisher => }/beat/pipeline.go (100%) diff --git a/filebeat/beater/acker.go b/filebeat/beater/acker.go index 3f08c0b816d..290ca0ec5e1 100644 --- a/filebeat/beater/acker.go +++ b/filebeat/beater/acker.go @@ -1,8 +1,9 @@ package beater import ( + "github.com/elastic/beats/libbeat/beat" + "github.com/elastic/beats/filebeat/util" - "github.com/elastic/beats/libbeat/publisher/beat" ) // eventAcker handles publisher pipeline ACKs and forwards diff --git a/filebeat/beater/filebeat.go b/filebeat/beater/filebeat.go index b0619722e4d..043f18b7f80 100644 --- a/filebeat/beater/filebeat.go +++ b/filebeat/beater/filebeat.go @@ -12,7 +12,6 @@ import ( "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" "github.com/elastic/beats/libbeat/outputs/elasticsearch" - pub "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/filebeat/channel" cfg "github.com/elastic/beats/filebeat/config" @@ -177,7 +176,7 @@ func (fb *Filebeat) Run(b *beat.Beat) error { // Make sure all events that were published in registrarChannel := newRegistrarLogger(registrar) - err = b.Publisher.SetACKHandler(pub.PipelineACKHandler{ + err = b.Publisher.SetACKHandler(beat.PipelineACKHandler{ ACKEvents: newEventACKer(registrarChannel).ackEvents, }) if err != nil { diff --git a/filebeat/channel/factory.go b/filebeat/channel/factory.go index 956019dc313..1093308bc21 100644 --- a/filebeat/channel/factory.go +++ b/filebeat/channel/factory.go @@ -1,9 +1,9 @@ package channel import ( + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" ) type OutletFactory struct { diff --git a/filebeat/channel/outlet.go b/filebeat/channel/outlet.go index 4d966bf7518..7794731793d 100644 --- a/filebeat/channel/outlet.go +++ b/filebeat/channel/outlet.go @@ -2,8 +2,8 @@ package channel import ( "github.com/elastic/beats/filebeat/util" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common/atomic" - "github.com/elastic/beats/libbeat/publisher/beat" ) type outlet struct { diff --git a/filebeat/harvester/reader/json.go b/filebeat/harvester/reader/json.go index 86588cbeb95..1ba816c6382 100644 --- a/filebeat/harvester/reader/json.go +++ b/filebeat/harvester/reader/json.go @@ -6,10 +6,10 @@ import ( "fmt" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/jsontransform" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) type JSON struct { diff --git a/filebeat/prospector/log/harvester.go b/filebeat/prospector/log/harvester.go index cbe6954857b..a163e3cd5b0 100644 --- a/filebeat/prospector/log/harvester.go +++ b/filebeat/prospector/log/harvester.go @@ -20,19 +20,20 @@ import ( "sync" "time" + "github.com/satori/go.uuid" + "golang.org/x/text/transform" + + "github.com/elastic/beats/libbeat/beat" + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/libbeat/monitoring" + "github.com/elastic/beats/filebeat/channel" "github.com/elastic/beats/filebeat/harvester" "github.com/elastic/beats/filebeat/harvester/encoding" "github.com/elastic/beats/filebeat/harvester/reader" "github.com/elastic/beats/filebeat/input/file" "github.com/elastic/beats/filebeat/util" - "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/publisher/beat" - - "github.com/satori/go.uuid" - "golang.org/x/text/transform" ) var ( diff --git a/filebeat/prospector/redis/harvester.go b/filebeat/prospector/redis/harvester.go index 039bceb9d04..aa9b471168f 100644 --- a/filebeat/prospector/redis/harvester.go +++ b/filebeat/prospector/redis/harvester.go @@ -8,11 +8,12 @@ import ( rd "github.com/garyburd/redigo/redis" "github.com/satori/go.uuid" - "github.com/elastic/beats/filebeat/harvester" - "github.com/elastic/beats/filebeat/util" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" + + "github.com/elastic/beats/filebeat/harvester" + "github.com/elastic/beats/filebeat/util" ) // Harvester contains all redis harvester data diff --git a/filebeat/prospector/udp/harvester.go b/filebeat/prospector/udp/harvester.go index c6ad4dcf4fe..7a928b23604 100644 --- a/filebeat/prospector/udp/harvester.go +++ b/filebeat/prospector/udp/harvester.go @@ -4,11 +4,12 @@ import ( "net" "time" - "github.com/elastic/beats/filebeat/harvester" - "github.com/elastic/beats/filebeat/util" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" + + "github.com/elastic/beats/filebeat/harvester" + "github.com/elastic/beats/filebeat/util" ) type Harvester struct { diff --git a/filebeat/util/data.go b/filebeat/util/data.go index 8c3a04222af..a47b4cb2db5 100644 --- a/filebeat/util/data.go +++ b/filebeat/util/data.go @@ -1,9 +1,10 @@ package util import ( - "github.com/elastic/beats/filebeat/input/file" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" + + "github.com/elastic/beats/filebeat/input/file" ) type Data struct { diff --git a/heartbeat/beater/manager.go b/heartbeat/beater/manager.go index 980c2333fa1..988cde98003 100644 --- a/heartbeat/beater/manager.go +++ b/heartbeat/beater/manager.go @@ -7,10 +7,10 @@ import ( "fmt" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/heartbeat/monitors" "github.com/elastic/beats/heartbeat/scheduler" diff --git a/heartbeat/monitors/monitors.go b/heartbeat/monitors/monitors.go index 3396472bae3..199786c71fb 100644 --- a/heartbeat/monitors/monitors.go +++ b/heartbeat/monitors/monitors.go @@ -5,8 +5,8 @@ import ( "sort" "strings" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" ) type Factory func(*common.Config) ([]Job, error) diff --git a/heartbeat/monitors/util.go b/heartbeat/monitors/util.go index a1e6ec9755a..503b59104b3 100644 --- a/heartbeat/monitors/util.go +++ b/heartbeat/monitors/util.go @@ -6,8 +6,8 @@ import ( "net" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/heartbeat/look" ) diff --git a/libbeat/beat/beat.go b/libbeat/beat/beat.go index f7ec9402da6..89c01f0d8b1 100644 --- a/libbeat/beat/beat.go +++ b/libbeat/beat/beat.go @@ -2,10 +2,6 @@ package beat import ( "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/paths" - "github.com/elastic/beats/libbeat/publisher/beat" - "github.com/elastic/beats/libbeat/publisher/pipeline" ) // Creator initializes and configures a new Beater instance used to execute @@ -37,32 +33,21 @@ type Beater interface { // events. type Beat struct { Info common.BeatInfo // beat metadata. - Publisher beat.Pipeline // Publisher pipeline + Publisher Pipeline // Publisher pipeline SetupMLCallback SetupMLCallback // setup callback for ML job configs InSetupCmd bool // this is set to true when the `setup` command is called // XXX: remove Config from public interface - Config BeatConfig // Common Beat configuration data. + Config *BeatConfig // Common Beat configuration data. BeatConfig *common.Config // The beats it's own configuration section } // BeatConfig struct contains the basic configuration of every beat type BeatConfig struct { - // beat top-level settings - Name string `config:"name"` - MaxProcs int `config:"max_procs"` - - // beat internal components configurations - HTTP *common.Config `config:"http"` - Path paths.Path `config:"path"` - Logging logp.Logging `config:"logging"` - // output/publishing related configurations - Pipeline pipeline.Config `config:",inline"` - Monitoring *common.Config `config:"xpack.monitoring"` - Output common.ConfigNamespace `config:"output"` + Output common.ConfigNamespace `config:"output"` // 'setup' configurations Dashboards *common.Config `config:"setup.dashboards"` diff --git a/libbeat/publisher/beat/event.go b/libbeat/beat/event.go similarity index 100% rename from libbeat/publisher/beat/event.go rename to libbeat/beat/event.go diff --git a/libbeat/publisher/beat/pipeline.go b/libbeat/beat/pipeline.go similarity index 100% rename from libbeat/publisher/beat/pipeline.go rename to libbeat/beat/pipeline.go diff --git a/libbeat/cmd/instance/beat.go b/libbeat/cmd/instance/beat.go index af1cd695bfb..aea4a599dcf 100644 --- a/libbeat/cmd/instance/beat.go +++ b/libbeat/cmd/instance/beat.go @@ -50,9 +50,29 @@ import ( type Beat struct { beat.Beat + Config beatConfig RawConfig *common.Config // Raw config that can be unpacked to get Beat specific config data. } +type beatConfig struct { + beat.BeatConfig `config:",inline"` + + // instance internal configs + + // beat top-level settings + Name string `config:"name"` + MaxProcs int `config:"max_procs"` + + // beat internal components configurations + HTTP *common.Config `config:"http"` + Path paths.Path `config:"path"` + Logging logp.Logging `config:"logging"` + + // output/publishing related configurations + Pipeline pipeline.Config `config:",inline"` + Monitoring *common.Config `config:"xpack.monitoring"` +} + var ( printVersion bool setup bool @@ -283,12 +303,14 @@ func (b *Beat) Setup(bt beat.Creator, template, dashboards, machineLearning bool } if template { - if b.Config.Output.Name() != "elasticsearch" { + outCfg := b.Config.Output + + if outCfg.Name() != "elasticsearch" { return fmt.Errorf("Template loading requested but the Elasticsearch output is not configured/enabled") } - esConfig := b.Config.Output.Config() - if b.Config.Template == nil || (b.Config.Template != nil && b.Config.Template.Enabled()) { + esConfig := outCfg.Config() + if tmplCfg := b.Config.Template; tmplCfg == nil || tmplCfg.Enabled() { loadCallback, err := b.templateLoadingCallback() if err != nil { return err @@ -372,6 +394,8 @@ func (b *Beat) configure() error { return fmt.Errorf("error unpacking config data: %v", err) } + b.Beat.Config = &b.Config.BeatConfig + err = cfgwarn.CheckRemoved5xSettings(cfg, "queue_size", "bulk_queue_size") if err != nil { return err diff --git a/libbeat/common/fmtstr/formatevents.go b/libbeat/common/fmtstr/formatevents.go index d88d8bf4c61..724d66e3f42 100644 --- a/libbeat/common/fmtstr/formatevents.go +++ b/libbeat/common/fmtstr/formatevents.go @@ -10,10 +10,10 @@ import ( "sync" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/dtfmt" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) // EventFormatString implements format string support on events diff --git a/libbeat/common/fmtstr/formatevents_test.go b/libbeat/common/fmtstr/formatevents_test.go index a45b80dd176..3d2cdeb4628 100644 --- a/libbeat/common/fmtstr/formatevents_test.go +++ b/libbeat/common/fmtstr/formatevents_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" ) func TestEventFormatString(t *testing.T) { diff --git a/libbeat/common/jsontransform/jsonhelper.go b/libbeat/common/jsontransform/jsonhelper.go index e9fe652bc7c..58f7df65826 100644 --- a/libbeat/common/jsontransform/jsonhelper.go +++ b/libbeat/common/jsontransform/jsonhelper.go @@ -4,9 +4,9 @@ import ( "fmt" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) // WriteJSONKeys writes the json keys to the given event based on the overwriteKeys option diff --git a/libbeat/mock/mockbeat.go b/libbeat/mock/mockbeat.go index dd1f2529590..93f5e3c50f1 100644 --- a/libbeat/mock/mockbeat.go +++ b/libbeat/mock/mockbeat.go @@ -6,7 +6,6 @@ import ( "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - pub "github.com/elastic/beats/libbeat/publisher/beat" ) ///*** Mock Beat Setup ***/// @@ -16,7 +15,7 @@ var Name = "mockbeat" type Mockbeat struct { done chan struct{} - client pub.Client + client beat.Client } // Creates beater @@ -37,7 +36,7 @@ func (mb *Mockbeat) Run(b *beat.Beat) error { } // Wait until mockbeat is done - mb.client.Publish(pub.Event{ + mb.client.Publish(beat.Event{ Timestamp: time.Now(), Fields: common.MapStr{ "type": "mock", diff --git a/libbeat/monitoring/report/elasticsearch/elasticsearch.go b/libbeat/monitoring/report/elasticsearch/elasticsearch.go index 729c9c1bd02..bf89d637c46 100644 --- a/libbeat/monitoring/report/elasticsearch/elasticsearch.go +++ b/libbeat/monitoring/report/elasticsearch/elasticsearch.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" @@ -16,7 +17,6 @@ import ( esout "github.com/elastic/beats/libbeat/outputs/elasticsearch" "github.com/elastic/beats/libbeat/outputs/outil" "github.com/elastic/beats/libbeat/outputs/transport" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/libbeat/publisher/pipeline" "github.com/elastic/beats/libbeat/publisher/queue" "github.com/elastic/beats/libbeat/publisher/queue/memqueue" diff --git a/libbeat/outputs/codec/codec.go b/libbeat/outputs/codec/codec.go index f9083444f29..9de8a684818 100644 --- a/libbeat/outputs/codec/codec.go +++ b/libbeat/outputs/codec/codec.go @@ -1,6 +1,6 @@ package codec -import "github.com/elastic/beats/libbeat/publisher/beat" +import "github.com/elastic/beats/libbeat/beat" type Codec interface { Encode(index string, event *beat.Event) ([]byte, error) diff --git a/libbeat/outputs/codec/format/format.go b/libbeat/outputs/codec/format/format.go index fc1ad7c179c..bf31d42f491 100644 --- a/libbeat/outputs/codec/format/format.go +++ b/libbeat/outputs/codec/format/format.go @@ -3,11 +3,11 @@ package format import ( "errors" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/fmtstr" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs/codec" - "github.com/elastic/beats/libbeat/publisher/beat" ) type Encoder struct { diff --git a/libbeat/outputs/codec/format/format_test.go b/libbeat/outputs/codec/format/format_test.go index 6159ee13a61..58a753d234f 100644 --- a/libbeat/outputs/codec/format/format_test.go +++ b/libbeat/outputs/codec/format/format_test.go @@ -3,9 +3,9 @@ package format import ( "testing" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/fmtstr" - "github.com/elastic/beats/libbeat/publisher/beat" ) func TestFormatStringWriter(t *testing.T) { diff --git a/libbeat/outputs/codec/json/event.go b/libbeat/outputs/codec/json/event.go index f3a4e82daa4..417022630c8 100644 --- a/libbeat/outputs/codec/json/event.go +++ b/libbeat/outputs/codec/json/event.go @@ -3,8 +3,8 @@ package json import ( "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" ) // Event describes the event structure for events diff --git a/libbeat/outputs/codec/json/json.go b/libbeat/outputs/codec/json/json.go index 3fec59e5caa..b1ed32d0505 100644 --- a/libbeat/outputs/codec/json/json.go +++ b/libbeat/outputs/codec/json/json.go @@ -7,10 +7,10 @@ import ( "github.com/urso/go-structform/gotype" "github.com/urso/go-structform/json" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs/codec" - "github.com/elastic/beats/libbeat/publisher/beat" ) type Encoder struct { diff --git a/libbeat/outputs/codec/json/json_test.go b/libbeat/outputs/codec/json/json_test.go index a20559ff84d..f8f1f97b656 100644 --- a/libbeat/outputs/codec/json/json_test.go +++ b/libbeat/outputs/codec/json/json_test.go @@ -3,8 +3,8 @@ package json import ( "testing" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" ) func TestJsonCodec(t *testing.T) { diff --git a/libbeat/outputs/console/console_test.go b/libbeat/outputs/console/console_test.go index 8816d3b1760..6ba0c17dbd7 100644 --- a/libbeat/outputs/console/console_test.go +++ b/libbeat/outputs/console/console_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/fmtstr" "github.com/elastic/beats/libbeat/outputs/codec" @@ -17,7 +18,6 @@ import ( "github.com/elastic/beats/libbeat/outputs/codec/json" "github.com/elastic/beats/libbeat/outputs/outest" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/beat" ) // capture stdout and return captured string diff --git a/libbeat/outputs/elasticsearch/client.go b/libbeat/outputs/elasticsearch/client.go index 990e7fcfea5..04ccca22bb5 100644 --- a/libbeat/outputs/elasticsearch/client.go +++ b/libbeat/outputs/elasticsearch/client.go @@ -11,12 +11,12 @@ import ( "net/url" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs" "github.com/elastic/beats/libbeat/outputs/outil" "github.com/elastic/beats/libbeat/outputs/transport" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/libbeat/testing" ) diff --git a/libbeat/outputs/elasticsearch/client_integration_test.go b/libbeat/outputs/elasticsearch/client_integration_test.go index a5e1823bd6a..783bf98953f 100644 --- a/libbeat/outputs/elasticsearch/client_integration_test.go +++ b/libbeat/outputs/elasticsearch/client_integration_test.go @@ -10,11 +10,11 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs" "github.com/elastic/beats/libbeat/outputs/outest" - "github.com/elastic/beats/libbeat/publisher/beat" ) func TestClientConnect(t *testing.T) { diff --git a/libbeat/outputs/elasticsearch/client_test.go b/libbeat/outputs/elasticsearch/client_test.go index cbef658c612..f20828353b1 100644 --- a/libbeat/outputs/elasticsearch/client_test.go +++ b/libbeat/outputs/elasticsearch/client_test.go @@ -12,13 +12,13 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/fmtstr" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs/outest" "github.com/elastic/beats/libbeat/outputs/outil" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/beat" ) func readStatusItem(in []byte) (int, string, error) { diff --git a/libbeat/outputs/elasticsearch/enc.go b/libbeat/outputs/elasticsearch/enc.go index 6bf59549652..a64510a94fe 100644 --- a/libbeat/outputs/elasticsearch/enc.go +++ b/libbeat/outputs/elasticsearch/enc.go @@ -10,9 +10,9 @@ import ( "github.com/urso/go-structform/gotype" "github.com/urso/go-structform/json" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/outputs/codec" - "github.com/elastic/beats/libbeat/publisher/beat" ) type bodyEncoder interface { diff --git a/libbeat/outputs/kafka/kafka_integration_test.go b/libbeat/outputs/kafka/kafka_integration_test.go index 1b6fc10c3d1..8af006c6f01 100644 --- a/libbeat/outputs/kafka/kafka_integration_test.go +++ b/libbeat/outputs/kafka/kafka_integration_test.go @@ -16,11 +16,11 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/fmtstr" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs/outest" - "github.com/elastic/beats/libbeat/publisher/beat" _ "github.com/elastic/beats/libbeat/outputs/codec/format" _ "github.com/elastic/beats/libbeat/outputs/codec/json" diff --git a/libbeat/outputs/kafka/partition_test.go b/libbeat/outputs/kafka/partition_test.go index 69fd109b750..cc25fecc3f8 100644 --- a/libbeat/outputs/kafka/partition_test.go +++ b/libbeat/outputs/kafka/partition_test.go @@ -11,9 +11,9 @@ import ( "github.com/Shopify/sarama" "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/beat" ) type partTestScenario func(*testing.T, bool, sarama.Partitioner) error diff --git a/libbeat/outputs/logstash/client_test.go b/libbeat/outputs/logstash/client_test.go index 4f70aeeb819..d08a95a10c2 100644 --- a/libbeat/outputs/logstash/client_test.go +++ b/libbeat/outputs/logstash/client_test.go @@ -9,11 +9,11 @@ import ( "github.com/elastic/go-lumber/server/v2" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/outputs/outest" "github.com/elastic/beats/libbeat/outputs/transport" "github.com/elastic/beats/libbeat/outputs/transport/transptest" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/stretchr/testify/assert" ) diff --git a/libbeat/outputs/logstash/enc.go b/libbeat/outputs/logstash/enc.go index 825c42c6973..28969ad184c 100644 --- a/libbeat/outputs/logstash/enc.go +++ b/libbeat/outputs/logstash/enc.go @@ -1,8 +1,8 @@ package logstash import ( + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/outputs/codec/json" - "github.com/elastic/beats/libbeat/publisher/beat" ) func makeLogstashEventEncoder(index string) func(interface{}) ([]byte, error) { diff --git a/libbeat/outputs/logstash/logstash_integration_test.go b/libbeat/outputs/logstash/logstash_integration_test.go index c23c607fe95..b310010a4ad 100644 --- a/libbeat/outputs/logstash/logstash_integration_test.go +++ b/libbeat/outputs/logstash/logstash_integration_test.go @@ -12,13 +12,13 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/fmtstr" "github.com/elastic/beats/libbeat/outputs" "github.com/elastic/beats/libbeat/outputs/elasticsearch" "github.com/elastic/beats/libbeat/outputs/outest" "github.com/elastic/beats/libbeat/outputs/outil" - "github.com/elastic/beats/libbeat/publisher/beat" ) const ( diff --git a/libbeat/outputs/logstash/logstash_test.go b/libbeat/outputs/logstash/logstash_test.go index ab914e724f9..4e76ecd49ae 100644 --- a/libbeat/outputs/logstash/logstash_test.go +++ b/libbeat/outputs/logstash/logstash_test.go @@ -11,11 +11,11 @@ import ( "github.com/elastic/go-lumber/server/v2" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/outputs" "github.com/elastic/beats/libbeat/outputs/outest" "github.com/elastic/beats/libbeat/outputs/transport/transptest" - "github.com/elastic/beats/libbeat/publisher/beat" ) const ( diff --git a/libbeat/outputs/outest/batch.go b/libbeat/outputs/outest/batch.go index 1c53823b05d..65f39b34a0f 100644 --- a/libbeat/outputs/outest/batch.go +++ b/libbeat/outputs/outest/batch.go @@ -1,8 +1,8 @@ package outest import ( + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/beat" ) type Batch struct { diff --git a/libbeat/outputs/outil/select.go b/libbeat/outputs/outil/select.go index f275024c2ef..3607211b725 100644 --- a/libbeat/outputs/outil/select.go +++ b/libbeat/outputs/outil/select.go @@ -3,10 +3,10 @@ package outil import ( "fmt" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/fmtstr" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" ) type Selector struct { diff --git a/libbeat/outputs/outil/select_test.go b/libbeat/outputs/outil/select_test.go index de8b5c557db..899997aa037 100644 --- a/libbeat/outputs/outil/select_test.go +++ b/libbeat/outputs/outil/select_test.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" ) type node map[string]interface{} diff --git a/libbeat/outputs/redis/client.go b/libbeat/outputs/redis/client.go index 8d34770cc31..e2d0504b841 100644 --- a/libbeat/outputs/redis/client.go +++ b/libbeat/outputs/redis/client.go @@ -8,6 +8,7 @@ import ( "github.com/garyburd/redigo/redis" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs" @@ -15,7 +16,6 @@ import ( "github.com/elastic/beats/libbeat/outputs/outil" "github.com/elastic/beats/libbeat/outputs/transport" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/beat" ) var ( diff --git a/libbeat/outputs/redis/redis_integration_test.go b/libbeat/outputs/redis/redis_integration_test.go index 05504bf2cdd..b4dd1a8fc1d 100644 --- a/libbeat/outputs/redis/redis_integration_test.go +++ b/libbeat/outputs/redis/redis_integration_test.go @@ -14,10 +14,10 @@ import ( "github.com/garyburd/redigo/redis" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/outputs" "github.com/elastic/beats/libbeat/outputs/outest" - "github.com/elastic/beats/libbeat/publisher/beat" _ "github.com/elastic/beats/libbeat/outputs/codec/format" _ "github.com/elastic/beats/libbeat/outputs/codec/json" diff --git a/libbeat/processors/actions/decode_json_fields.go b/libbeat/processors/actions/decode_json_fields.go index 9d2c4b18bd0..9b7ff709ea1 100644 --- a/libbeat/processors/actions/decode_json_fields.go +++ b/libbeat/processors/actions/decode_json_fields.go @@ -7,11 +7,11 @@ import ( "github.com/pkg/errors" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/jsontransform" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" ) type decodeJSONFields struct { diff --git a/libbeat/processors/actions/decode_json_fields_test.go b/libbeat/processors/actions/decode_json_fields_test.go index 695c7c4bbbd..58a41632858 100644 --- a/libbeat/processors/actions/decode_json_fields_test.go +++ b/libbeat/processors/actions/decode_json_fields_test.go @@ -5,9 +5,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) var fields = [1]string{"msg"} diff --git a/libbeat/processors/actions/drop_event.go b/libbeat/processors/actions/drop_event.go index 916118abb9f..c59cf7d7bc3 100644 --- a/libbeat/processors/actions/drop_event.go +++ b/libbeat/processors/actions/drop_event.go @@ -1,9 +1,9 @@ package actions import ( + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" ) type dropEvent struct{} diff --git a/libbeat/processors/actions/drop_fields.go b/libbeat/processors/actions/drop_fields.go index 9dc6ef3b13d..76ef347c794 100644 --- a/libbeat/processors/actions/drop_fields.go +++ b/libbeat/processors/actions/drop_fields.go @@ -4,9 +4,9 @@ import ( "fmt" "strings" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" ) type dropFields struct { diff --git a/libbeat/processors/actions/extract_field.go b/libbeat/processors/actions/extract_field.go index 1fb84e6672d..95af9ae49ae 100644 --- a/libbeat/processors/actions/extract_field.go +++ b/libbeat/processors/actions/extract_field.go @@ -4,9 +4,9 @@ import ( "fmt" "strings" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" ) type extract_field struct { diff --git a/libbeat/processors/actions/extract_field_test.go b/libbeat/processors/actions/extract_field_test.go index 5f1231f9c49..fcfe2e1eea3 100644 --- a/libbeat/processors/actions/extract_field_test.go +++ b/libbeat/processors/actions/extract_field_test.go @@ -5,9 +5,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) func TestCommonPaths(t *testing.T) { diff --git a/libbeat/processors/actions/include_fields.go b/libbeat/processors/actions/include_fields.go index 0f51f21fead..18a3703dc1c 100644 --- a/libbeat/processors/actions/include_fields.go +++ b/libbeat/processors/actions/include_fields.go @@ -6,9 +6,9 @@ import ( "github.com/pkg/errors" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" ) type includeFields struct { diff --git a/libbeat/processors/add_cloud_metadata/add_cloud_metadata.go b/libbeat/processors/add_cloud_metadata/add_cloud_metadata.go index 4d05e556cc0..5b1424fa029 100644 --- a/libbeat/processors/add_cloud_metadata/add_cloud_metadata.go +++ b/libbeat/processors/add_cloud_metadata/add_cloud_metadata.go @@ -12,10 +12,10 @@ import ( "github.com/pkg/errors" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" ) const ( diff --git a/libbeat/processors/add_cloud_metadata/provider_alibaba_cloud_test.go b/libbeat/processors/add_cloud_metadata/provider_alibaba_cloud_test.go index b83b09e3119..ef91331ef8c 100644 --- a/libbeat/processors/add_cloud_metadata/provider_alibaba_cloud_test.go +++ b/libbeat/processors/add_cloud_metadata/provider_alibaba_cloud_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) func initECSTestServer() *httptest.Server { diff --git a/libbeat/processors/add_cloud_metadata/provider_aws_ec2_test.go b/libbeat/processors/add_cloud_metadata/provider_aws_ec2_test.go index 6c9859e9b34..a9bdf60c5c0 100644 --- a/libbeat/processors/add_cloud_metadata/provider_aws_ec2_test.go +++ b/libbeat/processors/add_cloud_metadata/provider_aws_ec2_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) const ec2InstanceIdentityDocument = `{ diff --git a/libbeat/processors/add_cloud_metadata/provider_digital_ocean_test.go b/libbeat/processors/add_cloud_metadata/provider_digital_ocean_test.go index b7e908c04e3..6b4ecf8f2e3 100644 --- a/libbeat/processors/add_cloud_metadata/provider_digital_ocean_test.go +++ b/libbeat/processors/add_cloud_metadata/provider_digital_ocean_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) const digitalOceanMetadataV1 = `{ diff --git a/libbeat/processors/add_cloud_metadata/provider_google_gce_test.go b/libbeat/processors/add_cloud_metadata/provider_google_gce_test.go index 7dd16eaa549..c2f8e441bf5 100644 --- a/libbeat/processors/add_cloud_metadata/provider_google_gce_test.go +++ b/libbeat/processors/add_cloud_metadata/provider_google_gce_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) const gceMetadataV1 = `{ diff --git a/libbeat/processors/add_cloud_metadata/provider_tencent_cloud_test.go b/libbeat/processors/add_cloud_metadata/provider_tencent_cloud_test.go index 70cbabe55bf..88380c47d7c 100644 --- a/libbeat/processors/add_cloud_metadata/provider_tencent_cloud_test.go +++ b/libbeat/processors/add_cloud_metadata/provider_tencent_cloud_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) func initQCloudTestServer() *httptest.Server { diff --git a/libbeat/processors/add_docker_metadata/add_docker_metadata.go b/libbeat/processors/add_docker_metadata/add_docker_metadata.go index 1019a274022..a90046318e4 100644 --- a/libbeat/processors/add_docker_metadata/add_docker_metadata.go +++ b/libbeat/processors/add_docker_metadata/add_docker_metadata.go @@ -4,12 +4,12 @@ import ( "fmt" "strings" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/cfgwarn" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/processors" "github.com/elastic/beats/libbeat/processors/actions" - "github.com/elastic/beats/libbeat/publisher/beat" ) func init() { diff --git a/libbeat/processors/add_docker_metadata/add_docker_metadata_test.go b/libbeat/processors/add_docker_metadata/add_docker_metadata_test.go index 3aecdc656b0..dea7da0c738 100644 --- a/libbeat/processors/add_docker_metadata/add_docker_metadata_test.go +++ b/libbeat/processors/add_docker_metadata/add_docker_metadata_test.go @@ -5,8 +5,8 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" ) func TestInitialization(t *testing.T) { diff --git a/libbeat/processors/add_kubernetes_metadata/kubernetes.go b/libbeat/processors/add_kubernetes_metadata/kubernetes.go index e4c70cd8740..bcf9f932f8f 100644 --- a/libbeat/processors/add_kubernetes_metadata/kubernetes.go +++ b/libbeat/processors/add_kubernetes_metadata/kubernetes.go @@ -8,11 +8,11 @@ import ( "os" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/cfgwarn" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/ericchiang/k8s" "github.com/ghodss/yaml" diff --git a/libbeat/processors/add_locale/add_locale.go b/libbeat/processors/add_locale/add_locale.go index 4fde0bed05c..77d29d8075b 100644 --- a/libbeat/processors/add_locale/add_locale.go +++ b/libbeat/processors/add_locale/add_locale.go @@ -7,9 +7,9 @@ import ( "github.com/pkg/errors" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" ) type addLocale struct { diff --git a/libbeat/processors/add_locale/add_locale_test.go b/libbeat/processors/add_locale/add_locale_test.go index e367b1e0e70..b487ea4fcee 100644 --- a/libbeat/processors/add_locale/add_locale_test.go +++ b/libbeat/processors/add_locale/add_locale_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) func TestExportTimezone(t *testing.T) { diff --git a/libbeat/processors/condition.go b/libbeat/processors/condition.go index 4371dbfc093..1715e0989b0 100644 --- a/libbeat/processors/condition.go +++ b/libbeat/processors/condition.go @@ -7,10 +7,10 @@ import ( "strconv" "strings" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/match" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) type RangeValue struct { diff --git a/libbeat/processors/condition_test.go b/libbeat/processors/condition_test.go index 11e51fcb865..010bd63f5c3 100644 --- a/libbeat/processors/condition_test.go +++ b/libbeat/processors/condition_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) type countFilter struct { diff --git a/libbeat/processors/namespace_test.go b/libbeat/processors/namespace_test.go index 024c21cd9eb..8ae17c56389 100644 --- a/libbeat/processors/namespace_test.go +++ b/libbeat/processors/namespace_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" ) type testFilterRule struct { diff --git a/libbeat/processors/processor.go b/libbeat/processors/processor.go index ada75564e6f..b40bdaf7c28 100644 --- a/libbeat/processors/processor.go +++ b/libbeat/processors/processor.go @@ -4,9 +4,9 @@ import ( "fmt" "strings" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) type Processors struct { diff --git a/libbeat/processors/processor_test.go b/libbeat/processors/processor_test.go index f6b7e229f5d..cc498aa30de 100644 --- a/libbeat/processors/processor_test.go +++ b/libbeat/processors/processor_test.go @@ -6,12 +6,13 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/processors" + _ "github.com/elastic/beats/libbeat/processors/actions" _ "github.com/elastic/beats/libbeat/processors/add_cloud_metadata" - "github.com/elastic/beats/libbeat/publisher/beat" ) func GetProcessors(t *testing.T, yml []map[string]interface{}) *processors.Processors { diff --git a/libbeat/publisher/event.go b/libbeat/publisher/event.go index 408c1de2259..4f5dbedd23d 100644 --- a/libbeat/publisher/event.go +++ b/libbeat/publisher/event.go @@ -1,7 +1,7 @@ package publisher import ( - "github.com/elastic/beats/libbeat/publisher/beat" + "github.com/elastic/beats/libbeat/beat" ) // Batch is used to pass a batch of events to the outputs and asynchronously listening diff --git a/libbeat/publisher/pipeline/acker.go b/libbeat/publisher/pipeline/acker.go index c5542e13786..fc07a019976 100644 --- a/libbeat/publisher/pipeline/acker.go +++ b/libbeat/publisher/pipeline/acker.go @@ -4,8 +4,8 @@ import ( "sync" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common/atomic" - "github.com/elastic/beats/libbeat/publisher/beat" ) // acker is used to account for published and non-published events to be ACKed diff --git a/libbeat/publisher/pipeline/client.go b/libbeat/publisher/pipeline/client.go index d2582ee917e..9930ff30103 100644 --- a/libbeat/publisher/pipeline/client.go +++ b/libbeat/publisher/pipeline/client.go @@ -3,9 +3,9 @@ package pipeline import ( "sync" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common/atomic" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/libbeat/publisher/queue" ) diff --git a/libbeat/publisher/pipeline/client_ack.go b/libbeat/publisher/pipeline/client_ack.go index 0227a24095d..b882b3c2cca 100644 --- a/libbeat/publisher/pipeline/client_ack.go +++ b/libbeat/publisher/pipeline/client_ack.go @@ -3,8 +3,8 @@ package pipeline import ( "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common/atomic" - "github.com/elastic/beats/libbeat/publisher/beat" ) type clientACKer struct { diff --git a/libbeat/publisher/pipeline/config.go b/libbeat/publisher/pipeline/config.go index 6c74721e525..1c002cbb8eb 100644 --- a/libbeat/publisher/pipeline/config.go +++ b/libbeat/publisher/pipeline/config.go @@ -4,9 +4,9 @@ import ( "errors" "fmt" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" ) // Config object for loading a pipeline instance via Load. diff --git a/libbeat/publisher/pipeline/pipeline.go b/libbeat/publisher/pipeline/pipeline.go index aa62bb95601..1e80a0586bf 100644 --- a/libbeat/publisher/pipeline/pipeline.go +++ b/libbeat/publisher/pipeline/pipeline.go @@ -8,15 +8,14 @@ import ( "sync" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/atomic" - "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/libbeat/monitoring" "github.com/elastic/beats/libbeat/outputs" "github.com/elastic/beats/libbeat/processors" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/libbeat/publisher/queue" ) diff --git a/libbeat/publisher/pipeline/pipeline_ack.go b/libbeat/publisher/pipeline/pipeline_ack.go index eb4d1abc556..0d5a1d236b5 100644 --- a/libbeat/publisher/pipeline/pipeline_ack.go +++ b/libbeat/publisher/pipeline/pipeline_ack.go @@ -3,7 +3,7 @@ package pipeline import ( "errors" - "github.com/elastic/beats/libbeat/publisher/beat" + "github.com/elastic/beats/libbeat/beat" ) type ackBuilder interface { diff --git a/libbeat/publisher/pipeline/processor.go b/libbeat/publisher/pipeline/processor.go index c9fa921a07e..597af454011 100644 --- a/libbeat/publisher/pipeline/processor.go +++ b/libbeat/publisher/pipeline/processor.go @@ -5,11 +5,11 @@ import ( "strings" "sync" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs/codec/json" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" ) type program struct { diff --git a/libbeat/publisher/queue/memqueue/produce.go b/libbeat/publisher/queue/memqueue/produce.go index bede007c3f2..ccf6b568a36 100644 --- a/libbeat/publisher/queue/memqueue/produce.go +++ b/libbeat/publisher/queue/memqueue/produce.go @@ -1,9 +1,9 @@ package memqueue import ( + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common/atomic" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/libbeat/publisher/queue" ) diff --git a/libbeat/publisher/queue/queue.go b/libbeat/publisher/queue/queue.go index 6e19da004e5..a7da768ff31 100644 --- a/libbeat/publisher/queue/queue.go +++ b/libbeat/publisher/queue/queue.go @@ -3,9 +3,9 @@ package queue import ( "io" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/beat" ) // Factory for creating a queue used by a pipeline instance. diff --git a/libbeat/publisher/queue/queuetest/event.go b/libbeat/publisher/queue/queuetest/event.go index 2225927197d..4cffd6b39dd 100644 --- a/libbeat/publisher/queue/queuetest/event.go +++ b/libbeat/publisher/queue/queuetest/event.go @@ -3,9 +3,9 @@ package queuetest import ( "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/publisher" - "github.com/elastic/beats/libbeat/publisher/beat" ) func makeEvent(fields common.MapStr) publisher.Event { diff --git a/libbeat/publisher/testing/testing.go b/libbeat/publisher/testing/testing.go index 4228a8ca05f..3eb7c1ce54d 100644 --- a/libbeat/publisher/testing/testing.go +++ b/libbeat/publisher/testing/testing.go @@ -2,7 +2,7 @@ package testing // ChanClient implements Client interface, forwarding published events to some import ( - "github.com/elastic/beats/libbeat/publisher/beat" + "github.com/elastic/beats/libbeat/beat" ) type TestPublisher struct { diff --git a/libbeat/publisher/testing/testing_test.go b/libbeat/publisher/testing/testing_test.go index a460462f11e..e340715d572 100644 --- a/libbeat/publisher/testing/testing_test.go +++ b/libbeat/publisher/testing/testing_test.go @@ -5,8 +5,8 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" ) var cnt = 0 diff --git a/metricbeat/mb/module/connector.go b/metricbeat/mb/module/connector.go index f2bd16c39a6..d674763539f 100644 --- a/metricbeat/mb/module/connector.go +++ b/metricbeat/mb/module/connector.go @@ -1,9 +1,9 @@ package module import ( + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" ) // Connector configures ann establishes a beat.Client for publishing events diff --git a/metricbeat/mb/module/event.go b/metricbeat/mb/module/event.go index 174e9caf570..3b3c1bd0e93 100644 --- a/metricbeat/mb/module/event.go +++ b/metricbeat/mb/module/event.go @@ -3,9 +3,10 @@ package module import ( "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" + "github.com/elastic/beats/metricbeat/mb" ) diff --git a/metricbeat/mb/module/example_test.go b/metricbeat/mb/module/example_test.go index d205a75b2dc..c90687eff32 100644 --- a/metricbeat/mb/module/example_test.go +++ b/metricbeat/mb/module/example_test.go @@ -11,7 +11,7 @@ import ( "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/outputs/codec/json" - pub "github.com/elastic/beats/libbeat/publisher/beat" + "github.com/elastic/beats/metricbeat/mb" "github.com/elastic/beats/metricbeat/mb/module" ) @@ -129,7 +129,7 @@ func ExampleRunner() { runner.Stop() } -func encodeEvent(event pub.Event) (string, error) { +func encodeEvent(event beat.Event) (string, error) { output, err := json.New(false).Encode("noindex", &event) if err != nil { return "", nil diff --git a/metricbeat/mb/module/factory.go b/metricbeat/mb/module/factory.go index 01e541a3ab3..c64a1b5f7a4 100644 --- a/metricbeat/mb/module/factory.go +++ b/metricbeat/mb/module/factory.go @@ -5,10 +5,10 @@ import ( "github.com/joeshaw/multierror" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/cfgfile" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/cfgwarn" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/metricbeat/mb" ) diff --git a/metricbeat/mb/module/publish.go b/metricbeat/mb/module/publish.go index dabddb7255c..855998a3af8 100644 --- a/metricbeat/mb/module/publish.go +++ b/metricbeat/mb/module/publish.go @@ -3,7 +3,7 @@ package module import ( "sync" - "github.com/elastic/beats/libbeat/publisher/beat" + "github.com/elastic/beats/libbeat/beat" ) // PublishChannels publishes the events read from each channel to the given diff --git a/metricbeat/mb/module/runner.go b/metricbeat/mb/module/runner.go index 62e0e432702..90f6763b73a 100644 --- a/metricbeat/mb/module/runner.go +++ b/metricbeat/mb/module/runner.go @@ -3,7 +3,7 @@ package module import ( "sync" - "github.com/elastic/beats/libbeat/publisher/beat" + "github.com/elastic/beats/libbeat/beat" ) // Runner is a facade for a Wrapper that provides a simple interface diff --git a/metricbeat/mb/module/runner_test.go b/metricbeat/mb/module/runner_test.go index e7a6ca5b86b..ab8eeec85d2 100644 --- a/metricbeat/mb/module/runner_test.go +++ b/metricbeat/mb/module/runner_test.go @@ -5,8 +5,8 @@ package module_test import ( "testing" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" pubtest "github.com/elastic/beats/libbeat/publisher/testing" "github.com/elastic/beats/metricbeat/mb" "github.com/elastic/beats/metricbeat/mb/module" diff --git a/metricbeat/mb/module/wrapper.go b/metricbeat/mb/module/wrapper.go index d4fe9aa169f..a2399d2fcaa 100644 --- a/metricbeat/mb/module/wrapper.go +++ b/metricbeat/mb/module/wrapper.go @@ -6,10 +6,10 @@ import ( "sync" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/libbeat/testing" "github.com/elastic/beats/metricbeat/mb" diff --git a/metricbeat/mb/testing/data_generator.go b/metricbeat/mb/testing/data_generator.go index 729c521a109..1fe83e50977 100644 --- a/metricbeat/mb/testing/data_generator.go +++ b/metricbeat/mb/testing/data_generator.go @@ -8,9 +8,9 @@ import ( "testing" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/outputs/codec/json" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/metricbeat/mb" "github.com/elastic/beats/metricbeat/mb/module" ) diff --git a/packetbeat/beater/packetbeat.go b/packetbeat/beater/packetbeat.go index 42669f12c3f..e244a4a12c0 100644 --- a/packetbeat/beater/packetbeat.go +++ b/packetbeat/beater/packetbeat.go @@ -14,8 +14,8 @@ import ( "github.com/elastic/beats/libbeat/common/droppriv" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/processors" - pub "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/libbeat/service" + "github.com/elastic/beats/packetbeat/config" "github.com/elastic/beats/packetbeat/decoder" "github.com/elastic/beats/packetbeat/flows" @@ -35,7 +35,7 @@ type packetbeat struct { sniff *sniffer.SnifferSetup // publisher/pipeline - pipeline pub.Pipeline + pipeline beat.Pipeline transPub *publish.TransactionPublisher services []interface { @@ -220,7 +220,7 @@ func (pb *packetbeat) createWorker(dl layers.LinkType) (sniffer.Worker, error) { return nil, err } - client, err := pb.pipeline.ConnectWith(pub.ClientConfig{ + client, err := pb.pipeline.ConnectWith(beat.ClientConfig{ EventMetadata: config.Flows.EventMetadata, Processor: processors, }) diff --git a/packetbeat/flows/flows.go b/packetbeat/flows/flows.go index 60eb76d43ce..85d6ce1ef7b 100644 --- a/packetbeat/flows/flows.go +++ b/packetbeat/flows/flows.go @@ -3,8 +3,8 @@ package flows import ( "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/config" ) diff --git a/packetbeat/flows/flows_test.go b/packetbeat/flows/flows_test.go index ecfeade156c..1fc02c074ce 100644 --- a/packetbeat/flows/flows_test.go +++ b/packetbeat/flows/flows_test.go @@ -9,9 +9,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/config" ) diff --git a/packetbeat/flows/util.go b/packetbeat/flows/util.go index f29731374e8..b1616cacbba 100644 --- a/packetbeat/flows/util.go +++ b/packetbeat/flows/util.go @@ -4,8 +4,8 @@ import ( "sync" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) type worker struct { diff --git a/packetbeat/flows/worker.go b/packetbeat/flows/worker.go index 3f58dc87fbe..41b37f4154c 100644 --- a/packetbeat/flows/worker.go +++ b/packetbeat/flows/worker.go @@ -7,8 +7,8 @@ import ( "net" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" ) type flowsProcessor struct { diff --git a/packetbeat/protos/amqp/amqp.go b/packetbeat/protos/amqp/amqp.go index 9b9bfdd93ba..7a475931e96 100644 --- a/packetbeat/protos/amqp/amqp.go +++ b/packetbeat/protos/amqp/amqp.go @@ -5,10 +5,11 @@ import ( "strings" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/publisher/beat" + "github.com/elastic/beats/packetbeat/protos" "github.com/elastic/beats/packetbeat/protos/tcp" ) diff --git a/packetbeat/protos/amqp/amqp_test.go b/packetbeat/protos/amqp/amqp_test.go index d80f63edd3d..42a6511ddf7 100644 --- a/packetbeat/protos/amqp/amqp_test.go +++ b/packetbeat/protos/amqp/amqp_test.go @@ -7,9 +7,10 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" + "github.com/elastic/beats/packetbeat/protos" ) diff --git a/packetbeat/protos/applayer/applayer.go b/packetbeat/protos/applayer/applayer.go index 8869de6958e..f286f306e72 100644 --- a/packetbeat/protos/applayer/applayer.go +++ b/packetbeat/protos/applayer/applayer.go @@ -6,9 +6,9 @@ import ( "errors" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/streambuf" - "github.com/elastic/beats/libbeat/publisher/beat" ) // A Message its direction indicator diff --git a/packetbeat/protos/cassandra/pub.go b/packetbeat/protos/cassandra/pub.go index 1a6812ce072..4ad6af8de6a 100644 --- a/packetbeat/protos/cassandra/pub.go +++ b/packetbeat/protos/cassandra/pub.go @@ -3,8 +3,9 @@ package cassandra import ( "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" + "github.com/elastic/beats/packetbeat/protos" ) diff --git a/packetbeat/protos/dns/dns.go b/packetbeat/protos/dns/dns.go index c9b73f6804f..59e2c225cd8 100644 --- a/packetbeat/protos/dns/dns.go +++ b/packetbeat/protos/dns/dns.go @@ -15,10 +15,10 @@ import ( "strings" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/protos" diff --git a/packetbeat/protos/dns/dns_test.go b/packetbeat/protos/dns/dns_test.go index f3c474c83fe..436697e9854 100644 --- a/packetbeat/protos/dns/dns_test.go +++ b/packetbeat/protos/dns/dns_test.go @@ -14,9 +14,10 @@ import ( mkdns "github.com/miekg/dns" "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" + "github.com/elastic/beats/packetbeat/protos" ) diff --git a/packetbeat/protos/http/http.go b/packetbeat/protos/http/http.go index 5fe0893856c..3c47b2efa5f 100644 --- a/packetbeat/protos/http/http.go +++ b/packetbeat/protos/http/http.go @@ -7,10 +7,10 @@ import ( "strings" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/procs" "github.com/elastic/beats/packetbeat/protos" diff --git a/packetbeat/protos/http/http_test.go b/packetbeat/protos/http/http_test.go index 6a9162b5fbd..2f826623665 100644 --- a/packetbeat/protos/http/http_test.go +++ b/packetbeat/protos/http/http_test.go @@ -12,9 +12,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/protos" ) diff --git a/packetbeat/protos/icmp/icmp.go b/packetbeat/protos/icmp/icmp.go index b109222c291..450e03bcfa2 100644 --- a/packetbeat/protos/icmp/icmp.go +++ b/packetbeat/protos/icmp/icmp.go @@ -4,10 +4,10 @@ import ( "net" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/flows" "github.com/elastic/beats/packetbeat/protos" diff --git a/packetbeat/protos/icmp/icmp_test.go b/packetbeat/protos/icmp/icmp_test.go index 3f1ffd490ea..bf3bf6c13b0 100644 --- a/packetbeat/protos/icmp/icmp_test.go +++ b/packetbeat/protos/icmp/icmp_test.go @@ -7,9 +7,9 @@ import ( "net" "testing" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/protos" diff --git a/packetbeat/protos/memcache/memcache.go b/packetbeat/protos/memcache/memcache.go index abdaca12ade..e8dc1bb6bdf 100644 --- a/packetbeat/protos/memcache/memcache.go +++ b/packetbeat/protos/memcache/memcache.go @@ -7,10 +7,10 @@ import ( "math" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/protos" "github.com/elastic/beats/packetbeat/protos/applayer" diff --git a/packetbeat/protos/memcache/memcache_test.go b/packetbeat/protos/memcache/memcache_test.go index 4afda5f016a..5d8888fd369 100644 --- a/packetbeat/protos/memcache/memcache_test.go +++ b/packetbeat/protos/memcache/memcache_test.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" ) type memcacheTest struct { diff --git a/packetbeat/protos/mongodb/mongodb.go b/packetbeat/protos/mongodb/mongodb.go index 53df3affee3..bfb60779ee1 100644 --- a/packetbeat/protos/mongodb/mongodb.go +++ b/packetbeat/protos/mongodb/mongodb.go @@ -5,10 +5,10 @@ import ( "strings" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/procs" "github.com/elastic/beats/packetbeat/protos" "github.com/elastic/beats/packetbeat/protos/tcp" diff --git a/packetbeat/protos/mongodb/mongodb_test.go b/packetbeat/protos/mongodb/mongodb_test.go index 49079ffb1a5..85e9ce9a91b 100644 --- a/packetbeat/protos/mongodb/mongodb_test.go +++ b/packetbeat/protos/mongodb/mongodb_test.go @@ -9,9 +9,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/protos" ) diff --git a/packetbeat/protos/mysql/mysql.go b/packetbeat/protos/mysql/mysql.go index 0400714e1d6..4e3e1806da7 100644 --- a/packetbeat/protos/mysql/mysql.go +++ b/packetbeat/protos/mysql/mysql.go @@ -6,10 +6,10 @@ import ( "strings" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/procs" "github.com/elastic/beats/packetbeat/protos" diff --git a/packetbeat/protos/mysql/mysql_test.go b/packetbeat/protos/mysql/mysql_test.go index 67dd11e02f9..43df4740a9e 100644 --- a/packetbeat/protos/mysql/mysql_test.go +++ b/packetbeat/protos/mysql/mysql_test.go @@ -9,9 +9,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/protos" diff --git a/packetbeat/protos/nfs/nfs.go b/packetbeat/protos/nfs/nfs.go index 4cc4070633a..adaf201ef7c 100644 --- a/packetbeat/protos/nfs/nfs.go +++ b/packetbeat/protos/nfs/nfs.go @@ -1,8 +1,8 @@ package nfs import ( + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" ) type nfs struct { diff --git a/packetbeat/protos/nfs/request_handler.go b/packetbeat/protos/nfs/request_handler.go index 33549917f59..a5529690d97 100644 --- a/packetbeat/protos/nfs/request_handler.go +++ b/packetbeat/protos/nfs/request_handler.go @@ -6,9 +6,9 @@ import ( "fmt" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/protos/tcp" ) diff --git a/packetbeat/protos/pgsql/pgsql.go b/packetbeat/protos/pgsql/pgsql.go index d9558c8cf24..2786923dfc8 100644 --- a/packetbeat/protos/pgsql/pgsql.go +++ b/packetbeat/protos/pgsql/pgsql.go @@ -5,10 +5,10 @@ import ( "strings" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/procs" "github.com/elastic/beats/packetbeat/protos" diff --git a/packetbeat/protos/pgsql/pgsql_test.go b/packetbeat/protos/pgsql/pgsql_test.go index c6702a421bc..a0daa20ea60 100644 --- a/packetbeat/protos/pgsql/pgsql_test.go +++ b/packetbeat/protos/pgsql/pgsql_test.go @@ -10,9 +10,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/protos" ) diff --git a/packetbeat/protos/protos.go b/packetbeat/protos/protos.go index c5f0bee8afb..e43bc705e86 100644 --- a/packetbeat/protos/protos.go +++ b/packetbeat/protos/protos.go @@ -7,10 +7,10 @@ import ( "strings" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/cfgwarn" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" ) const ( diff --git a/packetbeat/protos/redis/redis.go b/packetbeat/protos/redis/redis.go index 78bf30d8686..43db9e9d114 100644 --- a/packetbeat/protos/redis/redis.go +++ b/packetbeat/protos/redis/redis.go @@ -4,10 +4,10 @@ import ( "bytes" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/procs" "github.com/elastic/beats/packetbeat/protos" diff --git a/packetbeat/protos/registry.go b/packetbeat/protos/registry.go index 1c4923dc4fc..b2ba6a2d849 100644 --- a/packetbeat/protos/registry.go +++ b/packetbeat/protos/registry.go @@ -3,8 +3,8 @@ package protos import ( "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" ) type ProtocolPlugin func( diff --git a/packetbeat/protos/thrift/thrift.go b/packetbeat/protos/thrift/thrift.go index a36e159e3c4..158e0b8c60f 100644 --- a/packetbeat/protos/thrift/thrift.go +++ b/packetbeat/protos/thrift/thrift.go @@ -10,10 +10,10 @@ import ( "time" "unicode/utf8" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" - "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/packetbeat/procs" "github.com/elastic/beats/packetbeat/protos" diff --git a/packetbeat/publish/publish.go b/packetbeat/publish/publish.go index 024c5e089b1..4699c0397ca 100644 --- a/packetbeat/publish/publish.go +++ b/packetbeat/publish/publish.go @@ -3,10 +3,10 @@ package publish import ( "errors" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" ) type TransactionPublisher struct { diff --git a/packetbeat/publish/publish_test.go b/packetbeat/publish/publish_test.go index a91d098aee0..fdcd088fb2b 100644 --- a/packetbeat/publish/publish_test.go +++ b/packetbeat/publish/publish_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/publisher/beat" ) func testEvent() beat.Event { diff --git a/winlogbeat/beater/eventlogger.go b/winlogbeat/beater/eventlogger.go index 5c53d5f7065..9c087a42987 100644 --- a/winlogbeat/beater/eventlogger.go +++ b/winlogbeat/beater/eventlogger.go @@ -3,10 +3,11 @@ package beater import ( "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/processors" - "github.com/elastic/beats/libbeat/publisher/beat" + "github.com/elastic/beats/winlogbeat/checkpoint" "github.com/elastic/beats/winlogbeat/eventlog" ) diff --git a/winlogbeat/beater/winlogbeat.go b/winlogbeat/beater/winlogbeat.go index cd101bff71c..4fb21f8bd32 100644 --- a/winlogbeat/beater/winlogbeat.go +++ b/winlogbeat/beater/winlogbeat.go @@ -14,7 +14,6 @@ import ( "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/paths" - pub "github.com/elastic/beats/libbeat/publisher/beat" "github.com/elastic/beats/winlogbeat/checkpoint" "github.com/elastic/beats/winlogbeat/config" @@ -39,7 +38,7 @@ type Winlogbeat struct { config config.WinlogbeatConfig // Configuration settings. eventLogs []*eventLogger // List of all event logs being monitored. done chan struct{} // Channel to initiate shutdown of main event loop. - pipeline pub.Pipeline // Interface to publish event. + pipeline beat.Pipeline // Interface to publish event. checkpoint *checkpoint.Checkpoint // Persists event log state to disk. } @@ -123,8 +122,8 @@ func (eb *Winlogbeat) Run(b *beat.Beat) error { initMetrics("total") // setup global event ACK handler - err := eb.pipeline.SetACKHandler(pub.PipelineACKHandler{ - ACKLastEvents: func(events []pub.Event) { + err := eb.pipeline.SetACKHandler(beat.PipelineACKHandler{ + ACKLastEvents: func(events []beat.Event) { for _, event := range events { priv := event.Private if priv == nil { diff --git a/winlogbeat/eventlog/eventlog.go b/winlogbeat/eventlog/eventlog.go index 31f0842d190..177a90031a3 100644 --- a/winlogbeat/eventlog/eventlog.go +++ b/winlogbeat/eventlog/eventlog.go @@ -7,9 +7,10 @@ import ( "strconv" "syscall" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - "github.com/elastic/beats/libbeat/publisher/beat" + "github.com/elastic/beats/winlogbeat/checkpoint" "github.com/elastic/beats/winlogbeat/sys" ) From d4c876e4fc30e58fd0b8f2fae084efc96be7c903 Mon Sep 17 00:00:00 2001 From: urso Date: Wed, 2 Aug 2017 22:48:50 +0200 Subject: [PATCH 050/139] move some more config fields to cmd/instance --- libbeat/beat/beat.go | 5 ----- libbeat/cmd/instance/beat.go | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libbeat/beat/beat.go b/libbeat/beat/beat.go index 89c01f0d8b1..3722622ab0c 100644 --- a/libbeat/beat/beat.go +++ b/libbeat/beat/beat.go @@ -48,11 +48,6 @@ type Beat struct { type BeatConfig struct { // output/publishing related configurations Output common.ConfigNamespace `config:"output"` - - // 'setup' configurations - Dashboards *common.Config `config:"setup.dashboards"` - Template *common.Config `config:"setup.template"` - Kibana *common.Config `config:"setup.kibana"` } // SetupMLCallback can be used by the Beat to register MachineLearning configurations diff --git a/libbeat/cmd/instance/beat.go b/libbeat/cmd/instance/beat.go index aea4a599dcf..12f6ec4c720 100644 --- a/libbeat/cmd/instance/beat.go +++ b/libbeat/cmd/instance/beat.go @@ -71,6 +71,11 @@ type beatConfig struct { // output/publishing related configurations Pipeline pipeline.Config `config:",inline"` Monitoring *common.Config `config:"xpack.monitoring"` + + // elastic stack 'setup' configurations + Dashboards *common.Config `config:"setup.dashboards"` + Template *common.Config `config:"setup.template"` + Kibana *common.Config `config:"setup.kibana"` } var ( From cb4dccd18d08709b9a71d91abf6e064cceb476ef Mon Sep 17 00:00:00 2001 From: urso Date: Wed, 2 Aug 2017 22:55:08 +0200 Subject: [PATCH 051/139] Move common.BeatInfo to beat.Info --- libbeat/api/server.go | 5 +++-- libbeat/beat/beat.go | 4 ++-- libbeat/{common => beat}/info.go | 4 ++-- libbeat/cmd/instance/beat.go | 2 +- libbeat/monitoring/report/elasticsearch/elasticsearch.go | 4 ++-- libbeat/monitoring/report/report.go | 5 +++-- libbeat/outputs/console/console.go | 3 ++- libbeat/outputs/elasticsearch/client_integration_test.go | 2 +- libbeat/outputs/elasticsearch/elasticsearch.go | 3 ++- libbeat/outputs/fileout/file.go | 5 +++-- libbeat/outputs/kafka/kafka.go | 3 ++- libbeat/outputs/kafka/kafka_integration_test.go | 2 +- libbeat/outputs/logstash/logstash.go | 3 ++- libbeat/outputs/logstash/logstash_integration_test.go | 2 +- libbeat/outputs/logstash/logstash_test.go | 2 +- libbeat/outputs/output_reg.go | 5 +++-- libbeat/outputs/redis/redis.go | 5 +++-- libbeat/outputs/redis/redis_integration_test.go | 2 +- libbeat/publisher/pipeline/module.go | 5 +++-- libbeat/template/load.go | 5 +++-- libbeat/template/load_integration_test.go | 3 ++- 21 files changed, 43 insertions(+), 31 deletions(-) rename libbeat/{common => beat}/info.go (90%) diff --git a/libbeat/api/server.go b/libbeat/api/server.go index 1326f1b0d69..59f3ff8143f 100644 --- a/libbeat/api/server.go +++ b/libbeat/api/server.go @@ -6,6 +6,7 @@ import ( "net/url" "strconv" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/cfgwarn" "github.com/elastic/beats/libbeat/logp" @@ -13,7 +14,7 @@ import ( ) // Start starts the metrics api endpoint on the configured host and port -func Start(cfg *common.Config, info common.BeatInfo) { +func Start(cfg *common.Config, info beat.Info) { cfgwarn.Beta("Metrics endpoint is enabled.") config := DefaultConfig cfg.Unpack(&config) @@ -33,7 +34,7 @@ func Start(cfg *common.Config, info common.BeatInfo) { }() } -func rootHandler(info common.BeatInfo) func(http.ResponseWriter, *http.Request) { +func rootHandler(info beat.Info) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { // Return error page if r.URL.Path != "/" { diff --git a/libbeat/beat/beat.go b/libbeat/beat/beat.go index 3722622ab0c..792a1027104 100644 --- a/libbeat/beat/beat.go +++ b/libbeat/beat/beat.go @@ -32,8 +32,8 @@ type Beater interface { // Beat contains the basic beat data and the publisher client used to publish // events. type Beat struct { - Info common.BeatInfo // beat metadata. - Publisher Pipeline // Publisher pipeline + Info Info // beat metadata. + Publisher Pipeline // Publisher pipeline SetupMLCallback SetupMLCallback // setup callback for ML job configs InSetupCmd bool // this is set to true when the `setup` command is called diff --git a/libbeat/common/info.go b/libbeat/beat/info.go similarity index 90% rename from libbeat/common/info.go rename to libbeat/beat/info.go index 0ec6a379cdb..3cd661ff35b 100644 --- a/libbeat/common/info.go +++ b/libbeat/beat/info.go @@ -1,9 +1,9 @@ -package common +package beat import "github.com/satori/go.uuid" // BeatInfo stores a beats instance meta data. -type BeatInfo struct { +type Info struct { Beat string // The actual beat its name Version string // The beat version. Defaults to the libbeat version when an implementation does not set a version Name string // configured beat name diff --git a/libbeat/cmd/instance/beat.go b/libbeat/cmd/instance/beat.go index 12f6ec4c720..ad0e0d1f82f 100644 --- a/libbeat/cmd/instance/beat.go +++ b/libbeat/cmd/instance/beat.go @@ -135,7 +135,7 @@ func NewBeat(name, v string) (*Beat, error) { } b := beat.Beat{ - Info: common.BeatInfo{ + Info: beat.Info{ Beat: name, Version: v, Name: hostname, diff --git a/libbeat/monitoring/report/elasticsearch/elasticsearch.go b/libbeat/monitoring/report/elasticsearch/elasticsearch.go index bf89d637c46..8383e9e4fa8 100644 --- a/libbeat/monitoring/report/elasticsearch/elasticsearch.go +++ b/libbeat/monitoring/report/elasticsearch/elasticsearch.go @@ -52,7 +52,7 @@ func init() { report.RegisterReporterFactory("elasticsearch", makeReporter) } -func makeReporter(beat common.BeatInfo, cfg *common.Config) (report.Reporter, error) { +func makeReporter(beat beat.Info, cfg *common.Config) (report.Reporter, error) { config := defaultConfig if err := cfg.Unpack(&config); err != nil { return nil, err @@ -264,7 +264,7 @@ func parseProxyURL(raw string) (*url.URL, error) { return url.Parse("http://" + raw) } -func makeMeta(beat common.BeatInfo) common.MapStr { +func makeMeta(beat beat.Info) common.MapStr { return common.MapStr{ "type": beat.Beat, "version": beat.Version, diff --git a/libbeat/monitoring/report/report.go b/libbeat/monitoring/report/report.go index 319388f6b80..89b50aca516 100644 --- a/libbeat/monitoring/report/report.go +++ b/libbeat/monitoring/report/report.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" ) @@ -16,7 +17,7 @@ type Reporter interface { Stop() } -type ReporterFactory func(common.BeatInfo, *common.Config) (Reporter, error) +type ReporterFactory func(beat.Info, *common.Config) (Reporter, error) var ( defaultConfig = config{} @@ -32,7 +33,7 @@ func RegisterReporterFactory(name string, f ReporterFactory) { } func New( - beat common.BeatInfo, + beat beat.Info, cfg *common.Config, outputs common.ConfigNamespace, ) (Reporter, error) { diff --git a/libbeat/outputs/console/console.go b/libbeat/outputs/console/console.go index 5a972d4bcb9..9ef7e84a90c 100644 --- a/libbeat/outputs/console/console.go +++ b/libbeat/outputs/console/console.go @@ -7,6 +7,7 @@ import ( "runtime" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs" @@ -35,7 +36,7 @@ func init() { } func makeConsole( - beat common.BeatInfo, + beat beat.Info, stats *outputs.Stats, cfg *common.Config, ) (outputs.Group, error) { diff --git a/libbeat/outputs/elasticsearch/client_integration_test.go b/libbeat/outputs/elasticsearch/client_integration_test.go index 783bf98953f..018f37bff5a 100644 --- a/libbeat/outputs/elasticsearch/client_integration_test.go +++ b/libbeat/outputs/elasticsearch/client_integration_test.go @@ -248,7 +248,7 @@ func connectTestEs(t *testing.T, cfg interface{}) (outputs.Client, *Client) { t.Fatal(err) } - output, err := makeES(common.BeatInfo{Beat: "libbeat"}, nil, config) + output, err := makeES(beat.Info{Beat: "libbeat"}, nil, config) if err != nil { t.Fatal(err) } diff --git a/libbeat/outputs/elasticsearch/elasticsearch.go b/libbeat/outputs/elasticsearch/elasticsearch.go index b4d8670f34a..bfc8dfc0650 100644 --- a/libbeat/outputs/elasticsearch/elasticsearch.go +++ b/libbeat/outputs/elasticsearch/elasticsearch.go @@ -5,6 +5,7 @@ import ( "fmt" "sync" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs" @@ -47,7 +48,7 @@ func RegisterConnectCallback(callback connectCallback) { } func makeES( - beat common.BeatInfo, + beat beat.Info, stats *outputs.Stats, cfg *common.Config, ) (outputs.Group, error) { diff --git a/libbeat/outputs/fileout/file.go b/libbeat/outputs/fileout/file.go index b19096a48bb..a0f0529b564 100644 --- a/libbeat/outputs/fileout/file.go +++ b/libbeat/outputs/fileout/file.go @@ -1,6 +1,7 @@ package fileout import ( + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs" @@ -13,7 +14,7 @@ func init() { } type fileOutput struct { - beat common.BeatInfo + beat beat.Info stats *outputs.Stats rotator logp.FileRotator codec codec.Codec @@ -21,7 +22,7 @@ type fileOutput struct { // New instantiates a new file output instance. func makeFileout( - beat common.BeatInfo, + beat beat.Info, stats *outputs.Stats, cfg *common.Config, ) (outputs.Group, error) { diff --git a/libbeat/outputs/kafka/kafka.go b/libbeat/outputs/kafka/kafka.go index f867c47445a..3abed124473 100644 --- a/libbeat/outputs/kafka/kafka.go +++ b/libbeat/outputs/kafka/kafka.go @@ -10,6 +10,7 @@ import ( "github.com/Shopify/sarama" gometrics "github.com/rcrowley/go-metrics" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" @@ -95,7 +96,7 @@ func kafkaMetricsRegistry() gometrics.Registry { } func makeKafka( - beat common.BeatInfo, + beat beat.Info, stats *outputs.Stats, cfg *common.Config, ) (outputs.Group, error) { diff --git a/libbeat/outputs/kafka/kafka_integration_test.go b/libbeat/outputs/kafka/kafka_integration_test.go index 8af006c6f01..6e1dbacc0b2 100644 --- a/libbeat/outputs/kafka/kafka_integration_test.go +++ b/libbeat/outputs/kafka/kafka_integration_test.go @@ -185,7 +185,7 @@ func TestKafkaPublish(t *testing.T) { } t.Run(name, func(t *testing.T) { - grp, err := makeKafka(common.BeatInfo{Beat: "libbeat"}, nil, cfg) + grp, err := makeKafka(beat.Info{Beat: "libbeat"}, nil, cfg) if err != nil { t.Fatal(err) } diff --git a/libbeat/outputs/logstash/logstash.go b/libbeat/outputs/logstash/logstash.go index 257f060663f..d8261586e82 100644 --- a/libbeat/outputs/logstash/logstash.go +++ b/libbeat/outputs/logstash/logstash.go @@ -1,6 +1,7 @@ package logstash import ( + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs" @@ -19,7 +20,7 @@ func init() { } func makeLogstash( - beat common.BeatInfo, + beat beat.Info, stats *outputs.Stats, cfg *common.Config, ) (outputs.Group, error) { diff --git a/libbeat/outputs/logstash/logstash_integration_test.go b/libbeat/outputs/logstash/logstash_integration_test.go index b310010a4ad..fa6e553ae19 100644 --- a/libbeat/outputs/logstash/logstash_integration_test.go +++ b/libbeat/outputs/logstash/logstash_integration_test.go @@ -160,7 +160,7 @@ func newTestElasticsearchOutput(t *testing.T, test string) *testOutputer { "template.enabled": false, }) - grp, err := plugin(common.BeatInfo{Beat: "libbeat"}, nil, config) + grp, err := plugin(beat.Info{Beat: "libbeat"}, nil, config) if err != nil { t.Fatalf("init elasticsearch output plugin failed: %v", err) } diff --git a/libbeat/outputs/logstash/logstash_test.go b/libbeat/outputs/logstash/logstash_test.go index 4e76ecd49ae..af753a2c507 100644 --- a/libbeat/outputs/logstash/logstash_test.go +++ b/libbeat/outputs/logstash/logstash_test.go @@ -164,7 +164,7 @@ func newTestLumberjackOutput( } cfg, _ := common.NewConfigFrom(config) - grp, err := outputs.Load(common.BeatInfo{}, nil, "logstash", cfg) + grp, err := outputs.Load(beat.Info{}, nil, "logstash", cfg) if err != nil { t.Fatalf("init logstash output plugin failed: %v", err) } diff --git a/libbeat/outputs/output_reg.go b/libbeat/outputs/output_reg.go index a8f176c3def..7d2782166c8 100644 --- a/libbeat/outputs/output_reg.go +++ b/libbeat/outputs/output_reg.go @@ -3,6 +3,7 @@ package outputs import ( "fmt" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" ) @@ -10,7 +11,7 @@ var outputReg = map[string]Factory{} // Factory is used by output plugins to build an output instance type Factory func( - beat common.BeatInfo, + beat beat.Info, stats *Stats, cfg *common.Config) (Group, error) @@ -36,7 +37,7 @@ func FindFactory(name string) Factory { } // Load creates and configures a output Group using a configuration object.. -func Load(info common.BeatInfo, stats *Stats, name string, config *common.Config) (Group, error) { +func Load(info beat.Info, stats *Stats, name string, config *common.Config) (Group, error) { factory := FindFactory(name) if factory == nil { return Group{}, fmt.Errorf("output type %v undefined", name) diff --git a/libbeat/outputs/redis/redis.go b/libbeat/outputs/redis/redis.go index 82dce9d97a0..2277d6dce27 100644 --- a/libbeat/outputs/redis/redis.go +++ b/libbeat/outputs/redis/redis.go @@ -4,6 +4,7 @@ import ( "errors" "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs" @@ -13,7 +14,7 @@ import ( ) type redisOut struct { - beat common.BeatInfo + beat beat.Info } var debugf = logp.MakeDebug("redis") @@ -28,7 +29,7 @@ func init() { } func makeRedis( - beat common.BeatInfo, + beat beat.Info, stats *outputs.Stats, cfg *common.Config, ) (outputs.Group, error) { diff --git a/libbeat/outputs/redis/redis_integration_test.go b/libbeat/outputs/redis/redis_integration_test.go index b4dd1a8fc1d..a6e2da8da7b 100644 --- a/libbeat/outputs/redis/redis_integration_test.go +++ b/libbeat/outputs/redis/redis_integration_test.go @@ -260,7 +260,7 @@ func newRedisTestingOutput(t *testing.T, cfg map[string]interface{}) *client { t.Fatalf("redis output module not registered") } - out, err := plugin(common.BeatInfo{Beat: "libbeat"}, nil, config) + out, err := plugin(beat.Info{Beat: "libbeat"}, nil, config) if err != nil { t.Fatalf("Failed to initialize redis output: %v", err) } diff --git a/libbeat/publisher/pipeline/module.go b/libbeat/publisher/pipeline/module.go index 3e8f269f021..6497e89a4dc 100644 --- a/libbeat/publisher/pipeline/module.go +++ b/libbeat/publisher/pipeline/module.go @@ -5,6 +5,7 @@ import ( "flag" "fmt" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" @@ -27,7 +28,7 @@ func init() { // Load uses a Config object to create a new complete Pipeline instance with // configured queue and outputs. func Load( - beatInfo common.BeatInfo, + beatInfo beat.Info, config Config, outcfg common.ConfigNamespace, ) (*Pipeline, error) { @@ -81,7 +82,7 @@ func Load( } func loadOutput( - beatInfo common.BeatInfo, + beatInfo beat.Info, reg *monitoring.Registry, outcfg common.ConfigNamespace, ) (outputs.Group, error) { diff --git a/libbeat/template/load.go b/libbeat/template/load.go index bfd420b32e8..b8648f809a0 100644 --- a/libbeat/template/load.go +++ b/libbeat/template/load.go @@ -3,6 +3,7 @@ package template import ( "fmt" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/paths" @@ -19,10 +20,10 @@ type ESClient interface { type Loader struct { config TemplateConfig client ESClient - beatInfo common.BeatInfo + beatInfo beat.Info } -func NewLoader(cfg *common.Config, client ESClient, beatInfo common.BeatInfo) (*Loader, error) { +func NewLoader(cfg *common.Config, client ESClient, beatInfo beat.Info) (*Loader, error) { config := DefaultConfig err := cfg.Unpack(&config) diff --git a/libbeat/template/load_integration_test.go b/libbeat/template/load_integration_test.go index 495f08ca908..b62ae19299c 100644 --- a/libbeat/template/load_integration_test.go +++ b/libbeat/template/load_integration_test.go @@ -7,6 +7,7 @@ import ( "path/filepath" "testing" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/outputs/elasticsearch" "github.com/elastic/beats/libbeat/version" @@ -214,7 +215,7 @@ func TestOverwrite(t *testing.T) { t.Fatal(err) } - beatInfo := common.BeatInfo{ + beatInfo := beat.Info{ Beat: "testbeat", Version: version.GetDefaultVersion(), } From 83e433a378dd95e3eca96821b6f8937da07072b4 Mon Sep 17 00:00:00 2001 From: urso Date: Wed, 2 Aug 2017 23:40:20 +0200 Subject: [PATCH 052/139] Fix conflict after rebase --- libbeat/processors/add_kubernetes_metadata/indexing.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbeat/processors/add_kubernetes_metadata/indexing.go b/libbeat/processors/add_kubernetes_metadata/indexing.go index aa03b32f321..06ecce7ae42 100644 --- a/libbeat/processors/add_kubernetes_metadata/indexing.go +++ b/libbeat/processors/add_kubernetes_metadata/indexing.go @@ -5,12 +5,12 @@ import ( "strings" "sync" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/fmtstr" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs/codec" "github.com/elastic/beats/libbeat/outputs/codec/format" - "github.com/elastic/beats/libbeat/publisher/beat" ) //Names of indexers and matchers that have been defined. From c983bc6e65c412eb3cbe7b67a57f59b5881eefd7 Mon Sep 17 00:00:00 2001 From: urso Date: Tue, 8 Aug 2017 16:38:49 +0200 Subject: [PATCH 053/139] Remove packetbeat -devices flag in cobra setup --- packetbeat/cmd/root.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/packetbeat/cmd/root.go b/packetbeat/cmd/root.go index 3b6b0c71bf3..c502d86311b 100644 --- a/packetbeat/cmd/root.go +++ b/packetbeat/cmd/root.go @@ -26,9 +26,6 @@ func init() { runFlags.AddGoFlag(flag.CommandLine.Lookup("l")) runFlags.AddGoFlag(flag.CommandLine.Lookup("dump")) - // TODO Deprecate this one in favor of subcommand - runFlags.AddGoFlag(flag.CommandLine.Lookup("devices")) - RootCmd = cmd.GenRootCmdWithRunFlags(Name, "", beater.New, runFlags) RootCmd.AddCommand(genDevicesCommand()) } From 592dbbe27d4e71f418863b0c9df02c21e348f637 Mon Sep 17 00:00:00 2001 From: urso Date: Tue, 8 Aug 2017 16:47:46 +0200 Subject: [PATCH 054/139] review fixes --- filebeat/beater/filebeat.go | 6 +++--- libbeat/beat/beat.go | 8 +++++--- libbeat/beat/info.go | 4 ++-- winlogbeat/beater/winlogbeat.go | 2 -- winlogbeat/config/config.go | 9 --------- winlogbeat/config/config_test.go | 2 +- 6 files changed, 11 insertions(+), 20 deletions(-) diff --git a/filebeat/beater/filebeat.go b/filebeat/beater/filebeat.go index 043f18b7f80..bf4559d2e67 100644 --- a/filebeat/beater/filebeat.go +++ b/filebeat/beater/filebeat.go @@ -82,10 +82,10 @@ func New(b *beat.Beat, rawConfig *common.Config) (beat.Beater, error) { if !config.ConfigProspector.Enabled() && !config.ConfigModules.Enabled() && !haveEnabledProspectors { if !b.InSetupCmd { return nil, errors.New("No modules or prospectors enabled and configuration reloading disabled. What files do you want me to watch?") - } else { - // in the `setup` command, log this only as a warning - logp.Warn("Setup called, but no modules enabled.") } + + // in the `setup` command, log this only as a warning + logp.Warn("Setup called, but no modules enabled.") } if *once && config.ConfigProspector.Enabled() && config.ConfigModules.Enabled() { diff --git a/libbeat/beat/beat.go b/libbeat/beat/beat.go index 792a1027104..86088dac8ce 100644 --- a/libbeat/beat/beat.go +++ b/libbeat/beat/beat.go @@ -5,7 +5,7 @@ import ( ) // Creator initializes and configures a new Beater instance used to execute -// the beat its run-loop. +// the beat's run-loop. type Creator func(*Beat, *common.Config) (Beater, error) // Beater is the interface that must be implemented by every Beat. A Beater @@ -38,10 +38,12 @@ type Beat struct { SetupMLCallback SetupMLCallback // setup callback for ML job configs InSetupCmd bool // this is set to true when the `setup` command is called - // XXX: remove Config from public interface + // XXX: remove Config from public interface. + // It's currently used by filebeat modules to setup the Ingest Node + // pipeline and ML jobs. Config *BeatConfig // Common Beat configuration data. - BeatConfig *common.Config // The beats it's own configuration section + BeatConfig *common.Config // The beat's own configuration section } // BeatConfig struct contains the basic configuration of every beat diff --git a/libbeat/beat/info.go b/libbeat/beat/info.go index 3cd661ff35b..36c74e47f64 100644 --- a/libbeat/beat/info.go +++ b/libbeat/beat/info.go @@ -2,9 +2,9 @@ package beat import "github.com/satori/go.uuid" -// BeatInfo stores a beats instance meta data. +// Info stores a beats instance meta data. type Info struct { - Beat string // The actual beat its name + Beat string // The actual beat's name Version string // The beat version. Defaults to the libbeat version when an implementation does not set a version Name string // configured beat name Hostname string // hostname diff --git a/winlogbeat/beater/winlogbeat.go b/winlogbeat/beater/winlogbeat.go index 4fb21f8bd32..e6cd037f4a1 100644 --- a/winlogbeat/beater/winlogbeat.go +++ b/winlogbeat/beater/winlogbeat.go @@ -45,8 +45,6 @@ type Winlogbeat struct { // New returns a new Winlogbeat. func New(b *beat.Beat, _ *common.Config) (beat.Beater, error) { // Read configuration. - // XXX: winlogbeat validates top-level config -> ignore beater config and - // parse complete top-level config config := config.DefaultSettings err := b.BeatConfig.Unpack(&config) if err != nil { diff --git a/winlogbeat/config/config.go b/winlogbeat/config/config.go index 4b33b4ea8d0..9bb6069d5bc 100644 --- a/winlogbeat/config/config.go +++ b/winlogbeat/config/config.go @@ -14,15 +14,6 @@ const ( DefaultRegistryFile = ".winlogbeat.yml" ) -// Validator is the interface for configuration data that can be validating. -// -// Validate reads the configuration and validates all fields. An error -// describing all problems is returned (versus returning an error only for the -// first problem encountered). -type Validator interface { - Validate() error -} - var ( DefaultSettings = WinlogbeatConfig{ RegistryFile: DefaultRegistryFile, diff --git a/winlogbeat/config/config_test.go b/winlogbeat/config/config_test.go index 841be21c546..b23ca31b0e3 100644 --- a/winlogbeat/config/config_test.go +++ b/winlogbeat/config/config_test.go @@ -11,7 +11,7 @@ import ( ) type validationTestCase struct { - config Validator + config WinlogbeatConfig errMsg string } From 5e308c99ffd9e7e347d8b807713189422bca2549 Mon Sep 17 00:00:00 2001 From: urso Date: Tue, 8 Aug 2017 17:45:05 +0200 Subject: [PATCH 055/139] Update generator --- generator/beat/{beat}/beater/{beat}.go.tmpl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/generator/beat/{beat}/beater/{beat}.go.tmpl b/generator/beat/{beat}/beater/{beat}.go.tmpl index 0a27be3639f..246b6f25546 100644 --- a/generator/beat/{beat}/beater/{beat}.go.tmpl +++ b/generator/beat/{beat}/beater/{beat}.go.tmpl @@ -7,7 +7,6 @@ import ( "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" - pub "github.com/elastic/beats/libbeat/publisher/beat" "{beat_path}/config" ) @@ -15,7 +14,7 @@ import ( type {Beat} struct { done chan struct{} config config.Config - client pub.Client + client beat.Client } // Creates beater @@ -50,7 +49,7 @@ func (bt *{Beat}) Run(b *beat.Beat) error { case <-ticker.C: } - event := pub.Event{ + event := beat.Event{ Timestamp: time.Now(), Fields: common.MapStr{ "type": b.Info.Name, From 11b03caa5706eab992878b43fcc55482dd527dd9 Mon Sep 17 00:00:00 2001 From: urso Date: Tue, 8 Aug 2017 18:02:00 +0200 Subject: [PATCH 056/139] metricbeat generator --- generator/metricbeat/{beat}/main.go.tmpl | 9 +++++---- metricbeat/cmd/root.go | 3 --- metricbeat/main.go | 3 +++ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/generator/metricbeat/{beat}/main.go.tmpl b/generator/metricbeat/{beat}/main.go.tmpl index 4f6a4e61ff7..f717f804273 100644 --- a/generator/metricbeat/{beat}/main.go.tmpl +++ b/generator/metricbeat/{beat}/main.go.tmpl @@ -3,19 +3,20 @@ package main import ( "os" - "github.com/elastic/beats/libbeat/beat" + "github.com/elastic/beats/libbeat/cmd/instance" "github.com/elastic/beats/metricbeat/beater" - // Make sure all your modules and metricsets are linked in this file - _ "{beat_path}/include" // Comment out the following line to exclude all official metricbeat modules and metricsets _ "github.com/elastic/beats/metricbeat/include" + + // Make sure all your modules and metricsets are linked in this file + _ "{beat_path}/include" ) var Name = "{beat}" func main() { - if err := beat.Run(Name, "", beater.New); err != nil { + if err := instance.Run(Name, "", beater.New); err != nil { os.Exit(1) } } diff --git a/metricbeat/cmd/root.go b/metricbeat/cmd/root.go index 38b84d8dcac..8598629d6fc 100644 --- a/metricbeat/cmd/root.go +++ b/metricbeat/cmd/root.go @@ -5,9 +5,6 @@ import ( "github.com/spf13/pflag" - // import modules - _ "github.com/elastic/beats/metricbeat/include" - cmd "github.com/elastic/beats/libbeat/cmd" "github.com/elastic/beats/metricbeat/beater" "github.com/elastic/beats/metricbeat/cmd/test" diff --git a/metricbeat/main.go b/metricbeat/main.go index 78a9589dd3f..cd84e60dffe 100644 --- a/metricbeat/main.go +++ b/metricbeat/main.go @@ -11,6 +11,9 @@ import ( "os" "github.com/elastic/beats/metricbeat/cmd" + + // import modules + _ "github.com/elastic/beats/metricbeat/include" ) func main() { From 0cacffef95674632cc2b1039376210716733b2c2 Mon Sep 17 00:00:00 2001 From: urso Date: Tue, 8 Aug 2017 22:12:58 +0200 Subject: [PATCH 057/139] fix panic on AddGoFlag --- metricbeat/cmd/root.go | 3 +++ metricbeat/main.go | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/metricbeat/cmd/root.go b/metricbeat/cmd/root.go index 8598629d6fc..5c925bb1378 100644 --- a/metricbeat/cmd/root.go +++ b/metricbeat/cmd/root.go @@ -8,6 +8,9 @@ import ( cmd "github.com/elastic/beats/libbeat/cmd" "github.com/elastic/beats/metricbeat/beater" "github.com/elastic/beats/metricbeat/cmd/test" + + // import modules + _ "github.com/elastic/beats/metricbeat/include" ) // Name of this beat diff --git a/metricbeat/main.go b/metricbeat/main.go index cd84e60dffe..78a9589dd3f 100644 --- a/metricbeat/main.go +++ b/metricbeat/main.go @@ -11,9 +11,6 @@ import ( "os" "github.com/elastic/beats/metricbeat/cmd" - - // import modules - _ "github.com/elastic/beats/metricbeat/include" ) func main() { From a1031e8963105f1d436fd5cb32dca6f8939db5b2 Mon Sep 17 00:00:00 2001 From: Steffen Siering Date: Wed, 9 Aug 2017 22:33:57 +0200 Subject: [PATCH 058/139] Fix monitor.name being empty by default (#4856) * Fix monitor.name being empty by default * Update dashboards to filter by monitor.type --- CHANGELOG.asciidoc | 2 ++ .../5.x/search/02014c80-29d2-11e7-a68f-bfaa2341cc52.json | 4 ++-- .../kibana/default/dashboard/Heartbeat-http-monitor.json | 4 ++-- heartbeat/beater/manager.go | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 82d8b24bed4..4299acecf0f 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -45,6 +45,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Heartbeat* +- Fix monitor.name being empty by default. {issue}4852[4852] + *Metricbeat* - Support `npipe` protocol (Windows) in Docker module. {pull}4751[4751] diff --git a/heartbeat/_meta/kibana/5.x/search/02014c80-29d2-11e7-a68f-bfaa2341cc52.json b/heartbeat/_meta/kibana/5.x/search/02014c80-29d2-11e7-a68f-bfaa2341cc52.json index 53ba45f044e..1af9cb94b66 100644 --- a/heartbeat/_meta/kibana/5.x/search/02014c80-29d2-11e7-a68f-bfaa2341cc52.json +++ b/heartbeat/_meta/kibana/5.x/search/02014c80-29d2-11e7-a68f-bfaa2341cc52.json @@ -8,7 +8,7 @@ "title": "Heartbeat HTTP pings", "version": 1, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\n \"index\": \"heartbeat-*\",\n \"highlightAll\": true,\n \"query\": {\n \"query_string\": {\n \"analyze_wildcard\": true,\n \"query\": \"*\"\n }\n },\n \"filter\": [\n {\n \"$state\": {\n \"store\": \"appState\"\n },\n \"meta\": {\n \"alias\": null,\n \"disabled\": false,\n \"index\": \"heartbeat-*\",\n \"key\": \"monitor.name\",\n \"negate\": false,\n \"value\": \"http\"\n },\n \"query\": {\n \"match\": {\n \"monitor.name\": {\n \"query\": \"http\",\n \"type\": \"phrase\"\n }\n }\n }\n }\n ]\n}" + "searchSourceJSON": "{\n \"index\": \"heartbeat-*\",\n \"highlightAll\": true,\n \"query\": {\n \"query_string\": {\n \"analyze_wildcard\": true,\n \"query\": \"*\"\n }\n },\n \"filter\": [\n {\n \"$state\": {\n \"store\": \"appState\"\n },\n \"meta\": {\n \"alias\": null,\n \"disabled\": false,\n \"index\": \"heartbeat-*\",\n \"key\": \"monitor.type\",\n \"negate\": false,\n \"value\": \"http\"\n },\n \"query\": {\n \"match\": {\n \"monitor.type\": {\n \"query\": \"http\",\n \"type\": \"phrase\"\n }\n }\n }\n }\n ]\n}" }, "columns": [ "monitor.id", @@ -21,4 +21,4 @@ "resolve.rtt.us", "http.rtt.content.us" ] -} \ No newline at end of file +} diff --git a/heartbeat/_meta/kibana/default/dashboard/Heartbeat-http-monitor.json b/heartbeat/_meta/kibana/default/dashboard/Heartbeat-http-monitor.json index f1a4b09b30d..4e254a001f9 100644 --- a/heartbeat/_meta/kibana/default/dashboard/Heartbeat-http-monitor.json +++ b/heartbeat/_meta/kibana/default/dashboard/Heartbeat-http-monitor.json @@ -96,7 +96,7 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\n \"index\": \"heartbeat-*\",\n \"highlightAll\": true,\n \"query\": {\n \"query_string\": {\n \"analyze_wildcard\": true,\n \"query\": \"*\"\n }\n },\n \"filter\": [\n {\n \"$state\": {\n \"store\": \"appState\"\n },\n \"meta\": {\n \"alias\": null,\n \"disabled\": false,\n \"index\": \"heartbeat-*\",\n \"key\": \"monitor.name\",\n \"negate\": false,\n \"value\": \"http\"\n },\n \"query\": {\n \"match\": {\n \"monitor.name\": {\n \"query\": \"http\",\n \"type\": \"phrase\"\n }\n }\n }\n }\n ]\n}" + "searchSourceJSON": "{\n \"index\": \"heartbeat-*\",\n \"highlightAll\": true,\n \"query\": {\n \"query_string\": {\n \"analyze_wildcard\": true,\n \"query\": \"*\"\n }\n },\n \"filter\": [\n {\n \"$state\": {\n \"store\": \"appState\"\n },\n \"meta\": {\n \"alias\": null,\n \"disabled\": false,\n \"index\": \"heartbeat-*\",\n \"key\": \"monitor.type\",\n \"negate\": false,\n \"value\": \"http\"\n },\n \"query\": {\n \"match\": {\n \"monitor.type\": {\n \"query\": \"http\",\n \"type\": \"phrase\"\n }\n }\n }\n }\n ]\n}" }, "sort": [ "@timestamp", @@ -129,4 +129,4 @@ } ], "version": "6.0.0-alpha3-SNAPSHOT" -} \ No newline at end of file +} diff --git a/heartbeat/beater/manager.go b/heartbeat/beater/manager.go index 988cde98003..6a4d3a8508b 100644 --- a/heartbeat/beater/manager.go +++ b/heartbeat/beater/manager.go @@ -270,7 +270,7 @@ func createWatchUpdater(monitor *monitor) func(content []byte) { func (m *monitorTask) createJob(client beat.Client) scheduler.TaskFunc { name := m.config.Name if name == "" { - name = m.config.Name + name = m.config.Type } meta := common.MapStr{ From 318cc1ae09ccbe7a8425c024483c0eaa0624aa90 Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Thu, 10 Aug 2017 09:51:00 +0200 Subject: [PATCH 059/139] Add exclude and skip-notice feature to generate_notice script (#4858) * Allow to use -e to provide a list of directories which should be excluded in case of hard code it * Allow to use -s to define NOTICE files which should be skipped * Set the description of the notice file based on the -b flag --- NOTICE | 2 +- dev-tools/generate_notice.py | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/NOTICE b/NOTICE index 9f0d7bdee7c..fe0ffa0ebd2 100644 --- a/NOTICE +++ b/NOTICE @@ -5,7 +5,7 @@ This product includes software developed by The Apache Software Foundation (http://www.apache.org/). ========================================================================== -Third party libraries used by the Beats project: +Third party libraries used by the Elastic Beats project: ========================================================================== diff --git a/dev-tools/generate_notice.py b/dev-tools/generate_notice.py index c0cc289036d..19b985db9a4 100644 --- a/dev-tools/generate_notice.py +++ b/dev-tools/generate_notice.py @@ -91,7 +91,7 @@ def write_notice_file(f, beat, copyright, dependencies): # Add licenses for 3rd party libraries f.write("==========================================================================\n") - f.write("Third party libraries used by the Beats project:\n") + f.write("Third party libraries used by the {} project:\n".format(beat)) f.write("==========================================================================\n\n") # Sort licenses by package path, ignore upper / lower case @@ -111,6 +111,11 @@ def write_notice_file(f, beat, copyright, dependencies): else: # it's an Apache License, so include only the NOTICE file f.write("Apache License 2.0\n\n") + + # Skipe NOTICE files not needed + if os.path.join(os.path.dirname(lib["license_file"])) in SKIP_NOTICE: + continue + for notice_file in glob.glob(os.path.join(os.path.dirname(lib["license_file"]), "NOTICE*")): notice_file_hdr = "-------{}-----\n".format(os.path.basename(notice_file)) f.write(notice_file_hdr) @@ -205,7 +210,7 @@ def detect_license_summary(content): return "Unknown" -EXCLUDES = ["dev-tools"] +SKIP_NOTICE = [] if __name__ == "__main__": @@ -219,13 +224,21 @@ def detect_license_summary(content): help="copyright owner") parser.add_argument("--csv", dest="csvfile", help="Output to a csv file") - + parser.add_argument("-e", "--excludes", default=["dev-tools"], + help="List of top directories to exclude") + parser.add_argument("-s", "--skip-notice", default=[], + help="List of NOTICE files to skip") args = parser.parse_args() cwd = os.getcwd() notice = os.path.join(cwd, "NOTICE") vendor_dirs = [] + excludes = args.excludes + if not isinstance(excludes, list): + excludes = [excludes] + SKIP_NOTICE = args.skip_notice + for root, dirs, files in os.walk(args.vendor): # Skips all hidden paths like ".git" @@ -236,7 +249,7 @@ def detect_license_summary(content): vendor_dirs.append(os.path.join(root, 'vendor')) dirs.remove('vendor') # don't walk down into sub-vendors - for exclude in EXCLUDES: + for exclude in excludes: if exclude in dirs: dirs.remove(exclude) From af3ecf91a654ade3e704c840ffdea82a2ea6c0a2 Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Thu, 10 Aug 2017 10:41:10 +0200 Subject: [PATCH 060/139] Add support for index to fields.yml (#4853) Setting `index: false` for a field was not possible so far. This adds this possibility. For more details in `index` see: https://www.elastic.co/guide/en/elasticsearch/reference/5.5/mapping-index.html Additional changes: * `enable` and `dynamic` are only available for objects. The functionality was move to object. https://www.elastic.co/guide/en/elasticsearch/reference/5.5/enabled.html * Add support for `enable` and `index` to the docs script so it is visible in the docs which fields are indexed and which ones not --- libbeat/scripts/generate_fields_docs.py | 8 ++++++++ libbeat/template/field.go | 20 +++++++++++------- libbeat/template/field_test.go | 27 +++++++++++++++++++------ 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/libbeat/scripts/generate_fields_docs.py b/libbeat/scripts/generate_fields_docs.py index 8745734bd39..8b7190bce10 100644 --- a/libbeat/scripts/generate_fields_docs.py +++ b/libbeat/scripts/generate_fields_docs.py @@ -54,6 +54,14 @@ def document_field(output, field, path): if "description" in field: output.write("{}\n\n".format(field["description"])) + if "index" in field: + if not field["index"]: + output.write("{}\n\n".format("Field is not indexed.")) + + if "enable" in field: + if not field["enable"]: + output.write("{}\n\n".format("Object is not enabled.")) + def fields_to_asciidoc(input, output, beat): diff --git a/libbeat/template/field.go b/libbeat/template/field.go index f8f6dfcd5db..384e7e108c9 100644 --- a/libbeat/template/field.go +++ b/libbeat/template/field.go @@ -25,6 +25,7 @@ type Field struct { SearchAnalyzer string `config:"search_analyzer"` Norms bool `config:"norms"` Dynamic dynamicType `config:"dynamic"` + Index *bool `config:"index"` path string esVersion common.Version @@ -161,6 +162,14 @@ func (f *Field) object() common.MapStr { properties := f.getDefaultProperties() properties["type"] = "object" + if f.Enabled != nil { + properties["enabled"] = *f.Enabled + } + + if f.Dynamic.value != nil { + properties["dynamic"] = f.Dynamic.value + } + return properties } @@ -183,16 +192,13 @@ func (f *Field) addDynamicTemplate(properties common.MapStr, matchType string) { func (f *Field) getDefaultProperties() common.MapStr { // Currently no defaults exist - property := common.MapStr{} - if f.Enabled != nil { - property["enabled"] = *f.Enabled - } + properties := common.MapStr{} - if f.Dynamic.value != nil { - property["dynamic"] = f.Dynamic.value + if f.Index != nil { + properties["index"] = *f.Index } - return property + return properties } // Recursively generates the correct key based on the dots diff --git a/libbeat/template/field_test.go b/libbeat/template/field_test.go index c8793b796e0..e8c5df8fb35 100644 --- a/libbeat/template/field_test.go +++ b/libbeat/template/field_test.go @@ -14,6 +14,7 @@ func TestField(t *testing.T) { assert.NoError(t, err) falseVar := false + trueVar := true tests := []struct { field Field @@ -52,7 +53,7 @@ func TestField(t *testing.T) { }, { field: Field{Type: "object", Enabled: &falseVar}, - method: func(f Field) common.MapStr { return f.other() }, + method: func(f Field) common.MapStr { return f.object() }, output: common.MapStr{ "type": "object", "enabled": false, @@ -135,23 +136,37 @@ func TestField(t *testing.T) { }, { field: Field{Dynamic: dynamicType{false}}, - method: func(f Field) common.MapStr { return f.other() }, + method: func(f Field) common.MapStr { return f.object() }, output: common.MapStr{ - "dynamic": false, + "dynamic": false, "type": "object", }, }, { field: Field{Dynamic: dynamicType{true}}, - method: func(f Field) common.MapStr { return f.other() }, + method: func(f Field) common.MapStr { return f.object() }, output: common.MapStr{ - "dynamic": true, + "dynamic": true, "type": "object", }, }, { field: Field{Dynamic: dynamicType{"strict"}}, + method: func(f Field) common.MapStr { return f.object() }, + output: common.MapStr{ + "dynamic": "strict", "type": "object", + }, + }, + { + field: Field{Type: "long", Index: &falseVar}, + method: func(f Field) common.MapStr { return f.other() }, + output: common.MapStr{ + "type": "long", "index": false, + }, + }, + { + field: Field{Type: "text", Index: &trueVar}, method: func(f Field) common.MapStr { return f.other() }, output: common.MapStr{ - "dynamic": "strict", + "type": "text", "index": true, }, }, } From cba395a2ce66bdba2c35ba3cd241197bba691fb5 Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Thu, 10 Aug 2017 11:05:33 +0200 Subject: [PATCH 061/139] Wait for registry to exist on tests (#4862) Quite a few of our tests fail because the registry does not exist yet when checked. This PR changes the get_registry function to wait until the registry exists and then return it. This should make some of the tests more stable. --- filebeat/tests/system/filebeat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filebeat/tests/system/filebeat.py b/filebeat/tests/system/filebeat.py index 6efee859b02..4d34de9ccca 100644 --- a/filebeat/tests/system/filebeat.py +++ b/filebeat/tests/system/filebeat.py @@ -19,7 +19,7 @@ def setUpClass(self): def get_registry(self): # Returns content of the registry file dotFilebeat = self.working_dir + '/registry' - assert os.path.isfile(dotFilebeat) is True + self.wait_until(cond=lambda: os.path.isfile(dotFilebeat)) with open(dotFilebeat) as file: return json.load(file) From f2d60350dc637610bb6bc597a51b8826ffd542be Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Thu, 10 Aug 2017 11:05:53 +0200 Subject: [PATCH 062/139] Fix flaky appveyor filebeat test (#4861) This should prevent the test_close_renamed test to be flaky on appveyor. Sometimes the registry was requested before it was written. See https://ci.appveyor.com/project/elastic-beats/beats/build/12109/job/g5lxn7k6fcgsi5ka as example. --- filebeat/tests/system/test_harvester.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/filebeat/tests/system/test_harvester.py b/filebeat/tests/system/test_harvester.py index c788bb9ebf9..6d0de35a8d6 100644 --- a/filebeat/tests/system/test_harvester.py +++ b/filebeat/tests/system/test_harvester.py @@ -58,6 +58,10 @@ def test_close_renamed(self): self.wait_until( lambda: self.output_has(lines=iterations1 + 1), max_timeout=10) + # Wait until registry file is created + self.wait_until( + lambda: self.log_contains_count("Registry file updated") > 1) + # Make sure new file was picked up. As it has the same file name, # one entry for the new and one for the old should exist self.wait_until( From 5a5e210a407732c4bc44264a6696c66f07bec360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Thu, 10 Aug 2017 21:58:22 +0200 Subject: [PATCH 063/139] libbeat: change deprecated _default_ mapping to doc in index templates (#4864) Closes #4840 --- CHANGELOG.asciidoc | 2 ++ libbeat/ml-importer/importer_integration_test.go | 2 +- libbeat/template/load_integration_test.go | 6 +++--- libbeat/template/template.go | 12 ++++++++++-- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 4299acecf0f..61c0d7cb411 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -35,6 +35,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Affecting all Beats* - Fix go plugins not loaded when beat starts {pull}4799[4799] +- Eliminate deprecated _default_ mapping in 6.x {pull}4864[4864] + *Auditbeat* - Fix `file.max_file_size` config option for the audit file metricset. {pull}4796[4796] diff --git a/libbeat/ml-importer/importer_integration_test.go b/libbeat/ml-importer/importer_integration_test.go index 1556da3bf2a..a08aa2b7311 100644 --- a/libbeat/ml-importer/importer_integration_test.go +++ b/libbeat/ml-importer/importer_integration_test.go @@ -49,7 +49,7 @@ const sampleDatafeed = ` "filebeat-*" ], "types": [ - "_default_", + "doc", "log" ], "query": { diff --git a/libbeat/template/load_integration_test.go b/libbeat/template/load_integration_test.go index b62ae19299c..827927a95e3 100644 --- a/libbeat/template/load_integration_test.go +++ b/libbeat/template/load_integration_test.go @@ -197,7 +197,7 @@ func TestTemplateSettings(t *testing.T) { assert.NoError(t, err) assert.Equal(t, val.(string), "1") - val, err = templateJSON.GetValue("mappings._default_._source.enabled") + val, err = templateJSON.GetValue("mappings.doc._source.enabled") assert.NoError(t, err) assert.Equal(t, val.(bool), false) @@ -255,7 +255,7 @@ func TestOverwrite(t *testing.T) { // Overwrite was not enabled, so the first version should still be there templateJSON := getTemplate(t, client, templateName) - _, err = templateJSON.GetValue("mappings._default_._source.enabled") + _, err = templateJSON.GetValue("mappings.doc._source.enabled") assert.Error(t, err) // Load template again, this time with custom settings AND overwrite: true @@ -276,7 +276,7 @@ func TestOverwrite(t *testing.T) { // Overwrite was enabled, so the custom setting should be there templateJSON = getTemplate(t, client, templateName) - val, err := templateJSON.GetValue("mappings._default_._source.enabled") + val, err := templateJSON.GetValue("mappings.doc._source.enabled") assert.NoError(t, err) assert.Equal(t, val.(bool), false) diff --git a/libbeat/template/template.go b/libbeat/template/template.go index 7e91ca4d475..26233bd655b 100644 --- a/libbeat/template/template.go +++ b/libbeat/template/template.go @@ -98,10 +98,17 @@ func (t *Template) generate(properties common.MapStr, dynamicTemplates []common. } indexSettings.DeepUpdate(t.settings.Index) + var mappingName string + if t.esVersion.Major >= 6 { + mappingName = "doc" + } else { + mappingName = "_default_" + } + // Load basic structure basicStructure := common.MapStr{ "mappings": common.MapStr{ - "_default_": common.MapStr{ + mappingName: common.MapStr{ "_meta": common.MapStr{ "version": t.beatVersion.String(), }, @@ -117,7 +124,8 @@ func (t *Template) generate(properties common.MapStr, dynamicTemplates []common. } if len(t.settings.Source) > 0 { - basicStructure.Put("mappings._default_._source", t.settings.Source) + key := fmt.Sprintf("mappings.%s._source", mappingName) + basicStructure.Put(key, t.settings.Source) } // ES 6 moved from template to index_patterns: https://github.com/elastic/elasticsearch/pull/21009 From 6c5f3b27d14ccc997d4ae80a04c1bab7f68f9e6f Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Thu, 10 Aug 2017 23:06:47 +0300 Subject: [PATCH 064/139] Added breaking changes doc for 6.0 (#4760) * Added breaking changes doc for 6.0 Part of #4737, but there are some TODOs left. * Add section for multiple outputs Also, addressed commits and removed the 5.0 breaking changes. --- libbeat/docs/breaking.asciidoc | 214 ++++++++++++++++++++------------- 1 file changed, 133 insertions(+), 81 deletions(-) diff --git a/libbeat/docs/breaking.asciidoc b/libbeat/docs/breaking.asciidoc index 78156627471..6264ba2578d 100644 --- a/libbeat/docs/breaking.asciidoc +++ b/libbeat/docs/breaking.asciidoc @@ -2,112 +2,164 @@ == Breaking changes As a general rule, we strive to keep backwards compatibility between minor -versions (e.g. 5.x to 5.y) so you can upgrade without any configuration file +versions (e.g. 6.x to 6.y) so you can upgrade without any configuration file changes, but there are breaking changes between major versions (e.g. 5.x to -6.y). +6.y). Migrating directly between non consecutive major versions (e.g. 1.x to +6.x) is not recommended. -* <> +[[breaking-changes-6.0]] +=== Breaking changes in 6.0 -We also list the breaking changes at the top of the <> -for each version. +This section discusses the main changes that you should be aware of if you +upgrade the Beats from version 5.x to 6.x. Please also review the relevant +Breaking Changes sections of the <>. -[[breaking-changes-5.0]] -=== Breaking changes in 5.0 +// TODO: better link to the consolidated release notes for 6.0.0. -This section discusses the changes that you should be aware of if you upgrade -the Beats from version 1.x to 5.x. -==== URL changes for DEB/RPM packages +[[breaking-changes-spooler-removed]] +==== Filebeat spooler removed -The previous `packages.elastic.co` URL has been altered to `artifacts.elastic.co`. -Ensure you update your repository files before running the upgrade process, or -your operating system may not see the new packages. +Version 6.0 comes with a new architecture for the internal pipeline of all +Beats. This architecture refactoring is mostly internal, but one of the more +visible effects is that the Spooler component of Filebeat is removed. The +functionality of the Spooler was similar to the one of the publisher queue from +libbeat (the code shared by all Beats), and the presence of multiple queues +made the performance tuning of Filebeat more complex than it needed to be. -==== Configuration file changes +As a result, the following options are removed: -Beats 5.0 comes with a more powerful and more robust <>. While this necessarily causes a few breaking changes, we -provide a migration script that should make upgrading easy. Please see the -<> section. +- `filebeat.spool_size` +- `filebeat.publish_async` +- `filebeat.idle_timeout` +- `queue_size` +- `bulk_queue_size` -For consistency and clarity, all configuration options that are specific to a -particular Beat are now prefixed by the name of the Beat. For example, the -`interfaces.device` option from Packetbeat becomes -`packetbeat.interfaces.device`. This change is made automatically by the -migration script. +The first three are specific to Filebeat, while `queue_size` and +`bulk_queue_size` exist in all Beats. If any of these options is set, Filebeat +6.0 will refuse to start. -Similarly, common settings available in all Beats are now top level. As part of -this effort, the options under the `shipper` section are moved to the top level. For -example, the `shipper.name` settings becomes `name`. This change is made -automatically by the migration script. +Instead of the settings above, the `queue.mem` settings are introduced. If you +had to tune the `spool_size` or the `queue_size` before, you might want to tune +the `queue.mem.events` when upgrading. However, it is best to leave the rest of +the `queue.mem` settings to their default values, as they are appropriate for +all loads. -For consistency with the rest of the Elastic stack, several TLS/SSL related -options where changed: +The `publish_async` option (which was deprecated since 5.3) is removed because +the new pipeline already works asynchronously by default. -* the name of the section was renamed from `tls` to `ssl` -* `certificate_key` was renamed to `key` -* `insecure` was replaced by `verification_mode` -* `min_version` and `max_version` were replaced with `supported_protocols` +// TODO: for the above new settings, link to their configuration settings. -These changes are made automatically by the migration script. +[[breaking-changes-single-output]] +==== Only one enabled output -In Filebeat, we refactored the configuration around when to close and when to -start ignoring files. Options like `close_older` and `force_close_older` were -changed or replaced with options from the `close_*` group. See the -{filebeat}/how-filebeat-works.html[How Filebeat Works] docs for details. These -changes are not made automatically by the migration script. +In versions prior to 6.0, you could enabled multiple outputs at the same time, +but only of different types. For example, you were able to enable the +Elasticsearch and Logstash outputs, but not two Logstash outputs. The drawback +of enabling multiple outputs was that the Beats that wait for acknowledgments +(Filebeat and Winlogbeat) before proceeding slowed down to the slowest output. +This implication was not obvious and hindered the use cases where multiple +outputs would have been useful. -==== Field renames +As part of the pipeline re-architecture that we did for 6.0, we removed the +option to enable multiple outputs at the same time. This helps with keeping the +pipeline simple and with clarifying the scope of outputs in Beats. -Beats 5.0 also comes with several changes in the exported fields. If you are -using these fields in Kibana dashboards, you will likely need to adjust the -dashbaords. +If you require multiple outputs, you have the following options: -Changes: +* use the Logstash output and then use Logstash to pipe the events to multiple + outputs +* run multiple instances of the same Beat -[options="header",] -|========================================================== -| Location | Old name | New Name -| Packetbeat HTTP module | http.phrase | http.response.phrase -| Packetbeat HTTP module | http.code | http.response.code -| Packetbeat HTTP module | http.response_headers | http.response.headers -| Packetbeat HTTP module | http.request_headers | http.request.headers -| Packetbeat HTTP module | http.params | http.request.params -| Packetbeat HTTP module | http.content_length | http.response.headers.content-length -| Packetbeat HTTP module | http.content_length | http.response.headers.content-length -| Packetbeat DNS module | dns.flags.recursion_allowed | dns.flags.recursion_available -| Packetbeat DNS module | dns.flags.recursion_allowed | dns.flags.recursion_available -|========================================================== +If you used the `file` or `console` outputs for debugging purposes, in addition +to the main output, we recommend using the `-d "publish"` option which logs the +published events in the Filebeat logs. -In addition, the unused `count` field was removed from all Packetbeat modules. +[[breaking-changes-types]] +==== Filebeat prospector type and document type changes -==== Installation paths +The `document_type` setting, from the prospector configuration, was removed +because the `_type` concept is being removed from Elasticsearch. Instead of the +`document_type` setting, you can use a custom field. -For 5.0 we have refactored the {filebeat}/directory-layout.html[directory -layout] of the Beats, so they are more consistent and in-line with the best -practices of each operating system. +This has led also to the rename of the `input_type` configuration setting to +`type`. This change is backwards compatible because the old setting still +works. However, the `input_type` output field was renamed to `prospector_type`. -A notable change is that on the DEB/RPM installations, the binary is no longer -installed in `/usr/bin` but in `/usr/share//bin`. Instead, a simple -shell script is placed under `/usr/bin` that is helpful for executing the Beat -in foreground. It also sets the path settings to the same values as the init -script would use. +[[breaking-changes-default-config]] +==== Filebeat default prospector disabled in the configuration file -For example, here are the contents of the `/usr/bin/filebeat.sh` script: +The default startup behaviour (based on the included sample configuration) of +Filebeat was to read all the files matching the `/var/log/*.log` pattern. +Starting with version 6.0, Filebeat doesn't read any files in its default +configuration. However, you can easily enable the `system` module, for example +with a CLI flag: +["source","sh",subs="attributes"] +---- +filebeat --modules=system +---- -[source,shell] ------------------------------------------------------------------------------- -> cat /usr/bin/filebeat.sh -#!/bin/bash +[[breaking-changes-import-dashboards]] +==== Changes for importing the Kibana dashboards -# Script to run filebeat in foreground with the same path settings that -# the init script / systemd unit file would do. +The `import_dashboards` program, used to load the Kibana dashboards in previous +versions of Beats, is replaced by the `setup` command. For example, the +following command: + +["source","sh",subs="attributes"] +---- +./scripts/import_dashboards -user elastic -pass changeme +---- + +Can be replaced with: + +["source","sh",subs="attributes"] +---- +./filebeat setup -E "output.elasticsearch.username=elastic" -E "output.elasticsearch.password=changeme" +---- + +Note that the `-E` flags are only required if the Elasticsearch output is not +already configured in the configuration file. + +Besides the change in the commands, it's important to note that loading the +Kibana dashboards works differently in the 6.0 version of the stack. Prior to +6.0, the dashboards were inserted directly in the `.kibana` Elasticsearch +index. Starting with 6.0, the Beats use a Kibana server API. This means that +the Beat that loads the dashboards needs direct access to Kibana and that the +Kibana URL needs to be set. The option to set the Kibana URL is +`setup.kibana.host`, which you can set in the configuration file or via the +`-E` CLI flag: + + +["source","sh",subs="attributes"] +---- +./filebeat setup -E "setup.kibana.host=http://kibana-host:5601" +---- + +The default value for the Kibana host is `localhost:5601`. + +[[breaking-changes-filters]] +==== Metricbeat filters renamed to processors + +The "local" processors, which are configured at the module level, used to be +called `filters` in Metricbeat, but were offering similar functionality with +the global `processors`. A notable difference between the two was that the +filters accessed fields relatively to the metricset (for example, +`mount_point`), while the processors referred to fields by their fully +qualified name (for example, `system.filesystem.mount_point`). + +Starting with version 6.0, the `filters` are renamed to `processors` and they +can access the fields only by using the fully qualified names. + +[[breaking-changes-cgo]] +==== Binaries are dynamically compiled against libc + +Prior to 6.0, Metricbeat and Packetbeat were compiled using +https://golang.org/cmd/cgo/[Cgo], while Filebeat, Winlogbeat, and Heartbeat +were compiled using the pure Go compiler. One of the side-effects of compiling +with Cgo is that libc is dynamically compiled. Starting with 6.0, all the Beats +are compiled using Cgo and therefore dynamically compiled against libc. This +can reduce the portability of the binaries, but none of the supported platforms +is affected. -/usr/share/filebeat/bin/filebeat \ - -path.home /usr/share/filebeat \ - -path.config /etc/filebeat \ - -path.data /var/lib/filebeat \ - -path.logs /var/log/filebeat \ - $@ ------------------------------------------------------------------------------- From 92ac985caa9952c6d5fb5e87c0caaa83d2b36507 Mon Sep 17 00:00:00 2001 From: Silvia Mitter Date: Thu, 10 Aug 2017 22:58:17 +0200 Subject: [PATCH 065/139] Revert "Add SetValue method to libbeat common.MapStr (#4838)" (#4868) This reverts commit fa77316a01d620078c0311dc4a607b0487e8e610. --- libbeat/common/mapstr.go | 49 ------------------------------- libbeat/common/mapstr_test.go | 54 ----------------------------------- 2 files changed, 103 deletions(-) diff --git a/libbeat/common/mapstr.go b/libbeat/common/mapstr.go index d33b84bfd5a..c38977d10f2 100644 --- a/libbeat/common/mapstr.go +++ b/libbeat/common/mapstr.go @@ -138,15 +138,6 @@ func (m MapStr) Put(key string, value interface{}) (interface{}, error) { return walkMap(key, m, mapStrOperation{putOperation{value}, true}) } -// SetValue dereferences a value if it is a pointer. Sets the dereferenced value if not nil. -// If value is a MapStr or an array, the value is set if not empty. -// Supported data types so far: *string, *int, *boolean, common.MapStr, array[]int, array[]string. -// Values of unsupported types are set if they are not nil. -// Sets a value for a given key if the (dereferenced) value is not nil or empty. -func (m MapStr) SetValue(key string, value interface{}) { - walkMap(key, m, mapStrOperation{setValueOperation{value}, true}) -} - // StringToPrint returns the MapStr as pretty JSON. func (m MapStr) StringToPrint() string { json, err := json.MarshalIndent(m, "", " ") @@ -389,43 +380,3 @@ func (op putOperation) Do(key string, data MapStr) (interface{}, error) { data[key] = op.Value return existingValue, nil } - -type setValueOperation struct { - Value interface{} -} - -func (op setValueOperation) Do(key string, data MapStr) (interface{}, error) { - if op.Value == nil { - return data, nil - } - - switch op.Value.(type) { - case *bool: - if newVal := op.Value.(*bool); newVal != nil { - data[key] = *newVal - } - case *int: - if newVal := op.Value.(*int); newVal != nil { - data[key] = *newVal - } - case *string: - if newVal := op.Value.(*string); newVal != nil { - data[key] = *newVal - } - case MapStr: - if valMap := op.Value.(MapStr); len(valMap) > 0 { - data[key] = valMap - } - case []int: - if valArr := op.Value.([]int); len(valArr) > 0 { - data[key] = valArr - } - case []string: - if valArr := op.Value.([]string); len(valArr) > 0 { - data[key] = valArr - } - default: - data[key] = op.Value - } - return data, nil -} diff --git a/libbeat/common/mapstr_test.go b/libbeat/common/mapstr_test.go index 403b986fbbf..633032a8f8f 100644 --- a/libbeat/common/mapstr_test.go +++ b/libbeat/common/mapstr_test.go @@ -221,60 +221,6 @@ func TestMapStrPut(t *testing.T) { assert.Equal(t, MapStr{"subMap": MapStr{"newMap": MapStr{"a": 1}}}, m) } -func TestMapStrSet(t *testing.T) { - m := MapStr{ - "i1": 123, - "s1": "123", - "b1": false, - "x3": MapStr{ - "b41": "val.b41", - }, - } - type io struct { - Key string - Val interface{} - Fetch string - Expected interface{} - } - - mapVal := MapStr{"newKey": "newVal"} - arrStrVal := []string{"v1", "v2"} - arrIntVal := []int{1, 2, 3} - str := "strPtr" - var emptyStrPtr *string - i := 44 - var emptyIntPtr *int - b := false - var emptyBoolPtr *bool - tests := []io{ - {Key: "x3.b42", Val: "b42New", Fetch: "x3", Expected: MapStr{"b41": "val.b41", "b42": "b42New"}}, - {Key: "m1", Val: mapVal, Fetch: "m1", Expected: mapVal}, - {Key: "m2", Val: MapStr{}, Fetch: "m2", Expected: nil}, - {Key: "a1", Val: arrStrVal, Fetch: "a1", Expected: arrStrVal}, - {Key: "a2", Val: []string{}, Fetch: "a2", Expected: nil}, - {Key: "a3", Val: arrIntVal, Fetch: "a3", Expected: arrIntVal}, - {Key: "a4", Val: []int{}, Fetch: "a2", Expected: nil}, - {Key: "s1", Val: nil, Fetch: "s1", Expected: "123"}, - {Key: "s1", Val: "s1New", Fetch: "s1", Expected: "s1New"}, - {Key: "s2", Val: emptyStrPtr, Fetch: "s2", Expected: nil}, - {Key: "s3", Val: &str, Fetch: "s3", Expected: "strPtr"}, - {Key: "i1", Val: nil, Fetch: "i1", Expected: 123}, - {Key: "i1", Val: 456, Fetch: "i1", Expected: 456}, - {Key: "i2", Val: emptyIntPtr, Fetch: "i2", Expected: nil}, - {Key: "i3", Val: &i, Fetch: "i3", Expected: 44}, - {Key: "b1", Val: nil, Fetch: "b1", Expected: false}, - {Key: "b1", Val: true, Fetch: "b1", Expected: true}, - {Key: "b2", Val: emptyBoolPtr, Fetch: "b2", Expected: nil}, - {Key: "b3", Val: &b, Fetch: "b3", Expected: false}, - } - for idx, test := range tests { - m.SetValue(test.Key, test.Val) - fetched, _ := m.GetValue(test.Fetch) - errMsg := fmt.Sprintf("Failed for %v: Expected %v, Received %v", idx, test.Expected, fetched) - assert.Equal(t, test.Expected, fetched, errMsg) - } -} - func TestClone(t *testing.T) { assert := assert.New(t) From 5adf7e148c6435830801657225ca7a911e06921a Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Fri, 11 Aug 2017 11:03:50 +0300 Subject: [PATCH 066/139] Fix missing MongoDB config from the `modules.d` folder (#4870) The command that collected the configurations, used something like this to list the modules: ls module | grep -v .go Problem was, `mongodb` matched the `.go` grep, so it was excluded :) This PR uses `find` to list the directories. --- CHANGELOG.asciidoc | 3 ++- filebeat/Makefile | 2 +- metricbeat/Makefile | 2 +- metricbeat/modules.d/mongodb.yml.disabled | 16 ++++++++++++++++ 4 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 metricbeat/modules.d/mongodb.yml.disabled diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 61c0d7cb411..9bf96c63123 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -52,6 +52,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Metricbeat* - Support `npipe` protocol (Windows) in Docker module. {pull}4751[4751] +- Added missing mongodb configuration file to the `modules.d` folder. {pull}4870[4870] *Packetbeat* @@ -80,7 +81,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Add graphite protocol metricbeat module. {pull}4734[4734] - Add http server metricset to support push metrics via http. {pull}4770[4770] - Make config object public for graphite and http server {pull}4820[4820] - + *Packetbeat* *Winlogbeat* diff --git a/filebeat/Makefile b/filebeat/Makefile index 7ca0c0fb018..040c27b8965 100644 --- a/filebeat/Makefile +++ b/filebeat/Makefile @@ -41,7 +41,7 @@ configs: python-env @${PYTHON_ENV}/bin/python ${ES_BEATS}/script/config_collector.py --beat ${BEAT_NAME} --full $(PWD) >> _meta/beat.reference.yml @cat ${ES_BEATS}/filebeat/_meta/common.reference.p2.yml >> _meta/beat.reference.yml @rm -rf modules.d && mkdir -p modules.d - @for MODULE in `ls module | grep -v .go`; do cp -a $(PWD)/module/$$MODULE/_meta/config.yml modules.d/$$MODULE.yml.disabled; done + @for MODULE in `find module -type d -maxdepth 1 -mindepth 1 -exec basename {} \;`; do cp -a $(PWD)/module/$$MODULE/_meta/config.yml modules.d/$$MODULE.yml.disabled; done @chmod go-w modules.d/* # Collects all module docs diff --git a/metricbeat/Makefile b/metricbeat/Makefile index 096c662a25f..b69e7b1914f 100644 --- a/metricbeat/Makefile +++ b/metricbeat/Makefile @@ -46,7 +46,7 @@ configs: python-env @cat ${ES_BEATS}/metricbeat/_meta/common.reference.yml > _meta/beat.reference.yml @${PYTHON_ENV}/bin/python ${ES_BEATS}/script/config_collector.py --beat ${BEAT_NAME} --full $(PWD) >> _meta/beat.reference.yml @rm -rf modules.d && mkdir -p modules.d - @for MODULE in `ls module | grep -v .go`; do cp -a $(PWD)/module/$$MODULE/_meta/config.yml modules.d/$$MODULE.yml.disabled; done + @for MODULE in `find module -type d -maxdepth 1 -mindepth 1 -exec basename {} \;`; do cp -a $(PWD)/module/$$MODULE/_meta/config.yml modules.d/$$MODULE.yml.disabled; done @chmod go-w modules.d/* @# Enable system by default: @if [ -f modules.d/system.yml.disabled ]; then mv modules.d/system.yml.disabled modules.d/system.yml; fi diff --git a/metricbeat/modules.d/mongodb.yml.disabled b/metricbeat/modules.d/mongodb.yml.disabled new file mode 100644 index 00000000000..fb6b19e7c68 --- /dev/null +++ b/metricbeat/modules.d/mongodb.yml.disabled @@ -0,0 +1,16 @@ +- module: mongodb + metricsets: ["dbstats", "status"] + period: 10s + + # The hosts must be passed as MongoDB URLs in the format: + # [mongodb://][user:pass@]host[:port]. + # The username and password can also be set using the respective configuration + # options. The credentials in the URL take precedence over the username and + # password configuration options. + hosts: ["localhost:27017"] + + # Username to use when connecting to MongoDB. Empty by default. + #username: user + + # Password to use when connecting to MongoDB. Empty by default. + #password: pass From 93cbda369f035b9d2f2722ff1d923c3a159180b1 Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Fri, 11 Aug 2017 12:52:41 +0200 Subject: [PATCH 067/139] Update build_docs.sh script to support dev-guide (#4873) Currently the dev-guide is not build as part of `make docs`. This adjusments to the scripts and Makefile add the dev-guide and offer more flexibility for docs build also for community beats. The script was also moved out of libbeat to the global script directory as it does not directly belong to libbeat. --- Makefile | 9 +++++---- libbeat/scripts/Makefile | 5 ++--- libbeat/scripts/build_docs.sh | 24 ------------------------ script/build_docs.sh | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 31 deletions(-) delete mode 100755 libbeat/scripts/build_docs.sh create mode 100755 script/build_docs.sh diff --git a/Makefile b/Makefile index 38847cdffc1..4a63e5d63df 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -BUILD_DIR=build +BUILD_DIR=$(CURDIR)/build COVERAGE_DIR=$(BUILD_DIR)/coverage BEATS=packetbeat filebeat winlogbeat metricbeat heartbeat auditbeat PROJECTS=libbeat $(BEATS) @@ -94,7 +94,8 @@ beats-dashboards: # Builds the documents for each beat .PHONY: docs docs: - @sh libbeat/scripts/build_docs.sh $(PROJECTS) + @$(foreach var,$(PROJECTS),BUILD_DIR=${BUILD_DIR} $(MAKE) -C $(var) docs || exit 1;) + sh ./script/build_docs.sh dev-guide github.com/elastic/beats/docs/dev-guide ${BUILD_DIR} .PHONY: package package: update beats-dashboards @@ -102,7 +103,7 @@ package: update beats-dashboards @echo "Start building the dashboards package" @mkdir -p build/upload/ - @BUILD_DIR=$(CURDIR)/build SNAPSHOT=$(SNAPSHOT) $(MAKE) -C dev-tools/packer package-dashboards $(CURDIR)/build/upload/build_id.txt + @BUILD_DIR=${BUILD_DIR} SNAPSHOT=$(SNAPSHOT) $(MAKE) -C dev-tools/packer package-dashboards ${BUILD_DIR}/upload/build_id.txt @mv build/upload build/dashboards-upload @# Copy build files over to top build directory @@ -110,7 +111,7 @@ package: update beats-dashboards @$(foreach var,$(BEATS),cp -r $(var)/build/upload/ build/upload/$(var) || exit 1;) @cp -r build/dashboards-upload build/upload/dashboards @# Run tests on the generated packages. - @go test ./dev-tools/package_test.go -files "$(CURDIR)/build/upload/*/*" + @go test ./dev-tools/package_test.go -files "${BUILD_DIR}/upload/*/*" # Upload nightly builds to S3 .PHONY: upload-nightlies-s3 diff --git a/libbeat/scripts/Makefile b/libbeat/scripts/Makefile index 93f626c02c4..1b757bedad1 100755 --- a/libbeat/scripts/Makefile +++ b/libbeat/scripts/Makefile @@ -290,13 +290,12 @@ endif .PHONY: docs docs: ## @build Builds the documents for the beat - sh ${ES_BEATS}/libbeat/scripts/build_docs.sh ${BEAT_NAME} + sh ${ES_BEATS}/script/build_docs.sh ${BEAT_NAME} ${BEAT_PATH}/docs ${BUILD_DIR} .PHONY: docs-preview docs-preview: ## @build Preview the documents for the beat in the browser - if [ ! -d "build/docs" ]; then $(MAKE) docs; fi; - ${BUILD_DIR}/docs/build_docs.pl --chunk=1 -open chunk=1 -open --doc ${BEAT_GOPATH}/src/github.com/elastic/beats/${BEAT_NAME}/docs/index.asciidoc -out ${BUILD_DIR}/html_docs + PREVIEW=1 $(MAKE) docs .PHONY: index-template index-template: ## @build Generate index templates for the given $VERSION. This is for manual testing. diff --git a/libbeat/scripts/build_docs.sh b/libbeat/scripts/build_docs.sh deleted file mode 100755 index 0936051d8af..00000000000 --- a/libbeat/scripts/build_docs.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -set -e - -# Checks if docs clone already exists -if [ ! -d "build/docs" ]; then - # Only head is cloned - git clone --depth=1 https://github.com/elastic/docs.git build/docs -else - echo "build/docs already exists. Not cloning." -fi - -# beatnames must be passed as parameters. Example: packetbeat filebeat -for name in $* -do - index="${GOPATH%%:*}/src/github.com/elastic/beats/${name}/docs/index.asciidoc" - echo $index - if [ -f "$index" ]; then - echo "Building docs for ${name}..." - dest_dir="build/html_docs/${name}" - mkdir -p "$dest_dir" - ./build/docs/build_docs.pl --doc "$index" -out "$dest_dir" - fi -done diff --git a/script/build_docs.sh b/script/build_docs.sh new file mode 100755 index 00000000000..9a77fa53608 --- /dev/null +++ b/script/build_docs.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +set -e + +name=$1 +path=$2 +build_dir=$3 + +docs_dir=$build_dir/docs +html_dir=$build_dir/html_docs + +# Checks if docs clone already exists +if [ ! -d $docs_dir ]; then + # Only head is cloned + git clone --depth=1 https://github.com/elastic/docs.git $docs_dir +else + echo "$docs_dir already exists. Not cloning." +fi + + +index="${GOPATH%%:*}/src/${path}/index.asciidoc" + +if [ -f "$index" ]; then + echo "Building docs for ${name}..." + dest_dir="$html_dir/${name}" + mkdir -p "$dest_dir" + params="" + if [ "$PREVIEW" = "1" ]; then + params="--chunk=1 -open chunk=1 -open" + fi + $docs_dir/build_docs.pl $params --doc "$index" -out "$dest_dir" +fi From 0718b44fdad27d38367eb48e1637dfbf20b7e1d3 Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Fri, 11 Aug 2017 16:43:34 +0300 Subject: [PATCH 068/139] Bootstrap xpack password (#4875) This is meant to make it easy for us to test with security enabled. --- testing/environments/docker/elasticsearch/Dockerfile-snapshot | 3 +++ 1 file changed, 3 insertions(+) diff --git a/testing/environments/docker/elasticsearch/Dockerfile-snapshot b/testing/environments/docker/elasticsearch/Dockerfile-snapshot index 414bbef7bf0..2491e558254 100644 --- a/testing/environments/docker/elasticsearch/Dockerfile-snapshot +++ b/testing/environments/docker/elasticsearch/Dockerfile-snapshot @@ -41,6 +41,9 @@ RUN if [ ${XPACK} = "1" ]; then elasticsearch-plugin install --batch ${DOWNLOAD_ RUN elasticsearch-plugin install --batch ${DOWNLOAD_URL}/elasticsearch-plugins/ingest-user-agent/ingest-user-agent-${ELASTIC_VERSION}.zip?c=${CACHE_BUST} RUN elasticsearch-plugin install --batch ${DOWNLOAD_URL}/elasticsearch-plugins/ingest-geoip/ingest-geoip-${ELASTIC_VERSION}.zip?c=${CACHE_BUST} +# Set bootstrap password (for when security is used) +RUN if [ ${XPACK} = "1" ]; then elasticsearch-keystore create; echo "changeme" | elasticsearch-keystore add -x 'bootstrap.password'; fi + COPY config/elasticsearch.yml config/ COPY config/log4j2.properties config/ COPY bin/es-docker bin/es-docker From e8f55ba12370166aefca53ba576e479fe6c330b3 Mon Sep 17 00:00:00 2001 From: Steffen Siering Date: Fri, 11 Aug 2017 17:13:55 +0200 Subject: [PATCH 069/139] Fix wrong timestamp in heartbeat events (#4855) --- CHANGELOG.asciidoc | 1 + heartbeat/monitors/util.go | 12 +++++------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 9bf96c63123..3c9b66414b5 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -48,6 +48,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Heartbeat* - Fix monitor.name being empty by default. {issue}4852[4852] +- Fix wrong event timestamps. {issue}4851[4851] *Metricbeat* diff --git a/heartbeat/monitors/util.go b/heartbeat/monitors/util.go index 503b59104b3..88b58984e2f 100644 --- a/heartbeat/monitors/util.go +++ b/heartbeat/monitors/util.go @@ -97,7 +97,11 @@ func MakeJob(settings JobSettings, f func() (common.MapStr, []TaskRunner, error) }, }) - return &funcJob{settings, annotated(settings, time.Now(), f)} + return &funcJob{settings, func() (beat.Event, []JobRunner, error) { + // Create and run new annotated Job whenever the Jobs root is Task is executed. + // This will set the jobs active start timestamp to the time.Now(). + return annotated(settings, time.Now(), f)() + }} } // annotated lifts a TaskRunner into a job, annotating events with common fields and start timestamp. @@ -406,12 +410,6 @@ func (f *funcJob) Run() (beat.Event, []JobRunner, error) { return f.run() } func (f funcTask) Run() (common.MapStr, []TaskRunner, error) { return f.run() } -/* -func (f funcTask) annotated(settings JobSettings, start time.Time) TaskRunner { - return annotated(settings, start, f.run) -} -*/ - // Unpack sets PingMode from a constant string. Unpack will be called by common.Unpack when // unpacking into an IPSettings type. func (p *PingMode) Unpack(s string) error { From c48a32e5015173368c6f3ede06eb3010401b01c8 Mon Sep 17 00:00:00 2001 From: Loek van Gool Date: Sat, 12 Aug 2017 15:21:03 +0200 Subject: [PATCH 070/139] Fix MySQL CRUD expression (#4857) Fix MySQL CRUD expression --- CHANGELOG.asciidoc | 1 + .../_meta/kibana/default/dashboard/Metricbeat-mysql.json | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 3c9b66414b5..a0333c8ef44 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -54,6 +54,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Support `npipe` protocol (Windows) in Docker module. {pull}4751[4751] - Added missing mongodb configuration file to the `modules.d` folder. {pull}4870[4870] +- Fix wrong MySQL CRUD queries timelion visualization {pull}4857[4857] *Packetbeat* diff --git a/metricbeat/module/mysql/_meta/kibana/default/dashboard/Metricbeat-mysql.json b/metricbeat/module/mysql/_meta/kibana/default/dashboard/Metricbeat-mysql.json index 1e283b345b7..8337da99a26 100644 --- a/metricbeat/module/mysql/_meta/kibana/default/dashboard/Metricbeat-mysql.json +++ b/metricbeat/module/mysql/_meta/kibana/default/dashboard/Metricbeat-mysql.json @@ -73,7 +73,7 @@ "title": "MySQL commands", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"MySQL commands\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(*, metric='avg:mysql.status.command.select').derivative().label(\\\"SELECT\\\"),.es(*, metric='avg:mysql.status.command.insert').derivative().label(\\\"INSERT\\\"),.es(*, metric='avg:mysql.status.command.insert').derivative().label(\\\"UPDATE\\\"),.es(*, metric='avg:mysql.status.command.insert').derivative().label(\\\"DELETE\\\")\",\"interval\":\"1m\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"MySQL commands\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(*, metric='avg:mysql.status.command.select').derivative().label(\\\"SELECT\\\"),.es(*, metric='avg:mysql.status.command.insert').derivative().label(\\\"INSERT\\\"),.es(*, metric='avg:mysql.status.command.update').derivative().label(\\\"UPDATE\\\"),.es(*, metric='avg:mysql.status.command.delete').derivative().label(\\\"DELETE\\\")\",\"interval\":\"1m\"},\"aggs\":[],\"listeners\":{}}" }, "id": "1eda2280-0008-11e7-82f3-2f380154876c", "type": "visualization", @@ -165,4 +165,4 @@ } ], "version": "6.0.0-alpha3-SNAPSHOT" -} \ No newline at end of file +} From f6f455f5356bfcda8867e4a40954e689c8edc430 Mon Sep 17 00:00:00 2001 From: Parker Zhou Date: Mon, 14 Aug 2017 17:10:53 +0800 Subject: [PATCH 071/139] metricbeat: enhance the system/diskio, add more metrics - iostat.read_request_merged_per_sec - iostat.write_request_merged_per_sec - iostat.read_request_per_sec - iostat.write_request_per_sec - iostat.read_byte_per_sec - iostat.write_byte_per_sec - iostat.avg_request_size - iostat.avg_queue_size - iostat.await - iostat.service_time - iostat.busy these metrics has same meaninig of `iostat`. docs and data.json are both updated. this feature is only avaliable on linux. --- metricbeat/docs/fields.asciidoc | 88 +++++++++++++++++ metricbeat/github.com/elastic/beats | 1 + .../module/system/diskio/_meta/data.json | 15 ++- .../module/system/diskio/_meta/fields.yml | 55 +++++++++++ metricbeat/module/system/diskio/diskio.go | 32 +++++- metricbeat/module/system/diskio/diskstat.go | 34 +++++++ .../module/system/diskio/diskstat_linux.go | 97 +++++++++++++++++++ .../system/diskio/diskstat_linux_test.go | 14 +++ .../module/system/diskio/diskstat_other.go | 27 ++++++ metricbeat/tests/system/test_system.py | 30 +++++- 10 files changed, 390 insertions(+), 3 deletions(-) create mode 160000 metricbeat/github.com/elastic/beats create mode 100644 metricbeat/module/system/diskio/diskstat.go create mode 100644 metricbeat/module/system/diskio/diskstat_linux.go create mode 100644 metricbeat/module/system/diskio/diskstat_linux_test.go create mode 100644 metricbeat/module/system/diskio/diskstat_other.go diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 08191e8c8ac..be3da81a9ed 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -8772,6 +8772,94 @@ type: long The total number of of milliseconds spent doing I/Os. +[float] +=== `system.diskio.iostat.read_request_merged_per_sec` + +type: float + +The number of read requests merged per second that were queued to the device. + + +[float] +=== `system.diskio.iostat.write_request_merged_per_sec` + +type: float + +The number of write requests merged per second that were queued to the device. + + +[float] +=== `system.diskio.iostat.read_request_per_sec` + +type: float + +The number of read requests that were issued to the device per second + + +[float] +=== `system.diskio.iostat.write_request_per_sec` + +type: float + +The number of write requests that were issued to the device per second + + +[float] +=== `system.diskio.iostat.read_byte_per_sec` + +type: float + +The number of Bytes read from the device per second. + + +[float] +=== `system.diskio.iostat.write_byte_per_sec` + +type: float + +The number of Bytes write from the device per second. + + +[float] +=== `system.diskio.iostat.avg_request_size` + +type: float + +The average size (in sectors) of the requests that were issued to the device. + + +[float] +=== `system.diskio.iostat.avg_queue_size` + +type: float + +The average queue length of the requests that were issued to the device. + + +[float] +=== `system.diskio.iostat.await` + +type: float + +The average queue length of the requests that were issued to the device. + + +[float] +=== `system.diskio.iostat.service_time` + +type: float + +The average service time (in milliseconds) for I/O requests that were issued to the device. + + +[float] +=== `system.diskio.iostat.busy` + +type: float + +Percentage of CPU time during which I/O requests were issued to the device (bandwidth utilization for the device). Device saturation occurs when this value is close to 100%. + + [float] == filesystem fields diff --git a/metricbeat/github.com/elastic/beats b/metricbeat/github.com/elastic/beats new file mode 160000 index 00000000000..2463fd83302 --- /dev/null +++ b/metricbeat/github.com/elastic/beats @@ -0,0 +1 @@ +Subproject commit 2463fd833024b2782962b18060ce642af2bdf1f4 diff --git a/metricbeat/module/system/diskio/_meta/data.json b/metricbeat/module/system/diskio/_meta/data.json index be73c483c72..be86541464f 100644 --- a/metricbeat/module/system/diskio/_meta/data.json +++ b/metricbeat/module/system/diskio/_meta/data.json @@ -25,8 +25,21 @@ "bytes": 2281472, "count": 224, "time": 29700 + }, + "iostat": { + "avg_queue_size": 0.020000, + "avg_request_size": 5120.000000, + "await": 0.010000, + "busy": 0.100000, + "read_byte_per_sec": 1034.420132, + "read_request_per_sec": 2.938410, + "read_request_merged_per_sec": 0.000000, + "service_time": 0.030000, + "write_byte_per_sec": 20531.328321, + "write_request_per_sec": 4.010025, + "write_request_merged_per_sec": 0.000000 } } }, "type": "metricsets" -} \ No newline at end of file +} diff --git a/metricbeat/module/system/diskio/_meta/fields.yml b/metricbeat/module/system/diskio/_meta/fields.yml index 7bc58269a1a..57f34696505 100644 --- a/metricbeat/module/system/diskio/_meta/fields.yml +++ b/metricbeat/module/system/diskio/_meta/fields.yml @@ -54,3 +54,58 @@ type: long description: > The total number of of milliseconds spent doing I/Os. + + - name: iostat.read_request_merged_per_sec + type: float + description: > + The number of read requests merged per second that were queued to the device. + + - name: iostat.write_request_merged_per_sec + type: float + description: > + The number of write requests merged per second that were queued to the device. + + - name: iostat.read_request_per_sec + type: float + description: > + The number of read requests that were issued to the device per second + + - name: iostat.write_request_per_sec + type: float + description: > + The number of write requests that were issued to the device per second + + - name: iostat.read_byte_per_sec + type: float + description: > + The number of Bytes read from the device per second. + + - name: iostat.write_byte_per_sec + type: float + description: > + The number of Bytes write from the device per second. + + - name: iostat.avg_request_size + type: float + description: > + The average size (in sectors) of the requests that were issued to the device. + + - name: iostat.avg_queue_size + type: float + description: > + The average queue length of the requests that were issued to the device. + + - name: iostat.await + type: float + description: > + The average queue length of the requests that were issued to the device. + + - name: iostat.service_time + type: float + description: > + The average service time (in milliseconds) for I/O requests that were issued to the device. + + - name: iostat.busy + type: float + description: > + Percentage of CPU time during which I/O requests were issued to the device (bandwidth utilization for the device). Device saturation occurs when this value is close to 100%. diff --git a/metricbeat/module/system/diskio/diskio.go b/metricbeat/module/system/diskio/diskio.go index fb3032ed448..765a9ae4f8b 100644 --- a/metricbeat/module/system/diskio/diskio.go +++ b/metricbeat/module/system/diskio/diskio.go @@ -20,11 +20,16 @@ func init() { // MetricSet for fetching system disk IO metrics. type MetricSet struct { mb.BaseMetricSet + statistics *DiskIOStat } // New is a mb.MetricSetFactory that returns a new MetricSet. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - return &MetricSet{base}, nil + ms := &MetricSet{ + BaseMetricSet: base, + statistics: NewDiskIOStat(), + } + return ms, nil } // Fetch fetches disk IO metrics from the OS. @@ -34,8 +39,12 @@ func (m *MetricSet) Fetch() ([]common.MapStr, error) { return nil, errors.Wrap(err, "disk io counters") } + // open a sampling means sample the current cpu counter + m.statistics.OpenSampling() + events := make([]common.MapStr, 0, len(stats)) for _, counters := range stats { + event := common.MapStr{ "name": counters.Name, "read": common.MapStr{ @@ -52,6 +61,24 @@ func (m *MetricSet) Fetch() ([]common.MapStr, error) { "time": counters.IoTime, }, } + + extraMetrics, err := m.statistics.CalIOStatistics(counters) + if err == nil { + event["iostat"] = common.MapStr{ + "read_request_merged_per_sec": extraMetrics.ReadRequestMergeCountPerSec, + "write_request_merged_per_sec": extraMetrics.WriteRequestMergeCountPerSec, + "read_request_per_sec": extraMetrics.ReadRequestCountPerSec, + "write_request_per_sec": extraMetrics.WriteRequestCountPerSec, + "read_byte_per_sec": extraMetrics.ReadBytesPerSec, + "write_byte_per_sec": extraMetrics.WriteBytesPerSec, + "avg_request_size": extraMetrics.AvgRequestSize, + "avg_queue_size": extraMetrics.AvgQueueSize, + "await": extraMetrics.AvgAwaitTime, + "service_time": extraMetrics.AvgServiceTime, + "busy": extraMetrics.BusyPct, + } + } + events = append(events, event) if counters.SerialNumber != "" { @@ -59,5 +86,8 @@ func (m *MetricSet) Fetch() ([]common.MapStr, error) { } } + // open a sampling means store the last cpu counter + m.statistics.CloseSampling() + return events, nil } diff --git a/metricbeat/module/system/diskio/diskstat.go b/metricbeat/module/system/diskio/diskstat.go new file mode 100644 index 00000000000..dace55cbd1d --- /dev/null +++ b/metricbeat/module/system/diskio/diskstat.go @@ -0,0 +1,34 @@ +// +build darwin freebsd linux windows + +package diskio + +import ( + "github.com/shirou/gopsutil/disk" + + sigar "github.com/elastic/gosigar" +) + +// mapping fields which output by `iostat -x` on linux +// +// Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await r_await w_await svctm %util +// sda 0.06 0.78 0.09 0.27 9.42 8.06 48.64 0.00 1.34 0.99 1.45 0.77 0.03 +type DiskIOMetric struct { + ReadRequestMergeCountPerSec float64 `json:"rrqmCps"` + WriteRequestMergeCountPerSec float64 `json:"wrqmCps"` + ReadRequestCountPerSec float64 `json:"rrqCps"` + WriteRequestCountPerSec float64 `json:"wrqCps"` + // using bytes instead of sector + ReadBytesPerSec float64 `json:"rBps"` + WriteBytesPerSec float64 `json:"wBps"` + AvgRequestSize float64 `json:"avgrqSz"` + AvgQueueSize float64 `json:"avgquSz"` + AvgAwaitTime float64 `json:"await"` + AvgServiceTime float64 `json:"svctm"` + BusyPct float64 `json:"busy"` +} + +type DiskIOStat struct { + lastDiskIOCounters map[string]disk.IOCountersStat + lastCpu sigar.Cpu + curCpu sigar.Cpu +} diff --git a/metricbeat/module/system/diskio/diskstat_linux.go b/metricbeat/module/system/diskio/diskstat_linux.go new file mode 100644 index 00000000000..f7ef4333506 --- /dev/null +++ b/metricbeat/module/system/diskio/diskstat_linux.go @@ -0,0 +1,97 @@ +// +build linux + +package diskio + +import ( + "github.com/pkg/errors" + "github.com/shirou/gopsutil/disk" + + "github.com/elastic/beats/metricbeat/module/system" +) + +func Get_CLK_TCK() uint32 { + //return uint32(C.sysconf(C._SC_CLK_TCK)) + //NOTE: _SC_CLK_TCK should be fetched from sysconf using cgo + return uint32(100) +} + +func NewDiskIOStat() *DiskIOStat { + d := &DiskIOStat{} + d.lastDiskIOCounters = make(map[string]disk.IOCountersStat) + return d +} + +// create current cpu sampling +// need call as soon as get IOCounters +func (stat *DiskIOStat) OpenSampling() error { + return stat.curCpu.Get() +} + +func (stat *DiskIOStat) CalIOStatistics(counter disk.IOCountersStat) (DiskIOMetric, error) { + var last disk.IOCountersStat + var ok bool + var result DiskIOMetric + + // if last counter not found, create one and return all 0 + if last, ok = stat.lastDiskIOCounters[counter.Name]; !ok { + stat.lastDiskIOCounters[counter.Name] = counter + return result, nil + } + + // calculate the delta ms between the CloseSampling and OpenSampling + deltams := 1000.0 * float64(stat.curCpu.Total()-stat.lastCpu.Total()) / float64(system.NumCPU) / float64(Get_CLK_TCK()) + if deltams <= 0 { + return result, errors.New("The delta cpu time between close sampling and open sampling is less or equal to 0") + } + + rd_ios := counter.ReadCount - last.ReadCount + rd_merges := counter.MergedReadCount - last.MergedReadCount + rd_bytes := counter.ReadBytes - last.ReadBytes + rd_ticks := counter.ReadTime - last.ReadTime + wr_ios := counter.WriteCount - last.WriteCount + wr_merges := counter.MergedWriteCount - last.MergedWriteCount + wr_bytes := counter.WriteBytes - last.WriteBytes + wr_ticks := counter.WriteTime - last.WriteTime + ticks := counter.IoTime - last.IoTime + aveq := counter.WeightedIO - last.WeightedIO + n_ios := rd_ios + wr_ios + n_ticks := rd_ticks + wr_ticks + n_bytes := rd_bytes + wr_bytes + size := float64(0) + wait := float64(0) + svct := float64(0) + + if n_ios > 0 { + size = float64(n_bytes) / float64(n_ios) + wait = float64(n_ticks) / float64(n_ios) + svct = float64(ticks) / float64(n_ios) + } + + queue := float64(aveq) / deltams + per_sec := func(x uint64) float64 { + return 1000.0 * float64(x) / deltams + } + + result.ReadRequestMergeCountPerSec = per_sec(rd_merges) + result.WriteRequestMergeCountPerSec = per_sec(wr_merges) + result.ReadRequestCountPerSec = per_sec(rd_ios) + result.WriteRequestCountPerSec = per_sec(wr_ios) + result.ReadBytesPerSec = per_sec(rd_bytes) + result.WriteBytesPerSec = per_sec(wr_bytes) + result.AvgRequestSize = size + result.AvgQueueSize = queue + result.AvgAwaitTime = wait + result.AvgServiceTime = svct + result.BusyPct = 100.0 * float64(ticks) / deltams + if result.BusyPct > 100.0 { + result.BusyPct = 100.0 + } + + stat.lastDiskIOCounters[counter.Name] = counter + return result, nil + +} + +func (stat *DiskIOStat) CloseSampling() { + stat.lastCpu = stat.curCpu +} diff --git a/metricbeat/module/system/diskio/diskstat_linux_test.go b/metricbeat/module/system/diskio/diskstat_linux_test.go new file mode 100644 index 00000000000..ff806e5cba1 --- /dev/null +++ b/metricbeat/module/system/diskio/diskstat_linux_test.go @@ -0,0 +1,14 @@ +// +build linux + +package diskio + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_Get_CLK_TCK(t *testing.T) { + //usually the tick is 100 + assert.Equal(t, uint32(100), Get_CLK_TCK()) +} diff --git a/metricbeat/module/system/diskio/diskstat_other.go b/metricbeat/module/system/diskio/diskstat_other.go new file mode 100644 index 00000000000..6f94950eaf1 --- /dev/null +++ b/metricbeat/module/system/diskio/diskstat_other.go @@ -0,0 +1,27 @@ +// +build darwin,cgo freebsd windows + +package diskio + +import ( + "github.com/pkg/errors" + "github.com/shirou/gopsutil/disk" +) + +func NewDiskIOStat() *DiskIOStat { + d := &DiskIOStat{} + d.lastDiskIOCounters = make(map[string]disk.IOCountersStat) + return d +} + +func (stat *DiskIOStat) OpenSampling() error { + return nil +} + +func (stat *DiskIOStat) CalIOStatistics(counter disk.IOCountersStat) (DiskIOMetric, error) { + var result DiskIOMetric + return result, errors.New("Not implemented out of linux") +} + +func (stat *DiskIOStat) CloseSampling() { + return +} diff --git a/metricbeat/tests/system/test_system.py b/metricbeat/tests/system/test_system.py index b0f2df4003e..582cc3078f5 100644 --- a/metricbeat/tests/system/test_system.py +++ b/metricbeat/tests/system/test_system.py @@ -27,6 +27,11 @@ SYSTEM_DISKIO_FIELDS = ["name", "read.count", "write.count", "read.bytes", "write.bytes", "read.time", "write.time", "io.time"] +SYSTEM_DISKIO_FIELDS_LINUX = ["name", "read.count", "write.count", "read.bytes", + "write.bytes", "read.time", "write.time", "io.time", + "iostat.read_request_merged_per_sec", "iostat.write_request_merged_per_sec", "iostat.read_request_per_sec", "iostat.write_request_per_sec", "iostat.read_byte_per_sec", "iostat.write_byte_per_sec" + "iostat.avg_request_size", "iostat.avg_queue_size", "iostat.await", "iostat.service_time", "iostat.busy"] + SYSTEM_FILESYSTEM_FIELDS = ["available", "device_name", "type", "files", "free", "free_files", "mount_point", "total", "used.bytes", "used.pct"] @@ -170,7 +175,7 @@ def test_load(self): cpu = evt["system"]["load"] self.assertItemsEqual(self.de_dot(SYSTEM_LOAD_FIELDS), cpu.keys()) - @unittest.skipUnless(re.match("(?i)win|linux|freebsd", sys.platform), "os") + @unittest.skipUnless(re.match("(?i)win|freebsd", sys.platform), "os") def test_diskio(self): """ Test system/diskio output. @@ -193,6 +198,29 @@ def test_diskio(self): diskio = evt["system"]["diskio"] self.assertItemsEqual(self.de_dot(SYSTEM_DISKIO_FIELDS), diskio.keys()) + @unittest.skipUnless(re.match("(?i)linux", sys.platform), "os") + def test_diskio_linux(self): + """ + Test system/diskio output on linux. + """ + self.render_config_template(modules=[{ + "name": "system", + "metricsets": ["diskio"], + "period": "5s" + }]) + proc = self.start_beat() + self.wait_until(lambda: self.output_lines() > 0) + proc.check_kill_and_wait() + self.assert_no_logged_warnings() + + output = self.read_output_json() + self.assertGreater(len(output), 0) + + for evt in output: + self.assert_fields_are_documented(evt) + diskio = evt["system"]["diskio"] + self.assertItemsEqual(self.de_dot(SYSTEM_DISKIO_FIELDS_LINUX), diskio.keys()) + @unittest.skipUnless(re.match("(?i)win|linux|darwin|freebsd|openbsd", sys.platform), "os") def test_filesystem(self): """ From 8bc9c80b43cf71b6347fd15e8ee3043bc4d9ca3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20P=C3=A9rez-Aradros=20Herce?= Date: Mon, 14 Aug 2017 12:18:14 +0200 Subject: [PATCH 072/139] Remove setup deprecation message (#4889) * Unmark setup as deprecated We decided to keep `-setup` as a shorthand for setup + run * Update `test output` help message --- libbeat/cmd/instance/beat.go | 4 ---- libbeat/cmd/run.go | 3 +-- libbeat/cmd/test/output.go | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/libbeat/cmd/instance/beat.go b/libbeat/cmd/instance/beat.go index ad0e0d1f82f..22afc618bdf 100644 --- a/libbeat/cmd/instance/beat.go +++ b/libbeat/cmd/instance/beat.go @@ -245,10 +245,6 @@ func (b *Beat) launch(bt beat.Creator) error { svc.HandleSignals(beater.Stop) - // TODO Deprecate this in favor of setup subcommand (7.0) - if setup { - cfgwarn.Deprecate("6.0", "-setup flag has been deprectad, use setup subcommand") - } err = b.loadDashboards(false) if err != nil { return err diff --git a/libbeat/cmd/run.go b/libbeat/cmd/run.go index b68d08e3997..19ae9a117d0 100644 --- a/libbeat/cmd/run.go +++ b/libbeat/cmd/run.go @@ -31,11 +31,10 @@ func genRunCmd(name, version string, beatCreator beat.Creator, runFlags *pflag.F // TODO deprecate in favor of subcommands (7.0): runCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("configtest")) - runCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("setup")) runCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("version")) runCmd.Flags().MarkDeprecated("version", "version flag has been deprectad, use version subcommand") - runCmd.Flags().MarkDeprecated("configtest", "setup flag has been deprectad, use configtest subcommand") + runCmd.Flags().MarkDeprecated("configtest", "configtest flag has been deprectad, use test config subcommand") if runFlags != nil { runCmd.Flags().AddFlagSet(runFlags) diff --git a/libbeat/cmd/test/output.go b/libbeat/cmd/test/output.go index c3b059e1caf..cba7cb57db8 100644 --- a/libbeat/cmd/test/output.go +++ b/libbeat/cmd/test/output.go @@ -14,7 +14,7 @@ import ( func GenTestOutputCmd(name, beatVersion string) *cobra.Command { return &cobra.Command{ Use: "output", - Short: "Test output works with current settings", + Short: "Test " + name + " can connect to the output by using the current settings", Run: func(cmd *cobra.Command, args []string) { b, err := instance.NewBeat(name, beatVersion) if err != nil { From fb3a7a32906ee35d05588a71c155d19079d2253c Mon Sep 17 00:00:00 2001 From: Monica Sarbu Date: Mon, 14 Aug 2017 14:06:50 +0300 Subject: [PATCH 073/139] - Set by the default the credentials for connecting to Kibana the same as for Elasticsearch (#4867) - Raise an error in case there are no dashboards to be imported --- CHANGELOG.asciidoc | 1 + libbeat/dashboards/dashboards.go | 84 ++++++++++++++--------------- libbeat/dashboards/importer.go | 11 ++++ libbeat/dashboards/kibana_loader.go | 5 ++ 4 files changed, 56 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index a0333c8ef44..89bda67a23b 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -65,6 +65,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Affecting all Beats* - Update init scripts to use the `test config` subcommand instead of the deprecated `-configtest` flag. {issue}4600[4600] +- Get by default the credentials for connecting to Kibana from the Elasticsearch output configuration. {pull}4867[4867] *Auditbeat* diff --git a/libbeat/dashboards/dashboards.go b/libbeat/dashboards/dashboards.go index f40465a79cf..080885deae1 100644 --- a/libbeat/dashboards/dashboards.go +++ b/libbeat/dashboards/dashboards.go @@ -29,34 +29,40 @@ func ImportDashboards(beatName, beatVersion, homePath string, return err } - if esConfig != nil { - status, err := ImportDashboardsViaElasticsearch(esConfig, &dashConfig, msgOutputter) - if err != nil { - return err - } - if status { - // the dashboards were imported via Elasticsearch - return nil - } - } - - err = ImportDashboardsViaKibana(kibanaConfig, &dashConfig, msgOutputter) + esLoader, err := NewElasticsearchLoader(esConfig, &dashConfig, msgOutputter) if err != nil { - return err + return fmt.Errorf("fail to create the Elasticsearch loader: %v", err) } + defer esLoader.Close() - return nil -} + esLoader.statusMsg("Elasticsearch URL %v", esLoader.client.Connection.URL) -func ImportDashboardsViaKibana(config *common.Config, dashConfig *Config, msgOutputter MessageOutputter) error { - if config == nil { - config = common.NewConfig() + majorVersion, _, err := getMajorAndMinorVersion(esLoader.version) + if err != nil { + return fmt.Errorf("wrong Elasticsearch version: %v", err) } - if !config.Enabled() { - return nil + + if majorVersion < 6 { + return ImportDashboardsViaElasticsearch(esLoader) + } + + logp.Info("For Elasticsearch version >= 6.0.0, the Kibana dashboards need to be imported via the Kibana API.") + + if kibanaConfig == nil { + kibanaConfig = common.NewConfig() } - kibanaLoader, err := NewKibanaLoader(config, dashConfig, msgOutputter) + // In Cloud, the Kibana URL is different than the Elasticsearch URL, + // but the credentials are the same. + // So, by default, use same credentials for connecting to Kibana as to Elasticsearch + if !kibanaConfig.HasField("username") && len(esLoader.client.Username) > 0 { + kibanaConfig.SetString("username", -1, esLoader.client.Username) + } + if !kibanaConfig.HasField("password") && len(esLoader.client.Password) > 0 { + kibanaConfig.SetString("password", -1, esLoader.client.Password) + } + + kibanaLoader, err := NewKibanaLoader(kibanaConfig, &dashConfig, msgOutputter) if err != nil { return fmt.Errorf("fail to create the Kibana loader: %v", err) } @@ -65,11 +71,16 @@ func ImportDashboardsViaKibana(config *common.Config, dashConfig *Config, msgOut kibanaLoader.statusMsg("Kibana URL %v", kibanaLoader.client.Connection.URL) + return ImportDashboardsViaKibana(kibanaLoader) +} + +func ImportDashboardsViaKibana(kibanaLoader *KibanaLoader) error { + if !isKibanaAPIavailable(kibanaLoader.version) { return fmt.Errorf("Kibana API is not available in Kibana version %s", kibanaLoader.version) } - importer, err := NewImporter("default", dashConfig, *kibanaLoader) + importer, err := NewImporter("default", kibanaLoader.config, kibanaLoader) if err != nil { return fmt.Errorf("fail to create a Kibana importer for loading the dashboards: %v", err) } @@ -81,39 +92,22 @@ func ImportDashboardsViaKibana(config *common.Config, dashConfig *Config, msgOut return nil } -func ImportDashboardsViaElasticsearch(config *common.Config, dashConfig *Config, msgOutputter MessageOutputter) (bool, error) { - esLoader, err := NewElasticsearchLoader(config, dashConfig, msgOutputter) - if err != nil { - return false, fmt.Errorf("fail to create the Elasticsearch loader: %v", err) - } - defer esLoader.Close() - - esLoader.statusMsg("Elasticsearch URL %v", esLoader.client.Connection.URL) - - majorVersion, _, err := getMajorAndMinorVersion(esLoader.version) - if err != nil { - return false, fmt.Errorf("wrong Elasticsearch version: %v", err) - } - - if majorVersion >= 6 { - logp.Info("For Elasticsearch version >= 6.0.0, the Kibana dashboards need to be imported via the Kibana API.") - return false, nil - } +func ImportDashboardsViaElasticsearch(esLoader *ElasticsearchLoader) error { if err := esLoader.CreateKibanaIndex(); err != nil { - return false, fmt.Errorf("fail to create the kibana index: %v", err) + return fmt.Errorf("fail to create the kibana index: %v", err) } - importer, err := NewImporter("5.x", dashConfig, *esLoader) + importer, err := NewImporter("5.x", esLoader.config, esLoader) if err != nil { - return false, fmt.Errorf("fail to create an Elasticsearch importer for loading the dashboards: %v", err) + return fmt.Errorf("fail to create an Elasticsearch importer for loading the dashboards: %v", err) } if err := importer.Import(); err != nil { - return false, fmt.Errorf("fail to import the dashboards in Elasticsearch: %v", err) + return fmt.Errorf("fail to import the dashboards in Elasticsearch: %v", err) } - return true, nil + return nil } func getMajorAndMinorVersion(version string) (int, int, error) { diff --git a/libbeat/dashboards/importer.go b/libbeat/dashboards/importer.go index 4de3b32d4ab..6d09da5f586 100644 --- a/libbeat/dashboards/importer.go +++ b/libbeat/dashboards/importer.go @@ -272,11 +272,22 @@ func (imp Importer) ImportKibanaDir(dir string) error { return fmt.Errorf("The directory %s does not contain the %s subdirectory."+ " There is nothing to import into Kibana.", dir, strings.Join(check, " or ")) } + + importDashboards := false for _, t := range types { err = imp.ImportDir(t, dir) if err != nil { return fmt.Errorf("Failed to import %s: %v", t, err) } + + if t == "dashboard" { + importDashboards = true + } + } + + if !importDashboards { + return fmt.Errorf("No dashboards to import. Please make sure the %s directory contains a dashboard directory.", + dir) } return nil } diff --git a/libbeat/dashboards/kibana_loader.go b/libbeat/dashboards/kibana_loader.go index 952f927ee3e..882a606d28f 100644 --- a/libbeat/dashboards/kibana_loader.go +++ b/libbeat/dashboards/kibana_loader.go @@ -21,6 +21,11 @@ type KibanaLoader struct { } func NewKibanaLoader(cfg *common.Config, dashboardsConfig *Config, msgOutputter MessageOutputter) (*KibanaLoader, error) { + + if cfg == nil || !cfg.Enabled() { + return nil, fmt.Errorf("Kibana is not configured or enabled") + } + client, err := kibana.NewKibanaClient(cfg) if err != nil { return nil, fmt.Errorf("Error creating Kibana client: %v", err) From a8b2192fab5519002b751d5d9921a4b2c9810217 Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Mon, 14 Aug 2017 15:30:27 +0200 Subject: [PATCH 074/139] Remove accidental submodule (#4893) --- metricbeat/github.com/elastic/beats | 1 - 1 file changed, 1 deletion(-) delete mode 160000 metricbeat/github.com/elastic/beats diff --git a/metricbeat/github.com/elastic/beats b/metricbeat/github.com/elastic/beats deleted file mode 160000 index 2463fd83302..00000000000 --- a/metricbeat/github.com/elastic/beats +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2463fd833024b2782962b18060ce642af2bdf1f4 From a1b64cdbe6945c8bad00e8fd8132765cb5f6a749 Mon Sep 17 00:00:00 2001 From: Steffen Siering Date: Mon, 14 Aug 2017 16:00:41 +0200 Subject: [PATCH 075/139] Remove all references to removed output.X.flush_interval settings (#4880) * Remove all references to flush_interval The outputs setting flush_interval has been removed in the past. Remove this setting from reference configuration and docs as well. * Fail if removed flush_interval is configured --- CHANGELOG.asciidoc | 1 + auditbeat/auditbeat.reference.yml | 8 -------- filebeat/filebeat.reference.yml | 8 -------- heartbeat/heartbeat.reference.yml | 8 -------- libbeat/_meta/config.reference.yml | 8 -------- libbeat/docs/outputconfig.asciidoc | 10 ---------- libbeat/outputs/fileout/file.go | 1 - libbeat/outputs/logstash/logstash_integration_test.go | 2 -- libbeat/outputs/output_reg.go | 5 +++++ libbeat/tests/system/test_base.py | 1 - metricbeat/metricbeat.reference.yml | 8 -------- packetbeat/packetbeat.reference.yml | 8 -------- winlogbeat/winlogbeat.reference.yml | 8 -------- 13 files changed, 6 insertions(+), 70 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 89bda67a23b..5694d20f952 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -15,6 +15,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Affecting all Beats* - The log directory (`path.log`) for Windows services is now set to `C:\ProgramData\[beatname]\logs`. {issue}4764[4764] +- Fail if removed setting output.X.flush_interval is explicitly configured. *Auditbeat* diff --git a/auditbeat/auditbeat.reference.yml b/auditbeat/auditbeat.reference.yml index ef9441b418a..049ba139cac 100644 --- a/auditbeat/auditbeat.reference.yml +++ b/auditbeat/auditbeat.reference.yml @@ -236,11 +236,6 @@ output.elasticsearch: # Configure http request timeout before failing an request to Elasticsearch. #timeout: 90 - # The number of seconds to wait for new events between two bulk API index requests. - # If `bulk_max_size` is reached before this interval expires, addition bulk index - # requests are made. - #flush_interval: 1s - # Use SSL settings for HTTPS. Default is true. #ssl.enabled: true @@ -440,9 +435,6 @@ output.elasticsearch: # on error. #required_acks: 1 - # The number of seconds to wait for new events between two producer API calls. - #flush_interval: 1s - # The configurable ClientID used for logging, debugging, and auditing # purposes. The default is "beats". #client_id: beats diff --git a/filebeat/filebeat.reference.yml b/filebeat/filebeat.reference.yml index dcd7d03653b..37c52fa679e 100644 --- a/filebeat/filebeat.reference.yml +++ b/filebeat/filebeat.reference.yml @@ -641,11 +641,6 @@ output.elasticsearch: # Configure http request timeout before failing an request to Elasticsearch. #timeout: 90 - # The number of seconds to wait for new events between two bulk API index requests. - # If `bulk_max_size` is reached before this interval expires, addition bulk index - # requests are made. - #flush_interval: 1s - # Use SSL settings for HTTPS. Default is true. #ssl.enabled: true @@ -845,9 +840,6 @@ output.elasticsearch: # on error. #required_acks: 1 - # The number of seconds to wait for new events between two producer API calls. - #flush_interval: 1s - # The configurable ClientID used for logging, debugging, and auditing # purposes. The default is "beats". #client_id: beats diff --git a/heartbeat/heartbeat.reference.yml b/heartbeat/heartbeat.reference.yml index ba14c3841bf..c3b0ebdce58 100644 --- a/heartbeat/heartbeat.reference.yml +++ b/heartbeat/heartbeat.reference.yml @@ -385,11 +385,6 @@ output.elasticsearch: # Configure http request timeout before failing an request to Elasticsearch. #timeout: 90 - # The number of seconds to wait for new events between two bulk API index requests. - # If `bulk_max_size` is reached before this interval expires, addition bulk index - # requests are made. - #flush_interval: 1s - # Use SSL settings for HTTPS. Default is true. #ssl.enabled: true @@ -589,9 +584,6 @@ output.elasticsearch: # on error. #required_acks: 1 - # The number of seconds to wait for new events between two producer API calls. - #flush_interval: 1s - # The configurable ClientID used for logging, debugging, and auditing # purposes. The default is "beats". #client_id: beats diff --git a/libbeat/_meta/config.reference.yml b/libbeat/_meta/config.reference.yml index 294c3b93039..478a48e97cc 100644 --- a/libbeat/_meta/config.reference.yml +++ b/libbeat/_meta/config.reference.yml @@ -171,11 +171,6 @@ output.elasticsearch: # Configure http request timeout before failing an request to Elasticsearch. #timeout: 90 - # The number of seconds to wait for new events between two bulk API index requests. - # If `bulk_max_size` is reached before this interval expires, addition bulk index - # requests are made. - #flush_interval: 1s - # Use SSL settings for HTTPS. Default is true. #ssl.enabled: true @@ -375,9 +370,6 @@ output.elasticsearch: # on error. #required_acks: 1 - # The number of seconds to wait for new events between two producer API calls. - #flush_interval: 1s - # The configurable ClientID used for logging, debugging, and auditing # purposes. The default is "beats". #client_id: beats diff --git a/libbeat/docs/outputconfig.asciidoc b/libbeat/docs/outputconfig.asciidoc index 751dd55650a..61ba17df75a 100644 --- a/libbeat/docs/outputconfig.asciidoc +++ b/libbeat/docs/outputconfig.asciidoc @@ -292,12 +292,6 @@ spooler size. The http request timeout in seconds for the Elasticsearch request. The default is 90. -===== `flush_interval` - -The number of seconds to wait for new events between two bulk API index requests. -If `bulk_max_size` is reached before this interval expires, additional bulk index -requests are made. - ===== `ssl` Configuration options for SSL parameters like the certificate authority to use @@ -731,10 +725,6 @@ The ACK reliability level required from broker. 0=no response, 1=wait for local Note: If set to 0, no ACKs are returned by Kafka. Messages might be lost silently on error. -===== `flush_interval` - -The number of seconds to wait for new events between two producer API calls. - ===== `ssl` Configuration options for SSL parameters like the root CA for Kafka connections. See diff --git a/libbeat/outputs/fileout/file.go b/libbeat/outputs/fileout/file.go index a0f0529b564..faa9cc79d7c 100644 --- a/libbeat/outputs/fileout/file.go +++ b/libbeat/outputs/fileout/file.go @@ -32,7 +32,6 @@ func makeFileout( } // disable bulk support in publisher pipeline - cfg.SetInt("flush_interval", -1, -1) cfg.SetInt("bulk_max_size", -1, -1) fo := &fileOutput{beat: beat, stats: stats} diff --git a/libbeat/outputs/logstash/logstash_integration_test.go b/libbeat/outputs/logstash/logstash_integration_test.go index fa6e553ae19..e69fb050b9b 100644 --- a/libbeat/outputs/logstash/logstash_integration_test.go +++ b/libbeat/outputs/logstash/logstash_integration_test.go @@ -148,12 +148,10 @@ func newTestElasticsearchOutput(t *testing.T, test string) *testOutputer { index := testElasticsearchIndex(test) connection := esConnect(t, index) - flushInterval := 0 bulkSize := 0 config, _ := common.NewConfigFrom(map[string]interface{}{ "hosts": []string{getElasticsearchHost()}, "index": connection.index, - "flush_interval": &flushInterval, "bulk_max_size": &bulkSize, "username": os.Getenv("ES_USER"), "password": os.Getenv("ES_PASS"), diff --git a/libbeat/outputs/output_reg.go b/libbeat/outputs/output_reg.go index 7d2782166c8..207d3ae5f6e 100644 --- a/libbeat/outputs/output_reg.go +++ b/libbeat/outputs/output_reg.go @@ -5,6 +5,7 @@ import ( "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/common/cfgwarn" ) var outputReg = map[string]Factory{} @@ -43,5 +44,9 @@ func Load(info beat.Info, stats *Stats, name string, config *common.Config) (Gro return Group{}, fmt.Errorf("output type %v undefined", name) } + if err := cfgwarn.CheckRemoved5xSetting(config, "flush_interval"); err != nil { + return Fail(err) + } + return factory(info, stats, config) } diff --git a/libbeat/tests/system/test_base.py b/libbeat/tests/system/test_base.py index 0bb8ccd1d96..c328500a57b 100644 --- a/libbeat/tests/system/test_base.py +++ b/libbeat/tests/system/test_base.py @@ -154,7 +154,6 @@ def test_console_output_size_flush(self): console={ "pretty": "false", "bulk_max_size": 1, - "flush_interval": "1h" } ) diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index ef8404cba83..dd6811e7b1b 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -605,11 +605,6 @@ output.elasticsearch: # Configure http request timeout before failing an request to Elasticsearch. #timeout: 90 - # The number of seconds to wait for new events between two bulk API index requests. - # If `bulk_max_size` is reached before this interval expires, addition bulk index - # requests are made. - #flush_interval: 1s - # Use SSL settings for HTTPS. Default is true. #ssl.enabled: true @@ -809,9 +804,6 @@ output.elasticsearch: # on error. #required_acks: 1 - # The number of seconds to wait for new events between two producer API calls. - #flush_interval: 1s - # The configurable ClientID used for logging, debugging, and auditing # purposes. The default is "beats". #client_id: beats diff --git a/packetbeat/packetbeat.reference.yml b/packetbeat/packetbeat.reference.yml index f2e44f01ba2..58e72b6228c 100644 --- a/packetbeat/packetbeat.reference.yml +++ b/packetbeat/packetbeat.reference.yml @@ -623,11 +623,6 @@ output.elasticsearch: # Configure http request timeout before failing an request to Elasticsearch. #timeout: 90 - # The number of seconds to wait for new events between two bulk API index requests. - # If `bulk_max_size` is reached before this interval expires, addition bulk index - # requests are made. - #flush_interval: 1s - # Use SSL settings for HTTPS. Default is true. #ssl.enabled: true @@ -827,9 +822,6 @@ output.elasticsearch: # on error. #required_acks: 1 - # The number of seconds to wait for new events between two producer API calls. - #flush_interval: 1s - # The configurable ClientID used for logging, debugging, and auditing # purposes. The default is "beats". #client_id: beats diff --git a/winlogbeat/winlogbeat.reference.yml b/winlogbeat/winlogbeat.reference.yml index 6c3bfac90cc..668b3deac40 100644 --- a/winlogbeat/winlogbeat.reference.yml +++ b/winlogbeat/winlogbeat.reference.yml @@ -200,11 +200,6 @@ output.elasticsearch: # Configure http request timeout before failing an request to Elasticsearch. #timeout: 90 - # The number of seconds to wait for new events between two bulk API index requests. - # If `bulk_max_size` is reached before this interval expires, addition bulk index - # requests are made. - #flush_interval: 1s - # Use SSL settings for HTTPS. Default is true. #ssl.enabled: true @@ -404,9 +399,6 @@ output.elasticsearch: # on error. #required_acks: 1 - # The number of seconds to wait for new events between two producer API calls. - #flush_interval: 1s - # The configurable ClientID used for logging, debugging, and auditing # purposes. The default is "beats". #client_id: beats From 43cd1e7eeb1de68d6ec485bc370003ee29965828 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Mon, 14 Aug 2017 14:57:44 -0400 Subject: [PATCH 076/139] Add system uptime metricset (#4887) This adds a new metricset that reports the system uptime. The metricset is enabled by default with a period of 15m. The metricset reports one field `system.uptime.duration.ms` that is the system's uptime reported in milliseconds. In Kibana the field is formatted as a `duration` and shown in human-readable format (e.g. "8 days"). Closes #4848 --- CHANGELOG.asciidoc | 3 +- libbeat/scripts/generate_index_pattern.py | 5 +++ metricbeat/docs/fields.asciidoc | 17 ++++++++ metricbeat/docs/modules/system.asciidoc | 9 ++++ .../docs/modules/system/uptime.asciidoc | 19 +++++++++ metricbeat/include/list.go | 1 + metricbeat/metricbeat.reference.yml | 1 + .../module/system/_meta/config.reference.yml | 1 + metricbeat/module/system/_meta/config.yml | 5 +++ .../module/system/uptime/_meta/data.json | 23 ++++++++++ .../module/system/uptime/_meta/docs.asciidoc | 10 +++++ .../module/system/uptime/_meta/fields.yml | 11 +++++ metricbeat/module/system/uptime/doc.go | 2 + metricbeat/module/system/uptime/metricset.go | 42 +++++++++++++++++++ .../module/system/uptime/metricset_test.go | 28 +++++++++++++ metricbeat/modules.d/system.yml | 5 +++ 16 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 metricbeat/docs/modules/system/uptime.asciidoc create mode 100644 metricbeat/module/system/uptime/_meta/data.json create mode 100644 metricbeat/module/system/uptime/_meta/docs.asciidoc create mode 100644 metricbeat/module/system/uptime/_meta/fields.yml create mode 100644 metricbeat/module/system/uptime/doc.go create mode 100644 metricbeat/module/system/uptime/metricset.go create mode 100644 metricbeat/module/system/uptime/metricset_test.go diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 5694d20f952..9cd26606fb5 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -85,7 +85,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Add graphite protocol metricbeat module. {pull}4734[4734] - Add http server metricset to support push metrics via http. {pull}4770[4770] - Make config object public for graphite and http server {pull}4820[4820] - +- Add system uptime metricset. {issue}[4848[4848] + *Packetbeat* *Winlogbeat* diff --git a/libbeat/scripts/generate_index_pattern.py b/libbeat/scripts/generate_index_pattern.py index f48068e806f..7ad6c2be65b 100644 --- a/libbeat/scripts/generate_index_pattern.py +++ b/libbeat/scripts/generate_index_pattern.py @@ -79,6 +79,11 @@ def field_to_json(fields, desc, path, output, if "format" in desc: fieldFormat["id"] = desc["format"] + if "input_format" in desc: + fieldFormat["params"] = { + "inputFormat": desc["input_format"] + } + if "pattern" in desc: fieldFormat["params"] = { "pattern": desc["pattern"] diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index be3da81a9ed..cf12c65ebbc 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -10232,6 +10232,23 @@ type: keyword Name of the user running the process. +[float] +== uptime fields + +`uptime` contains the operating system uptime metric. + + + +[float] +=== `system.uptime.duration.ms` + +type: long + +format: duration + +The OS uptime in milliseconds. + + [[exported-fields-vsphere]] == vSphere fields diff --git a/metricbeat/docs/modules/system.asciidoc b/metricbeat/docs/modules/system.asciidoc index d5b9a50f447..1fb694e6c6c 100644 --- a/metricbeat/docs/modules/system.asciidoc +++ b/metricbeat/docs/modules/system.asciidoc @@ -109,6 +109,11 @@ metricbeat.modules: processors: - drop_event.when.regexp: system.filesystem.mount_point: '^/(sys|cgroup|proc|dev|etc|host|lib)($|/)' + +- module: system + period: 15m + metricsets: + - uptime ---- [float] @@ -138,6 +143,8 @@ The following metricsets are available: * <> +* <> + include::system/core.asciidoc[] include::system/cpu.asciidoc[] @@ -160,3 +167,5 @@ include::system/process_summary.asciidoc[] include::system/socket.asciidoc[] +include::system/uptime.asciidoc[] + diff --git a/metricbeat/docs/modules/system/uptime.asciidoc b/metricbeat/docs/modules/system/uptime.asciidoc new file mode 100644 index 00000000000..9087b0be0b4 --- /dev/null +++ b/metricbeat/docs/modules/system/uptime.asciidoc @@ -0,0 +1,19 @@ +//// +This file is generated! See scripts/docs_collector.py +//// + +[[metricbeat-metricset-system-uptime]] +include::../../../module/system/uptime/_meta/docs.asciidoc[] + + +==== Fields + +For a description of each field in the metricset, see the +<> section. + +Here is an example document generated by this metricset: + +[source,json] +---- +include::../../../module/system/uptime/_meta/data.json[] +---- diff --git a/metricbeat/include/list.go b/metricbeat/include/list.go index fa77791b829..880a6b196bf 100644 --- a/metricbeat/include/list.go +++ b/metricbeat/include/list.go @@ -101,6 +101,7 @@ import ( _ "github.com/elastic/beats/metricbeat/module/system/process" _ "github.com/elastic/beats/metricbeat/module/system/process_summary" _ "github.com/elastic/beats/metricbeat/module/system/socket" + _ "github.com/elastic/beats/metricbeat/module/system/uptime" _ "github.com/elastic/beats/metricbeat/module/vsphere" _ "github.com/elastic/beats/metricbeat/module/vsphere/datastore" _ "github.com/elastic/beats/metricbeat/module/vsphere/host" diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index dd6811e7b1b..bc24e9f98fe 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -40,6 +40,7 @@ metricbeat.modules: - network # Network IO - process # Per process metrics - process_summary # Process summary + - uptime # System Uptime #- core # Per CPU core usage #- diskio # Disk IO #- socket # Sockets and connection info (linux only) diff --git a/metricbeat/module/system/_meta/config.reference.yml b/metricbeat/module/system/_meta/config.reference.yml index 93928f7c185..099b2b1f36b 100644 --- a/metricbeat/module/system/_meta/config.reference.yml +++ b/metricbeat/module/system/_meta/config.reference.yml @@ -8,6 +8,7 @@ - network # Network IO - process # Per process metrics - process_summary # Process summary + - uptime # System Uptime #- core # Per CPU core usage #- diskio # Disk IO #- socket # Sockets and connection info (linux only) diff --git a/metricbeat/module/system/_meta/config.yml b/metricbeat/module/system/_meta/config.yml index ac2e8ce00d9..409ec1b636c 100644 --- a/metricbeat/module/system/_meta/config.yml +++ b/metricbeat/module/system/_meta/config.yml @@ -23,3 +23,8 @@ processors: - drop_event.when.regexp: system.filesystem.mount_point: '^/(sys|cgroup|proc|dev|etc|host|lib)($|/)' + +- module: system + period: 15m + metricsets: + - uptime diff --git a/metricbeat/module/system/uptime/_meta/data.json b/metricbeat/module/system/uptime/_meta/data.json new file mode 100644 index 00000000000..519c26f3012 --- /dev/null +++ b/metricbeat/module/system/uptime/_meta/data.json @@ -0,0 +1,23 @@ +{ + "@timestamp": "2016-05-23T08:05:34.853Z", + "@metadata": { + "beat": "noindex", + "type": "doc" + }, + "system": { + "uptime": { + "duration": { + "ms": 695499821 + } + } + }, + "metricset": { + "module": "system", + "name": "uptime", + "rtt": 115 + }, + "beat": { + "name": "host.example.com", + "hostname": "host.example.com" + } +} \ No newline at end of file diff --git a/metricbeat/module/system/uptime/_meta/docs.asciidoc b/metricbeat/module/system/uptime/_meta/docs.asciidoc new file mode 100644 index 00000000000..f738283cb5a --- /dev/null +++ b/metricbeat/module/system/uptime/_meta/docs.asciidoc @@ -0,0 +1,10 @@ +=== System Uptime Metricset + +The System `uptime` metricset provides the uptime of the host operating system. + +This metricset is available on: + +- Darwin +- Linux +- OpenBSD +- Windows diff --git a/metricbeat/module/system/uptime/_meta/fields.yml b/metricbeat/module/system/uptime/_meta/fields.yml new file mode 100644 index 00000000000..b641786a1dd --- /dev/null +++ b/metricbeat/module/system/uptime/_meta/fields.yml @@ -0,0 +1,11 @@ +- name: uptime + type: group + description: > + `uptime` contains the operating system uptime metric. + fields: + - name: duration.ms + type: long + format: duration + input_format: milliseconds + description: > + The OS uptime in milliseconds. diff --git a/metricbeat/module/system/uptime/doc.go b/metricbeat/module/system/uptime/doc.go new file mode 100644 index 00000000000..289e4a3f97b --- /dev/null +++ b/metricbeat/module/system/uptime/doc.go @@ -0,0 +1,2 @@ +// Package uptime reports the system's uptime. +package uptime diff --git a/metricbeat/module/system/uptime/metricset.go b/metricbeat/module/system/uptime/metricset.go new file mode 100644 index 00000000000..67133fb4643 --- /dev/null +++ b/metricbeat/module/system/uptime/metricset.go @@ -0,0 +1,42 @@ +// +build darwin linux openbsd windows + +package uptime + +import ( + "github.com/pkg/errors" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/metricbeat/mb" + "github.com/elastic/beats/metricbeat/mb/parse" + sigar "github.com/elastic/gosigar" +) + +func init() { + if err := mb.Registry.AddMetricSet("system", "uptime", New, parse.EmptyHostParser); err != nil { + panic(err) + } +} + +// MetricSet for fetching an OS uptime metric. +type MetricSet struct { + mb.BaseMetricSet +} + +// New is a mb.MetricSetFactory that returns a new MetricSet. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + return &MetricSet{base}, nil +} + +// Fetch fetches the uptime metric from the OS. +func (m *MetricSet) Fetch() (common.MapStr, error) { + var uptime sigar.Uptime + if err := uptime.Get(); err != nil { + return nil, errors.Wrap(err, "failed to get uptime") + } + + return common.MapStr{ + "duration": common.MapStr{ + "ms": int64(uptime.Length * 1000), + }, + }, nil +} diff --git a/metricbeat/module/system/uptime/metricset_test.go b/metricbeat/module/system/uptime/metricset_test.go new file mode 100644 index 00000000000..524bf871c58 --- /dev/null +++ b/metricbeat/module/system/uptime/metricset_test.go @@ -0,0 +1,28 @@ +// +build darwin linux openbsd windows + +package uptime + +import ( + "testing" + + mbtest "github.com/elastic/beats/metricbeat/mb/testing" +) + +func TestData(t *testing.T) { + f := mbtest.NewEventFetcher(t, getConfig()) + + uptime, err := f.Fetch() + if err != nil { + t.Fatal(err) + } + + event := mbtest.CreateFullEvent(f, uptime) + mbtest.WriteEventToDataJSON(t, event) +} + +func getConfig() map[string]interface{} { + return map[string]interface{}{ + "module": "system", + "metricsets": []string{"uptime"}, + } +} diff --git a/metricbeat/modules.d/system.yml b/metricbeat/modules.d/system.yml index ac2e8ce00d9..409ec1b636c 100644 --- a/metricbeat/modules.d/system.yml +++ b/metricbeat/modules.d/system.yml @@ -23,3 +23,8 @@ processors: - drop_event.when.regexp: system.filesystem.mount_point: '^/(sys|cgroup|proc|dev|etc|host|lib)($|/)' + +- module: system + period: 15m + metricsets: + - uptime From d1263b9a310fe43e812bea43d6ef210e9b740e4f Mon Sep 17 00:00:00 2001 From: Silvia Mitter Date: Mon, 14 Aug 2017 21:35:23 +0200 Subject: [PATCH 077/139] Set array type to ObjectType of field if available. (#4896) Type of array items needs to be defined when creating a mapping for arrays. For dynamic mapping ES uses the type of the first array item. For pre-defined mapping use ObjectType information set in the fields.yml if available. --- libbeat/template/field.go | 6 +++++- libbeat/template/field_test.go | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/libbeat/template/field.go b/libbeat/template/field.go index 384e7e108c9..bc1e5b2aec4 100644 --- a/libbeat/template/field.go +++ b/libbeat/template/field.go @@ -137,7 +137,11 @@ func (f *Field) text() common.MapStr { } func (f *Field) array() common.MapStr { - return f.getDefaultProperties() + properties := f.getDefaultProperties() + if f.ObjectType != "" { + properties["type"] = f.ObjectType + } + return properties } func (f *Field) object() common.MapStr { diff --git a/libbeat/template/field_test.go b/libbeat/template/field_test.go index e8c5df8fb35..f27a2ba592b 100644 --- a/libbeat/template/field_test.go +++ b/libbeat/template/field_test.go @@ -59,6 +59,21 @@ func TestField(t *testing.T) { "enabled": false, }, }, + { + field: Field{Type: "array"}, + method: func(f Field) common.MapStr { return f.array() }, + output: common.MapStr{}, + }, + { + field: Field{Type: "array", ObjectType: "text"}, + method: func(f Field) common.MapStr { return f.array() }, + output: common.MapStr{"type": "text"}, + }, + { + field: Field{Type: "array", Index: &falseVar, ObjectType: "keyword"}, + method: func(f Field) common.MapStr { return f.array() }, + output: common.MapStr{"index": false, "type": "keyword"}, + }, { field: Field{Type: "object", Enabled: &falseVar}, method: func(f Field) common.MapStr { return f.object() }, From a7103d1125adfb68bdf193484c5a2aaf476516e1 Mon Sep 17 00:00:00 2001 From: Silvia Mitter Date: Mon, 14 Aug 2017 21:36:44 +0200 Subject: [PATCH 078/139] Set value 'dynamic' for groups. (#4894) --- libbeat/template/fields.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libbeat/template/fields.go b/libbeat/template/fields.go index 1242607dbe7..ae08718036a 100644 --- a/libbeat/template/fields.go +++ b/libbeat/template/fields.go @@ -50,9 +50,11 @@ func (f Fields) process(path string, esVersion common.Version) common.MapStr { } else { newPath = path + "." + field.Name } - mapping = common.MapStr{ - "properties": field.Fields.process(newPath, esVersion), + mapping = common.MapStr{} + if field.Dynamic.value != nil { + mapping["dynamic"] = field.Dynamic.value } + mapping["properties"] = field.Fields.process(newPath, esVersion) default: mapping = field.other() } From 38aae1ea257ed4b5d6c6199b0681427ce4f78856 Mon Sep 17 00:00:00 2001 From: Vijay Samuel Date: Tue, 15 Aug 2017 07:21:16 -0700 Subject: [PATCH 079/139] Register kubernetes field_format matcher and remove logger in Encode API (#4888) --- CHANGELOG.asciidoc | 2 +- libbeat/libbeat.full.yml | 647 ++++++++++++++++++ libbeat/outputs/codec/format/format.go | 7 +- libbeat/outputs/redis/client.go | 2 + .../add_kubernetes_metadata/kubernetes.go | 2 + 5 files changed, 653 insertions(+), 7 deletions(-) create mode 100644 libbeat/libbeat.full.yml diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 9cd26606fb5..05e93e68425 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -35,8 +35,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Affecting all Beats* - Fix go plugins not loaded when beat starts {pull}4799[4799] - - Eliminate deprecated _default_ mapping in 6.x {pull}4864[4864] +- Register kubernetes `field_format` matcher and remove logger in `Encode` API {pull}4888[4888] *Auditbeat* diff --git a/libbeat/libbeat.full.yml b/libbeat/libbeat.full.yml new file mode 100644 index 00000000000..1e9023a8247 --- /dev/null +++ b/libbeat/libbeat.full.yml @@ -0,0 +1,647 @@ + +#================================ General ====================================== + +# The name of the shipper that publishes the network data. It can be used to group +# all the transactions sent by a single shipper in the web interface. +# If this options is not defined, the hostname is used. +#name: + +# The tags of the shipper are included in their own field with each +# transaction published. Tags make it easy to group servers by different +# logical properties. +#tags: ["service-X", "web-tier"] + +# Optional fields that you can specify to add additional information to the +# output. Fields can be scalar values, arrays, dictionaries, or any nested +# combination of these. +#fields: +# env: staging + +# If this option is set to true, the custom fields are stored as top-level +# fields in the output document instead of being grouped under a fields +# sub-dictionary. Default is false. +#fields_under_root: false + +# Internal queue size for single events in processing pipeline +#queue_size: 1000 + +# The internal queue size for bulk events in the processing pipeline. +# Do not modify this value. +#bulk_queue_size: 0 + +# Sets the maximum number of CPUs that can be executing simultaneously. The +# default is the number of logical CPUs available in the system. +#max_procs: + +#================================ Processors =================================== + +# Processors are used to reduce the number of fields in the exported event or to +# enhance the event with external metadata. This section defines a list of +# processors that are applied one by one and the first one receives the initial +# event: +# +# event -> filter1 -> event1 -> filter2 ->event2 ... +# +# The supported processors are drop_fields, drop_event, include_fields, and +# add_cloud_metadata. +# +# For example, you can use the following processors to keep the fields that +# contain CPU load percentages, but remove the fields that contain CPU ticks +# values: +# +#processors: +#- include_fields: +# fields: ["cpu"] +#- drop_fields: +# fields: ["cpu.user", "cpu.system"] +# +# The following example drops the events that have the HTTP response code 200: +# +#processors: +#- drop_event: +# when: +# equals: +# http.code: 200 +# +# The following example enriches each event with metadata from the cloud +# provider about the host machine. It works on EC2, GCE, and DigitalOcean. +# +#processors: +#- add_cloud_metadata: +# +# The following example enriches each event with the local timezone. +# +#processors: +#- add_locale: +# + +#================================ Outputs ====================================== + +# Configure what outputs to use when sending the data collected by the beat. +# Multiple outputs may be used. + +#-------------------------- Elasticsearch output ------------------------------- +output.elasticsearch: + # Boolean flag to enable or disable the output module. + #enabled: true + + # Array of hosts to connect to. + # Scheme and port can be left out and will be set to the default (http and 9200) + # In case you specify and additional path, the scheme is required: http://localhost:9200/path + # IPv6 addresses should always be defined as: https://[2001:db8::1]:9200 + hosts: ["localhost:9200"] + + # Set gzip compression level. + #compression_level: 0 + + # Optional protocol and basic auth credentials. + #protocol: "https" + #username: "elastic" + #password: "changeme" + + # Dictionary of HTTP parameters to pass within the url with index operations. + #parameters: + #param1: value1 + #param2: value2 + + # Number of workers per Elasticsearch host. + #worker: 1 + + # Optional index name. The default is "libbeat" plus date + # and generates [libbeat-]YYYY.MM.DD keys. + #index: "libbeat-%{[beat.version]}-%{+yyyy.MM.dd}" + + # Optional ingest node pipeline. By default no pipeline will be used. + #pipeline: "" + + # Optional HTTP Path + #path: "/elasticsearch" + + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + + # Proxy server url + #proxy_url: http://proxy:3128 + + # The number of times a particular Elasticsearch index operation is attempted. If + # the indexing operation doesn't succeed after this many retries, the events are + # dropped. The default is 3. + #max_retries: 3 + + # The maximum number of events to bulk in a single Elasticsearch bulk API index request. + # The default is 50. + #bulk_max_size: 50 + + # Configure http request timeout before failing an request to Elasticsearch. + #timeout: 90 + + # The number of seconds to wait for new events between two bulk API index requests. + # If `bulk_max_size` is reached before this interval expires, addition bulk index + # requests are made. + #flush_interval: 1s + + # Use SSL settings for HTTPS. Default is true. + #ssl.enabled: true + + # Configure SSL verification mode. If `none` is configured, all server hosts + # and certificates will be accepted. In this mode, SSL based connections are + # susceptible to man-in-the-middle attacks. Use only for testing. Default is + # `full`. + #ssl.verification_mode: full + + # List of supported/valid TLS versions. By default all TLS versions 1.0 up to + # 1.2 are enabled. + #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] + + # SSL configuration. By default is off. + # List of root certificates for HTTPS server verifications + #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] + + # Certificate for SSL client authentication + #ssl.certificate: "/etc/pki/client/cert.pem" + + # Client Certificate Key + #ssl.key: "/etc/pki/client/cert.key" + + # Optional passphrase for decrypting the Certificate Key. + #ssl.key_passphrase: '' + + # Configure cipher suites to be used for SSL connections + #ssl.cipher_suites: [] + + # Configure curve types for ECDHE based cipher suites + #ssl.curve_types: [] + + +#----------------------------- Logstash output --------------------------------- +#output.logstash: + # Boolean flag to enable or disable the output module. + #enabled: true + + # The Logstash hosts + #hosts: ["localhost:5044"] + + # Number of workers per Logstash host. + #worker: 1 + + # Set gzip compression level. + #compression_level: 3 + + # Optional load balance the events between the Logstash hosts + #loadbalance: true + + # Number of batches to be send asynchronously to logstash while processing + # new batches. + #pipelining: 0 + + # Optional index name. The default index name is set to name of the beat + # in all lowercase. + #index: 'libbeat' + + # SOCKS5 proxy server URL + #proxy_url: socks5://user:password@socks5-server:2233 + + # Resolve names locally when using a proxy server. Defaults to false. + #proxy_use_local_resolver: false + + # Enable SSL support. SSL is automatically enabled, if any SSL setting is set. + #ssl.enabled: true + + # Configure SSL verification mode. If `none` is configured, all server hosts + # and certificates will be accepted. In this mode, SSL based connections are + # susceptible to man-in-the-middle attacks. Use only for testing. Default is + # `full`. + #ssl.verification_mode: full + + # List of supported/valid TLS versions. By default all TLS versions 1.0 up to + # 1.2 are enabled. + #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] + + # Optional SSL configuration options. SSL is off by default. + # List of root certificates for HTTPS server verifications + #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] + + # Certificate for SSL client authentication + #ssl.certificate: "/etc/pki/client/cert.pem" + + # Client Certificate Key + #ssl.key: "/etc/pki/client/cert.key" + + # Optional passphrase for decrypting the Certificate Key. + #ssl.key_passphrase: '' + + # Configure cipher suites to be used for SSL connections + #ssl.cipher_suites: [] + + # Configure curve types for ECDHE based cipher suites + #ssl.curve_types: [] + +#------------------------------- Kafka output ---------------------------------- +#output.kafka: + # Boolean flag to enable or disable the output module. + #enabled: true + + # The list of Kafka broker addresses from where to fetch the cluster metadata. + # The cluster metadata contain the actual Kafka brokers events are published + # to. + #hosts: ["localhost:9092"] + + # The Kafka topic used for produced events. The setting can be a format string + # using any event field. To set the topic from document type use `%{[type]}`. + #topic: beats + + # The Kafka event key setting. Use format string to create unique event key. + # By default no event key will be generated. + #key: '' + + # The Kafka event partitioning strategy. Default hashing strategy is `hash` + # using the `output.kafka.key` setting or randomly distributes events if + # `output.kafka.key` is not configured. + #partition.hash: + # If enabled, events will only be published to partitions with reachable + # leaders. Default is false. + #reachable_only: false + + # Configure alternative event field names used to compute the hash value. + # If empty `output.kafka.key` setting will be used. + # Default value is empty list. + #hash: [] + + # Authentication details. Password is required if username is set. + #username: '' + #password: '' + + # Kafka version libbeat is assumed to run against. Defaults to the oldest + # supported stable version (currently version 0.8.2.0) + #version: 0.8.2 + + # Metadata update configuration. Metadata do contain leader information + # deciding which broker to use when publishing. + #metadata: + # Max metadata request retry attempts when cluster is in middle of leader + # election. Defaults to 3 retries. + #retry.max: 3 + + # Waiting time between retries during leader elections. Default is 250ms. + #retry.backoff: 250ms + + # Refresh metadata interval. Defaults to every 10 minutes. + #refresh_frequency: 10m + + # The number of concurrent load-balanced Kafka output workers. + #worker: 1 + + # The number of times to retry publishing an event after a publishing failure. + # After the specified number of retries, the events are typically dropped. + # Some Beats, such as Filebeat, ignore the max_retries setting and retry until + # all events are published. Set max_retries to a value less than 0 to retry + # until all events are published. The default is 3. + #max_retries: 3 + + # The maximum number of events to bulk in a single Kafka request. The default + # is 2048. + #bulk_max_size: 2048 + + # The number of seconds to wait for responses from the Kafka brokers before + # timing out. The default is 30s. + #timeout: 30s + + # The maximum duration a broker will wait for number of required ACKs. The + # default is 10s. + #broker_timeout: 10s + + # The number of messages buffered for each Kafka broker. The default is 256. + #channel_buffer_size: 256 + + # The keep-alive period for an active network connection. If 0s, keep-alives + # are disabled. The default is 0 seconds. + #keep_alive: 0 + + # Sets the output compression codec. Must be one of none, snappy and gzip. The + # default is gzip. + #compression: gzip + + # The maximum permitted size of JSON-encoded messages. Bigger messages will be + # dropped. The default value is 1000000 (bytes). This value should be equal to + # or less than the broker's message.max.bytes. + #max_message_bytes: 1000000 + + # The ACK reliability level required from broker. 0=no response, 1=wait for + # local commit, -1=wait for all replicas to commit. The default is 1. Note: + # If set to 0, no ACKs are returned by Kafka. Messages might be lost silently + # on error. + #required_acks: 1 + + # The number of seconds to wait for new events between two producer API calls. + #flush_interval: 1s + + # The configurable ClientID used for logging, debugging, and auditing + # purposes. The default is "beats". + #client_id: beats + + # Enable SSL support. SSL is automatically enabled, if any SSL setting is set. + #ssl.enabled: true + + # Optional SSL configuration options. SSL is off by default. + # List of root certificates for HTTPS server verifications + #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] + + # Configure SSL verification mode. If `none` is configured, all server hosts + # and certificates will be accepted. In this mode, SSL based connections are + # susceptible to man-in-the-middle attacks. Use only for testing. Default is + # `full`. + #ssl.verification_mode: full + + # List of supported/valid TLS versions. By default all TLS versions 1.0 up to + # 1.2 are enabled. + #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] + + # Certificate for SSL client authentication + #ssl.certificate: "/etc/pki/client/cert.pem" + + # Client Certificate Key + #ssl.key: "/etc/pki/client/cert.key" + + # Optional passphrase for decrypting the Certificate Key. + #ssl.key_passphrase: '' + + # Configure cipher suites to be used for SSL connections + #ssl.cipher_suites: [] + + # Configure curve types for ECDHE based cipher suites + #ssl.curve_types: [] + +#------------------------------- Redis output ---------------------------------- +#output.redis: + # Boolean flag to enable or disable the output module. + #enabled: true + + # The list of Redis servers to connect to. If load balancing is enabled, the + # events are distributed to the servers in the list. If one server becomes + # unreachable, the events are distributed to the reachable servers only. + #hosts: ["localhost:6379"] + + # The Redis port to use if hosts does not contain a port number. The default + # is 6379. + #port: 6379 + + # The name of the Redis list or channel the events are published to. The + # default is libbeat. + #key: libbeat + + # The password to authenticate with. The default is no authentication. + #password: + + # The Redis database number where the events are published. The default is 0. + #db: 0 + + # The Redis data type to use for publishing events. If the data type is list, + # the Redis RPUSH command is used. If the data type is channel, the Redis + # PUBLISH command is used. The default value is list. + #datatype: list + + # The number of workers to use for each host configured to publish events to + # Redis. Use this setting along with the loadbalance option. For example, if + # you have 2 hosts and 3 workers, in total 6 workers are started (3 for each + # host). + #worker: 1 + + # If set to true and multiple hosts or workers are configured, the output + # plugin load balances published events onto all Redis hosts. If set to false, + # the output plugin sends all events to only one host (determined at random) + # and will switch to another host if the currently selected one becomes + # unreachable. The default value is true. + #loadbalance: true + + # The Redis connection timeout in seconds. The default is 5 seconds. + #timeout: 5s + + # The number of times to retry publishing an event after a publishing failure. + # After the specified number of retries, the events are typically dropped. + # Some Beats, such as Filebeat, ignore the max_retries setting and retry until + # all events are published. Set max_retries to a value less than 0 to retry + # until all events are published. The default is 3. + #max_retries: 3 + + # The maximum number of events to bulk in a single Redis request or pipeline. + # The default is 2048. + #bulk_max_size: 2048 + + # The URL of the SOCKS5 proxy to use when connecting to the Redis servers. The + # value must be a URL with a scheme of socks5://. + #proxy_url: + + # This option determines whether Redis hostnames are resolved locally when + # using a proxy. The default value is false, which means that name resolution + # occurs on the proxy server. + #proxy_use_local_resolver: false + + # Enable SSL support. SSL is automatically enabled, if any SSL setting is set. + #ssl.enabled: true + + # Configure SSL verification mode. If `none` is configured, all server hosts + # and certificates will be accepted. In this mode, SSL based connections are + # susceptible to man-in-the-middle attacks. Use only for testing. Default is + # `full`. + #ssl.verification_mode: full + + # List of supported/valid TLS versions. By default all TLS versions 1.0 up to + # 1.2 are enabled. + #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] + + # Optional SSL configuration options. SSL is off by default. + # List of root certificates for HTTPS server verifications + #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] + + # Certificate for SSL client authentication + #ssl.certificate: "/etc/pki/client/cert.pem" + + # Client Certificate Key + #ssl.key: "/etc/pki/client/cert.key" + + # Optional passphrase for decrypting the Certificate Key. + #ssl.key_passphrase: '' + + # Configure cipher suites to be used for SSL connections + #ssl.cipher_suites: [] + + # Configure curve types for ECDHE based cipher suites + #ssl.curve_types: [] + + +#------------------------------- File output ----------------------------------- +#output.file: + # Boolean flag to enable or disable the output module. + #enabled: true + + # Path to the directory where to save the generated files. The option is + # mandatory. + #path: "/tmp/libbeat" + + # Name of the generated files. The default is `libbeat` and it generates + # files: `libbeat`, `libbeat.1`, `libbeat.2`, etc. + #filename: libbeat + + # Maximum size in kilobytes of each file. When this size is reached, and on + # every libbeat restart, the files are rotated. The default value is 10240 + # kB. + #rotate_every_kb: 10000 + + # Maximum number of files under path. When this number of files is reached, + # the oldest file is deleted and the rest are shifted from last to first. The + # default is 7 files. + #number_of_files: 7 + + +#----------------------------- Console output --------------------------------- +#output.console: + # Boolean flag to enable or disable the output module. + #enabled: true + + # Pretty print json event + #pretty: false + +#================================= Paths ====================================== + +# The home path for the libbeat installation. This is the default base path +# for all other path settings and for miscellaneous files that come with the +# distribution (for example, the sample dashboards). +# If not set by a CLI flag or in the configuration file, the default for the +# home path is the location of the binary. +#path.home: + +# The configuration path for the libbeat installation. This is the default +# base path for configuration files, including the main YAML configuration file +# and the Elasticsearch template file. If not set by a CLI flag or in the +# configuration file, the default for the configuration path is the home path. +#path.config: ${path.home} + +# The data path for the libbeat installation. This is the default base path +# for all the files in which libbeat needs to store its data. If not set by a +# CLI flag or in the configuration file, the default for the data path is a data +# subdirectory inside the home path. +#path.data: ${path.home}/data + +# The logs path for a libbeat installation. This is the default location for +# the Beat's log files. If not set by a CLI flag or in the configuration file, +# the default for the logs path is a logs subdirectory inside the home path. +#path.logs: ${path.home}/logs + +#============================== Dashboards ===================================== +# These settings control loading the sample dashboards to the Kibana index. Loading +# the dashboards is disabled by default and can be enabled either by setting the +# options here, or by using the `-setup` CLI flag. +#setup.dashboards.enabled: false + +# The URL from where to download the dashboards archive. By default this URL +# has a value which is computed based on the Beat name and version. For released +# versions, this URL points to the dashboard archive on the artifacts.elastic.co +# website. +#setup.dashboards.url: + +# The directory from where to read the dashboards. It is used instead of the URL +# when it has a value. +#setup.dashboards.directory: + +# The file archive (zip file) from where to read the dashboards. It is used instead +# of the URL when it has a value. +#setup.dashboards.file: + +# If this option is enabled, the snapshot URL is used instead of the default URL. +#setup.dashboards.snapshot: false + +# The URL from where to download the snapshot version of the dashboards. By default +# this has a value which is computed based on the Beat name and version. +#setup.dashboards.snapshot_url + +# In case the archive contains the dashboards from multiple Beats, this lets you +# select which one to load. You can load all the dashboards in the archive by +# setting this to the empty string. +#setup.dashboards.beat: libbeat + +# The name of the Kibana index to use for setting the configuration. Default is ".kibana" +#setup.dashboards.kibana_index: .kibana + +# The Elasticsearch index name. This overwrites the index name defined in the +# dashboards and index pattern. Example: testbeat-* +#setup.dashboards.index: + +#============================== Template ===================================== + +# A template is used to set the mapping in Elasticsearch +# By default template loading is enabled and the template is loaded. +# These settings can be adjusted to load your own template or overwrite existing ones. + +# Set to false to disable template loading. +#setup.template.enabled: true + +# Template name. By default the template name is libbeat. +# The version of the beat will always be appended to the given name +# so the final name is libbeat-%{[beat.version]}. +#setup.template.name: "libbeat" + +# Path to fields.yml file to generate the template +#setup.template.fields: "${path.config}/fields.yml" + +# Overwrite existing template +#setup.template.overwrite: false + + +#================================ HTTP Endpoint ====================================== +# Each beat can expose internal data points through a http endpoint. For security +# reason the endpoint is disabled by default. This feature is currently in beta. + +# Defines if http endpoint is enabled +#http.enabled: false + +# Host to expose the http endpoint to. It is recommended to use only localhost. +#http.host: localhost + +# Port on which the http endpoint is exposed. Default is 5066 +#http.port: 5066 + +#================================ Logging ====================================== +# There are three options for the log output: syslog, file, stderr. +# Under Windows systems, the log files are per default sent to the file output, +# under all other system per default to syslog. + +# Sets log level. The default log level is info. +# Available log levels are: critical, error, warning, info, debug +#logging.level: info + +# Enable debug output for selected components. To enable all selectors use ["*"] +# Other available selectors are "beat", "publish", "service" +# Multiple selectors can be chained. +#logging.selectors: [ ] + +# Send all logging output to syslog. The default is false. +#logging.to_syslog: true + +# If enabled, libbeat periodically logs its internal metrics that have changed +# in the last period. For each metric that changed, the delta from the value at +# the beginning of the period is logged. Also, the total values for +# all non-zero internal metrics are logged on shutdown. The default is true. +#logging.metrics.enabled: true + +# The period after which to log the internal metrics. The default is 30s. +#logging.metrics.period: 30s + +# Logging to rotating files files. Set logging.to_files to false to disable logging to +# files. +logging.to_files: true +logging.files: + # Configure the path where the logs are written. The default is the logs directory + # under the home path (the binary location). + #path: /var/log/libbeat + + # The name of the files where the logs are written to. + #name: libbeat + + # Configure log file size limit. If limit is reached, log file will be + # automatically rotated + #rotateeverybytes: 10485760 # = 10MB + + # Number of rotated log files to keep. Oldest files will be deleted first. + #keepfiles: 7 + diff --git a/libbeat/outputs/codec/format/format.go b/libbeat/outputs/codec/format/format.go index bf31d42f491..ab346ba9af3 100644 --- a/libbeat/outputs/codec/format/format.go +++ b/libbeat/outputs/codec/format/format.go @@ -6,7 +6,6 @@ import ( "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/fmtstr" - "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs/codec" ) @@ -38,9 +37,5 @@ func New(fmt *fmtstr.EventFormatString) *Encoder { } func (e *Encoder) Encode(_ string, event *beat.Event) ([]byte, error) { - serializedEvent, err := e.Format.RunBytes(event) - if err != nil { - logp.Err("Fail to format event (%v): %#v", err, event) - } - return serializedEvent, err + return e.Format.RunBytes(event) } diff --git a/libbeat/outputs/redis/client.go b/libbeat/outputs/redis/client.go index e2d0504b841..c4b56789ffa 100644 --- a/libbeat/outputs/redis/client.go +++ b/libbeat/outputs/redis/client.go @@ -287,6 +287,7 @@ func serializeEvents( for _, d := range data { serializedEvent, err := codec.Encode(index, &d.Content) if err != nil { + logp.Err("Encoding event failed with error: %v", err) goto failLoop } @@ -303,6 +304,7 @@ failLoop: for _, d := range rest { serializedEvent, err := codec.Encode(index, &d.Content) if err != nil { + logp.Err("Encoding event failed with error: %v", err) i++ continue } diff --git a/libbeat/processors/add_kubernetes_metadata/kubernetes.go b/libbeat/processors/add_kubernetes_metadata/kubernetes.go index bcf9f932f8f..c41b65582c6 100644 --- a/libbeat/processors/add_kubernetes_metadata/kubernetes.go +++ b/libbeat/processors/add_kubernetes_metadata/kubernetes.go @@ -38,6 +38,7 @@ func init() { Indexing.AddIndexer(PodNameIndexerName, NewPodNameIndexer) Indexing.AddIndexer(ContainerIndexerName, NewContainerIndexer) Indexing.AddMatcher(FieldMatcherName, NewFieldMatcher) + Indexing.AddMatcher(FieldFormatMatcherName, NewFieldFormatMatcher) } func newKubernetesAnnotator(cfg *common.Config) (processors.Processor, error) { @@ -112,6 +113,7 @@ func newKubernetesAnnotator(cfg *common.Config) (processors.Processor, error) { matchFunc := Indexing.GetMatcher(name) if matchFunc == nil { logp.Warn("Unable to find matcher plugin %s", name) + continue } matcher, err := matchFunc(pluginConfig) From 7f4fd5bdce3f80d3ee62e4b13a993261ee30078e Mon Sep 17 00:00:00 2001 From: Silvia Mitter Date: Tue, 15 Aug 2017 18:53:38 +0200 Subject: [PATCH 080/139] Add doc_values handling for template creation. (#4904) --- libbeat/template/field.go | 4 ++++ libbeat/template/field_test.go | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/libbeat/template/field.go b/libbeat/template/field.go index bc1e5b2aec4..70967bc7540 100644 --- a/libbeat/template/field.go +++ b/libbeat/template/field.go @@ -26,6 +26,7 @@ type Field struct { Norms bool `config:"norms"` Dynamic dynamicType `config:"dynamic"` Index *bool `config:"index"` + DocValues *bool `config:"doc_values"` path string esVersion common.Version @@ -202,6 +203,9 @@ func (f *Field) getDefaultProperties() common.MapStr { properties["index"] = *f.Index } + if f.DocValues != nil { + properties["doc_values"] = *f.DocValues + } return properties } diff --git a/libbeat/template/field_test.go b/libbeat/template/field_test.go index f27a2ba592b..fe8a9a2728f 100644 --- a/libbeat/template/field_test.go +++ b/libbeat/template/field_test.go @@ -184,6 +184,20 @@ func TestField(t *testing.T) { "type": "text", "index": true, }, }, + { + field: Field{Type: "long", DocValues: &falseVar}, + method: func(f Field) common.MapStr { return f.other() }, + output: common.MapStr{ + "type": "long", "doc_values": false, + }, + }, + { + field: Field{Type: "text", DocValues: &trueVar}, + method: func(f Field) common.MapStr { return f.other() }, + output: common.MapStr{ + "type": "text", "doc_values": true, + }, + }, } for _, test := range tests { From 0e91ea0a35f6911d09fd4641c6919415c54b5aa6 Mon Sep 17 00:00:00 2001 From: DeDe Morton Date: Tue, 15 Aug 2017 13:11:36 -0700 Subject: [PATCH 081/139] Add docs for new subcommands (#4832) * Add docs for new subcommands * Add changes from review --- auditbeat/docs/command-line.asciidoc | 7 - auditbeat/docs/index.asciidoc | 6 +- auditbeat/docs/setting-up-running.asciidoc | 25 + filebeat/docs/command-line.asciidoc | 22 - filebeat/docs/index.asciidoc | 6 +- filebeat/docs/setting-up-running.asciidoc | 30 + heartbeat/docs/command-line.asciidoc | 15 - heartbeat/docs/index.asciidoc | 6 +- heartbeat/docs/setting-up-running.asciidoc | 29 + libbeat/docs/command-reference.asciidoc | 565 ++++++++++++++++++ libbeat/docs/shared-command-line.asciidoc | 74 --- libbeat/docs/shared-directory-layout.asciidoc | 16 + libbeat/docs/shared-docker.asciidoc | 8 +- metricbeat/docs/command-line.asciidoc | 7 - metricbeat/docs/index.asciidoc | 6 +- metricbeat/docs/running-on-docker.asciidoc | 4 +- metricbeat/docs/setting-up-running.asciidoc | 29 + packetbeat/docs/command-line.asciidoc | 39 -- packetbeat/docs/index.asciidoc | 6 +- packetbeat/docs/running-on-docker.asciidoc | 6 +- packetbeat/docs/setting-up-running.asciidoc | 29 + winlogbeat/docs/command-line.asciidoc | 13 - winlogbeat/docs/index.asciidoc | 4 +- winlogbeat/docs/setting-up-running.asciidoc | 25 + 24 files changed, 765 insertions(+), 212 deletions(-) delete mode 100644 auditbeat/docs/command-line.asciidoc create mode 100644 auditbeat/docs/setting-up-running.asciidoc delete mode 100644 filebeat/docs/command-line.asciidoc create mode 100644 filebeat/docs/setting-up-running.asciidoc delete mode 100644 heartbeat/docs/command-line.asciidoc create mode 100644 heartbeat/docs/setting-up-running.asciidoc create mode 100644 libbeat/docs/command-reference.asciidoc delete mode 100644 libbeat/docs/shared-command-line.asciidoc delete mode 100644 metricbeat/docs/command-line.asciidoc create mode 100644 metricbeat/docs/setting-up-running.asciidoc delete mode 100644 packetbeat/docs/command-line.asciidoc create mode 100644 packetbeat/docs/setting-up-running.asciidoc delete mode 100644 winlogbeat/docs/command-line.asciidoc create mode 100644 winlogbeat/docs/setting-up-running.asciidoc diff --git a/auditbeat/docs/command-line.asciidoc b/auditbeat/docs/command-line.asciidoc deleted file mode 100644 index 28ace4c1927..00000000000 --- a/auditbeat/docs/command-line.asciidoc +++ /dev/null @@ -1,7 +0,0 @@ -[[command-line-options]] -=== Command line options - -The following command line options are available for {beatname_uc}. To use these -options, you need to start {beatname_uc} in the foreground. - -include::../../libbeat/docs/shared-command-line.asciidoc[] diff --git a/auditbeat/docs/index.asciidoc b/auditbeat/docs/index.asciidoc index d9a96ec02d4..5b52054e561 100644 --- a/auditbeat/docs/index.asciidoc +++ b/auditbeat/docs/index.asciidoc @@ -23,12 +23,10 @@ include::../../libbeat/docs/contributing-to-beats.asciidoc[] include::./getting-started.asciidoc[] -include::./command-line.asciidoc[] - -include::../../libbeat/docs/shared-directory-layout.asciidoc[] - include::../../libbeat/docs/repositories.asciidoc[] +include::./setting-up-running.asciidoc[] + include::./configuring-howto.asciidoc[] include::./modules.asciidoc[] diff --git a/auditbeat/docs/setting-up-running.asciidoc b/auditbeat/docs/setting-up-running.asciidoc new file mode 100644 index 00000000000..0486f98928f --- /dev/null +++ b/auditbeat/docs/setting-up-running.asciidoc @@ -0,0 +1,25 @@ +///// +// NOTE: +// Each beat has its own setup overview to allow for the addition of content +// that is unique to each beat. +///// + +[[seting-up-and-running]] +== Setting up and running {beatname_uc} + +Before reading this section, see the +<<{beatname_lc}-getting-started,getting started documentation>> for basic +installation instructions to get you started. + +This section includes additional information on how to set up and run +{beatname_uc}, including: + +* <> + +* <> + +//MAINTAINERS: If you add a new file to this section, make sure you update the bulletedl ist ^^ too. + +include::../../libbeat/docs/shared-directory-layout.asciidoc[] + +include::../../libbeat/docs/command-reference.asciidoc[] diff --git a/filebeat/docs/command-line.asciidoc b/filebeat/docs/command-line.asciidoc deleted file mode 100644 index 8582ec8a806..00000000000 --- a/filebeat/docs/command-line.asciidoc +++ /dev/null @@ -1,22 +0,0 @@ -[[command-line-options]] -=== Command line options - -The following command line option is specific to Filebeat. - -*`-once`*:: -When the `-once` flag is used, Filebeat starts all configured harvesters and prospectors, and runs -each prospector until the harvesters are closed. If you set the `-once` flag, you should also set -`close_eof` so the harvester is closed when the end of the file is reached. -By default harvesters are closed after `close_inactive` is reached. - -The following command line options from libbeat are also available for Filebeat. To -use these options, you need to start Filebeat in the foreground. - -To start Filebeat, you must use the `-c config/path` option to specify the path to the -configuration file. - -TIP: Run `./filebeat -h` to see the full list of options from the command line. - -include::../../libbeat/docs/shared-command-line.asciidoc[] - - diff --git a/filebeat/docs/index.asciidoc b/filebeat/docs/index.asciidoc index 659e843c9de..bac7ea45adb 100644 --- a/filebeat/docs/index.asciidoc +++ b/filebeat/docs/index.asciidoc @@ -28,13 +28,9 @@ include::./getting-started.asciidoc[] include::./modules-getting-started.asciidoc[] -include::./command-line.asciidoc[] - -include::../../libbeat/docs/shared-directory-layout.asciidoc[] - include::../../libbeat/docs/repositories.asciidoc[] -include::./running-on-docker.asciidoc[] +include::./setting-up-running.asciidoc[] include::./upgrading.asciidoc[] diff --git a/filebeat/docs/setting-up-running.asciidoc b/filebeat/docs/setting-up-running.asciidoc new file mode 100644 index 00000000000..757d463de66 --- /dev/null +++ b/filebeat/docs/setting-up-running.asciidoc @@ -0,0 +1,30 @@ +///// +// NOTE: +// Each beat has its own setup overview to allow for the addition of content +// that is unique to each beat. +///// + +[[seting-up-and-running]] +== Setting up and running {beatname_uc} + +Before reading this section, see the +<<{beatname_lc}-getting-started,getting started documentation>> for basic +installation instructions to get you started. + +This section includes additional information on how to set up and run +{beatname_uc}, including: + +* <> + +* <> + +* <> + + +//MAINTAINERS: If you add a new file to this section, make sure you update the bulletedl ist ^^ too. + +include::../../libbeat/docs/shared-directory-layout.asciidoc[] + +include::../../libbeat/docs/command-reference.asciidoc[] + +include::./running-on-docker.asciidoc[] diff --git a/heartbeat/docs/command-line.asciidoc b/heartbeat/docs/command-line.asciidoc deleted file mode 100644 index 86ddf90da28..00000000000 --- a/heartbeat/docs/command-line.asciidoc +++ /dev/null @@ -1,15 +0,0 @@ -[[command-line-options]] -=== Command line options - -Heartbeat does not have any Heartbeat-specific command line options. -Instead, you configure the behaviour of Heartbeat by specifying options in -the configuration file. - -The following command line options from libbeat are also available for -Heartbeat. To use these options, you need to start Heartbeat in the -foreground. - -TIP: Run `./heartbeat -h` to see the full list of options from the command -line. - -include::../../libbeat/docs/shared-command-line.asciidoc[] diff --git a/heartbeat/docs/index.asciidoc b/heartbeat/docs/index.asciidoc index 3cffdbe48e6..300986c7fe2 100644 --- a/heartbeat/docs/index.asciidoc +++ b/heartbeat/docs/index.asciidoc @@ -26,13 +26,9 @@ include::../../libbeat/docs/contributing-to-beats.asciidoc[] include::./getting-started.asciidoc[] -include::./command-line.asciidoc[] - -include::../../libbeat/docs/shared-directory-layout.asciidoc[] - include::../../libbeat/docs/repositories.asciidoc[] -include::./running-on-docker.asciidoc[] +include::./setting-up-running.asciidoc[] // //include::./upgrading.asciidoc[] diff --git a/heartbeat/docs/setting-up-running.asciidoc b/heartbeat/docs/setting-up-running.asciidoc new file mode 100644 index 00000000000..388cd8c5d88 --- /dev/null +++ b/heartbeat/docs/setting-up-running.asciidoc @@ -0,0 +1,29 @@ +///// +// NOTE: +// Each beat has its own setup overview to allow for the addition of content +// that is unique to each beat. +///// + +[[seting-up-and-running]] +== Setting up and running {beatname_uc} + +Before reading this section, see the +<<{beatname_lc}-getting-started,getting started documentation>> for basic +installation instructions to get you started. + +This section includes additional information on how to set up and run +{beatname_uc}, including: + +* <> + +* <> + +* <> + +//MAINTAINERS: If you add a new file to this section, make sure you update the bulletedl ist ^^ too. + +include::../../libbeat/docs/shared-directory-layout.asciidoc[] + +include::../../libbeat/docs/command-reference.asciidoc[] + +include::./running-on-docker.asciidoc[] diff --git a/libbeat/docs/command-reference.asciidoc b/libbeat/docs/command-reference.asciidoc new file mode 100644 index 00000000000..3fe3759c1e6 --- /dev/null +++ b/libbeat/docs/command-reference.asciidoc @@ -0,0 +1,565 @@ +////////////////////////////////////////////////////////////////////////// +//// This content is shared by all Elastic Beats. Make sure you keep the +//// descriptions here generic enough to work for all Beats that include +//// this file. When using cross references, make sure that the cross +//// references resolve correctly for any files that include this one. +//// Use the appropriate variables defined in the index.asciidoc file to +//// resolve Beat names: beatname_uc and beatname_lc +//// Use the following include to pull this content into a doc file: +//// include::../../libbeat/docs/command-reference.asciidoc[] +////////////////////////////////////////////////////////////////////////// + + +// These attributes are used to resolve short descriptions + +:global-flags: Also see <>. + +:export-command-short-desc: Exports the configuration or index template to stdout +:help-command-short-desc: Shows help for any command +:modules-command-short-desc: Manages configured modules +:run-command-short-desc: Runs {beatname_uc}. This command is used by default if you start {beatname_uc} without specifying a command +:setup-command-short-desc: Sets up the initial environment, including the index template, Kibana dashboards (when available), and machine learning jobs (when available) +:test-command-short-desc: Tests the configuration +:version-command-short-desc: Shows information about the current version + + +[[command-line-options]] +=== {beatname_uc} commands + +{beatname_uc} provides a command-line interface for running the Beat and +performing common tasks, like testing configuration files and loading +dashboards. The command-line also supports <> +for controlling global behaviors. + +ifeval::["{beatname_lc}"!="winlogbeat"] + +[NOTE] +========================= +You may need to use `sudo` to run the following commands if you've: + +* changed ownership of the config file to `root` +* enabled the Beat to capture data that requires `root` access + +========================= + +endif::[] + +[horizontal] +<>:: +{export-command-short-desc}. + +<>:: +{help-command-short-desc}. + +ifeval::[("{beatname_lc}"=="filebeat") or ("{beatname_lc}"=="metricbeat")] + +<>:: +{modules-command-short-desc}. + +endif::[] + +<>:: +{run-command-short-desc}. + +<>:: +{setup-command-short-desc}. + +<>:: +{test-command-short-desc}. + +<>:: +{version-command-short-desc}. + +Also see <>. + +[[export-command]] +==== `export` command + +{export-command-short-desc}. You can use this +command to quickly view your configuration or the contents of the index +template. + +*SYNOPSIS* + +["source","sh",subs="attributes"] +---- +{beatname_lc} export SUBCOMMAND [FLAGS] +---- + + +*SUBCOMMANDS* + +*`config`*:: +Exports the current configuration to stdout. If you use the `-c` flag, this +command exports the configuration that's defined in the specified file. + +[[template-subcommand]] +*`template`*:: +Exports the index template to stdout. You can specify the `--es.version` and +`--index` flags to futher define what gets exported. + +*FLAGS* + +*`--es.version VERSION`*:: +When specified along with <>, exports an index +template that is compatible with the specified version. + +*`-h, --help`*:: +Shows help for the `export` command. + +*`--index BASE_NAME`*:: +When specified along with <>, sets the base name +to use for the index template. If this flag is not specified, the default base +name is +{beatname_lc}+. + +{global-flags} + +*EXAMPLES* + +["source","sh",subs="attributes"] +----- +{beatname_lc} export config +{beatname_lc} export template --es.version {stack-version} --index myindexname +----- + + +[[help-command]] +==== `help` command + +{help-command-short-desc}. If no command is specified, shows help for the +`run` command. + +*SYNOPSIS* + +["source","sh",subs="attributes"] +---- +{beatname_lc} help COMMAND_NAME [FLAGS] +---- + + +*`COMMAND_NAME`*:: +Specifies the name of the command to show help for. + +*FLAGS* + +*`-h, --help`*:: Shows help for the `help` command. + +{global-flags} + +*EXAMPLE* + +["source","sh",subs="attributes"] +----- +{beatname_lc} help export +----- + +ifeval::[("{beatname_lc}"=="filebeat") or ("{beatname_lc}"=="metricbeat")] + +[[modules-command]] +==== `modules` command + +{modules-command-short-desc}. You can use this command to enable and disable +specific modules. The changes you make with this command are persisted and +used for subsequent runs of {beatname_uc}. To see which modules are enabled +and disabled, run the `list` subcommand. + +*SYNOPSIS* + +["source","sh",subs="attributes"] +---- +{beatname_lc} modules SUBCOMMAND [FLAGS] +---- + + +*SUBCOMMANDS* + +*`disable MODULE_LIST`*:: +Disables the modules specified in the space-separated list. + +*`enable MODULE_LIST`*:: +Enables the modules specified in the space-separated list. + +*`list`*:: +Lists the modules that are currently enabled and disabled. + + +*FLAGS* + +*`-h, --help`*:: +Shows help for the `export` command. + + +{global-flags} + +*EXAMPLES* + +ifeval::["{beatname_lc}"=="filebeat"] + +["source","sh",subs="attributes"] +----- +{beatname_lc} modules list +{beatname_lc} modules enable apache2 auditd mysql +----- + +endif::[] + +ifeval::["{beatname_lc}"=="metricbeat"] + +["source","sh",subs="attributes"] +----- +{beatname_lc} modules list +{beatname_lc} modules enable apache nginx system +----- + + +endif::[] + +endif::[] + + +[[run-command]] +==== `run` command + +{run-command-short-desc}. + +*SYNOPSIS* + +["source","sh",subs="attributes"] +----- +{beatname_lc} run [FLAGS] +----- + + +*FLAGS* + +ifeval::["{beatname_lc}"=="packetbeat"] + +*`-I, --I FILE`*:: +Reads packet data from the specified file instead of reading packets from the +network. This option is useful only for testing {beatname_uc}. ++ +["source","sh",subs="attributes"] +----- +{beatname_lc} run -I ~/pcaps/network_traffic.pcap +----- + +endif::[] + +*`-N, --N`*:: +Disables the publishing of events to the defined output. This option is useful +only for testing {beatname_uc}. + +ifeval::["{beatname_lc}"=="packetbeat"] + +*`-O, --O`*:: +Read packets one by one by pressing _Enter_ after each. This option is useful +only for testing {beatname_uc}. + +endif::[] + +*`--cpuprofile FILE`*:: +Writes CPU profile data to the specified file. This option is useful for +troubleshooting {beatname_uc}. + +ifeval::["{beatname_lc}"=="packetbeat"] + +*`-devices`*:: +Prints the list of devices that are available for sniffing and then exits. + +endif::[] + +ifeval::["{beatname_lc}"=="packetbeat"] + +*`-dump FILE`*:: +Writes all captured packets to the specified file. This option is useful for +troubleshooting {beatname_uc}. + +endif::[] + +*`-h, --help`*:: +Shows help for the `run` command. + +*`--httpprof [HOST]:PORT`*:: +Starts an http server for profiling. This option is useful for troubleshooting +and profiling {beatname_uc}. + +ifeval::["{beatname_lc}"=="packetbeat"] + +*`-l N`*:: +Reads the pcap file `N` number of times. The default is 1. Use this option in +combination with the `-I` option. For an infinite loop, use _0_. The `-l` +option is useful only for testing {beatname_uc}. + +endif::[] + +*`--memprofile FILE`*:: +Writes memory profile data to the specified output file. This option is useful +for troubleshooting {beatname_uc}. + +ifeval::["{beatname_lc}"=="filebeat"] + +*`--modules MODULE_LIST`*:: +Specifies a comma-separated list of modules to run. For example: ++ +["source","sh",subs="attributes"] +----- +{beatname_lc} run --modules nginx,mysql,system +----- ++ +Rather than specifying the list of modules every time you run {beatname_uc}, +you can use the <> command to enable and disable +specific modules. Then when you run {beatname_uc}, it will run any modules +that are enabled. + +endif::[] + +ifeval::["{beatname_lc}"=="filebeat"] + +*`--once`*:: +When the `--once` flag is used, {beatname_uc} starts all configured harvesters +and prospectors, and runs each prospector until the harvesters are closed. If +you set the `--once` flag, you should also set `close_eof` so the harvester is +closed when the end of the file is reached. By default harvesters are closed +after `close_inactive` is reached. + +endif::[] + +*`--setup`*:: +Loads the sample Kibana dashboards. If you want to load the dashboards without +running {beatname_uc}, use the <> command instead. + +ifeval::["{beatname_lc}"=="metricbeat"] + +*`--system.hostfs MOUNT_POINT`*:: + +Specifies the mount point of the host's filesystem for use in monitoring a host +from within a container. + +endif::[] + +ifeval::["{beatname_lc}"=="packetbeat"] + +*`-t`*:: +Reads packets from the pcap file as fast as possible without sleeping. Use this +option in combination with the `-I` option. The `-t` option is useful only for +testing Packetbeat. + +endif::[] + +{global-flags} + +*EXAMPLE* + +["source","sh",subs="attributes"] +----- +{beatname_lc} run -e +----- + + +[[setup-command]] +==== `setup` command + +{setup-command-short-desc}. + +* The index template ensures that fields are mapped correctly in Elasticsearch. +* The Kibana dashboards make it easier for you to visualize {beatname_uc} data +in Kibana. +* The machine learning jobs contain the configuration information and metadata +necessary to analyze data for anomalies. + +*SYNOPSIS* + +["source","sh",subs="attributes"] +---- +{beatname_lc} setup [FLAGS] +---- + + +*FLAGS* + +*`--dashboards`*:: +Sets up the Kibana dashboards only. + +*`-h, --help`*:: +Shows help for the `setup` command. + +*`--machine-learning`*:: +Sets up machine learning job configurations only. + +ifeval::["{beatname_lc}"=="filebeat"] + +*`--modules MODULE_LIST`*:: +Specifies a comma-separated list of modules. Use this flag to avoid errors when +there are no modules defined in the +{beatname_lc}.yml+ file. + +endif::[] + +*`--template`*:: +Sets up the index template only. + +{global-flags} + +*EXAMPLE* + +["source","sh",subs="attributes"] +----- +{beatname_lc} setup --dashboards +----- + + +[[test-command]] +==== `test` command + +{test-command-short-desc}. + +*SYNOPSIS* + +["source","sh",subs="attributes"] +---- +{beatname_lc} test SUBCOMMAND [FLAGS] +---- + +*SUBCOMMANDS* + +*`config`*:: +Tests the configuration settings. + +ifeval::["{beatname_lc}"=="metricbeat"] + +*`modules [MODULE_NAME] [METRICSET_NAME]`*:: +Tests module settings for all configured modules. When you run this command, +{beatname_uc} does a test run that applies the current settings, retrieves the +metrics, and shows them as output. To test the settings for a specific module, +specify `MODULE_NAME`. To test the settings for a specific metricset in the +module, also specify `METRICSET_NAME`. + +endif::[] + +*`output`*:: +Tests that {beatname_uc} can connect to the output by using the +current settings. + +*FLAGS* + +*`-h, --help`*:: Shows help for the `test` command. + +{global-flags} + +ifeval::["{beatname_lc}"!="metricbeat"] + +*EXAMPLE* + +["source","sh",subs="attributes"] +----- +{beatname_lc} test config +----- + +endif::[] + +ifeval::["{beatname_lc}"=="metricbeat"] + +*EXAMPLES* + +["source","sh",subs="attributes"] +----- +{beatname_lc} test config +{beatname_lc} test modules system cpu +----- + +endif::[] + +[[version-command]] +==== `version` command + +{version-command-short-desc}. + +*SYNOPSIS* + +["source","sh",subs="attributes"] +---- +{beatname_lc} version [FLAGS] +---- + + +*FLAGS* + +*`-h, --help`*:: Shows help for the `version` command. + +{global-flags} + +*EXAMPLE* + +["source","sh",subs="attributes"] +----- +{beatname_lc} version +---- + + +[float] +[[global-flags]] +=== Global flags + +These global flags are available whenever you run {beatname_uc}. + +*`-E, --E "SETTING_NAME=VALUE"`*:: +Overrides a specific configuration setting. You can specify multiple overrides. +For example: ++ +["source","sh",subs="attributes"] +---------------------------------------------------------------------- +{beatname_lc} -E "name=mybeat" -E "output.elasticsearch.hosts=["http://myhost:9200"]" +---------------------------------------------------------------------- ++ +This setting is applied to the currently running {beatname_uc} process. +The {beatname_uc} configuration file is not changed. + +ifeval::["{beatname_lc}"=="filebeat"] + +*`-M, --M "VAR_NAME=VALUE"`*:: Overrides the default configuration for a +{beatname_uc} module. You can specify multiple variable overrides. For example: ++ +["source","sh",subs="attributes"] +---------------------------------------------------------------------- +{beatname_lc} -modules=nginx -M "nginx.access.var.paths=[/var/log/nginx/access.log*]" -M "nginx.access.var.pipeline=no_plugins" +---------------------------------------------------------------------- + +endif::[] + +*`-c, --c FILE`*:: +Specifies the configuration file to use for {beatname_uc}. The file you specify +here is relative to `path.config`. If the `-c` flag is not specified, the +default config file, +{beatname_lc}.yml+, is used. + +*`-d, --d SELECTORS`*:: +Enables debugging for the specified selectors. For the selectors, you can +specify a comma-separated +list of components, or you can use `-d "*"` to enable debugging for all +components. For example, `-d "publish"` displays all the "publish" related +messages. + +*`-e, --e`*:: +Logs to stderr and disables syslog/file output. + +*`--path.config`*:: +Sets the path for configuration files. See the <> section for +details. + +*`--path.data`*:: +Sets the path for data files. See the <> section for details. + +*`--path.home`*:: +Sets the path for miscellaneous files. See the <> section for +details. + +*`--path.logs`*:: +Sets the path for log files. See the <> section for details. + +*`--strict.perms`*:: +Sets strict permission checking on configuration files. The default is +`-strict.perms=true`. See +{libbeat}/config-file-permissions.html[Config file ownership and permissions] in +the _Beats Platform Reference_ for more information. + +*`-v, --v`*:: +Logs INFO-level messages. + diff --git a/libbeat/docs/shared-command-line.asciidoc b/libbeat/docs/shared-command-line.asciidoc deleted file mode 100644 index 04ad1cec016..00000000000 --- a/libbeat/docs/shared-command-line.asciidoc +++ /dev/null @@ -1,74 +0,0 @@ -////////////////////////////////////////////////////////////////////////// -//// This content is shared by all Elastic Beats. Make sure you keep the -//// descriptions here generic enough to work for all Beats that include -//// this file. When using cross references, make sure that the cross -//// references resolve correctly for any files that include this one. -//// Use the appropriate variables defined in the index.asciidoc file to -//// resolve Beat names: beatname_uc and beatname_lc -//// Use the following include to pull this content into a doc file: -//// include::../../libbeat/docs/shared-command-line.asciidoc[] -////////////////////////////////////////////////////////////////////////// - -*`-E =`*:: -Override a specific configuration setting. For example: -+ -["source","sh",subs="attributes"] ----------------------------------------------------------------------- -sudo ./{beatname_lc} -c {beatname_lc}.yml -E name=mybeat ----------------------------------------------------------------------- -+ -This setting is applied to the currently running {beatname_uc} process. -The {beatname_uc} configuration file is not changed. - -*`-N`*:: -Disable the publishing of events to the defined output. This option is useful only -for testing the Beat. - -*`-c `*:: -Pass the location of a configuration file for the Beat. - -*`-configtest`*:: -Test the configuration file and then exit. This option is useful for -troubleshooting the configuration of a Beat. - -*`-cpuprofile `*:: -Write CPU profile data to the specified file. This option is useful for -troubleshooting the Beat. - -*`-d `*:: -Enable debugging for the specified selectors. For the selectors, you can specify a comma-separated -list of components, or you can use `-d "*"` to enable debugging for all components. For example, -`-d "publish"` displays all the "publish" related messages. - -*`-e`*:: -Log to stderr and disable syslog/file output. - -*`-httpprof []:`*:: -Start http server for profiling. This option is useful for troubleshooting and profiling the Beat. - -*`-memprofile `*:: -Write memory profile data to the specified output file. This option is useful for -troubleshooting the Beat. - -*`-path.config`*:: -Set the default location for configuration (e.g. the Elasticsearch template). See the <> section for -details. - -*`-path.data`*:: -Set the default location for data files. See the <> section for details. - -*`-path.home`*:: -Set the default location for miscellaneous files. See the <> section for details. - -*`-path.logs`*:: -Set the default location for log files. See the <> section for details. - -*`-setup`*:: -Load the sample Kibana dashboards. By default, this downloads an archive file containing the Beats dashboards -from the elastic.co website. See the <> section for more details and more options. - -*`-v`*:: -Enable verbose output to show INFO-level messages. - -*`-version`*:: -Display the Beat version and exit. diff --git a/libbeat/docs/shared-directory-layout.asciidoc b/libbeat/docs/shared-directory-layout.asciidoc index 73dffd3e287..0199a9ca9e3 100644 --- a/libbeat/docs/shared-directory-layout.asciidoc +++ b/libbeat/docs/shared-directory-layout.asciidoc @@ -31,6 +31,8 @@ file. {beatname_uc} uses the following default paths unless you explicitly change them. +ifeval::["{beatname_lc}"!="winlogbeat"] + [float] ===== deb and rpm [cols="> for basic +installation instructions to get you started. + +This section includes additional information on how to set up and run +{beatname_uc}, including: + +* <> + +* <> + +* <> + +//MAINTAINERS: If you add a new file to this section, make sure you update the bulletedl ist ^^ too. + +include::../../libbeat/docs/shared-directory-layout.asciidoc[] + +include::../../libbeat/docs/command-reference.asciidoc[] + +include::./running-on-docker.asciidoc[] diff --git a/packetbeat/docs/command-line.asciidoc b/packetbeat/docs/command-line.asciidoc deleted file mode 100644 index 70b289d55d2..00000000000 --- a/packetbeat/docs/command-line.asciidoc +++ /dev/null @@ -1,39 +0,0 @@ -[[command-line-options]] -=== Command line options - -The following command line options are available for Packetbeat. To use these options, -you need to start Packetbeat in the foreground. - -TIP: Run `./packetbeat -h` to see the full list of options from the command line. - -==== Packetbeat-specific options -These command line options are specific to Packetbeat: - -*`-I `*:: -Pass a pcap file as input to Packetbeat instead of reading packets from the network. -This option is useful only for testing Packetbeat. Example: `-I ~/pcaps/network_traffic.pcap`. - -*`-O`*:: -Read packets one by one by pressing _Enter_ after each. This option is useful only for testing Packetbeat. - -*`-devices`*:: -Print the list of devices that are available for sniffing. - -*`-dump `*:: -Write all captured packets to a file. This option is useful for troubleshooting Packetbeat. - -*`-l `*:: -Read the pcap file `n` number of times. Use this option in combination with the `-I` option. -For an infinite loop, use _0_. The `-l` option is useful only for testing Packetbeat. - -*`-t`*:: -Read the packets from the pcap file as fast as possible without sleeping. Use this option in combination with the `-I` option. The `-t` option is useful only for testing Packetbeat. - -==== Other options - -These command line options from libbeat are also available for Packetbeat: - -include::../../libbeat/docs/shared-command-line.asciidoc[] - - - diff --git a/packetbeat/docs/index.asciidoc b/packetbeat/docs/index.asciidoc index 9c6f55d1a79..7ef49bd6243 100644 --- a/packetbeat/docs/index.asciidoc +++ b/packetbeat/docs/index.asciidoc @@ -27,13 +27,9 @@ include::../../libbeat/docs/contributing-to-beats.asciidoc[] include::./gettingstarted.asciidoc[] -include::./command-line.asciidoc[] - -include::../../libbeat/docs/shared-directory-layout.asciidoc[] - include::../../libbeat/docs/repositories.asciidoc[] -include::./running-on-docker.asciidoc[] +include::./setting-up-running.asciidoc[] include::./upgrading.asciidoc[] diff --git a/packetbeat/docs/running-on-docker.asciidoc b/packetbeat/docs/running-on-docker.asciidoc index 090577c58da..743f227ddb9 100644 --- a/packetbeat/docs/running-on-docker.asciidoc +++ b/packetbeat/docs/running-on-docker.asciidoc @@ -1,6 +1,7 @@ include::../../libbeat/docs/shared-docker.asciidoc[] -=== Required network capabilities +[float] +==== Required network capabilities Under Docker, Packetbeat runs as a non-root user, but requires some privileged network capabilities to operate correctly. Ensure that the +NET_ADMIN+ @@ -11,7 +12,8 @@ capability is available to the container. docker run --cap-add=NET_ADMIN {dockerimage} ---- -=== Capture traffic from the host system +[float] +==== Capture traffic from the host system By default, Docker networking will connect the Packetbeat container to an isolated virtual network, with a limited view of network traffic. You may wish diff --git a/packetbeat/docs/setting-up-running.asciidoc b/packetbeat/docs/setting-up-running.asciidoc new file mode 100644 index 00000000000..388cd8c5d88 --- /dev/null +++ b/packetbeat/docs/setting-up-running.asciidoc @@ -0,0 +1,29 @@ +///// +// NOTE: +// Each beat has its own setup overview to allow for the addition of content +// that is unique to each beat. +///// + +[[seting-up-and-running]] +== Setting up and running {beatname_uc} + +Before reading this section, see the +<<{beatname_lc}-getting-started,getting started documentation>> for basic +installation instructions to get you started. + +This section includes additional information on how to set up and run +{beatname_uc}, including: + +* <> + +* <> + +* <> + +//MAINTAINERS: If you add a new file to this section, make sure you update the bulletedl ist ^^ too. + +include::../../libbeat/docs/shared-directory-layout.asciidoc[] + +include::../../libbeat/docs/command-reference.asciidoc[] + +include::./running-on-docker.asciidoc[] diff --git a/winlogbeat/docs/command-line.asciidoc b/winlogbeat/docs/command-line.asciidoc deleted file mode 100644 index cef2d72f953..00000000000 --- a/winlogbeat/docs/command-line.asciidoc +++ /dev/null @@ -1,13 +0,0 @@ -[[command-line-options]] -=== Command line options - -Winlogbeat does not have any Winlogbeat-specific command line options. Instead, -you configure the behavior of Winlogbeat by specifying options in the -configuration file. - -The following command line options from libbeat are also available for -Winlogbeat. - -TIP: Run `winlogbeat -h` to see the full list of options from the command line. - -include::../../libbeat/docs/shared-command-line.asciidoc[] diff --git a/winlogbeat/docs/index.asciidoc b/winlogbeat/docs/index.asciidoc index fc24f8382b9..4919f504179 100644 --- a/winlogbeat/docs/index.asciidoc +++ b/winlogbeat/docs/index.asciidoc @@ -24,9 +24,7 @@ include::../../libbeat/docs/contributing-to-beats.asciidoc[] include::./getting-started.asciidoc[] -include::./command-line.asciidoc[] - -include::../../libbeat/docs/shared-directory-layout.asciidoc[] +include::./setting-up-running.asciidoc[] include::./upgrading.asciidoc[] diff --git a/winlogbeat/docs/setting-up-running.asciidoc b/winlogbeat/docs/setting-up-running.asciidoc new file mode 100644 index 00000000000..0486f98928f --- /dev/null +++ b/winlogbeat/docs/setting-up-running.asciidoc @@ -0,0 +1,25 @@ +///// +// NOTE: +// Each beat has its own setup overview to allow for the addition of content +// that is unique to each beat. +///// + +[[seting-up-and-running]] +== Setting up and running {beatname_uc} + +Before reading this section, see the +<<{beatname_lc}-getting-started,getting started documentation>> for basic +installation instructions to get you started. + +This section includes additional information on how to set up and run +{beatname_uc}, including: + +* <> + +* <> + +//MAINTAINERS: If you add a new file to this section, make sure you update the bulletedl ist ^^ too. + +include::../../libbeat/docs/shared-directory-layout.asciidoc[] + +include::../../libbeat/docs/command-reference.asciidoc[] From 8c6b706f5c1646a5dd82d8e64b0919059677c32e Mon Sep 17 00:00:00 2001 From: DeDe Morton Date: Tue, 15 Aug 2017 17:13:36 -0700 Subject: [PATCH 082/139] Update getting started to include info about credentials and new command syntax (#4841) * Update getting started to include info about credentials and new command syntax * Add fixes from review --- auditbeat/docs/getting-started.asciidoc | 8 ++ filebeat/docs/getting-started.asciidoc | 8 ++ filebeat/docs/images/kibana-system.png | Bin 256416 -> 180102 bytes .../docs/modules-getting-started.asciidoc | 70 +++++++++--------- heartbeat/docs/getting-started.asciidoc | 10 ++- libbeat/docs/dashboards.asciidoc | 6 ++ libbeat/docs/reference-yml.asciidoc | 2 - .../shared-passing-credentials-setup.asciidoc | 45 +++++++++++ libbeat/docs/shared-path-config.asciidoc | 2 - libbeat/docs/shared-ssl-config.asciidoc | 2 - libbeat/docs/shared-template-load.asciidoc | 39 ++++++++++ .../docs/step-configure-credentials.asciidoc | 30 ++++++++ .../step-configure-kibana-endpoint.asciidoc | 3 - libbeat/docs/step-test-config.asciidoc | 2 - metricbeat/docs/gettingstarted.asciidoc | 8 ++ packetbeat/docs/gettingstarted.asciidoc | 11 ++- winlogbeat/docs/getting-started.asciidoc | 9 +++ 17 files changed, 207 insertions(+), 48 deletions(-) create mode 100644 libbeat/docs/shared-passing-credentials-setup.asciidoc create mode 100644 libbeat/docs/step-configure-credentials.asciidoc diff --git a/auditbeat/docs/getting-started.asciidoc b/auditbeat/docs/getting-started.asciidoc index 5abc893f51e..6a97c407e18 100644 --- a/auditbeat/docs/getting-started.asciidoc +++ b/auditbeat/docs/getting-started.asciidoc @@ -178,6 +178,8 @@ If you are sending output to Logstash, make sure you include::../../libbeat/docs/step-configure-kibana-endpoint.asciidoc[] +include::../../libbeat/docs/step-configure-credentials.asciidoc[] + include::../../libbeat/docs/step-test-config.asciidoc[] include::../../libbeat/docs/step-look-at-config.asciidoc[] @@ -242,6 +244,12 @@ PS C:{backslash}Program Files{backslash}{beatname_uc}> Start-Service {beatname_l By default the log files are stored in +C:{backslash}ProgramData{backslash}{beatname_lc}{backslash}Logs+. +[id="{beatname_lc}-passing-credentials"] +==== Pass credentials + +:start-type: start +include::../../libbeat/docs/shared-passing-credentials-setup.asciidoc[] + ==== Test the {beatname_uc} installation To verify that your server's statistics are present in Elasticsearch, issue diff --git a/filebeat/docs/getting-started.asciidoc b/filebeat/docs/getting-started.asciidoc index 5a18fe63fa7..e09a06a545f 100644 --- a/filebeat/docs/getting-started.asciidoc +++ b/filebeat/docs/getting-started.asciidoc @@ -202,6 +202,8 @@ configure the Logstash output in <>. include::../../libbeat/docs/step-configure-kibana-endpoint.asciidoc[] +include::../../libbeat/docs/step-configure-credentials.asciidoc[] + include::../../libbeat/docs/step-test-config.asciidoc[] include::../../libbeat/docs/step-look-at-config.asciidoc[] @@ -279,6 +281,12 @@ By default, Windows log files are stored in `C:\ProgramData\filebeat\Logs`. Filebeat is now ready to send log files to your defined output. +[id="{beatname_lc}-passing-credentials"] +==== Pass credentials + +:start-type: start +include::../../libbeat/docs/shared-passing-credentials-setup.asciidoc[] + [[view-kibana-dashboards]] === Step 7: View the sample Kibana dashboards diff --git a/filebeat/docs/images/kibana-system.png b/filebeat/docs/images/kibana-system.png index fccfbd81f4a186778928f6450af7c6849ad56868..eded1a605403d5d618c61b003bd059479ac2771d 100644 GIT binary patch literal 180102 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≠KCuq?7?YWU_l2?Ok*; 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

    PJ^W6uno1rMta#9Z%VK$Y%f%r=9sUhH|61ihv^C zxwGh5wUQ05RpE;k-P&tVuL0nPJ?5;~d0B;|DE&=i<2!Acy9Ft~F#1?GvhIf(+N|SG z*Q|y&?~Rym&p$EWs4Qr&L=R-9zS;x6Q#(JIJQm#qY2Ak;aZ#vyzF%|_2%OmwYzCN^ z?cUFQ=ermhp}p#$hy^uSs9VTuih2K99X&o7RDE?jj&%LTXJ8jHRJhBNH;R8D0?y8}0_GR=!J{L} zwP59fh$#qeh)(GF_g_Zkejm4QZN6WdtxT?Xq!~sy^xt zg{OYCn#52}T|pu4V_@gJhp*P2;&fMWG+I|VC$6alI>;lgmy>j%%cJ{q-KG02(qklk zAU0PKy6dG=LT#Wj^VG}18$gEcFaYeK;mbgst!!AmRu{U#tw?3geu*PB<4K@d3%!yG zVjMp~(d%_6R9LlE^9R)$7|<2Yt8lVj>dvfku03NQ)7V+D!R;5>@4JE7jbX(=vB(i& z1Eb(fe|-JaY*a5u{A$}P=PtOHn;7DVj$t#6BCXwn(jwKd_Wew@OBSMTE3BHyyj&+q z&#Xw#%vn+G2OjWf_E)TXVZUIjdtugx|6P^(EUhdX-mWrW^KeCxHryF3oOpLIMT)w* z#2>2D7Y|bQaTaO2B!A5a!L=QgY6^pI<$6{ZU<kKfefnAOhR)CF3O6_Sh`?q zAFeP^qJh_IM0UXnCk}n-GvPB}j1N+skvI}C$}%-@Xu4yR*i}lj13Du@5DHA<@(J4Z zu{_kQ@*tYL&!_12uV8j0R`nOm#>6vM0I+SsrL_&iEf?7^yD3AxrqA%CWCW=9 zB2J2(m3R9+&TN&f)UNq$?!`z!4MrOe>&b(|3dBbr5$(@*L+P7&n>dnRs2IIq(Q1-SA1K*8yqD z8js?Qb}mch&qj}QMyidVW`Dm!2zW77dp*sQD`2qFl~mz=S>VHvwYAt69mWe12=EB- z_MICzL9%1b0#hZ?ZiVes)Ho*3xdkj7ifH|pJR20fd&VxCSc7lT9jG7A3HOMjHQ}4F z;0%@YwOOGwU6vlM<++SiY@{qWwvxZiDAw~}1fES9IIbE@QkkVT++niLX?Y&vF*mE# zN6ZRKN(v4&>@KKocnb}?c`D`+9$DPfBhuDjj?d!ud}Ji^Lc%nlD1iEyIg|12o=yJ)H$>b>`MEv*?TL{tjS zbq88J^wzlQr`Z&O_AfFmV%ptM#^(=duX^-*XRVWD{3&>GY8t?@M;VY9R|^HKZqVc; zD+~Wqg+yD?=Q#6APZ>aW>;J9z@d2Vj%G=IWGZW`L#~T2n-*3@<1wRm@r0BN+)LU&9 z@&+EDOjC16>x|+#CeIS-O_?>bArxr5%b)v<6kD(o z`qe~7P;We(RRJj25a#uO(?NVb&?ihkDWLCjD4;fHt7KOk(+nypB(< zrZU+AAGpo{0@TYcr9D~&I&b9h6FT8*EXs^)=~W5|m=5I|SlR=80h^kt@oB9lMQStN#q87`w)Z==` zT?Gn)k-g(5O*JySoL*HqF3v083Vq7JnbqXhcnivQ!y|^&Etrq6<%)B3WNkL2m@{G@ z1VNC{;f9Gvu$C>*ZiaGpy~PU(a$VS*AMfa&((0wRimQ*=R=B1a&*YJSLfs{X{GRln zP2kU_35XI?)E=#n=j0w7K46Hg_hRZ;NFmJtKSYi;Y(P%+0LS;7fDO3HH4fU!y9Gu+ z+-WEFg;ej1Qw4mXRifaWdIKv_YJTQbM!TQNR+GHXoE(eV6i!TN&jB1__rg)1%b3uR zC6NQ#!^21rFu6^rf1Kux2QjUbaPmwtZq{ zTiW!k9^c*llj?@ji>?l!SX&&9fqT&{9_CUafLBKGW1Xi5y`8fW>n`4aTc%Za{|+r? z{)$c?>-2_GPVsp{=ty5=HFJIWxRWj(4`g5miiAg?>AU0&!;?!qFemW$1LhZtDa>lf|t1reO5dLTWLgRF;Rw zQCt4GgX|U$&a-b7f|NbI3J|z_*7N?~q3r6>EDj=}2q0{yDuV+V-$t681$1uWiZO9a z>3q|sR1;f9e<`>k0ETBlY@X$GaMmz%WPixU8ahzdJp$(SgFkQzVUEcFB-Fs?Uek%PmVu0q5vzU*B{u4 zlCRkj*r|2{E31Fg+Mu}}LKN2GjsWLHhTYnDcivY@%3b+XzxOARgOndxOFXctIZz`& zMLuInAHB{~|9<8laIo_m{=rzLqC>9ZAz4voI5bx~Yxa`Chv;7daS4$3;S=rWt%P*Y zSm9)5J7pLH$WdPzsLpB~ebiKVDfAau>$Ivst!RT$LQE%^9o-`|Gh{7KTlvFy?6MNp z4y<&^4~}NtY%Z@z^wFDjdu~$r+#=T05+wIBXqt-P`|}7XHVnclz}UMNCzZhKC5M#a z%*ZwJbl#MtrHf$86nQk?I;d6NniN6k8J#44qT>yKhX`%PO&ax6WP!1V)FB>2;@w_< zYNvniF!xg}$UrGO1hY*cVbH7(=2==vb_avwy(O1Tw8lG5P35t1_g33qwBK=_hA zxb*JxU}t#Fl%2Czw{G(n+H76po70x;Ni+clM=Jn?Zqd7sI(QT=)%!QlH~ND~`VXf9 zxb28na zE3i$bUA@Q>jP$nbq?etDN>mE2Q7~%!>GWP1iZ9(Vh}W0 zx9H+%S`m}UAq%Q5PQp-0=3_pml@VY$G(ClD11QszI*o>TrCsE%pmX&3rG`qypZ;_* zyRp&|*lm|5awbwJMos3)GZwPyJ%&s!!Wwve`5ZlEg*3%tfey0pX(7ag(TV_5C3jw3 zKqhX?`1}}N$caOpDk@|AK0UU6W&j1tQCQ7;YE9UbH|o4wISaxqOY*zsH7oEwtv?j2>1&u#qply+r_ zlTw2QZ3CWU&|EfG3pmB0kG4p0xR?aPG|cy(>qwgrJ`1 zyh2g_e>%}|YIJ-^m|7cTkP|C$8K~lx@WBaG8Uqx+Q=3H8X-ppS*su=6 zP8Y0(#^l^z%5ABz*BY=?9PteFyCw_?Ou?Ht)-?LXT0z3WD{M^t8c~HQ^5* z=+w-?u)iIB*q>S(LsxBg`CL<5L$%*lo&mQ$PfNIm=E*m*ctpH++1_gYx%il=;%!xS zm!n!(XQ#Dc@W3f&W=!FWJ!FcLB(QV)IE{+#e|L-b z;&0v?4h>2H?=|Wm=SwY=bHV4k29bkp5}G90FRlhl*=j;UU#wP$AQ8fTzJKE5j6Xol z>kO@v&ou2d0#xn5i{uC6O*QA#%yp!H-MdrUQF3}m;%_ysx@+9NdbIPx7Ys?FVwjqQ ziF8y|A03)lE&TP#Zvc?Os2CZHMSj+<&=zPv1AkjC+-xfp8}I+1e~4g0)w9_oKPgu! zArK|8Y9r^hw|y_MzqwLRck>+BAGUdRyj`n86x(xlW@dRJ3}(^P6SeorAC=b@FY~7R?SmP=>^IF%)klF<%0Su!9S1O4Kq^+EuY- zm~zYj3M3T}5nuo~Yo`*DsctLk0@~l~PN*cjw4Gx!0Mo@e7#VdT6c~MR^Jq+T$ek|@U|87OnZv&YiP$^wo^AO_Q@)&_PJ@B-AM=bl45lRx zf?`u_G@E0nb42vT;h&L@punbt2vuA5&vu{)oUa_M(OWC6_ie-4emj zCcJWGM=HpcUS})LCoL35I?cb36x}5eEvS&0#W4hW+1el zfVFJMnjgpZ1Rc&-Eeynfaw!b)bNS)UgJD_PU+f_So|B`k6a+PQeMN44lotm3X3sLV zj$~V+>R&4|E7$TLSvy`?BVFC}l=UH3IKHXFIlQ7@vjhtqm%rGYi?4D<^+z6)^sTZ( z?Sve{eG+IBj`2_)2`a`BE~|&>Ph0Gb;ABuhDW8IF{(_7nX*S^!UPl;TEm4>4!(6ZU zlp8dz@=~Wy@A=aTZT#RgSK{MDylZltetMTvXIb%}ylW&ub9LFW9bj?@@6|2e`)Myi zMB1TALzA=cr6i|rn>EcE;q>F(cPG6}v4JwS9+|2J^UJHN$UWm_16qMCCF{l^$=h{Qj(CH-pyPusL9oVvWt6k!&ao45bE^t zyc~GsZJs}b#x?(@k!Q_9r)jz28+EXOIY=7#OYfHcm?H+56tIm9mAqFz^iQK%8fnK6p4iDk3#v+9j~+c0b>T zV6|6TaMW5fU!-c35?sl}I7ZyA-FD|b5IKBB@8JF(p2M)85Vga|1e%g3GonIQAmJkl z0zt|t^ZYP7bPT*?!;mKH^=;KqgIkO|ZDttS5kc44l`lc@NJbUTO(+QaI|Un0wQa+z zgT6939ksrP#yxgfdK-BVBV*@DnKK;?`_>mkr}@_21)FxUCN(XP?Q!vTS>`!MgMm{4 zwL})L)$7Tusw!o1$VuzW)E|>zYLsG+h9`Cu_t9uva_N-#OII8Zwb|e!2IgfF$Jgl# z(he2ELhiIM0J>62d^){Mf=elTz4c2p6Puvl%uFgI;YTJ2vc!W|UCqidMMuS87m9w~ z4F-Zzt@H>7ipT>NgO8SBw?Pr?7|?D2sIrYoOiWqk{YIcFQ?=Vc?7)T0C9yJRZCJ=o zkd3VRU_y|7E$DNGcZaXU>26{vb0r?_HmKoO= z&n~%^g@t{7lXLAFCDU@OOJ7xpe@$!zUS)mOUK6i7?a@s-`J0a63C9{PK=)sC`jlMW zw@3F}AWf|;Um&0Lsvr4AZA}VpvZ(BPcQ&0s*E9@@rY9nw`%n}Iq2oo~70Xs3c56aM zM1Jef9ligM#gymZzY5&+yBD^x6i|ZSb3J}}0vGlQQP`dcy{|I9rg-EAlG+`7u(^!d z!%B22N)91!-9JciO`tGCKnxE`jp;Cfd>Kk3bbS-@7W@2kxuKcpF$vXX+9K9 z*bT`!XEpN3GJ6EGH0<*E5cIVj@(?z-ao~odc$9Bt_A$~2h@Zz)KO9RHzSlYtSj)`6 z6Le_}R!c%O2D3_khd`V8cE4t*XgW4msbktZG%IcQ>h*>TPc>a&kWgAit)#j+C_5a& zfhI5mjuz(fzyG?X-S=fBhQ1fA4)gYP8YG0BPJk%@Hs`!gDtT0zfABzPNLfQ{=t-OOKT4|YE24uRuJlaW+0?I&(G zd5yr0xS27U4$CVYcE3(`c1&m1)orZ2(1>7uHT*={u>x!K{s3oH`K$zcHp`GyrQL^` z-1$wAYFv}!+A}<}=0kP2$5)#tdCqrUnwQH*eRq$qU_PTy!dxpG_$#m|WRbmHYwh{w zu%@@T1*hxlP2axJTJ*>;u{4*FSAF+wwoGjJe3h5++%VYt^&!ZZuN9vA_A+iptiJW7 zc>OY4oFI!?PLwm!N+p7e#BC#=o-SJ{m?c3fDSY%-#KqQ3v2(K)jrof%?p*rhb=y+z zuQ=bnYd4!ZeW!A+-X*1prChDd@JdY=L^o=QFXxAt%XA;eMnApSW4dX6%j4)DY_{oD z-HLmliERLPu(rJSaA>n@n4?SzM_W(h-K}`NIPkkCv>1j-t5SSf*lMhL({^ZknB#2Y z+VebgNcB|(BS_qQDo|gt5Of!XYrvz4B-4855qB>}9FZxlw!U`3^kv`d&Vo~qabvVR z;^$mtcrfMXl=30^Ee;aXW>LoYr>ZG%tyd^PG3p?`R%)h(J*WBQ8peV{_V%1y*2Wb{ zD$aO zUw|k2a8*o^4{KRii+>!y3ge6{0iM}|DBWnv0n+C%2G@th;VCn!$I2*ykb>8ViFG_~ zABhPGU!9;F`MN63z%fieW+vLLRz%Y6#m~eSi&g`5!?HO<$iOb_>Rygv&h%ZRxm%T+ z*kk6hSb?zcc%%a}Z@>V-+uPd(l^U8s{&ukxAmzzZn-AJIr3zTN3Kw4q#iI}uvFb*L zb_5lwqUpdqvy@Y#dhag$_<2Ojw{EJn#w7`73^!ta2vXnl^ErAFV;ijLd=b3YI9G7o zamw9s)-8DXLQ^j52e)xn$mDX2R_C8D(g;%AtD0s~&Yd#Gw6TMgs$>qLY~JNlskd)2 zQaO@rJm5^vh=C$>QYv<$>qAUEdQlEOo#5Za6s;m%KW%WK(CrSrTAMZsSJVD-|x)6<@_%q=y=coj$>Tv?n8aR?2qoSi0a;S{Rt46JK*t zxe9&%i;JBc#5@ZXbl9~w>r962@yafEM$)Q1*CwybLr@+pe_p$ZvukMjuNM(LxxCZ^uV+%Tdc`>-C@4))V&A zE#sRHHZa!5s}gNA+T(O_IzKI4v&VTep%~A|J{q7R13?yh!#VP;37EHZvosY8?aD)s z{;1dpvk0<2Ss(qXa27D&b_&>WS+*%C|L$A-X`^ft;rf>ry~WbJYNe6yUOXrx7=Ds%y!o31zm` z+-;^|>IVHQlYC`LU}Q7ZP|(!##eTYBJOHEP=j;@?!>G881MjY%sx7$78dB+Z-`gqg zPNZc((;Hlk+J%yfA3{MJqkv?_#_@Ljzey}@kV3_Uko%#mFMTB5mj($bjklCuI@H&W z)o!v__aC(ZyAd!8SCFaHRB%3{^ckF{TuVTR9q}`<4PPJ`5Yd*1+DM*_Z6D4adLsHn z(vEIhwg7E0MB8memRrSD{RJPB9U70gX51z@?Szy|uB)LjQmqv zblK2F8{VO#@=>ak9N(rrlqKt{lsR#^K0q(|XOw0T(#OOyn2Xv(V-Fi}SdtBu$84nw z)1V{U6QVWTZ%eLD`Yd9tb`5J$faO?er;TAu^<^bm2Exaa`-k6Y63@Adm*`|ek`gZ1x)EjvgL*lS2B}c5_xdxiDmZ(juzz(NZ$If1Jg1_z< z)FN-KA_CFCLF;Yx2GMj-?ZFyR!^I1brsVRcC$eO{L-yl<^NKFkg*qXo~$AwjDc*l=!TdhfHzaPbg z>&0a1rh<=x4nK7jx{5tCodO2dPh!oyABqefuA(`5)WA)i#}EZ)pjv!aOB>8U*d4}L za>~KkqPDW&EY27BXY09B5+#JZ?{-GegSvzACvjF#C;D zt09RdlTbFWjzzBb#K71CuNgyY>|Fuf@h598^+ug_t4JkKfZHrKNI+r4zliDDMmqe) z)X>6dZ0_T}yoL-L! zS5=BxtAd#A+RL$gcf7{&g;c{m|JeKm97Jdeuo)J;o}>TiuMK2fG$hg^a=u|Gz14O- zwCe16zCmMZfV;OM260g1#fB^AtJ9E+bS@M#1LHf@plbu{nTbHFARZ=sye+cr_W8hL zBLmDkhS-b=4!l4fKb=z}?XlKM)ymuNt=ZcX(ym`p^dd#F#6f?Gar^h(YcrQ-6_-7{ z&dEbx8hk`mc+)^B`~@nUdl8@ss>=P0VCst3bwv_$Wxz!)m7T7|OJHH}Aeh8hN7L_h zfe@%nrP01>&54r@npD%#1f$Gu{{_x!6*r7W%O4|%dP+$(s>mnsTh#vEPYW3--$u&8 z#WuaKb99mMgys+qAMif12<)T@d`mnaTD%qzj%LxVXE1%e8hJVn65X5(87H#oaZBQ6 zpGqmg&G4Z6k-A-bI~ zk5MVE=|8Ee;f{o^_;CtZiE`@0YYK$+*pvt+QMGZH75vOij9DEad35<|MOkJlNTt<% zHh(QfealgP>45CPqc)THnKk%L_@Q}+4j0Pa~~`Qf?xHks=7gtyN0m1 zN^n+G?LrvZPqlm-v(BuBJgZ%wNwj1)?vSkc))Q;q>YBJz`xRGWKodx6&juZ9C;wDP z?i$4y6dvV$nRD(t=Zwlj5xFQm4*RxgAl(on4&_pBlQ1RB@0eNPOEd5UY`AczW16#h`%4AS{t7WZT%gB65h3W7T!f968ba?Fy zi^05lc+&sF-B$(0p>1sj3oaqJhG4-hxQF2G?rwqL?iL^rg1fuBL*q{4(l`WnZJg;N z|I|JA=1$dA&C|T~LwDESYp=cb((g0x^>ifh54EbS>sMuu%`Yd>teCx2f9 zKovi%PxSfuZK2&K2E`kw^NLzq?q_G|gnE>)hV^S&grr8HsxX$)06G(_z{D` z21(*PC3wQeSO_;^t{fBkPkJPai!baK8flP5aE_8n?BD6bh#j}KjPeFk1>o6rrCJ)>}-o?N_-o+kW6T*L6Jj8EtfkNl|=<=tX`w=jhoqo2_-JEo09ilSecd(Jp z?9nfx8Pc=%m{Ri^t7#U3diA8%N?ry;g-qZ-pq`%_{jNp9UK>HjRxM^JC&mW$-v#t9LX6*7Kh? zD`RQg+x&(qWC4*gc_z)&+-pB>1APsHmjl~(rz;t(3;sEY^Tis9(Zor6O^@R*T;7ZK z7_KJdYM)QUZE{kG^w#*i>2kfn6&5-}(=G^!@+3WimVIyZN&{SudK)BcmJ(s5z2H8Q zXv}9+7(nQL3}z6qD)o^4`|RfRw-7ZRj-_lOIxGt7@aQ&IpW87ucE1P~=%s~&qE;r= z?N>Wl4&sN})aAbY8@SW*R|sH)`@o6=$6sZCA~>T)hJiM0PssC4bgkVW{sP~Uqupa= zFU=P`8zC@|xocbew#sYK>hZRRL#KhH1XP7e5Hcgys5Wc+4e62F5==m^{XjQI3Ty@& z`>W>wkR`fktO2!6c9KQRh1wUIkGInqHk5=Y9$C{%OVYfFyLv5)4*$j(u$HmMP7)yXuv5JI{5@><#$NZ=r|%4vZO?OSje+>GmTm> zb&QTAr7pb|4;kCtXA3>$ihA4ePFVU(TA{gfBnAC|*Lcf~!7hw9r}Y|`cj!M=corkK z11B%PFg-RsM>dew-muB&Y7_8hoJ40OeZReLdNORHQ~!)A>sg|c zd-tIZY5bHo0Ja&lNf?wN8)3W!YQOJDyviZU1Lw?us(=Bnub(g|kJY&o5WfT#o}dO_ zhK86t-VP-$d>ck!$_!h1Dbh=RJ###Pi_Y;Of0jkkW5TCFX?UWdyQ+IDV!A=8M3&ir-TL`6Do0+SX)Pad$xKw>}=(L^jiB+D~Q*uzV&cYDT- zC|t5$eQ{*u?dofoQT!o^;Xyzj1-2E;sO1o5Qmdag=2;!yHA&dF$=35+SU$4(A_jg& zBs$mPj-1`Esm zm9U4ZTwier1tejf1-0_fvGWss>r+gun~y>-w#46b{DkawAUU?s`K*1U5(5fKcT@M6 zDDgAz1H8IzPW|d|3e>o54ANa0)mo7|y%RxpE8&yIp7*o@U4R+M+ii_=s+^aoysG7p zIdiSj-z7rHJIme&M=)!SO#_Jm;ol4E%UtMn4N%<(vcj8w5`{XCboA@f-qUf=l6Wq9 zyx3e1OZ;%xot;%{<&U9VFGj;N(}n zDX{Q$b>?rJo^0An$cA5;c~e=lx8RG>-!XxW+QJvaY;9AemKe(7prJo=nLshSWayUp zFww3Fo5ERA0mnL<9|g0nYB%>rDb#%Fwp4j)rIt0r=ULFL+ELY(QzX8$eQHUeKu z``OYnU7lznFiZ>cFtB{Uv=>HR8YHf$U8+rx6Q$psEqG%AB^n`*0dltZj>9f(q25Qr zTgtywQNGm7+0Vy`#b08c9?b?tsP+W_Ouc!hW;7&Z`4JIyqQd#wplni@?UXPl(eb*kjs4)55vrclw$1f4FhOkoIofbE;z<#^ zVZ9MwZ~Jhwy6`1XvHcSf>xT57m#1k9jvhyc%LzkVy|Oo7nPtA$kd?B>gjIK%eLj}U zXP2i8RQw`0K5|`PqFULOH!9<(Hk|Y_DSqqVt+La#^hScC6{+^g;kH_dVI&_iFW{6*}U>-5(0-otUznNt~X z$M!T#i`XXIcfT&w*BYtYvF+hpN6V z(%d1UnWVM)KgjrvZBz3#FnB^$2g&RNoermA&Zj(YGFO(W$nT*$lEH67I%i<+*WI-l z?`y}JQnXACCQSL|o6SAKlxFHQDxhYEJ&g~8KT>2w!3U&W4syBD)>4=E&;U!mn+Vg9 z9*2?Tk)J#t(%JADcUKd~BvI>k*?Meci`{Rkp(UPE{^_qQ`$NMgGIWi*JH~jN2ee;P z!az@YEyLcfIVV0PT}DJKFuxenuR1I|d+Md5x4&SwO_aAdPI-YM?w+i@tV{g9yuo%H zJ3l%_K3fBF3cuu0NHVaWZ9W()h`;cDiJDJA_x3+0wGmTrAu~qI$5+lzt-$1-nCG@D*R6_bweoKaAiMZY# z#msKv1-5*)UjeQBHUGD+v05*KW(bk`<4gj|W9#-?9iE0a2`Edus+?{kGqTUNdO=-9 z0)D)9?%uwj%AcN(!$Hjw=;1=L(Yaxq_2PGFtGVti)I$qZCa6;(E@C3SOIOl2Q@1$? zhzrl9%0VTgC4UEo7a{<3vZ=S1>*pr7vp=(bbv$W+yTmojpH9Utp7pCfg`bycqWeQQ z&9s$Ue0K=WRM^?fHDw3ZEsryb<+L~hf92ZcPd@C!E9eF|nBmK%rfs;s93r&1MPUM)7gC^#|H!n5t#)PTk7^bN*QI7*CP zgX#I{Y$sI?;dYI;MO_q>d~zV1>amC6*UQyw2V1FOIcs}_el)Tp-}buO^zdwgr^+h|%2LujX~ z5FutA8;g3;y}Fr$ZntDbSXmk-&MeZ#r!zrMFQAe-Rj4kr31 ztUA@jzbAvi+rH&(IIJ-rvh>3(T$e@)z*R2+xUlI-V*b0OqU-@+85t zEPay)lZlgT?=eUUJ`;hS2^n8+ll&M}o2Vx`WA4s+E%>YDcz_r4jDFgROV6ze=bbX> zXxW`4-T{e<`aXwt}F51RS%D19r(@!@5^NiI@G|h}<|IgC4GWfhInVf4IDszeM z?bIX}i`7XF^&vgA3H?v03w_tkGVgjjC?OaUz3Yo;yq&OD7>&~D(Y`VRZ?%hlr&r(e zrt0E@(N`$CgbHEeJJQd~=UZWP^H8}hDd#t#F(35G(MsZ3q?)ZJiCmM7ro%9N5og5o zyC&BX*4t$%CvW_Dw2l;l3FW^$U}vTaWTDP>dgRv>+DBfeuiX*vWY7lRI(q02A=P}Fg;*VOXK!v+Tyi9&6eK2tNSENFNg)#7@??9#YgPlukx9c=i8K3*ZVtP-%vnxv0CLZ+U@&8^`hHriMkJ5BXzcDQFQg7Q^T&&Bf<`Ak+CT z>AxepZyNC{EZ@erEWULfmAHDj!)?MINi$_MoyUb}4WzwvO-$TZ+lu@>&sF2`U@fBd z4iNCjFbQHgJ+M8y81yf)LKWzjup3QoSWOaOKN}oj$`!@FP8|x;jachX(~q*4zq`E! zPzZMv0LKFy5yrS*4rECO1_x5R$tgu~_&#Pm1fs4N8VUCESWK&qNO>}6E(dAWb^s=^ z?u@CuCaxx9+}hmV8O?P@SQ7r+2rL(_gMqIBa-aGFxMT7@Yq}p`^@Y3 zN@W1}FGWZO1MFHep6An3jJ8WDWco~gAUONBa!FUHBctL&#vv3_`!vChpVnNze!MMZDn5% zR8C1(8`k`ApPQChG^qYCpeO2f?0SCi=)SOg>0S4u6Snl>ZZYIZLXi}-ysZ~a8i)gW zpbGW;KpvhTLl_;~q59QKJ#G|)7H2a-DqqhRh`#e!aJ{a2T3B6)GNa?@S!qhp7e47; zehx``0g&58>gOv+FwtLjAlj2W<+P77{&Yt}TkpwzX)ve0$-7&V_zk`o5Z*L7CcPM;^>9$HVB^guRqvZ&UE@TRT>w~DJ#&Gx~YErQ0Zfv5@Wyd(>vekSSKMYF|@B4ImjERD_?}} z2p;H(ZusQq1TEWXF9lsOP~S`^E&1c^i3fV0Z!Wq)s`D&Z3U!J6(`LbJx0Up*GQ(hO zSWqulQoB{ocjt~#-xqE_<&f~AgHl!H(v&AMX<}PNo(D`my&Lr#=}q9iNEzP~p~1vT z^HU)isyWjh%o?qzlV}91Qjb*mxy&wxtA``6?&i+(~ z2IA)uzluUHjZR;oL;CEk(a4&V!(+BA%@_DLv=O{yeAb&JxKnqAj}*w z?fEjgl!J?(1?v0(%$?8MV$4LpYHOJ4u(Y4&ygTu8o?_h{3M|NpI87}O$g}I)6L&6M zzZyY{!LA9N(S^bUg)X)dO-=%jbz}-*vw#6J6BN~+TgGHu~(M; zf{Oi@=L8BAJT}C)`X|A)zFr}X^G~I4-~)Ua4Q8Y8QGNWaW$mdp(yc;zAsc&AnKS`x zpr8V>ua^M6KIy2CL9KuiI^sGUxV!h;7IT%W9nDgJ7JsPa1DLZSGEzF#UWI}716#P= z4}*%OeA_U-Vs$I+Uxs*(B6X5pDF0eN-Y8MldLMfg#MfcUeiL`(pV;3Pq(`=@Az;YL zLCx76pt6J}7@}1GJ>6gmLhlh9L zh*{<)KVVXwT+C=3>$w&=!Djk4skO2Wcz!Tf9+v=aq<`Bx|GB)Dcn@#{zi;E-wR4IA zPtUMCZMgGco_aazj8Hd%Q&uEaD=XzQqjn!=2Luq2zRaEEy0|xl{+e#BB_8p3w>_$N zH_~t!M#1p?!0OwR7T{84&meM71K(QU_7(iF)4)t)!PfOIiEyn){Kne_=xBZo<%^kJJ~@-E8CY`y}&;)_R$tca)xP8upR`oecy$a;v_;oD6q(GhpXE z*nRHi>&p%jmsezGGq&OWUkP6SZrrm^g-{|GHJ;=?t1c31^of8%8$B`o8HCa=5y)Dl z+o30cp;_J~D3b|Q#)x*!dc`*$ zrV0Ka{2aD4wvY13D$h8ANh%??5wy3@BnjQHD@hBv@(y2dWFrsMA6{%%b z+1IZuEZg|OV6c>~nzNZHT=Yu}83a1C%{nQ;JkgN6+HsIj1J@aG)`<^?F`G z-zn^@cMZ|!rshg&a5?zUSTSe6men=8mB=dKi}0F}X543FUJk$nzVX@Y5&GE*eC&Dp z!4uay9N#Jj0u2PGQx{XVzGD<4?_S%zR$G&6eok@Nj_OMwXQ9zPDD>*w!%o>kycN+%V^Z5`*> zM-!!V>dY^djfHC;KCUqnmCg~14Xh?sse06|3Z6^OD7wc(>ifsHZyjUHlM}3i21sHx zL2oe)N>+)ktKOJzQcBQFUvV|^;;(I6q)(G3mS#7MiWnffhk!kaHfk1Bb!re@8xi{M zMGvBfn^$_Yv?!$;Nh2HTXPppj6@lh793cXXr_}ZOZvuO8j4NQpX8A6g+vg7~xZ`_r zjTqmGKpme>N4gTV2I0J^*lm{)*dqEhUo&`NFA6CsSay>}yp5853aW$*qB z1r*+`!IiLE1XFL*F{L&(vM>!*(0oVgZ3d}e%v|qKc5&>oy)I7FD%$Jkd}2B-wghpJ zJm@4VLGV#;*TiJ1!DzJdqs9@e?r5y;+uvVBUf1g%J0Q4mEqvX6XV z8GL&ueXF>Jg85jBH=+feQRcqY4m9~)F9S%!BJ}EKrwpazT{M^lwEAs~m?R!uY7y1o z<6JMGnvF#P$5*rVjM(ep`eR%fH#&bEqVRVQz+{THDE36%xMOjM74MglEt;e0CzVgN zKj>~hJ+FKHU$irLRM2YZ&{K35du?C+*~<`X5e?~O82q(Zmq6cG%@8(UryVT<v-90?8FGEsNQaJCeDd>*+y9R!b+X zl1r6ue&Qo?+@1r`Ui}Xiz~JsjYi$S5O3QC165a)hJDy|BQ^}A)TH3*Y?1mqN3zG;(hisI|Yzd=-ymKUMpPc6fX;4*ik)^|drT-m=$yW3p%!->`2vD5&&nPr=-lc>oF(nw*rDO4 z;|GmQo$zTM_E|>{%vJty=klI>pGT2{BL_I84rIB1N;C;}&{Ve?d11ElNBim6F$WG2 z`5~{nu~q2ta-ePI#{&kZB=AUkIhK0-Xg|>|B4+s=rg@f_4&zO6u3@EpvNcuXroAGbWR8VoIeP0E?54n~7sZ z7u@o>-N-zKh-?IkL%34ych=E}_{dF%pjk`jPrH-3@EaKXXa8*C2vUX_kz(pO zVA$Adz$Nvqm9K!>%uU!B5jjDygE05<3gRh}?;*KVf-2ysX1UkG8ZdwHg$J_MwHv=x zoxiux;~-Y72~)7YL|6p-3Gb-X*`C9z8&&_R%OTdO93OrGr;V{gAY$2H*AZomCJ{Nu*VHZQe^ zUPnb-rz7p96vZ|Ht+2*#y8D=_opHycT=sr>lj?JMa&(|ko;sU#t7CP7m+7Zh$pL&M zh^%RXC%>TRGud#aJNW(mT%vQcm#rCI(Q%iy$s)F%-z8$o%m_IE)vXog;2Dw&uESYxHZ>tg$YYz?{3~PAepfat9GS!SC9hEco!^Lh`rPf*(;|!TY`t!*8mbE=e^> zhk!*2>?IVy8rL)RcFpchP1LNm0r$_K>XG55LXB(8xxFvk~t5&D0t(BB2} zrf<+EdaUxdt)%O_yCLrxrO?y3)e6O;Gc2AD4x>WLDo3`48mYToZ)D2ivlp$2mEtTF zLGpJ&{h!ZIVldW033&XwQIsra*9c~E>`_ke(aG*|t4y~9A4nlmYp{TPcV?$_8z z-}NuZC_3P4H3R&ocF&U=3#7uB*s_W)PE)vKafAqhnXWJ=E*4!Crlq0nq~C9kcqnAd zSgm;1#cvQAPE9o6y>#*78I?OZC%>F&9xg{|0j79Nv~-DATexw2I}n)AH1jI!NEBgE zy%`pCly;Kh{4$UnI8N~*uOo~p5wwMgg+jYz-*B71$%wa}Y0DxLUJaWa--G&eD1E3* z!$%u2Mj_{hJ}oY;6&>GGdn#(-=+)rk&T3?0(ZoRy^5D=o;H@dwOJJx>nyqCqY3@*O zUqQxu*KMcu; zq+<+eR=2qSC^ciV@AmCRYgTf#8g$5LJn-IX(CHEU)H!+bXs+>ew|jGy4UYcoT^uy0 zJWtjVUmHsH;Q4id(1Oh!bEkvj6Ht98-1{(HU~#!F_VujM7g0$7s<-~|qosPB)p&~% zAlT1zh#ptm{og6GyO5JiQLcu*$Ampy%IommqYrZ;hzrFQ6fL)LFNf=zX60X9sPOai zQ$Xi;)YyXD@u4bn)D}6|A3=Y%o}|h44~U4Z>ubK+pN;xQ>q!MphGM(S_HdbL>de=> z;nAgL`&a@n!*)xFYC_zUfaF1m?KmRw&6VMH#nRD_(T)6)Qcz8U2=9m8k6ZNDvWx7v z|uc~7vmZjne*4JLD(elwmpn~DisW0V`L)O+84fy!0*B8#T zl8z2M4kEm-jqz{i_RG9i6vPgU%D=dKk#Fy99Ax}*LAPs~8(pV@0He9bu4~f&<>vki zN_Un4EZ^D0LUz;b6zK zj4WKp5Z;GccyM^rtI$T=bHc%c-?0z)dto#U=e@sEfUf-;+WUW+PX490MouM!O*kTA*dkqZpI1!vi5&|#LD@jJRCNb^Pk;6f4}AdxDbwl_3xU{ z|8WR^pU3|jVc;QE)8mNxYpbmeZ$GtFwssW5;}~Cr`?8!h z?_#(-E$X=5iEex%zz%Nh<@xt+!&h)f`Uc>Wm9U72X{4L0tIs148`_Ks!Io#kXKHGP zRjR&;b*ANkap}5{#?T{OArwd!uRM@Lt zWAEJqTXEY^&2*&bf~hk+iP(uk2UFz@zehOmdf4@ddw$2ecob5p_chP#{<)~XVRNnL zc2e6j8Qg1GaGN}SzphJ;N14Y$n8?uE@%EeC80#RnFMj5;^skQ5Ez5_hXE$0Y z*crg0>PXdw6YGi9${QHodXY=o4rVuOpp3OIrO4i{cOD$yVNl}$`HI&2UW{nfksSla zG7>+&4y$aOGaFDby57k=oN&lTL^qGzhxT-ZK9+SFcM@Rs@_};+fPowbf+A_awCH8R z>r&X9t%R!oSY^Y0lP_6SudI$@Gmp{b^V$uU={q3I-m(z(!*}7PN?p1u2=6^~M)AV! zkhvD1R&VPDZ-EDvWEb6dwT(18)YN~b?jzAcJ@Sj1MWjEtL8NFhQZSF$5z-W<3*xTQ zg;5y}8$g#<7eP-2m2PkLp%OG7_Y7d3$^qzmvM2+^fKNTG)5iAiqqTJNXFvL@qU4ErvkTfoE67 z<0pa$&Z)i%QdLgSlH%+ydOohR{uD8=aoy*c2GS%u$6CEVgpHztGOXC_@~{MaCop|1 zFM&C|AVVlG1Sz0@2Q9Jg{#D2Q=e=)i5rS~bw6(WS7Rr+zH;a8I(2DQr?ye|3fb{w4 z+O+MtV1B@zM6T?-r692+4yTm>+@P)*b`NxRQ+!AHG7bC1!KTM$)^jSd+&3e*uNIA9 z=*NCmYd57^k{{gZcyHw0n(-RTZblAA?o6+n_nxaV|9UZLr9X#i1%Sv?#zWX6_b2R| z6**F|vhd}h24A41JH7u;#%KB%$7afjdlKKK{G-0La|ic+VH*Km6iO=&QMlV|_pNYH zb1|FQ=GJ!Srb&QpJY_8obI_tzlTHdjW#jfb@RE6Ztg)_=Q!PD??S~8K-UC{%1G^pq z&D2M$Rk^r{t@2rAO{zF#zj+C**{j2l+!z5A#}pFeEx2BfPinBp)M`&t%gs3QOZY#m zznJ7z6}J+JH+jtKIi`4&;mHT1Z%mP$D!z%hS3YJjO2<&9@hW zazs*Ap;fG?lb|NV7~f}9<(`X$l%tR=G1vVFA~@&XL!hX^%PHacwEmQ`)1u++>`{~= zddLoH*9ylK$gh=`y*H(gmu0s+`Nlesz|}b^b=n7SwK-1vpn~dbtqMBE_cM9hj$B&I zNDKR{r`_uYU%a>7(MBU7s2ZNXm_}nO!@j%-XL>NI3D!QF6k*TdWv}A!+i2>vSV={X z0SxL3+Ec384$V+AT8izfJ5Jg)c@kGA63lZkEv^@&i(G9&WyH^TT^_G%y=?mcg_)l; z%usGZO1dL{WBdjM{rC1P=(Xw)&;=ivcSe(QQ7!Ejsth}@A#Ov5B5UrF2*7WB{Q?l9 zVeQy9*(S>V`MHfyI)N}>-Rx_f)y9PJbSu$8gRfA>=)%R2_U-wgPx2+}jHN`2>tfB6 z_EjE=VP_DtZBf(kJyrur9O#z9$gAv+tvC zFV>lEsi@>U^5^39ij!UYb8S%Te1tmep)*G{0{A_RDE5k7aYM;!g#sHp>|;IS3oMlM z(GARYe!f&*j1)O3h+L`ZQ_l@4Jfz=hd*qv??E1DRlmEsqnWz3iWgSe!?|~IdB^!`Z zdl`(YCp4DAUdhCUt8OaBt&{eP3~BiU+A8=anzJxR@w03km@X>L7i_%!8o%GRIQ-Qi zQ5@y_l$?H`bd|oE8s}}}f+uZBfHZFt3lT zw&!f|(HfatjXFok36@)`ukS||YObg$U`5~YWfA?b$HS%IbuF$;0jc+KO-I=!W*-WC zINpwsnq87e2OAz9fUA#mIO~c`d-E^FtG6^*mcc^2p6M61uy@}H@=3ZkO&>6pxrkJ0 z-N;TP(n3tnYOV`rk8dS@<8YKy8dPg2ROoQS!g5`KhC^vt_ma`WMspC52Wf@P$BFyV zYktJoI&!M@0iN3xK`yUUC$r@cy}Z_02|xjH2Wi|;o~}>t^*ufzOJ#dz%4rEHkUk!x zY6|HzC^en#uS(oK658Cm<8utXL0+D$a`s);pa0-lywLDO8jtbyC1VChigiSvS1FpP zH$miE((Ty_i2Ff=aoft0mR;0w3(ZE3(cf$%zAO=+!onRoH7avvSRH=FwEjlib5GWPr*o-p;hnr`E|9E znr)XF?$mfWue>Gu7aVc{$7BYYtcN@VMjjki)!ACY^4eZFPTXblV!p-J3ZTtt(E!C+2JO z!r39Mh^of)Q#mZ;wQWxDM9Ku-5`+%dcg+mc!pf-LDInvyo7xp76pr>={&3;yXH|~P z8+RC7K_+3eNjr!q<>fRm`PovkWO#}HsV_Wl zgD3G9dCoTeP_ulh^@ZwKX8cDCEFDT<*8q`2>%j&xb<{@M)y+q9JcSw=N)^Pj z)&uq^L>WYC`y-S0e2`>Fk(K6va^u(`A$yDMy9JEjyjTv{1`}-RBpLKp(02q^^j6=^ zy?Ze+5Tb=eXhvR6B zm&R^Jv&=a#N&agf`z1lh%8E88H#g?Tk1SPTIMGto($`FtZI$}nS-WE`p7e?TEjYEu zl#rC{T5b0< z<{Hk^!|ea?_aZ`YIJ3+)*lBcSeuX6kw9@g#!!9}-%X6^KGGp<@Q%yW}(ur%p5_;7F z+E(Tf)nmwEcb-yR{+`mTi5w1zwOG+O`yB#o$rKja z@h`&*0;)MZ=|(duOUh9^R*!hcFMh8@Uy%K^$@VlCy87Byo4OkeA%b=d+5Z=b{o|wm zd$K>~)|+I@D1Kuf{yfkh>X5v|C2gP6e>+~G7z{|tKw_Cn?dNaR=aq!GlG2nd`q%v_ z$};Unw1Yb{+v@6SJYE<28Arus6w&Ibvfnw!5JVFn#5{73HJ`jhbTNB(V-mLZNblBX zC_cWUec3ai@(Ba1M$(v%gd7I0Ht!#yyC++mbweF*KD+zGRQZzWCDlNvO@b+jraK9~ z4@apN>H{{O9^MeAzOxL^wYt@XymL14N=IZw+~(tDHAAowb&D)x&3ow!&RlOYFmS;J$7OF6u@vNnn*4;)UNLK!wn{@rz zTc-`7(64a+N{f%UAyTBhDh49*$RRloQiiOuJWn9Q@8pvp60 z6YI9A{x$Be88?huT+0)VLb$MTp*P!Z$)R=#_bU%5CoPrO&~;gdrZ!%e_@hq_aB|M1 zWKdHh3+>04;m*l^aM4W&M=5AV{;+)M0ePis06Js=VU-s##-%+CAD^~yf-`!>99WO5 zJ;l9tK2>dqame|Fi+&V`Li06^FfQ)l=Ym~x2E6+#rm%0oAzRoYjpk^8`WC`Qt zd7}>Cc4p4K%~%TG?|DW?tN~A#I{2)seCBptfDKn4@P@I0{9F@Jr6kQ;qG{5Qt0SZN znq>tx-c;y%lx%ss#I(ajO8XTrHyodI0=?#|{A~tl_B7q=lPmCi;7kL+TrqhoRv6f} zVqWmub7@QzI`_b1vqdQJ)cWz`$mRQ`tyIv=rvI(?LzVS|%Ml2-91hhv%ZY-bsjE?q zox0MhD}Eh^Fws<^E#ueKeQ^@A9fKF|BYb81IRVL+?O^uP=-yEVbCWuE(>mX(Koo9x z=vKbKNn;Wr)5I<{?XUY>xb3KG6;c8DR=N@c3f|HQ3q>?&4>!l%H^;3Q-s5BrT70nW zlph`rXJT%B<}G_q9`MNvKW|DsK_QIS(`)a{zj)ET=CduQ8TOY)vuj)t75H7M77FQ? zB&1ChYaQo1xIk`9#tyNs)KO0)$$4u0v!=qJyRxttcFSl>dUt?)u6_O_a?(wvXI*S| zmtBsVj^OB%0Xw75Io`>E8~U(s!|RQ)l%dT}+(ES_VfRG?RAi3j=TmORO1PSF61HE% zIGQ((QWle1#CWs#VOM$4UI?>7T0L`m4r9;0k3zMW+)L0an&q+aqL-&2Y zD{QccVYuY51+AOioYl?t+>}9QZuNifIos%|7bzLog|K)+@Dx63|J1(V4s{)3&{S9Z zeJ(gl0anhiPbV3DdU~2{FEQ$>Zg}tRv%Jd5839hi&+xrBq7>pUAu*LcK{Tgdy63mv z*AWm%nO3A_SjWdQT3kB29M1u0G`CiX{b&@qD66NGGVaeDW3{pnAiL!YINN+__ou)w zA;E1YUX%Lav}rtDUfQNUuotY){fo)bXFOIk+$SwEb7@q(&~HTJaTpf=lRgeufEU(( zQqb@uyd96l1#w5Fb+s>%D12nwbh<#cUKKQJb!-(889B3a(WVNWX~p&MYbf@Zp-80| zGsE}U{o%R%KA>mGZkD&l;67X($$2JB*=WOZN{qME{ zg@l#lXYP!W%za2u(-}$5%hdH=m<2tVxb91>(XHVuY10R~{KMQ8rgijW<4Y;G@*~Gk z9H#FE8dav!A4yQhbTqwRLNfj7Y!&pzirpEim9)#pJb;q1DAum^$#SHVIN~KLQr*UL zO%^nrqY~xSY79jatJhe^C2h-5i_n>Z&$qcaS9Nd#vj@kVr32=QXl}IDH&>&_!~?%| z&(_i2*lWz~(lT^JUfap_;}W`T**no28KWCtFQ02Tfr!6*1Y47@9+^^@$UoEHkY<(smHC%Onph$cL_cw;K%peR^)I_T9*^^{S|)M5}S?@&uT2 z{uF0G#Y@)z{d)sV2L|2K2#H(`+5hk|01PzmkO}jp`%J!)0XJzW_Kjj;C9TfM5P5Kb z(^%<01@^V3coUN=)FndlS{YBRc2&PfO763M7EI*e#@(+g+&y*LYjK%5yMZVa40zcQ z=!|Lyj)N;AYW!uQewo5kF!+3bwLk5)o9K8jz7uq2d<#TW@il7P_XUHN4yuv5H%lVmEx( zWtFBH6m#Vs5oOk@)T&ka!&dRm#`4M_Yb*R}@u$X!D;j~BylR!WN;EKvm>0)}OnpfA z`Ya7%h*gzVS_-)fcgsEPG}!(_M1QdZE3ETCutwX^KI(n?&m75LUs-N}RR306z#;6v zcj_VGR)q+p{C6m{Mfp38`=f3KD5nEt{T~+M|DM7?+w{>)?M|&Iu=EDkr5*3e$r<;* z$Or;4^g&_4pI?2}Q57CS*{v>#e63M!6igUGzdVH$|1WaRM_Lqj-pFs$b9o%o(<{@%(u(N{B?K3RAijQqp%ZOj6k%hFX_&AOzG09z+KZcE2u$pvXZ`&PPmn9nl|Gcml;t&}dpN^ zPNUHz7Pqh7PR~|Yl3S0IAFP`5(|N*S1~wzq>Zj!m`;#W|t`BgYPw2EA3@lX(9KC*kfz)NLw7RsZEklW13E@(ohD6BY1~o5iI`<7Hn(JWAjQ^vWH+} z4$@YcZv?s(oxbJz5#7~OW{TC@QCTQja~j!uRao#oPh6Ru*0cw2JV zzPIFT`{u#ek9v5hF_>}!Mo)A&HNM^Z4`DnkOE(1lDU1^nh)SLQY6Ui|K||{`od(J- zTpm{58tR0pWlkuLoE=trR@v#vyXE(7ftdum2G))zpL;yKt~F*3+0fQ}Usy=26!Z^? zc^taTh?cK{y?p_B>}dSPm{sl@BR6_^-Whi&;)|wNI8CQz0gOLF_yyYxeNX4?z!+3M zFSu%*&#yrB)}hf28I4rD;a|O%vUF3c7czG?Q%-L-ZwsQ&9+!&!w28!=Y(rPc=l6s& z>T)%>?u8$~fFJTcwZ6VO4`AgT?})Vqq8`xf^kw-P2~bAMpSW~Q$h#Q)Bl@L=N@f}~ zmGvy5;X_YcQSp^MkN;`rb$PoMx_z_DCV1%>s#JP_2v|RmB^)?W;ls=DG72*72){Q( z>qkMGJy>*E$2tm^Zk)HhOsvdGuTON(G%qkXq*-dldt`PGTPd?$Grav`?Sx!>&+7ORur_Mk19Exgb+(zYKQ!#vqXRBY?|j- z0wnjDUo$_!fW34>)O(Vic>St7pZtT%o@XQ>C!xC5$BC)RbQUb{(6OL=ADE)&9K{ha z!}F67P&0p~KxFpI1Ae|XUl8u|G+d~UFLL`yx*htx3DXbp4+?J3v=(f8*LGh4O1LlX z8-fVYYti1tlwVyN@57>_2edQyx;msi=QbV!anJ1X6A<{0Hwo^5WB%CF2FUSo$OuC2 z<<@lv#nUh^+TO5Z50QYkx`EZ(FN?gmfTHl)C&7&x>rNmnWj4dNCz-0Buo6}A6Q2Uu z4Wyw{vM_}(KTs6us0eMp=iH`hq{T%p60(3Rqj-lA7o-*zkE#-2i-?4%Pr2Vofg^b& zZlvw{=H_LbyEQe|#MP0-(vJ@&m4A11l$WhDncMt^|8%s>8|hpw--P@jHX>3fDv!}G zKZp2rp`3`(ueGngfE-t01Yxg+z>~AdT!ql;Px$+qzHc1s84)f8PdVg>kxxp{V=x6p z>Fg{%qda;eReSo-_Mh<4K?99#yG@ShY@+e$<_xqMhF%8PW6}x#D}qiQVkde0r)RuNj#2x?_mVy zhjZfq!`xfr+E3!2KReBBR;19oztw#6CcC9flg(b~$?t!$_s&6rbjiE$w5C06O?%q5 zZQHhOYudJL+qP}nw)OSA@9y6Fi@Uq={e9y`R8(|yWOroc$*Rme&y#r+%;5`hTCZAB zIUPuMdN~JLmSKWy)jKy$0Ij^aET1=5AZ?-(Wv=}}QejR*Mt}EK<`(sUV!rroFUjde z*_@EK4Cdo9WD`vsAoVQD2bawcs`CTpYdw`1?u6&E+lAyqUuv-6-}VED zqecHlTE>KhD>*6pMmN|YcgQjm_p$bomD+HiR;ZM9GItsjd#H}<4hx5g>r$i5ql&Qs zpRX^lA*QO%8P=-Ntevc@Lv=LA!#Glm=Uu0_a>154fNa2Z+t*Qc1jbjkgCJskg za>mKI#7c%lH~X1obNg7&a)FzRKwmsGKZZj z{IYvo5vj``XD$1f__-cdSGQahv{u^qEb2KnzKC6iaT6K+?NxI00n;J#v*6LR@e#Zf zJfp(RBS7BW8@QP&?U;P>8Jdhb>n)5OA(Z;9e;bTi$<^xv9sNh7h&QmXH?XBKpuFqG z)ck1AIvDWV+?Z1B`t`1aQrL&{h3DBy6VUN2Z{06XuQx^gizOc=qu?0swd`130KAao z^HPR+NW#2=UnC?T*N)EsuaS?^Wu9Bp(cGm7(xyQBBiq=tVCXke+J{3ISC@2>W~G=B z9oZ^oY3r|K6!J54@A=qGp?DCuGBN#2^X^N+f6L2EI;JY{U*&{uD~We7Ab4OB^5MFIG~xswl`i z#+SS3wYq^FBvy(LyV;o8Ir4A?vbED(&@$9d zB~yajG2X6!e55-9^Oc%HUMV1A)m?s~QO}1JrTd$E60-B%G7SteY33 z3$fYwN!`v-fWk^XkwR;fk=DctX#H(^LT66fUYH}h&W$k?V*VwV%f#>tbx;^Y8HwOT z-2>rRf&mH+-7O9>zcAY!33o@YtpZu=6V=F&01pp23MpQ37qzZ^V%Yv&o6xGJ=ecq z-B4a57HCuQFN5+}HlH-lKR5vzCmmga5Ar9MMndarJh&|2cl36m(~4d&VM*ywElF8q zCvUYNN4W600lzK_?{D!L7FjVWedv*0T^$ajOMU<6fNc1qzw=T~p%&t3mtCQDUUT07PR`AA-fCXDZRg4VkaXf$%v;;#jsF2dZ9XVf*Le=4W?IiCDV>nj+rC2k^1zhj;gKx}%;;H#im^Dg5cl`59l=uz>i)lnseVIvHofkJ8jbPNu5g zFBo1iO-1ceo(<7|V6)Em#~`xFSnOeYVY-*4!+aCo*8Tf_a3_g#Q~{#pXQx|~-PhjR z@cY~8$Luv;b&rJdtC$2@aT)4hpU^I7BMu>w14Y6j)K-h%d=G{ytNBlgo5~h;EN$5h6hJquC&t(b!-@ zJzX@ey8MSPhR&&buz`!ScZ;cDW;BgM+q{_n6E%YsZyF!VrJX9tRs88Mi+eK(IIoTq zLjE72Qx|f#Miu=l1h;jt?O0_dI;^-7P>-fk zkKj^^?e}PM+DVR^ulD;;Wg=RBE-E)Ok~d3A98y1@-k2J&v0}f0M|}fdO9C#sYoj@h z&u{4lXD-i6>!*KZ@seSw9BOZFRmESXrsw%|)rO z@N9qGIgb++h(EOkJQkGRfB=#Jr2OlYp0x1^%|l`(sA;h7cD)AZxg+F3dLbqSUJw!K zV)v=3jLIYZe6S*E~xS6~#Chx4T?r3S^U9jGORhyOFzU7FzNU$waz!KiEKpG9b8-Nd@B# z9)O%PID+}PF}f=K(UoqvoHxYLd4rV|Q{B+rDU?=JHvgBSh3u7L;-$0-;zK0Fp}0Ls zn9dTF2?N%$>GY44Mw$x8Za>zWd578$*};b{(!EfmjF!xOHS!@WJkfphVVAv4kpgF; z6VV0}vHE=sLGhpjEL@18uGgyeEkxS}^0~NgqBL!b)nmZ{19|39m=(Af;pYN5CL^{+ zZ>pQ|6O!B2R)AQqwSzSa;(G_H{L{pgM}+S!_3D}ZuvnD2|s|vkVGqKVYRK$Wtoiw3W3NBwhY8 z1Mw3)ecvps6HYjO0zar2?nB43auQgCDS6ebeF#)7zLE!XHkUeM8=rN8dUPr8X4uy} zKSsOwc)@Px;B&w15w>vTW(m3B;`^L?UV8p89fV8`;P_m&`U>%XqP+W`DE~ES1HJ(q zaGt9~y+6L&YXxjw)%0L3e#wbhsGyI_-*3?C6e8ybtK*rsCs&x?<@l$@u50AQI_wQc zWCJZj&y62&3U8O<4Lbiw0rBe1M9-XrmDvNOZg7zw$cKEU>j`X`ir7f?AaenCU#LS) zN(rmgf%uq)2kgTZK$3RnFVWWaq()=VAJ`kAN`>o@gAecXxbw4#sUP}mRG0NmCo={rr?tz@|i}kNB7Q!l5dWl<}QbZvZNzB2QED>bPfVlz2v&&o>Og|A& zD*N|j_mYOl^+e06UHI; z-VwMp1?Ko~B@?(xjCdt+u%uEly20L>O7`CG3%Du!W-8k@6sm(!()>aJTcbPf7$a20lBEe#2WK$# z{I_3TX!geor<~gAY63P&Io65X*~36BA6}qH{PU&9sloUkkBsea%lm|MLA)e2`;t=L z-X3LzU8Dc{>ZvCJv#KXH8y1Lc3F2>6QC=g2roE(zlre`-=pYa({&;!gD-3HrG}6hx zR9}wcVdP4wmkPB#yb=nNsn;vqxn07Bl)m5R;_)}a^L{ zZb`)Q-T)dyWq(H_7kxK?HWP6U)8n;Y5!ODya!-r(jpexL29#mqjBf;b5RuXu{a{F{ z*P`m{?G^AbvW7m9diasDU$;(ab8ZMc62Oi|W~7@KgLg_Cp;n8y9Z`Y)^O3mci*1~s zr9rKe)q5iLQdY?9HLcH_P;k`=+S)+Xmxox7e29E)5}47ev|SJGGzEnJ0lTn;XNMqnfb4`G*MPbwTLCyf@PnhWPy>y7KCzajkdRw#ctoq%b z6B3>+fRlORvi=f^1GHl)^pLNM6TXV+F_)Rm43Oo?efRc;H$7Su<mfr~{p6AeHhqGJ_;u7XH5!*b_}J1z`}JX~9QP33n_ ztF1`29^aSkRHPP*Xg`kxma6**(K9i*4PCPjm^@twvCiG-NF|RDoI0PJu@!$R>Mv_F zW3PJVIf=RzreJnsNr#M;K}bwAL7UY(YMJe$2))?CxNu>j5Je1f%G8ur*yb++pSe1u zJ;3jnCtKRQRF`?Y*d*XVDC$mhAXs<2P;Y3Z)N?V%?ly*cA3osoEIDNF}Jv0*T7qGac88VA3CxcW!-x^V)+KIH<+{`-cB!h?f$0t%5 zkW<)oMTge9Hz69tj1Tw>jjBF-hB2q8hBEm9SrZZTM|;@nP$HFAxrEK9qjwEf4xY~^ z6hNt+9QvWUnNSVUj1Z241g>YBF_)$j@p>A|S9mP%E?jA8P9TrmP6tH4DIZSY+&kjW z&{s@z#;ndMYoFosbVe&!F2QH-w@GZnYGCCsP)MwLBF91|TQ~%Dh$l{rVj+PDrEt<& z4Tic)h*8TAWV=0-G)y0yAFr%7 zY^0}oQaJ6+6|qKYvflzezvPH1NK!R`EyESTjqonUk(@E}hFAJQV(?>6c#OjZ`@ypg zYh51QX~ZT`zTB*SG@pFo1)sc^;;}Piv%QE>1t_FXl-1qsH1O&h)% zTNw#=`J)SRvl`=8#3Zi_d26rH!FrxVJ@j0ix zia{}Yj*U`^n&z(Tr<7mCXea)u3BGYEQ*xH09`=s<=zKCJ)%{LzV&SP|H1sngDZ9ec z3hn9Tq{HY5%etzLgy+gj9mqM1&UuRV-NU=QqvK@U5hv;tn>2!+73ZEjf zpEO$eEZ4k&RE1-+IH3n#w-?5$H}vXcw%oOd`DonnMUA*$;qi^+a=izyeDgnN0T{4U z-nO!U&3#Sbit!M#DeupZ_9!f7*ex#ix;-_tS2%S+j@KI<2!9f1>|~374|sTMCm@{5 zznT-J^hl5RYhAL=;j?CH&lfnvB>xm)i^KqQJ!ce}82D+_S=Ajf;=Z*V@~|>2Z)_|DDKRf3X4qK+3TyDp8yEcLDov?o)zb z(#Ok!q$&OQe`)Zy9{=O+^EJ0hbh1HqmYnEM+3|0$I=HXwupv6ckmm0_q5q}pzf{jE zhy7Z|@;UlZkw5GBZ!ZhKKNWUfj*9p{4Dvq|`Ab1#vahPgoQz@IHs(L*62*;xWsdl$VGa9uqg#YlADu5`I>c-JE zcCK!r+WFG|QAr%1g!h zWGMbP46;js*uVFLKPH*_^=GN!$`C~X@wbw@2$X9mnvPhwF|kYMA)YT6Ogt?;QeJaL zd;`Vlon$5A3vEofvD*Dg6CHs1m>6Cib`&yr9=3nc3&q6u584!EW4y;QI-Zh6Y;vUt<&H<-cm1@FU3YUaAM68g}{S%NE*k*#Z59SK-nFAJiJMsNSa ziMCd7x$_U}Q_L7O_fj8E zZKhIY35t`|5UvLYWs);o*#TF*tDHh|U~O*hxi1>R+g$3Om9KZ0?G@?}83+mK$~pp} z&RJH%ku167DSnzN$3WeOgVCQQYrmd3L7x#R?n$~LgN{HwUVJ~ObWEjxnEf77M3gkL z8tYsM?ouj5-M$JB(EKUb-?!DY{k&AP;}$;2xI&x&CH@c3S^VR+mC+&Ej1?S!hm)Cu zW|i$ zFUz!h_L*2WJcnyH@5%h10OtGqO-}u(JtWxA&!AVoS%64ZCFj9%CCv#sd2ZSstK7A) zAn@0E93g3px3TN336e>YUN3OY>Jf3coDf(mF#`<-JIfZOAg?4o&Qd=E6@hA-ml zLZqCGHovnx;mgft?m*yK9+p^$u5z|J(Ri zC-WQu>cX~zK6)9kSRd_Wb^H86NJEVi^_qczVSjNNih6>rh=@o~cu+r9@FmBFz#ci) ze#oNT9V=pDTPWx7s2tgrihfSYhDx$Hyz20)je9XX@0bH+I+`GPzYzh1MTX5y;J0K0ufV>%2X-#_FME5P9B??R}wW`lmM5;A^83#wAni92O zh<}=_ybEMup<(~WHJ**j2J2WzGnyp2ib3+qZT9+4x@bVTOop7LwNPOe#*(?;yV(7H zPhi{lAuzWVM|5RuD~YW6@`;7yml98$^^kmVysA9}G!@mA0lpb-it3fdFFwxp70DaxnxzPSh0*1Zc*6bsY*!q zZO)Ew|9HFkRpTAJhQEJB1g3Rmw{`|Ay`p4~LrDvr(~hRWV|qHP={^pH%+`=I!XhUu z6MI#Td{-`Q=Sc$4R*a&*lulEixaEC>PP=36weeE@z3fjB5ZzqtgVpYi9qNZK`0|QDCd<5nHXku*Q~9g-n5k#kD}CfxAGj zt8ZlzZ}1IyAVYN+17|*)gNO~!PkBWCNYeJ8aV`xxXa8Nn204O`w~&vVcw zrvW{lE`T$1cGYesT#Jz_>7B1wjG`Sdmuit-<{t2=n2P@O@a3FH1mg|A5Znc-jmWqH zdF_iI5Q^dSJZxIT4-wg|$pieJA%F~!PP)Nw`^iG8wIA9m*qb3$C{J-#I?LzeBo8BX z9>|DGrMaTmJ(VtaI)t1u?tli*s)Cbm&+Z@M1d!9jb_8R4Ye;&)=6WgEP|_-L`n@ zXk%8cAYq!+lei&&o4j#~s?@hs2~Vi`$>TrNCXw4I~@`lWtW7M{=02XYxfvHBYnB-wj5->;>3cx zv8S|e5ENxQxUm&aZSHq(0Oc7=1#KR{X5v*y|BT6p2r_Hr}8O>(Tq!!E)kdftQB zK__4N?9kNWkZQ&;0rR=XLNNSYzC9>37VR5CqrQmON@%u`k+wHqLC6}z19AKdUlr{J7;%5$OI;k<=qf(4kDYa*@-m1JS40FT6Y7G4 zyePPDLxCy+Kq@i!dE#J5evV}`lXYKuRj90NF~eSA!Ju5s%Jr;uV5ejnB0Q zzrbN&R8__m3>3e&GXM9Zf|QiJmye{Dhk?30dB5Sv?^>O7NfaZ6pav4c`+$5sKBXG4 zs5rDhaT*0RD!>VEy6ippn*g{#)C}91OB&KSZR|~AOI#-SoEMMqScv|VC8Ye>OA?4# z^WEbImqWoma`lO;xiP&|+j-|`5h8C2o!=Fi1JM*Thv;x@aY9RTW%+8CCz@RouNZrokf6P$tJ4Ye8 zPsb_ssPJgS34`r$2uNi@v>rki0CaUP;^G*-F3FiWhe5>U6>W*Ha^}OW;OGqzLP2-+ z-dnF#j=QjLIxjNgF)QTnxgIv03xv=}{)eZ`^zW8Ngs1LgW@qtcGtnK+0m{eFy*_H# zd~I#QQ)zXT8l5p8=wQrC$B0-`$USY%8K&!$mGZ_%0aa z(1b$g0peF7fgs(kd+g4n2R#_Wn9xJ(!sUXV^L@aq79*^xLj;{+WSi!nr91a2{Lxg) zFr5Q@6DJsO$S-O}#s+^{GC3qB{oX-$Fq-JmJNmw@eF~YpJFGm!#Ef(j91MU0qAKcL zM|MhMSPAT2N5=UXl;8^Sw0B6xSbkm>BDLqU0hfXN6hnxFBDM3#~ zi*OvS3=`qY5vyz9amBSd-_zBlou#%mGY}JK(``OrXbz={pUzDJ0jCzV;u;R64W?if zRj7nTUtqkPL>Af{vCxg&g901NXAr{~-c2)}Up9Rl3*-B9<w1@ZOIG@ zM_r&A0Xnfc;TE=2r@zQaBO|tPqu=@S4UoVf5d}(R0>qMDeYgB5h=rv+O;wE{1_s-L z+jupiPr~3(4G_$f72pFA3=RbxjDK(!tw+#87iq#MCXbYfnlrdu&+-xjY<3N&lxjVy zdH2^|_H`%cN?Tu=d%Uz0&V-aU4rHm8PlL3-S8idCOp=Ejmh#Mx$TTC)sjW;C#Cy49 z5?P41Lt3*+kbGFZi>H31#+0adIsSn5mzwUpYDXj0L}8DAB_u73;B^-lT3hjAZK%MA z9BqYuS;TRb4Fr$BNhKyhMR<|0lvL7~?%>Nap5V`I?s5wiRt1`X)}hmT6*M&}X9= zTtgP#z&MoM-WB{t*gH*v($Uudx72I60moUoT{6+DRG^$H!%;;3P+rC1uW7(b7JLi_ z9ay6AcXTe5*_~5UmCp)`v2?JV=saDkbUcWmJ1xVijg&@hGS25HvR*aHr&AjNMt&lD z#Aa4-hCf>Ze@38D%?__Hd=TPG zd4eGAAdq^L4;6A`D4aTqa-M&zo344ykLG!?;yX`_KGxGh1<$a^6Aj_PTl0OLFxA_L zV%td7JBMg;S?fM!b;4RE+S(}SW^Rh^e?n#dug#=Is6Taaa*4KJg#w`Hc5+4r<>@L& zgE+E*=vhdQaM|Q?koCQ<0{N!sj{=>yIA3SUIK>pYk0OSHo=>c?hz}-B_UJ$>&;V^2 zLCWubXr556Aw;GjK~04+uuLEXft%btb-;f5C|itXK#q=#1((}Pi%m39%CIE$!WKsI zQm%>(BbLQtJ=A)S!1|dPYUSL}M*&qQ3cLJu;_IHd5Il6yA>J$CKPSj;GzWc3VQ^ak zxYB@nT+I~S<_U_Tpkr2c4?jdj6ldp&og^xM8ckSp(w4tPiIXv1rUWHv1mFZ$>kj9| znYGM}Zq0i0)hZvXgJwp6N}FREElqWYZEbK^cV|Dz{WeEB>?5s%bQicTCquBZ9j+u^ zi!9}GmNlIyHnu-JgxJ^vQh00};18bPItNp0g;3iW(3xC9Xc4FsE^kPhis!Zx8D zK%QNtcLEEgf%q#V>%0nTv3=Zh7F9(~h6Smg>Ey7-86TM{VgPhKv)5GSU^Pxw-R?e* zKxd*DIx_CQ2F2*16B3WrE8O?6qigcAsB$f)A$x7%Ms^!9OG7qhm)7p+LQP@}ST)j^(!AGDlf<#OO=Y26M74I^-tFWn>s3CqL=Uq{QRdDGB+eGih6S8aEo@DWeh#n ze!wSqSs7rGMi^#KLO=Q+erFRW)*BQOum}5hclL_`rQz1-z0!$_wI0@m4Sl=hw&jqv2SUWf3{Z# zpCNZX5GA$H0h?{4gK;fqtCy>&Xlj!1UUIAIlL(Hp6-i{1vsEL6>LY{^y>49K1`doS zR_X0n-YKUjmh&rY)F5xfOxMyM3``YNJZgI%3ye)K2q2P;VAfg-78pE0({`&hThtgX z6jK__oM8muMVeZ2}UlbH1G%z`^Hq8w|LhJa^DOOYJk$s1Ij5cGL8+gy# zYNyph8X{Rg9rH5h5~+RSBO=l(t9 zPq9$2RH_8*D4$ju<$ko#S!lapcJ7v>d^E3gA@okAcLvd}l_kq)_w$qNiK8^3G76u+ z`;2N-!cUN@Z$*b7iCsJW;iT(~I8~982=y5m)5KR@dk#@%jjObgELbMymX-O&=FP0Ve;q9M+BC;id-eLn{6{-8ge1S^Ug0c@z9rZY?Yn85%oiWmyA zJ?wVnEWlL7Ja?Ylng5^Lo^$}Ju9{!H3~i0XKCKrmkZuoW-Hjdh<;dcP7&A;xJ&-C+ zi{icZC>fEjL4gS*PL?zNAZ_jkz5@Li;m(XE+tM2jzQ6wD@>Nr!x5aH zJ@(b^_ARC98NJhZk=j=S7*JB~+zG(a=vUu%7qAga8H|YESJTzih5=-T-oCNznvn|6 zt2(0TfFfxgS|lJGpyQlIRWoZuUKvPLJ{{@O00aWVZCEpEJO-J+NnypoGzicf;VC z?b|Fnu>UL}R=P|Jf6TZn?1zkSLn|fcqb4`3blk9eGjrDAK6HJr`?k3yb*al$m0%zYvsMrFf2(lT{G z8>1Yqo2$%;%xm*hmLksJ%LuL}zY)z24Hc?Gxw?khZJf<-xzB8#*korr&kBB8j2$Vp zO1k5DMvN)+-|PrjDTO@Vj8Pm}q+MGgcIj0DpLh_8ulXMjUiMZMji;n_7n6W}N_!C| zwLd^kUuB^LtT|}DxWpkZdY(F;ZG6(5Gt;}EE2g_)AnfGU+ua*&cOcYomQ@5XZRCc( z+b?Hj;+YAs!0S^S=0_xPY1Uy^2HN-LfpEnipZi`nsCTZA!NCM*nmfbW z#3EdgHS2adpc3}2lXys9j&9uKTmanYXW{t>B3N@;nQLVTs*YeNy^*yO>UA;_GM~3R zNURvw!(#o-A^L(a>lgvB@j1#pL8ha-pn1A7a3ONg=Savz4Ga&a0!2v5o#}Q!nd`fM z&B8hC$E9#KQRZ+_UOvH2GRJW_?6Lp^OGLatlf#>-RTeW(gqx>je^E2?_XRUTPFb*_ zqt95v8tFL(OHSqDHc-I5+>it&KdUMV9s9dW1u>6!)(?5eGy2A+CaZAcUahfW?DAC_ zJ=y!MskHW66QGK<6z(rhloO|&xujfPq|_I0&I&Z;S2Eu3Ud+jT3*rauR8!cg?zbs8 zCJpT3R{6B<2yauL=jA4>2-B*~;HF+p%R4Nximvz1iXA@>)*Lc#JUfRTj!(AAUv`WWEHde$(Zbt@GCz_q zCM2pLW-t&ia8_o_mXWA%*->qVhpl|=gHS)xwhc4!Tjuu`>@P#32z|5DGi!e`vN<#;2c}8%Z(&oP z1|jd(#>RG5qu~FD;cf*Gej$(08tvp5|15F;4*OYVxvg*OVhB_1r)O^AGUsQl8vuN(Gfxeaf<}_0ON@V}X4^xJJ z-l%MWk%{B;|I4xZ|3L1*pHlsU=TqE>C;kVc{-L%A{NbZ~u`%NQi%k6=8P&aH%K!Kx zL~)1yVVek4$r6J{c^d&HY7aMToXhZp_y$j&aay!3RLi7FXcssfh(-vNal z`>WJWjU*t5?qb6K7c1aBz_vrgo=kMK9cGR6W|LQ6AAf_iL4io0EqoXbZpC50kTVsc zRQ+Q=f4@R+DTKylK|hXRD^Wn@11l^jj9Xql&i&W*(21}0e#OmX64JETqulX+qC#PI z1S#j-o6tqsfl3TZn;=%Yi$`zNVhZnFZOLyAc&U9{i0Jl$E$8Cgv-`MJf>NLD63MoR zp&&Ts^Vj#CJbAu?I(??{`PQ{&#M`vj*?Nm@&$!Oez=c z+tcmAA$%9mKlm<9l;BI8uixm1u<6(ze=0$lxtQEP<=M!fwU7Xpp~y^H&*#of+6L;( zWOuq1!0OA^T;*D(P8XE4 zr+hvO;N@(nm0O0BO6S`kcS>#gzR4a`_lwE{Sa())?#)6m^XK-+d3!Yr8+zb=EJbEC zZbwV!IUhc>>);h%j~}%gs`$ar>Gcf6!~Jce(#PHyt#4uzR5k{uwM%NwDm|*zWEO}I z1Z}`#JOH+h?7m8}a@K3va1^!Xy!vOkLk}jPspYPSD-KtssvGhjHMKB!MuQj>>o{6M zn(O<#hzYT>$Xg%#uQJk6k#~ojLMtAXEuL%68<69pm--tP zOv(HTf8&#J@K&(@6G@lN`EN-2+x7bof*hnmTTN>fD#EXxGsa)YZulLK&M48f&T(X# zlhdct>Nk`x_*T978dAR$$%!%<@{WPEYheZ?LqYyCmhRhWm*nO2lT@4vkCG9P%jGRA z!76qVO}~I@W=3WqA+pkQGoRlcJl^-nq_fM9r#pqbv&)T|aIT=x>=hBsU!&TtTl-0b z`LjqydFvC6QN>=8F%@l;?k1{!Ptx7;2~PI`a_Xkw1_cq(yW}_1wL_;C4&hLe>A0Rk zL+k>Jv**zHjt;UQ8SI7)LPSt~;i2s*#K2GxB5|m=)%M+7*%Fs0KINoZpb8CBuL)i$ zxttqk-KxwYW710*T>pV4Kkp2qJ{|LijCfEatmKXFxI6j_)M>;+z9h*!!063}-=$nD zH9tunfqKsjiuT0XZ@ZYD;Crubxz@wn)Nc&0pI~$-z<9U&xjVb#m8y)9|KuMH;8=sR zm|@w4%V1?xkKWU^>{le8U~xnfy-`l7#_sGtm7XZ+N{m@!PB!<n$v1xP>9=NKD%45s!-e-&>{$jVMXgK1-Cm|sBNBoR#61;RC>oSMWl6+Q@ zl-i*l`=A%>luw0Q7q3*7nzB(h9ZR$B*e7P-7e1QM7FETrPr{UBN}9w}Zv&-z67E3e9f$#gfyR1F*cpmS3609`+ih8A4}YUc_k>OL-z#rNz53GT9`3 zvt@tgh*>)oT~bSg@>LY^gZciUbP#2Lw;_Mneg6rq#x%+o z;QhP5@d%Gf@mr7kb%-wcl2fJ9Xv9qqUX|A?CrLdqP(9*1&6p>M0aA`5y&GvG#1ZK0 z{OTPu*0V8SJ-}O9WCq_x#K)7x0O5Pi%jqk}QY-UG_Zl?GY-{lMdwXdALb9rQ*#yEO zUV&;5Ih4<@KDy(Jn;Dog;u=IiCnYULkbvGzBbXBN{Gm$Y$V;;j^Yxc*t{cy~R3+T~ zhl4|XS&CSpe`G?|?Fdz%Q2i-qC~&%z{WDAY#59b14}6=C9G|6<(r{`i0lgwoE}rmWj5;Xj7;NEoKdlhcnL)g?5Z1yE z?-D0;n@$>_(rv6itj!~r{C1Nccf?c_i74+AmA#y+!jvX-6xB&TXg(LK`qm@lT4$mh zCrL3lIT{CoAa7D$c6~>$`ks%M+AnFIUcL{Ht~6KA<+= z_QVZ+28h@UC0}H$dVdale6avFwq4E|*CJCxeh72c+61M%O1m%oUjLZf#T+%SBU=jg8wPK3J+wdLGWTiLue|y?ySoSh^`|}7EqdRp>!rjP z*PmRcj?zapC3ImNN{-0KEZ$qzoi#p_B6_fYyQ)G@No0na zRZgx7V}cMu`gOlrx0pDDrg{yXc}H@|psqCV3PTE7+G9mUTKR_H?Kdwqbw^~;(HkuM z0>X!n4;XCd(6_^)<>aJ9E4jsuq=dK-YBcAUm-OzlI%alaGhR{@RQMn2=fAtYMWbbr znF(kF5p<$PQV%Dxhn%Xk#i3q7Qo_*H=%hE zS48n9?<43FFo1a&9QavjgZ03Ab2E5C+}PcYHSCB+YH5qdjj3Os1{_7V zTi4ItCea=_vUEa=)MkDSMVS{9B#WS&+{+fN5~u&lSVrXu0>23 zW}9DyWuVqfP2TooFXVM4?NutOvhT~q%c-Xk($0LTYnt*2j10o{I*97jhmbYd_lqL z1%=x{Z3fR!?Vu$6`9?+%U_#!<;N)XXm@wZpd&H}+(A)dnFbKvQCu5hYOE6>PcBoge zybBld%w~tmqx@2L-Y$4g-dZte5a6)yS#yLc2byVCZBp4>9<0%(l-z**AAvv4MRZIA zCf=}hCo*NPS7(2KWL0(&TTEt;WZ{<8Xu|rK7A?a%{R`v${=T96^cTWA9|>1TdqXze z3_+CY-WI1u!lp5y*986aeidBxV>7IyKvZ5aAy=Idhm@j}TRDqZHJnzxXAK*e$ef4g z_l=xfn=Ccwfy5qCM5#FSV7rcwqkKrxdifQmu`m5(yAtWD7F&2f3!Vi85 zN|M}D?={T-MFm{t*5NQ1%8%(Qw~GP_!SOMR;FfU(j9G{?es19_h`m6YeNP$1qvHo$ zgz!mu-(M6K#SY&`dO7nqqO+aWkqz5^!wZ9+eK$SSl3>Zmj0rglaXiBK36YuOwe3bX zS6dC4G2(#`FDHb{S%7DG&V{L_6d}}@Y7d?vh@*%`wMI+d#ERz9q1i!|r^-SKA+$e- zH;G}7WRwsgI3{}@^VW>EiRq4|xY<3l-T@^i*JqUg^CF=Us9^HgGui7rVTZ=L{Q%dv z)$bB|<*NezWV=b9_Uwv(_m~|6lnEGyhPo@R-T@?CVc76=>@vquR<#;nO68ydV37Ur zkV)RtRU}X$_7s7(PwU)L7SC1p(sE1)Jk+{tTk7l@{P;I4D}avTC(42NTsK&I)1$(| z0PL&d7$Ri(lo3YKlWh)^Cg~>fVRfhi=`QBFo~Eb1s#G=1%r>?;d`b8;5_;=pyl;$p zd0@IoAuSv7r?@JS*m4nW685iQne|K~6fu!Cc*-)U!S^ia0>ioFU=qYE zNdeb#KXzDTR81ygA4dN-EH*U1`xn|A3|MUAndBi!22?rTPKF@Q8e$xVClL57JZy}H z_i9;&W34@e`BG!0jUEm|Q90I1D=?}ThO=UWYIG|;6rH0KcY}DPEr~QxOR$1}L51B= zZ1JjR*mCM|A=|Qy>QC=O0~Go=rUTBoJ&vwK?}pXHj~rb#KNutCKW zL?l2Lomxd;gq(x$$!OkS75oiV#*;j1tcM*+ZfR+bz@{^To`3K3VP7V%F`E722R-Tg>^!pO~5(z-h(&;%abY@0rpeSQEeXvZ# z?0Pr6v$rOx0{$=T)Ql>N0aw(!+hvcCN}g(jYgf#cudV>o6?O5aKiXiEsEQ><#3_Ut z_&WE-_-sXZ^X^|vmpTf-w2h61lhk|*V4sKcRkM%@WCdqYPf2~rfODT?RMwD(S%#WEr`t((0)y|B_+!Z_4S`h|n5_^Rj#xQeZld&mwNk2`c53qLZ za>-hukn}DWDOg#k zFCh!Hd{;R=LcLO^@Z#VT{e%gn?=EqpC~`d4zCpDy%=tII;$3R1Gih1}Bgn;ec0|uw zeisvy5*5Bt4!|6aNEqcnu?s{)iM#=+qwWkE&XxYw@yCXPcxs)Y{*A*L#tOBNQjoFj z8*!nj*<`Gp)YeVEkA-M-2i@9=U(=WA#LEfh3nfXM0ZkRBoD!+cit0V{^36P3)=wYp z#2f=?tlcBOD?Ml}Q?eHW!l)ZyUU$+K4EZ+GQNV-X^JL1TM{+K?)1S;VIt++<{kvp^ zzTY|nms)?a$WY$2);HdQm_w24R^VeXPMk+Mz|#z}_LNZy>{C(m_QrF~^0hy?j4AKD z0`t#K@J3j0-V;sj7B=@#DfDBOJ*d1On^5z|G-5MH?v=&o@-ORgv~hi@GEd4OzBYn^ zReC#V;$*`#@ivL!nfm5PoaJb%8832ah=_i3&VXMG(gaw}8{vPTi!l+N^FXtI!ix+% zGA?jW;0E-QUpmaJkply?23=~<9k?^=MqlhU2;_)0>ORv`lP&uJIs)+p2P6FmKxK(f zd;mt!M-`In+C*5NN^0^KToD5T2JXUn>x=0vUZ9dUU9j12h@-Bn{b zSn@N}$pAM&?S=Ms&_&s7v zTd|f#pe;NazN5kLSQxCe>Ql;dLk&#e-;$je8ctG6Zo+>j_EzEE!OO;sRzp!N(I1s< z=e?PnZkH8S9%V6fSV+MCf-l2~l&q$PUXkqJlfKf}5C>Y|Qe%O3lm{Hq_|0F=Ia*{N z$UDNJs)k(+kB5k$ZG}RoV80Xo9RE+?%hHtYvip2@RSfPsgQs`K6%$H+V=Un?i(=@EDJ)H1T)>&~sdl8lKLi4+I)^?^ z8EjV?{>9l|kYAGRS}7L_AT*=6I#L*o=4ZHQ$sHflfsCa>hKCj^&p7S^koLSj`0+Dr81Ru*LPjy#2wQn@Y=ieN4pw!&isS zt>NY!$?byywHH^h@~jka`7>3!MECKfNpXMTklPI(B#x9oY@$2b$aA*({87L~6;Ms+ z&^&%`y&N9A)k?{jF{H@Igi6O&H-6}&vlwt)=cVpd z8bo5%S85lf$LC%T813~S-6g&@$uAhU(QKPFqrV?x*$-Q1vK+MQtahRB3&#zU#!f6b zd=inA#Uf1{Tb_aVY3HPKFx*y6Y{p7L93FRc*GjyXfJ-ylOx2%IdBbD0$AMHfG5rU4 zDCu-C4#cBbjao98kS}tR)S8r59wURwL%C=#?{dCJufigsdMp{dwLr9PP$t0r+@TnG zYa^$>9Y$Ng8CmS)ZNzX*y9nA8?Jbo|#!wPD#2uMj;ksHvU--P5LQbN^c7Z7|MKUUW8m`5a6}1ve zk?<%Tno(-UxB^XI{T^c?GikD#RQ)HSC~z#FcRXkZ66(~Tys7#RkOSJ19%I?Umqhw{8O?<6s0zp|%kWM<_0GH*^ zrC6QI>L+K>S%*NTdz!q~oQvBiPSx++Z}*+>kKO>7=DkGqAA~}h$9AX7HEaPgO9^#j zp2)AycXN?trKQs?b@F(*nx$7kiJ45+m;PXtnjq(&Ham5ct4T@mr2QZKswBYJ9Bz|z z2Oe?E;VQLYMm0G);u|1_77QM+i`c^32(7N#pIYJ;rp^8Y8C_jO8*AG2HAmILbpL@d z+9%0ATyG2)zvlIR9q;(e>HUq{4-)qe6tw%jrTj$QoGd}q6d%phqEO%E*D;UP%mE~4xe&4s?{CO2Tkk?Kc=}SsIG*cY4&{B0?;_5S>5rtpCg<{`=obtlyfMZ;Auq z|Jg+UKph!>i*aFd`f30BRR6MsCD`B0%(PNnq5l!>^#;TItqu;9(MA6omGMd7??(zr zMY_Ddxf<-d8XDgRJrK+i>^G>{ff(9D|DVm(4a=V`UnE5(hx$()uvQpYtJ8%im0_3* z!GCm=53~61b4(@YC}m~!PoeH#mia!X&c+XKf7Sx{*A)N10s{XNEd1LNJZ6aRhp%Cn zLGy2HjruP9{SEd0|55eLfz%8p-UyDy2~oVG*Pw>~YlCfKszTaMTfyZrI%Hp}wB(vm z3U)Xz$@;F=()+Q{uuH1_AGoIfzDRBDBMTgg!n|lMm1Z#ohcADCMOqK6>Q=%5=DM^P zC4_b1x}&5nSq*mYh#8~R5)rN8aVw$q8Fx^5ak+UUsU?h(B;mOeRdU#`a$_^%@C99} zq#D^lNAvgUW22~}Ay=w89F`Kc?M2@LQTyJ{O+C?X&@YzSAdV*wQlob<7}xo>TN?|d z%mq|kR_)vaQt^M5P#aYIn}j;NZ0x^DsLOGGD86CT5x5?CQgi@oj~VA>2ZB<64QDKH zh|>ox4d*dbS)pI6$p?EXy%%8LF5wWsuU$gMrg4bx$h2+KXQI_u2w6hJpaUW0tgYD= z*q>9wokZ^?lOpdWm)k)O(CRzbX@=PADWMFxfLywX`DU}3Fd{yjigBjPX?i34$sq3= zcak>=PP~4>LUG(rq^9lkJgC(_pwituQBmU+wiAvtF10V==Vjc!XY*eKejPR(+a$WtRk$vky;dIc_m8q%dfRBMnzon+I_h;m z?#KY=%Qz7mfKjd?=Keq++zqSSC?`@GtQ=mNrHu>JI zYe~!Pj9UpreFVS!{>Yn~qpnI;DS9G>cdf($z2VIYS3oT$i3_C0gvRuZxlB63dhdR7 zIXxqy?|LM0Y8XL#W9uG2_EU!*x_%mhA-vy+24U-3+;%$$(EQF*WW&PGc3FgHoywZr&>V?viRG?+A+_dm$AB+m zM8DQqPF(UyAB2v#A3kJ>Gl49Rj@ev@F1c4PJFV^Zp8D^G_nCZ_?VQ&;b$hOxYh zOWS{W3ELHB7Ujg&X!dM$GlQd4OPb4@3$B4NRZF@Hif6lf0T8#Qk*|oyn&beyYxB%J z^0eT9oQWRh1|#M1{!G~AUxX@94Zdw_;e$Z0gH4wfhVhQCfur~A#C8{)2f#_zEVs?` zi?_*^#T=~n-fA&fZJ>T9N;@@1r*{M2y(|0>C5tH{3QcLbyx|5NBLdA#KbSeFA9jxM zUdH!b9rEdAsI5A;IEO(W23t=rSLK_T{tL6j|V(0 zC%yslr6X*;W`2?+ORM?v$Pa;a^gvW&q|QryCc#?xSj8Fch=}Y^%geqHxuUNfXT|A$ z+ei|0;4Q%u!6UyGspdZ95T*$6+Qv}bAb<;lvsA$bNS*7`K4XdRI4ZWQ#4qxIV^@Av zWvge_+Y{w^j5B^|D!7%Km;LfgOuX7^P8bW}7|=QPc^3y8=2+HJ?VzHojLa2B7q+k5 z1NMOPTkh8-H7lu(XLK!cG&{`|hm=b?=)(JGY16mRIAtLnH&+ltD%`M1?m@7TnCNZg zaFob56_;|z*+cw?qX>fS4-(!`8l)iQx9w8dtSO7aKgy~)dkZDgs$K7nPhy{TFzlu+ z_H946?K$iMHkFj44K^8GG!{b_OP%P}O#}^lN_-D85^Zg4Y=S?B^lODy;aq?~&kC{b zIN;SG?x8?To1MaGtaEC*>TwCj6oPs$Fhi>5r;A;PiFaIe?9i7h4qZNF8|+ygZisGU{%gBOYz;2@IP3(7p&kaha7V*PT-NwJ1b771MfX+X{C#B+N z91w>@H0BNUu3VoH$`@FN3yLVOmT*utP|3My$V5(iK@f{lABCv&J}ins#^FmBxzaiG z*XnD{wkY5aEfY~3uy`h^V zV=hgce*;k!GZS%*UZZ7Jxjv!e09R*D+Oa(7>k&jQ_Zn3Fl_|1$<~}1MZ_Cq|THs24 zyst)+$ei73#jp{Ty!=v4e^Z=$h-PE#fSbFWn?1)$k?E?&=i)_R)S2!jcJfod#Y05G z7nGQU-d(r)EP$P9Lu5YmHofbth>!o`GzP>F;HGc6|B{3T#^jw?xkzOg@ zao(A!C(BK6G|dMVAK(@@Y3}x_mJh@T zzHgK`Szia?2g7yXEZz)NThBpZrsy9~c`ep?^;-#doTS$&B9Hs2Fm0<4Dk#>2!P9W~ zv*}crW`Xjm49%J%udpSoUgpZGB(`j>ya^j%3%ZQ(nixp?aplLn!Oi;_Py@k`l%@iH zH9DNrKq#J@fl}YIHZ@&Ce=)rQ*#oM_-&O0aw*|V&3vvt@zQMQ|a*6>ziQGKh2y6F{ z+_H%j`&Izoj3KB<@WfZ1kr}0k|Qp zQlg@DJLR}Sa;K_gV=|#|)ZDR{^qav`W%^PdK?n7$qhrvUH{$^yV?q5K77nbaQzsYW z@_w}TIjQ%&^&3?4@^A-XI*oWTiu@F03$|g^T-6Isu?A*=c@TK1yVQ^NT#b>3pnc#& zd7vS*Z+x}(@p8=eLcmk9$HPu1imv>VNbdRrc>@Dtv2oSp=zAv)&f2iPp*OQ0RlAZk zrVeddcLy{Xql*5k)W+QdIsKPFIKi~8d6||5;ClZn8L3g!g-?Y?^6PnQqMWkt15k)C z>)3QNab`J_p11L^AZSEYHiQMI0VAN-s_!B?6Wu_2Q%G$0(YReJi(=vGLGE1G6Lvv0 zNh>%$k-s{#++!ku{Sx46Q!OTEnc4STL;ko|>SUuaJgyNGJlW(%m2}rjgOJ7oeg>_? zP8BZe0A|*O8|JUm^{EqIUbO8d6IDi*7947zeW1DKKZD5Mmpa0V+Vu+nzL=jznSiz0R``yLs;0oCYmK61=DQt3PL};cNDqbYgrF!y8)O4Of1r7X&U> zjIS`NJEb7%t4!~#TJ17T?D6DQ@p(DNwp=zDL$P_$wx9-b#fRkh6yY-yyg>Jua8Jh+ z0;!>46S)2S<)ZgGTSmwBtzqa3A^781tT$TdVdLew3ba6@9o*{1*tFqz#sBE zBY^EEH*#{Sj$EB1P{s{7RUVb#wp|z@IQ7s(PDUg`pPGvJJf&Zpw|sua&C+#A;^yLv zg(VCunOm*yL_4-U;SNR{k7L_FG2C$16&d%;DAMSXsXhokYATJ3dT&X2s$xPoRUG;6 zAuW#4&||xt)J5I{Cxn?hjNz`Ca;IX++_|`yD)Wg_QmT4lk%OcNP{f&}&XU&J)!uGN zkUH5rQ1@mP_6R~59&*l(6s7h~OHP}9U||aArRc)xx1qc-*J9Tv?ar=r&5AEn(GouJ zo4_r5_6hVydcYtZt*2-CtliUe`}!ReOsBr$1XO2ohI`y~3G3Qp7e0H2ewKq9mD=lc z-ODXXnlpV(9&OJ)1`W@6fvZR-&rP6!h-uNG1R(}Io0Wa@^vLXiRObvV>h$T&HUE5@ z_vAjI<1TTseD?;g`xLk}W_R4nR~{bK!wpB=M(JcSFddlQh0iwbp@BvN7(jnTsDPx% z=W<;$i|QdN1leuBpQ=qt>Y|?`MjH~bD{H6f>f6p2!A4B%i?}_~^1mV`=>|*gb|Czb z)6#5tWXmU!t%!&aDt%Q|prLrBGyl?H_-v^7CBAs=$C(ae`eVQD?DNaJ8@~`r0?FDE z!?@7$3-mx$8z{(JsH~ZT&-*dgM>eZSax7il-?KYGfyTM!^ds_GIyH^Jf%h@)X&^5; zhU45dMfrSS$~I^Bz0cW%vQQMsnV*zF42R^N_$vlaiM5LVMr2C(r5m zU+*!yJ!>lWL5|y=R#QU5n)oin#c4%dvK1{ox)IWIAwJgJiU6=px%lQaR#&@$@wYtR zbC9tIpo7(drnKGWT`Z?!m$E|n>kx5pA|A<)ifaN02&U)1YDgYY9g>(#Vr#jowiuW2 zvr>)R%YR^6K1u0OD?2|xu!HUT)Pd`O6~wPXJ`}@by+oCgA*JXB^VuY9L9w}C)%_#wb!fG!^2@tn?)wbv=QNb>2r9tT$sa)G4=C45>W)c zln7?$CibFet+2<)lY>qEb=qSmI6D!Q)4Y-^bgN>^yC=s}-vv7``0@j5?3>X%1d;dy z1G6JG>YjVZIbm;sTY=^|O^m8LfY~a`o5$3w&|A1#XY4!BrLkRLmgg+b;>pH57>f^j zYRSg=9yC&d`4MGtnWlUz(86Rye}?We#D(jpnOg#0TZJyiF5a_mvpQ$&=FIk#}b>5CUk2Xah#))`*ht5G0e9C z(Xp+hn|T(h8IzZRCL8EB!pCI71F0HhmV5;B_0-cAjBzcpi7QDdGT77Z)ry#msgAyeJbt#Gz{&ji&&$Af&>HOnmXZ5v|(FLo8ycwpED48z0tC$yubVf5G(Gg z>%K+JQ*Z+ALuU*r1b0X<;d!3ZxjJ8n%)}TIeXaD1g?SQJ;I*FHx0f(K0o$`fsAry< zUrA05R~cn1aG{TH*Hzcrf+i=Gdn*&2cjvN(!nH)gWt0q-7%&5HzIogd9c0~2wHkN~ zj+B}7;i0im&UzlV=)6l~VhE|DnfT~7x2zjrW6AbO>{ZSxpXlvdM?b1wt)mwyy$7Qm zhPz=@HsYE$*G;bVq07rCe!@%XpkPD$du;X6D6&6G;X1Sd^%FFgxRXG-7qe^SZZPOP z;R3#X)^~rK(JHZMTbGL_-DiK^XOgvnE_(kfKB`&_!E&77@fG*>_+C*+UT*BH1D%kz zr#+$JToEDySz5#jI#84wR=n<_XU7wbE{PI2sBb!i7#rSEsJE2LjE;pT2%kza{&g=QBY5^qQhcL9ab5`L#7AOfqo-8QJqWL-(8VpgSkvZ-$GJ<<>d#X=R-7Igb&Z${w;yxGQcoeCVsaO>m?KVE zJ3w^lWxo(g4P19PO9VT^3>4H7EFccktc$^a$t7|W9-V~Qp8n3KT-#e5>pl9=!zZ31 z7((R=%T4Z&U=162uhDTmt(!m51|PH^$tU{D<@(x9G#~uVNwB+M@z9&r75!1_F(jzY z)obW1iSH#yma~=YTKeLqI5NcPBOEFDz%QySQSr5HB%+h4d(AdJr+e*3!P?-Zj|`#4 zDVyW6!I8#6ZO`L__h=+PuFui?E2^Riw#3ET9wL#T9c9-(A99^PWM9}}nIW|zYupIa z>Q%3Lf>3}Gow*BXX7$DJvT7*hmM&PtNu(2p8_z!SoTUL!;V6d1*u>fK8MHTvl>mgB zK?HBP+1?#6DCMHMYE=bjXsBy#OeVZP%XeROXK%af+BTTwKKn9%a}6l@?AK=iR|)nM z3GBS8C`sha1#CxNmwUq@t;2W+IN| zYQt16$#yM1N1MOxpmD^2(ld{k+(vBRdmCW&^(nKdwdE2wI?)N4Pk=<;w^zWBVN zFXkCvae{g9jU_Eg)z8{P>)wm<@e8g-$sub zdUWItBL@+5UeD>^qxp($X2`0VTzHMLAY|+9hz$qjvr=;V_!++GO6qzUWi0|-`5&}W zL&FljT{lxEjjw5^`i*;H!VF#roDB!C)Og~xR=7{4Kp2GI>v)dJAE}&rT{L)EBFsAQ zuCLg;I$Faa)jPdiOvd=Ora5Mv$94<9=XYp*3Xz(3BH1s`nzmdcz5-K^RgP8^aeWBAi#vdmwNZ5^sZy1$$}8D3&-*rqV%H!~8hMhw=v3r*eZgUOkg9nPKM>n7>2clH)*Dv|$A~Vc9es?QCCc zxkURyiiqTq=lm9ThG{7O%zF(|jP@0X?aeJgB?w-hhp)zcnEFDT0UbNi!>AoZ3kG!L zr1;#Qr)!FpCp{Ppx>D6|S)y7L0M02RnZH91z(FQ*GkgHHP)~ubp?u>!BL8F}maSzN&mSXC%mf{Y?HuR!N z{@bI^%b2@xT%pbWKOt!-1i0sLoCzL~J~tE@UFHN)j>ab7q9T16@;$A`azI_}KK&}Vy{h3E? z2Vucu!I99R=l-e!)WQYXKW8lQCrweLj^kume2#0ITsWLb7-7z(Mv@l@Xh3dEr!Ma5 z0r59Z#g%sni&3gCjEB>$Nmd(GK7KYB{~ zr>9cKx({UhcrGT{k!~$lhqJ|CmUB65YFgyRyDqiY6@yhm0FSYrEZM*f#>3%3! zvH8fknZ|(tFc$a5-wEkzdMWJ{ENiEAPC;v5&Pu$3@0pCnFD`ryF&dBxgaYO#IMS^rB z2IU%`$KHhEi*uRg1X1yj*#6lc%Up;0U(I-57;==_)mBL_i98Mm`DQ^~1LlHk$Y23f zgGZPls|~ESYMa@`8fE0HzIyc>%Y1R7;#3|8-^D4YoUq}&QcX@oc}p0|{a0#w+Cswv zlSX`X`mE>}00<}W629;rIU1*`s*-WehZlmn#>7HYY(!K!(~#N*kU>cMGSbGgWe)FlY4ED?T;pD2qVVY3tn z3=L=t2vpp}C1xyzu7s?$g)3aSs9|}Uc!Dx=(NFI2YMdjT6IMS?WAgBUdjC9o{~sGRmYGSpNx zXz<0%^YIHZT>2+l^5ALt&z#|ux0ry3xy~dy&xUns8F9RsV?X$oAzgGWjB`I5GtKjlSjxP>c~k@IrDQ_&BzRXg$U@2SRt zz4e2dL_x9HV>m)IPOXq!q`WIcbI_3(PlA4kIsDog$2L9K-k*gyE3WFCHEN%S;E1-z z+svrP9xA3mY$#}LN8ZzSIk%@co3C18eD1vyIO5mc?lWr8oiZqis)+?Jk+MXx@5m(s zUC~D&S`FT;Dq9${>lx*c&AQjNn zYnXykw_MAT=AUZ?(_GgQj~URx%$Zw7g!7l44HB++e`J{cS*Kybo^<&20S!kfwFwGF z+C@l2sd7yzR73PY4lB>#wCuVodl6#(oeLj3==3ujUpi;2$t}jC6sHjOmdk2(G%H4{ z{F9gPmAKn?{p7;~6Dd@i$a_ofh?trjIm}VkXqEd;i`n&0HvsbNn2XTK&WS%MPGIl69{N3_k~V=7tyY<{{aV-Ol}KOq!3jOYpt(*M@N{rTMGzNhI7C-7 ze|{%d)sLMYy%tN=E`FFgzeX`qC@PwT5F{-;D{3WTLRCndb>y)x-Y5d-U*f;tIV65i zK(0HkSsc#fL98}e!RMqQ{_3x3CV3AZmS^iq@>$lUBYCDWIcuCQHp@(9l;KN0uhE}( z-?+dx3oktM#}<3(>ga%n>S=dZhyO&!?o@)F3qnrs$y&=FiLNaDY`FSPnOqlL7V2bT zV$8|mM5yE1@c%J1zvJO{4;!B6L4;HJ;-6H|k@&fAD^GikNDLr8H!E`(UOBy)2xnBn z=AGXnk5hDu(1CE#X{jA5rDR&-(N)yp@A@-Ho2utm`^L1R1euG5_F`jLPKRHk{;aO> zMi*@wLJB7FYibX~p<#8#Ruxc(*@#jp z@yj#{w%2jo$DJy^d1hK5vCqvAc?<^BW}(`H7|-5YgckvN zw+mOD2!bVDR=8X$*U`u{UrnhNlOgm}`nitUU;LLY-MLpxRmP@Lj2YlLE@nXO9`GsM zu$6Fe{RDzp%$pD)3 zihK>cX6LK9Sdx2;$nd}1K#o2)!uB|Os}I&M>7lOm9w!|L-yOEn)7o(>4U9^I)5q(6 zyo|Kvcm{Y$suNN{BgI;OI4bC)r6&*%C2fdu%FIrCVGs>LzN*y3-s5)hzzq};|I{$X zN%DXbKLF>{7{;!r#rIxUSv30l*`tc0{;Du~3k~#?{`8X0+1vg6E?ye&$Eo9l=eCRV z`;j6rl4R|0jyXyA(Lq5vchZ;i&Bc8pgC|d~H-979BRsJq&`1Okg1DdX5y?e@_Why6 zm0l43^SMjps!KESlH+@`ot0n3_UjI(aOLD_!TE=svn`Kxj1ORE@BqMef=7LAMkV$m z(Y2B?Vc@;3RMQY}qW0C9vzmc~<_(7`3)|o6(A6VKg=6!Mnl0CJ^6{&qMP_6%Ii0g# zA~Id!3KF z$I{GlVsrplYLlo`U57~o|2$Z0X#-Xs(JJfU3sz!(ADMh3~@S+%<^aXU2&LV&Zukr5ymP}Y#a8s+ay-Vo8)h-&rTD- zm}@hEV3ZQikoyX$LtV~CNtn%t)5Z1SS(Dq z@ztVu)wB@Ar#FACscPcnYzfYv#*uInv+{3IfVg;23osZSs$^c!(Hvtkz;>1u?bHak z+=bFx*qDEI`P7z}q(gaDMY->(yBX)8TjcsnVzGbJZI`VO-pv44z+f9;6~s6vnuycx zG|vc5p3tKeJNXy=$M+bgGSgeeGL$M7TS~YU{-=38le&BcoXr$7r@efEEenaYALMea zDDN%au|G-yEkoT&UvWHYJBls0lm+vgt-w(J1p#y5ZO@)&)(_UU>mnTvh_AIHh*RA} zGjpzz{Wk8ygNUu)y#AGf_?jmL7vvsix|r=GBi1Hf1N!D(n7i9>_6xwWqsfhOtl5>jfkQLuL@u*q z9WAD@HOrm5Dv|eQG%queNP5T9xS&Xj*{wx!H8*kG?8YoVeTgJp&kZ4ZtyFkT$$zF4 zPZx;r+ST+-!!iF15#US{R4YN3-8@JRT}UoXh(`cE(X3V5os`TY4_Q24HnJkrv8T@N0j~oqrMT+gXPt?*e!zoT`H}s4hL!Jm(~Y-lI5f>zG_Z& zcMIN?{~ddN=zM!NTX#9gKnRr#vYkT;+i8_MQdL$aRrPiabV#o&DDngQMemcA?%fn5 zuQv_9tZt1x=ZlxixpHiMdg7{(}cqJP$Zy&dUf?(xBpAaLmg{PpfJK28OaV4M$`$&I&2+v`zU`3jQRI zH7*Y?U6~F((JXwpc7=Ddc$%e7dT=KjGeN}b%I{dwjt~v9SzL=C<0zQNyq}@4;7y5a z(qqEq7V@}H#MRaV`Axfk`KaWo1;ZIR24+e25fpbLHUfsGoDb-&ZxU64dy6s=?hAf+ zmSf(Qvtmvh@)7{=uMHRh7{x)+{yrATzhPI2A4TFnfHP=_3=dy%#jGv#ZsrPlh>d=K zdoj|Fy|ZKU{?{SD z^9UbFrdJ`W-)V{)bdxl{FaN&}_+w(JU@Au?Awit~0EhplVa68kqgGbW(GQaTGME2- zwB$QIWxl^J^M8NmzwF@sUQO$Ll(~gd_|4cKw)u~f^Co#Wy6Lu#^j|*uFFX8s1vRYq zQH_o4gHHy3vq%Y^xOdc>>8hIaZ*5T#@jgm@4QB`Vx2DY&^-jo4bzc5A|Ni$i_$&(j zNL)IPhN|A&=z zODA?OX?txD7#!^VE)x{+x3jj+d*2W@LNN#SfA4C<-`+tir;PtQPy1jAzT4niC`ZxX z`tZH5&iCIuSc9BD{q-NW>pIzQT9fQ9tLESP+W)tEzyL6R>*^muh~EniA_%6A{?;7t z{es@NG=YjL+5hO1-{p82`|#QQ`UJ z<`A2uoQ3z2JM1S$;(3~%3XtBO_vbM6H;Z>b>i_ob1$KKOlh^a7DiB?CF%hrtXKd;x zQD8jvd;)II&)FIn(B+Yj&eF&!3+zFXj0nNW!Bh`HX*)GW#iqSu5K>zPpL!F@GeVjEa`vlKOel1_hoqzMNfK((CBG2ObS$cpD<(*l}5o!g$JNp^oM+lR3ZGvVFbeL=Wh zvj^vP`*5ON&^T?e{bqQu7AGq5i+uS&wQJ*gu0F0bkC2YF3+gk+iJ1sTZKQL3RUz?6 zPGtzs+#uM=(?i;_6eU?I2LwbJvWFAW&4DUu!dZO?0VWj5H8Tz#BcW9Uq~S#t`p1PU zwE%v-8{g1&y5Kb6r;gip?@&93Vv5v=WH7cO3N8Xv_*fh)2E%`*z#QrFT57hXCO783YCPRGqB zH?MFShUE3-u;i7!B^m?(&)jDIDMA` zrx5FXiaaL7YzGS4;<{J(hZ7B3!pZ(6@uLoN0{D)ef|)Cz5vlZQJPK@Y(zx z>`MV=9JNYK0q1R$$cdBL&xfVliUC%A<#W7FKaWwwCn?F3RZdK;kNZ%PQ)po{rS%D$ zq0R=$hi9#-;KUf~(4W6P)*g`61qXLO$4lz@K(syXP?#-N{TIrVwUgHIrjq?E8Itstsj3LI zbp%y;6J4fG?NkA3?~b%CLP-HHg3feO8yy%Jz^5nr;zr)-*bYM`g0&aEPhlKj|&zBDe(rM@|F0l)@8c5TlKbB|6?7nVRI)1>KfjR){=(`S#oRa$M+S zJ~!PXS8z)hXms5@*^}{8i~hHVVGta5_LrWaA&5609T5?2U*;l>HN5(#A+1xfG_s|I z=#MHz)&7l2xcsIX-`chy^~o#nsSK9?je=U_xK9AR$h}kUB~5hUXxa1^3hHX#K?m}g z+p@$1A;~>g`8Y@EWmhnN*$n~;8hFN}?A83-mnsOU-SMOwX%o(L$|m>_QS0pf{$0G_ z;hLMD;;i=Tc4xL({F}K$8T4rStl2pkD)G~ zJCf5k90z5_XFj#0Wh6emuRvJ^(6%IOuwhc3p)>>ifzC3RgR{oEtB%traoI8%=wHV* zne%*T?SO*EvbK8JVzPW?!5*-!L`8#&Jf0DZ6YwMwaY}tx1Lp!91DhW@!92xXgP&p@ zg0H2Na>LdY^m}gSX+QM994WFKXbZ#R*Z<{Asm2I}RO=zrv`^=6pG6vV!3b9%a36i# zY?~mcx6^5wCX0c_L&KHe(Wa2tDjl8vL{t9aj55*HKlY6d!g|4vc?)Is(Io3cR{JM9 z;ldc@l=A#O2la@1{~u9u_TBGb>ZCoWV)CuU8x92i~8`NU+z%U(}?xuH^8^X7*^mK?l`4i=3_lIo5$90ltAe3t< ze&cs3EQbnQ4no_5_|=+Hy^ZMvr=niNPcmtDZ#2~b*P6*~P+JyRk>Psx^e*|w9K^&E zk#(-cOo9!#rBbDzjJ(wyUQpzuVrxc1J%uJY{d>cxO3Vs;YDwi zk$m~OdY)LJY~ZE+x$f1w6jP43BvIY})~BK~j#8ZgTeT2%yw6wqK<^}&i&n#$`Uk1q zind5%q+Dy@WN;P^INrvC)Lv3L-ix+46$Jnwt2^22U*ENJ6r;J`E(kT5Y5>p-3fiPW z?`(xBu2b4}mQ-&&{TF$Yl8QShAMfJf^op~(0lsca)75n@;Rk2e%y3a_YLfwDW06ER zolkIlYF+LZ8#Yr0=zy)jEqqQoXov!|Px%6oQG+LUC2}}kG<%-AOEMV_M*$)xtY9ZM zFgn!hKH4*3eu}ZSH`t3&l07sdr4P-~DJ^h_83re~Q(x3*fFLy?^3##!X$8RG4~oLo z_a`+X==Wwnu;>%&*)L2!qJYasSD%WPuc~?jfjBC3xn&C4!<{HwiSc3&b?rc+>)Fh{ z0P3Beq_~Dy#mJmBBGvR__?Aam6I z&?B!s4EmC|NI=*nQp)a?*IIWy+@w`k`VRu9!Zx(T=y=|JJv@J>h!A(11Y(QcE@R2- z{sHBH+Yyp=b}TitS#9!4bL@K%HB6_c_1IM`?bLu#(XLSmL@+Zf_>no^6qDuTp(W-T z(2Zur26DX9;G=atG5B(W+Xqp7AFS%(gf@Vj{b@f5?En)%`~CaZB+NnX^NNO7Jcrruj|)b#O3ZAb;1Q^3183o02uB8HWQgDfIOxEN?T zSuq|l?y^pB4fV%Uh|eN#H^1Es8~sF!KFCsN!(S<{mVl>eWRA?Oni<~&X(jS*eaR(#ft^RuLFXToM!GnJ% zHx?3=)NnsX>LjBid4E-7Ho0Z>bIEsiO{XODzk&Ju>6pEHN`PKcfycI2*WxJ*2|?hA z8T`I)JlRWES~TEN?l0^{4a%wl;;zQ$$@~uv;NQ?ag-D^LsA;N%Q3Bq(J>9X2@}4qz zzv^mEfX_SKG%%o`Sp{q+C4P^+<|$i$_Qq#%a7E!nmX(3!(p~ZVgWjm$KyfP&sS7Sp z(RWbAdCbvdG;$(6kh2mT87Tyex1V3;Lqs$-MW`&iMYWG(G=ih)DA%Z;&q+_zeo@i_Q&{sT^6 zXoz4~;7$-PI5~gq>fjoaBEZLa`8yXce60O9kY0$~rs~kUW+*^T$IBeARhPH$Y+djS=W9H^=u^wfD}HWwEsfhp8sab98wcBI@X zdTw}uHSO~8xg-tT8>pH=1+N-WTH(qtE(?(iUU-EHI>URF8Qt3{MEt*`Hx88YUtYHy zq8*Cc^wGMwQQW$)i}Fg^Dx-X5aiDJqbDTH28{A#?+O9yd-B>g&QWUKE8FU^-M_bRS zi0$<``AeANMS4QTgNHAjt^kpMmHsJuB+*d-VuwbatMm0Jnd{H{530p4*~;r;<8_)j zNtC@N2ZHfGwQ6M~F%kF{e_|Rw$5OuC$P;9gh{ZLOc@AgoK3Z zWFBgz&8%7XG#uf<(+Rei`j^+t&C+-y;9n zUz0>9PJSY{w|(oW4?65xKu)Yrr@LEHxl96Ue`wMCXnadtV1aRrjM>XJwiF)={Bc1g z`e1fYP5gw!QKJ`;Z*2cy$Ib93^Dl`0+HJPw3#sd6pioP|duw@xK8wMuKxtnC=TELD zX0qz)5vI={WDOKyeSsn~rSU(J_g}w$B|##l>y@U2Dew>`+~lJ>%PVy+yn$(oWhy5N z*@&sV@nvC5o?bBIPXJTsghy2yr4%!tF?$rn_xColu0J?V2tp;a*z{mwbV3$;o{CG_ z5+|T4?gD^NHwZ!a&ww5}^-l4G9=LiX*~U{p{e}7`TJ|cSVjC+5+`6u*2Y%z?t$j1! zY5>?9{R+?~3UkJx%{!!;pTrJ040dcTn=&`|(gC5qh~!;=h94V(@va_)rW&1((l^M!Oa!I_}AaL}upZR)bGv*6ruR zFkFylrH|J_(vJ`Un{?w!wL&=u#FR6ib8PbkHUe>4!9$UVs(T`B(BCd;BG|q`c7eMq zS2sKdhaXl-lfpV4+m+c-8XUJ|e7s9~;F99f<`4L9=6z&4o>$4l)X?6XR!A92j?26w zeeId}itZ@W0sPqcDPBIHdyDR?k`Ev%HL}QM)Ii9pu%^b*QK5LhEj^&kxG!~ZTtE1t zQUB@O3pur6kQhg&jg zMRp3?ifacKgTobk7Fy#6)a;)w07Z1}uOtIf+X!x74)}ZRS_1Sf!m{bfu>Z^k8xek_ z@Ik|tUHu9C7=w03mpC28;S!+E9*syC%)bA(WM4D3>Q@jzc6b-#&dW)s*tTI@MI*s$CFPo$jB z-$}V)QEGoF1Q=+&{tjNzh#NI@SBizN zDKl?Hot|uKtbsYxshRXnwXl8do#c3FWuO;4Qvr-aVJ;A^gPBp3E+QqPIOIo_$k?o!-dZ0N(MokgW8)(Fn}MOuz-SXpB!nQH`WM|-?WP^ z6510N42#8hZH?n=DHUe)ze~s+EN$|^-p3J=lZO9A$f*t#m)d_q?CvZ)!(QHGIv6*R z2l*-uKZSuHD297NuwDZ%h^El0K6T0K>VlkJ-2K=UVZ%@=?HJ?F^;TYL;)`2XKO*|_ zRV~h@ez~~+*>QNL(XO9wgv8DbhBTIWlUZ$ja0D!RU4R1ihDalt z$$tldD2rff$;sV831W<)p#E(|w$0h>TZSSDSEYf*rueLme|SP7%Iquu)AHa^C5u(q z%XW-QYW3#i?uOORs%@VNd3|v?0$y^NzQGX!p&OC4#zA8Ow;oo1H@kZvKc$_c~KrY4X*&s8E;SVw~9( zdz<|ove*si@Az0LQb9#@k$NhA;U09zNPS8SK8xU}FXb(cX>tDeePiB?&EVA~ad=Dy zVjNqqXj0{KFVQXB=V!8`v9cd!+%(`^xBfQOhWhsP%FGVb@O8h^24H#|SC^V=^IB1NK;$oWp#xxzf2k(6=HLWLFMZl~-567)kV^GxDb zRPR0$Ni9>k6YzhqW2o$6lG%9xDcuE_Y|HJBfM$MKr;y4isj+X^2s1Xwafrw{@-3P2 z0zsbI6WG$82f`q5p7~In9SE12b#bp*$_^Cs`3KtJ*?UWQ7#EC{uuNRh0dzg&We6zw z3OEKP)Frs89;#0*5ZofPl3Q;9Ixj)06cI$Gqk=hrCnRx~Hi>ud9ASIzn!tGO;upR6 zRD$j8l$OxVEryK-Z^Q4bp{%g=8WpXfoboIEF=^!3EO+e!?<`zR)I3NPbbh6y*Ck8h z7ooE7G$~gd!8@Z6YjAjj)un?d6A)J%0_0Jgz z@)Gb5v9NiZM2A!QOPEVshN*3aC67(PI^t7h*gh2VZ;|x2Md_ibV%T-L9nYefSF+fb zKW5yW9A|8n5u{0YDT}D61z1%w*waPX?@kz@pB;%su|?ppxk`~-sl?pF;wgmfZBnyN zkOa_%7V4uX?mRg2X{maD;s!h3Ze6pZ1EY_J(#yGZf&2tO@1~~x>_KYo$fig7QdbRE zPOP+_iPM3@N7}jwm(PZ(U4t{YI#Aq3SCj>@58)+7beg?pW^78%rqZyB8qiEIH3q++ z&knq3L_a%d7m*G;*_af%EcfWqxWC#+o*T-ha)LR21~0qI;4aDhs-?!fGYQ19KSg)0%zm#D8 zHDl7Xixb*iiX!-#7#UeHi{<_c)F^61_m*isjk|C++H12!%I0y&h*m*6YUEhDpZTtu z9A7AyF>GO(6f^E4?VZy`hCA?%5w=L+3D=gsv89;r(Zk^)Q}E2lOdSIvTQ0et%%)XB z39xVq`@FR%>@?)n`N@6$pT<7%7!jqz z+#6)=@b&c8@kLT(u8^SaR00rGq5$y9z=gVGi-W#)2l(k_0JJ(F1OdrX<~t7O!&V+ zT)8aIQv9zFSDp9a&mx~IwjvKWU9`@*{PZJxM|yp$ZZ&!&u%l(!4A*igf$3_MaIO2K zTc~UF_on7suk4D-j8gd%W(RYK@pRaqe)&ZGfZFTd0KH9aMD)-l#&u&BDR@B>(ro3X zgs+~{LQ(m#AFCs1v)f2pdBv&FJ1FtB23E_>Nr)BeExxm$JQ~>_T!h8zc19Z&Et;@D zc6pFpYHIu~IgdZYX^|@8I>EbXC`8gGc4m%CNPGexGoc_$~?rd?6xI zL7>3hFZw0tQheakY5mKJT&$;=OCwvs?M)l;KooIwZ9$qw+t8iprAB=0FRf0Fd?+qO z;;F+V8e?VyY*&!p9(n>?U-)gf*I*7JRECu=#$r>zzOEU$4p>zE^=piuUGKTcFdZ>l zflWt<@JL%K?Wo=<#yNRjdPhQ>^s&p$3dz561-H%52W7XX&7RSE)|zo^z@CN;hk6Q) zu6*6XY|+@jM~-xC4~;0wq~{7!Pc6hZ5rtaMB5!C7z$HEAGV!%hTNnvF1UAys8U#Uy zm&UA|#J#KTce1+s%z?KLUT}1~O^liwyV0v@v|*M$()NP@rz|)APQneU41rQA5o3Iw z?nZH1s5v9Y9Cx?ng|88bVG`VLp>1eNp?n-wVbC9()stUk6?IvVH{%9`8o>QUKj55A zxe)M&3p$mgy+fry2Gglhe?DvF-)U9Kg=16mSpD8&(&>(Y>se1%N*5P8_K%|&6A)V; zCwYd?60P@dFrWrA*>7)wY}x{(V`Has=4AO_Ed5s_a^?EbIWZGmzk6Uhd>FS*FQt!~kluxNIk{pAl1 zk@{##7ljFhC)VmCwTUlyGl~zf7YFlnMjFm@voX8ItFYy_bE5{-jiPFE{{@_}QM)r* z387KF;|s&i`Td~y+dokCcho_x0#n_t{B8e*JbftQaUKq=`#DkcrDz zT{fr2(VTS*J9=zg2WQ+rdp(;_a`vJ-%otF{?+|7Ncfi?Sx~GrhU)Y*gI$7$Havrls ze{tPDbSW=N;^&;0O{fX?1d7Q-J*m;ObW=%K=`0{GB^Fa?&0RM$J5rdC`Cniyqf;!? z7t_^Jg9RZ=>Zv>m(~;Ssz@Rd;MPRT@y3fSkg2(antC5ab3+rUn}y0D$QNN4-2uF#GAGjkFE;5><2XjMj*W4gxu= zF|ek*7~XSa>$T@=&qX1W*XYDQBV9JRg8)_d-@X<^D0_uMT|YEaB%QV*Z!Zd!9H{;b z^Zo*V{w(*-fn6@H%nx1K|9ez|@B@n(Ss6$+_!scVA5hYd58&nhzuDhN7uElF$IM$z zRlkCDRy+$0q~mcr)Sz#h?HO~M& zmfPFiB0#4HV8;GWa4i3t8f%gP9JrlxhiqH^^?&q{?gIN*gkXxuBmZpm{|QWWh2sIX z)OUf5**{-2ekPvSRexa<~qrB8r9$9vj4V${uq2p zUI4!Ie*~Gb2SU-FVBYa@@dD*S4*hc5sYLwbeD_pM9l}whw>>CX(tJ%IDKV5Q*d(aJ z%;RQTyMd!|hPI26(H|MDXZ}QsK~-!V)hBhtt9}HBLG@-#{}|b}QLisyL5#HT%OYpq zPD(4E1iP~owq1PWx^QrbqqPz+}b411g2&?bc~$zxjbssyXw%XK+0} zd{<`qgYB8EWPNAi<>R|@Xx{Gr^~_q}=O?`ApZVBWUpGNo*iy6X3}wn%kSETgfWV-l zF!-RuZv@uU+k2!*B3Q`|Vt8)yJ0va&t0q(U!YQ5{+FJf5c$b@Qw7(Y5ut^OI)7f1v zTFDXjT19vQ+|B4I|1 zj3|-e>#Gpb(Hi`8Qx-eou*?q^4uasE8UdRU-6#lB`ydtMRez0|5DD!NzQ~Zl_AI%T z2#`H7zK8!Z!ZxK?!bI6+f)TL=K7No~NRJ*=d}$k?H9X{UX*8wc&HW)c;(o|=yk_w5 z#GS3yC-CPsuv!BL0DCR?2Ow&Ye}FypiyEyKzv>k+2H4gpA8%}%mGr+n=^9MAnBWVV zKXW5RBO_XV_a5p)is_usv4vDJhvXCV;DR{PN$emPjU z8~RfVQd&J|PWz zuFIl?6+Xq>EnyWV)-C;z{KDUDETgPu-@ga=)xmyR6KMRjaBOm``G#!G7O^u3yY0-! zwC$K?1BowLhUD3|B!I1@U_mQNvO2>gMr(ESTX>7iX1n^b>&Gd5;-=HIV%^3iq9Ru7 zTu~XATB-*~c1mYE0SQ#PjrBH)MLz(ahw;fo_^!)Wr z9yTtblcEt1UCW94_qqILs%7($zr8WUo(^bb zM-^Dn9!>T}#Rk)fZuJ#(Y7b<{+Z7PA`d;`ZwX%F-HI0mkOvn^-u#Kdc>TayXc5`#v z#1cI`opvY&;%ZK_-5Sl4n<0jFa zFuvEcQq0*N9#I5-4Qr$$E~At(F>@gL;Mb9sbhnc zv6h)S!a$PZq|9#Pj;7!E1%oY_uoBouz#^@qa}CSCyYzIKkHL1{?9e=kYdO6mnG9JI zhuj)cwoIA7h;^mN1z`vokeLa`MdW!Kk{sE8Mx9#|ag2F~pc|wV&AAbI@l6!C3&86v z*XkLcRs|%uJxSUALm5{-EvWTB8skVgZ)};_DQ_}`*DI?O9V#P7T4t5m%X5%E>8yTp zcG21LFmwenm#NmiMwobJ2|Uj2omX(%G&AizD9|2kJVOjot8Y`5rg6k`h@#_StYNQz zaSCL4*9V&V3e~;cNAfre!vDHR?uIi}pqirjc;^md8uQ#s@ao2<4KM%|K_<8=OivEq z06jCJSvknjdej=wu|-1-rU^c#T9o%k$hovJ)JKZ1m|WQ%Wsq=-Y2TDHNT4nDWQP1k|}(dMN(2@hqU=#;Sf$!do5a#bzh76K^* z`tT80$F1^c$dUrTWKIk&z`1KRZT{?nMfJp0VS|99`JY5;399mniaC90{@})*gR}Up zEN-Wr$Z3p;E$Xu`UwV}sKie;eVpJN7c~A*7SRP8(J&8fbtBp=dtVY_{+&^M1EeHO( zpql<0ilf)8EBKd3jWB<|tcX7?0zQF#w{go+xG-?dcLowz7H?2!=k8g)IHEJrhWpyI zXrkqoH?IzZ7n#FfZ@3A#GY92sDZ$=8YZ-Q`k7k8SB89iG!9E+mUB{Yfa~X<<_fj9J zky6#Nv36JqzVgeRG6B>J<0W*m=yLi)omYqtsj%`rq2d{00zZ3|4!=@yN0d8x2PJ9z zxuNru$ZkGoAf)<0uata&;E21CA^~z*Fb|aqIntjX4q}MTOh{}LUEXcDkaZ9CrCDc0 zgc;LgypO2T9vhC@*8FxY-zd#lI@Qp`ct82{=NLQ&GV5Toc!>mQYFMt&Jf2#aeG>*~ zJphIS_OCFULKW_!@3>+kvuM9Vr=787H#&h~GljeHA-NLpLOn>djVV=5QAF$yEae>) zv7Q!81>?`;+k!#?TQL@(oa8*~jiQd3o}`lFKSyPiFzI|^6}!@S2Ei!G3zhE}rmeLm ze1dj~)*WcO^pwdwH=$Q`ZvOd%yD%o&%~@=T&wcUS7IzEbO}(B6Vl4hyM zxRFJV7LH8`)}+yGU`04uK2qW)UxFTRj%#$t#8+>g zwXKr_p@eTl!{|B1d-IM^y=6@xAk#G>xszyP_J;eR0x z3>>i(*b-wgc9)d>RtgeLwKzXz(`?ZJ(SKMz^)dr5E{kOpucn-q#?}szP8zAYC4B>z zvp=%{x?f08s*p`=gGi2Jg30B1CUelN$VCn_E@)@Ruw9s!JAfPlrs{EUWFl(G!z^OE ze>pumA|Qr2Vl2{-2~^arF$uMxYR?^*WctW>cvrN-g3%+&8d2uGlThCcX$fN=-`s(% zNN`U)iir)v&ySD1u}MJMSY9W8H3XY`iT;%Ax8YR?Xu}9U1MA6ybQ+e2vvGNiTJ!VH z8(RhFV5|jcgJlDA)%);K86>%=;}94w){g!Crv_g>%{SQZW5l8|5{~#@WqvN~4aP>& z1GY`=x*#*YWWzm=ZM!c=4aUDS+vz_S)rkK7{m`;%+Ih4Mq{u6gm7fKqxSgjJtmp%& z6+)f@w4b0B{L+!TqiRB=wMX|kC4^KNT*4=QdCV_1r&F`*Rfq&B#V@5rY3Dujro+*h zdiAA-#P~U_=cVI<^?>!jZQ{D);)d%0qiHOd*VF_%g**XlVuo&0?^T4O(;DIVu{kzA zn%f76V^4Vbt1(ni>@huu8^L~|hcApTa9)cn^#il;n6Xbe`(Rh-b4u!g?NVJiELWz7 zY>nNF%x@!QEA&*nmzbU#N{r0+IKo&34}Zq{lyDJYRb(MW7dV#XSAD;kK#*aXm*oeh zJ56fpnvj_s97A?WnJV>$5hBQv%|lAC#aE<3$g-}|p##WckhBeiqBXNOboWL|K1XzJ zb&eJ-G?fFjvN8FUuY|@lCY!ZxL@ln(vOhh=mzqB<*RADc5jB_6Z`Nu7-GvS?7}$6F zU1nB2gsnErKO0*wIJ_=vY$YyTKco3ZRhJb$yPpZwg87VAHv87Xt?~wX>#% z!sfsXJk-_Tr=BDuZ2y4`qo@u(*aAlD%XegC{>wQuE0gUzSHkz|d3J2m1Z17%?e&J2 z*nTOYNs!aO5+vU2F+XzI>6Fq)iL3(QtcV4)tgNg!_d*KDEF=O29Wi)3N_QECHupGX z^B&o&7^Dq&PxgVC&&ZWyu1P?fG<(HsF283e&$IEM31OVDOATbyL(|}q`Drk$(fG%G z*FkSi>QN>>m;s-LWJ}Hsz-QQ`1cBM`dW~+yR0aeVDQqX@Q^U@WcAq>P3aavs!XPvH zRy&1udTkB9WUa@?H9V0h8G(&LCyG=_7cTUv_cSz7(^xI4icA+F^Ia^1LQjB)3Wd^L zqx=EPTm^`J05ivF0V^S$FzB$oSs-@P3E5?3AcS?FWn`>L+tx$?z>GH1{$m$C1zfXs zkCZrMcu!JR`_OPKQgH(6`DekJ03$E*?!ng;jt z@ayaYhl%dCnpeMw=vC$(z45c9e4XCguN-xDBdS-F$i84FN?Jlw>X8B%0V8Q$h6^T4 z_QkO7J9q7%Rb>(Z3qHA4*f2y0hv{XzLt088+gxt%Y$-okBU z%gfVL2_VX<>~<1R4ZtC8D7Tyck!lkTg%yDLPJAVcP;avl)x#`P_q{!El{#Ncz7PAJ zQUDKK_g37}7N%0$@^V&LeOWn#9e+DHqcH$t*B~ej+HlTS$dqi9da^UPNPR5t{DcP5jhf4>D?sNG;Xx;mL z=#0o!vLhTF9{f6M@}Uk^4#aQ{tIaO~vsbIiH5MYFM=)!{)Xi{n%+gJY2^UOai?Dup z?!krM3V4@a{z~v{M&JNWbnH3kEC`NtpR+H;MMZP&&Q?!|QyB=ExF%uM=o+H+Ket20 z?5S;4qlP8hLD>o$6SD4!mD8bAOlmo7PAWSSeT8ju)ixGIZgC~o08Q`5XY{umDjkAO z_UjpQgkz$F(l}~%T9Won2M{mptPA9YVbNcrr9Q(vWTImn57Aw)8lhtgcxyAf zmZL3p&vtTBr6PIqMpZLpmhr0bN`+XeBro-mbuwJgkYyx^GaAY;uwB=JR^E6Qz3lUR z)?<7mX=5%I&>1qqK(!ZaI3z4)3Kd}m&o)g+Gg4Zxr{5FHN152Z=F8Dv%Ua+G!3dO? z^wOOb+}663+@;Ff10lIh9Oa}H@I#sy$G&+;6T+a(t}-;izEwXK2+3L-!Xj`z=_{bE zE6B0J3*p)%)ZqXbP581s+hAMe9rq-djhOh8(O4$Qt$HiEN<-0_ZBY_+bsIEd&oeS{ zSzhT6BNU$qoV86X6?lJq^>0;-V_W#>Y2R;A@xkX761107D2IlUng_fiQX?_ZaRbw| z_&*$$=h=WMH?l};0lbT6_8vC+CYPzc0=W+`33$;uLVyVFDB-%iQhd5eXVwa2`BAcc z2V!oU>M(8i-;7X}&ep)U`S}Wp_LU`bGAD(gJDmh#8*TCGuj`CFZFrZrV^!d#=C{r13W;O~-iU@Wx>dw{wK77x4W0(|ZEK=nwTX zaw@`p?=1{Bz4u6Ro<(4j$`UhTHTW&{s344ICma$-$GDR;T4=_Rh>oyCu0Br zi>Vr?@A-0k5_$Otz~XAK#UU|z%1bS7vd4t%83w-ND4OcW0(nsJ(0#sIs}~<*`p)jH zV$P1|?I4W;Ayp0e)&x?W9F;nCw6PRTzmMX6bTi4cOmwfdrcut`S& zMQAGa6f)~sU;a*DPExtlTjvPfpVnQz&_g^AHTec zfu6lOS=23L{nRnsp?)%#i=WeX*<6cXh+*hA9H^{aNO(e@X8Z-%@_o{`Vj~`>jQQ=Wx(;8%9xzm1PAOz7HF;eWByNh38l(H`oIFRkf zBb*C&Y=ZrxZ$SEW$+Jm~TXcLBnmi&=KEL7tK^y*I zruV(C^^Bm7&Q2{|^?nV*0P3)hJpKcCi$+qs7or64(a)20k(NP1JrvPxO5LW{aKS*6 z8=Y}P0JiwuduDZqC0dDsGc<_y4yc?KGM1V0ffr&j%^ob-tkrWGy$I}a%C?){ ztZEpsL4*+eQ$oTF0k0}B?b9gb<sfnAgD&r|?uyC^ zMSz3RMuKoGCgbmZyBfE;rjP<#tLr|R+w}x*o~<`ykx$j1VQE}OX=_w#{bD>ZhZ&Kv z2>r(pgkkEHqC)B~Whaoeo0Jb^j*Nh_AA3vTkQcB$YKMIn=vSX*()7+`%498cpO}Y+ zMFfkrp;Sx!GfyRF`t7;OX297u;)X~RDMx=U=O4eVnq;-9?50z ze5;FnJ1G$ap$fek!uO|BzFOcw{@ zJmOFIFJ9nf7m=p|QJU4k*GuIPwlw=yMM?c5)8UHlGiW@p3o>0`;68)L1g%fYTt4x3 z5Fg6F_)FV4@MlUU7G-`Fww4$l)cU=JlDFf4@1Sk|&e9hEDtfS;NfM_B?2E$CD_!17bX+x5d#Pb!6N%^`i@GT*h20v-6?+/ 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 MMdd^)g!KLY2m99G9RL6T literal 256416 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

    KpaD^T{|;+~9Tg;bxvhc3h&HVAp(1 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%0DebqGnB9CLX5T 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�fe+n`Q?tH7tPaAo;{6zwz@DJ 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 Yl9Wu)YH9@!?%ZDT(xB&Ml5hO~4|8`jWdHyG diff --git a/filebeat/docs/modules-getting-started.asciidoc b/filebeat/docs/modules-getting-started.asciidoc index 4256205e213..6191105c6df 100644 --- a/filebeat/docs/modules-getting-started.asciidoc +++ b/filebeat/docs/modules-getting-started.asciidoc @@ -47,31 +47,41 @@ ready to receive data from Filebeat. [[running-modules-quickstart]] ==== Running Filebeat with modules enabled -To set up and run one or more Filebeat modules, you issue the following command: +To set up and run Filebeat modules: +. Run the `setup` command to set up the initial environment. This command +loads the recommended index template for writing to Elasticsearch and deploys +the sample dashboards for visualizing the data in Kibana. For example: ++ [source,shell] ---------------------------------------------------------------------- -./filebeat -e -modules=MODULES -setup +./filebeat setup -e ---------------------------------------------------------------------- - -Where `MODULES` is the name of the module (or a comma-separated list of -modules) that you want to enable. The `-e` flag is optional and sends output ++ +The value that you pass with the `-modules` flag is a comma-separated list of +modules that you want to set up. The `-e` flag is optional and sends output to standard error instead of syslog. -The `-setup` flag is a one-time setup step. For subsequent runs of Filebeat, -do not specify this flag. - -The following example starts Filebeat with the `system` module enabled and -loads the sample Kibana dashboards: - +. Start Filebeat and use the `-modules` flag to specify the list of modules +you want to run. The following example starts Filebeat with the `system` module +enabled (it's assumed that you've already loaded the sample dashboards): ++ +[source,shell] +---------------------------------------------------------------------- +./filebeat -e -modules=system +---------------------------------------------------------------------- ++ +This command takes care of configuring Filebeat and loading the ingest node +pipelines and other configuration settings required to parse the log files. ++ +To run more than one module, specify a comma-separated list of modules. For +example: ++ [source,shell] ---------------------------------------------------------------------- -./filebeat -e -modules=system -setup +./filebeat -e -modules=system,nginx,mysql ---------------------------------------------------------------------- -This command takes care of configuring Filebeat, loading the recommended index -template for writing to Elasticsearch, and deploying the sample dashboards -for visualizing the data in Kibana. NOTE: Depending on how you've installed Filebeat, you might see errors related to file ownership or permissions when you try to run Filebeat modules. @@ -79,30 +89,15 @@ See {libbeat}/config-file-permissions.html[Config File Ownership and Permissions in the _Beats Platform Reference_ if you encounter errors related to file ownership or permissions. -include::system-module-note.asciidoc[] +//include::system-module-note.asciidoc[] -To start Filebeat with the `system`, `nginx`, and `mysql` modules enabled -and load the sample dashboards, run: - -[source,shell] ----------------------------------------------------------------------- -./filebeat -e -modules=system,nginx,mysql -setup ----------------------------------------------------------------------- - -To start Filebeat with the `system` module enabled (it's assumed that -you've already loaded the sample dashboards), run: - -[source,shell] ----------------------------------------------------------------------- -./filebeat -e -modules=system ----------------------------------------------------------------------- TIP: In a production environment, you'll probably want to use a configuration file, rather than command-line flags, to specify which modules to run. See the detailed documentation for more about configuring and running modules. [[setting-variables]] -==== Setting the path variable +==== Set the path variable The examples here assume that the logs you're harvesting are in the location expected for your OS and that the default behavior of Filebeat is appropriate @@ -119,8 +114,14 @@ logs: See the <> for more information about setting variables and advanced options. +[[passing-credentials-modules]] +==== Pass credentials + +:start-type: modules +include::../../libbeat/docs/shared-passing-credentials-setup.asciidoc[] + [[visualizing-data]] -==== Visualizing the data in Kibana +==== Visualize the data in Kibana After you've confirmed that Filebeat is sending events to Elasticsearch, launch the Kibana web interface by pointing your browser to port 5601. For example, @@ -128,6 +129,9 @@ http://127.0.0.1:5601[http://127.0.0.1:5601]. Open the dashboard and explore the visualizations for your parsed logs. +TIP: If you don't see data in Kibana, try changing the date range to a larger +range. By default, Kibana shows the last 15 minutes. + Here's an example of the syslog dashboard: image:./images/kibana-system.png[Syslog dashboard] diff --git a/heartbeat/docs/getting-started.asciidoc b/heartbeat/docs/getting-started.asciidoc index d47a6dcdb4e..78bdc4df0f8 100644 --- a/heartbeat/docs/getting-started.asciidoc +++ b/heartbeat/docs/getting-started.asciidoc @@ -220,6 +220,8 @@ If you are sending output to Logstash, make sure you include::../../libbeat/docs/step-configure-kibana-endpoint.asciidoc[] +include::../../libbeat/docs/step-configure-credentials.asciidoc[] + include::../../libbeat/docs/step-test-config.asciidoc[] include::../../libbeat/docs/step-look-at-config.asciidoc[] @@ -245,8 +247,6 @@ NOTE: If you use an init.d script to start Heartbeat on deb or rpm, you can't specify command line flags (see <>). To specify flags, start Heartbeat in the foreground. -//REVIEWERS: Should the deb and rpm examples say start or run? - *deb:* ["source","sh",subs="attributes"] @@ -285,6 +285,12 @@ By default, Windows log files are stored in +C:\ProgramData\heartbeat\Logs+. Heartbeat is now ready to check the status of your services and send events to your defined output. +[id="{beatname_lc}-passing-credentials"] +==== Pass credentials + +:start-type: start +include::../../libbeat/docs/shared-passing-credentials-setup.asciidoc[] + [[view-kibana-dashboards]] === Step 6: View the sample Kibana dashboards diff --git a/libbeat/docs/dashboards.asciidoc b/libbeat/docs/dashboards.asciidoc index f169129c9c6..5d96b3728c1 100644 --- a/libbeat/docs/dashboards.asciidoc +++ b/libbeat/docs/dashboards.asciidoc @@ -72,3 +72,9 @@ and run: ---------------------------------------------------------------------- PS > {beatname_lc} setup --dashboards ---------------------------------------------------------------------- + +[[passing-credentials-dashboard-loading]] +==== Pass credentials + +:start-type: setup-dashboards +include::./shared-passing-credentials-setup.asciidoc[] diff --git a/libbeat/docs/reference-yml.asciidoc b/libbeat/docs/reference-yml.asciidoc index 7f9b1854d9b..0b04a14a013 100644 --- a/libbeat/docs/reference-yml.asciidoc +++ b/libbeat/docs/reference-yml.asciidoc @@ -1,8 +1,6 @@ [id="{beatname_lc}-reference-yml"] == {beatname_lc}.reference.yml -//REVIEWERS: Right now, I'm referencing the path to the file in the beats repo, but to make sure we don't expose new config options prematurely (for example, for 6.0.1) I'll need to make a copy of the file and put in the docs directory. - The following reference file is available with your {beatname_uc} installation. It shows all non-deprecated {beatname_uc} options. You can copy from this file and paste configurations into the +{beatname_lc}.yml+ file to customize it. diff --git a/libbeat/docs/shared-passing-credentials-setup.asciidoc b/libbeat/docs/shared-passing-credentials-setup.asciidoc new file mode 100644 index 00000000000..a6d4cf9c724 --- /dev/null +++ b/libbeat/docs/shared-passing-credentials-setup.asciidoc @@ -0,0 +1,45 @@ +If you've secured Elasticsearch and Kibana, you need to pass credentials when +you run {beatname_uc} commands. You can specify credentials from the command +line, or in the config file. For example, from the command line, specify: + +ifeval::["{start-type}"=="setup-index"] + +["source","sh",subs="attributes"] +---- +{beatname_lc} setup --template -e -E output.elasticsearch.username=elastic -E output.elasticsearch.password=elastic +---- + +endif::[] + +ifeval::["{start-type}"=="setup-dashboards"] + +["source","sh",subs="attributes"] +---- +{beatname_lc} setup --dashboards -e -E output.elasticsearch.username=elastic -E output.elasticsearch.password=elastic -E setup.kibana.username=elastic -E setup.kibana.password=elastic +---- + +endif::[] + +ifeval::["{start-type}"=="start"] + +["source","sh",subs="attributes"] +---- +{beatname_lc} -e -c {beatname_lc}.yml -d "publish" -E output.elasticsearch.username=elastic -E output.elasticsearch.password=elastic +---- + +If you start {beatname_uc} as a service instead of running it in the +foreground, you must specify credentials in the config file. + +endif::[] + +ifeval::["{start-type}"=="modules"] + +["source","sh",subs="attributes"] +---- +{beatname_lc} setup -e -E output.elasticsearch.username=elastic -E output.elasticsearch.password=elastic -E setup.kibana.username=elastic -E setup.kibana.password=elastic +---- + +endif::[] + +See <<{beatname_lc}-configuration>> for more information about specifying +credentials in the config file. diff --git a/libbeat/docs/shared-path-config.asciidoc b/libbeat/docs/shared-path-config.asciidoc index 1b1c6e6230d..f08d2810c68 100644 --- a/libbeat/docs/shared-path-config.asciidoc +++ b/libbeat/docs/shared-path-config.asciidoc @@ -13,8 +13,6 @@ [[configuration-path]] == Set up project paths -//REVIEWERS: I'm not sure if "project paths" is the right way to describe these settings, but I want to differentiate the path users set here from other paths (like the prospector setting). - The `path` section of the +{beatname_lc}.yml+ config file contains configuration options that define where the Beat looks for its files. For example, all Beats look for the Elasticsearch template file in the configuration path, Filebeat and diff --git a/libbeat/docs/shared-ssl-config.asciidoc b/libbeat/docs/shared-ssl-config.asciidoc index 61fe8c7f416..6b0b1f6795f 100644 --- a/libbeat/docs/shared-ssl-config.asciidoc +++ b/libbeat/docs/shared-ssl-config.asciidoc @@ -74,8 +74,6 @@ The passphrase used to decrypt an encrypted key stored in the configured `key` f [float] ==== `supported_protocols` -//REVIEWERS: This description is kind of garbled. Can we fix the language, but maybe without going into details about how the client and server negotiate which version to use? - List of allowed SSL/TLS versions. If SSL/TLS server decides for protocol versions not configured, the connection will be dropped during or after the handshake. The setting is a list of allowed protocol versions: diff --git a/libbeat/docs/shared-template-load.asciidoc b/libbeat/docs/shared-template-load.asciidoc index ab6a8a3583a..adf653a7361 100644 --- a/libbeat/docs/shared-template-load.asciidoc +++ b/libbeat/docs/shared-template-load.asciidoc @@ -61,6 +61,10 @@ Logstash output. If you disable automatic template loading, you can run the `setup` command to load the template manually. +ifdef::allplatforms[] + +*deb, rpm, and mac:* + ["source","sh",subs="attributes"] ---- ./{beatname_lc} setup --template @@ -73,6 +77,34 @@ command with `sudo`. endif::[] +ifeval::["{beatname_lc}"!="auditbeat"] + +*docker:* + +["source","sh",subs="attributes"] +---------------------------------------------------------------------- +docker run {dockerimage} setup --template +---------------------------------------------------------------------- + +endif::[] + +*win:* + +endif::allplatforms[] + +Open a PowerShell prompt as an Administrator (right-click the PowerShell icon +and select *Run As Administrator*). If you are running Windows XP, you may need +to download and install PowerShell. + +From the PowerShell prompt, change to the directory where you installed {beatname_uc}, +and run: + +["source","sh",subs="attributes,callouts"] +---------------------------------------------------------------------- +PS > {beatname_lc} setup --template +---------------------------------------------------------------------- + + NOTE: If you've already used {beatname_uc} to index data into Elasticsearch, the index may contain old documents. After you load the index template, you can delete the old documents from {beatname_lc}-* to force Kibana to look @@ -82,3 +114,10 @@ at the newest documents. Use this command: ---------------------------------------------------------------------- curl -XDELETE 'http://localhost:9200/{beatname_lc}-*' ---------------------------------------------------------------------- + +[[passing-credentials-template-loading]] +==== Pass credentials + +:start-type: setup-index +include::./shared-passing-credentials-setup.asciidoc[] + diff --git a/libbeat/docs/step-configure-credentials.asciidoc b/libbeat/docs/step-configure-credentials.asciidoc new file mode 100644 index 00000000000..b49aebe97dc --- /dev/null +++ b/libbeat/docs/step-configure-credentials.asciidoc @@ -0,0 +1,30 @@ +ifeval::["{beatname_lc}"!="winlogbeat"] +. If you've secured Elasticsearch and Kibana, you need to pass credentials when +you run the commands that set up and start {beatname_uc}. You can either pass +credentials at the <> (as shown later in the +getting started guide), or specify credentials in the config file. If you plan +to run {beatname_uc} as a service, you must specify credentials in the config +file. +endif::[] +ifeval::["{beatname_lc}"=="winlogbeat"] +. If you've secured Elasticsearch and Kibana, you need to specify credentials +in the config file before you run the commands that set up and start +{beatname_uc}. +endif::[] ++ +For example: ++ +[source,yaml] +---- +output.elasticsearch: + hosts: ["myEShost:9200"] + username: elastic + password: elastic +setup.kibana: + host: "mykibanahost:5601" + username: elastic + password: elastic +---- ++ +Also see the security-related options described in <> and +<>. diff --git a/libbeat/docs/step-configure-kibana-endpoint.asciidoc b/libbeat/docs/step-configure-kibana-endpoint.asciidoc index 00fe1397703..97cc82d1609 100644 --- a/libbeat/docs/step-configure-kibana-endpoint.asciidoc +++ b/libbeat/docs/step-configure-kibana-endpoint.asciidoc @@ -14,7 +14,4 @@ for example, `localhost:5601`. NOTE: If you specify a path after the port number, you need to include the scheme and port: `http://localhost:5601/path`. -Also see the security-related options in <> if you are -connecting to a secured instance of Kibana. - -- diff --git a/libbeat/docs/step-test-config.asciidoc b/libbeat/docs/step-test-config.asciidoc index 9cb57683386..d83a45f0eda 100644 --- a/libbeat/docs/step-test-config.asciidoc +++ b/libbeat/docs/step-test-config.asciidoc @@ -6,8 +6,6 @@ the following options specified: +./{beatname_lc} test config -e+. Make sure you config files are in the path expected by {beatname_uc} (see <>), or use the `-c` flag to specify the path to the config file. -//REVIEWERS: I'm assuming that the test command works the same on all platforms - endif::[] ifeval::["{requires-sudo}"=="yes"] diff --git a/metricbeat/docs/gettingstarted.asciidoc b/metricbeat/docs/gettingstarted.asciidoc index b7ce54c8b02..7fdd39fe2d7 100644 --- a/metricbeat/docs/gettingstarted.asciidoc +++ b/metricbeat/docs/gettingstarted.asciidoc @@ -229,6 +229,8 @@ If you are sending output to Logstash, make sure you include::../../libbeat/docs/step-configure-kibana-endpoint.asciidoc[] +include::../../libbeat/docs/step-configure-credentials.asciidoc[] + include::../../libbeat/docs/step-test-config.asciidoc[] include::../../libbeat/docs/step-look-at-config.asciidoc[] @@ -301,6 +303,12 @@ By default the log files are stored in `C:\ProgramData\metricbeat\Logs`. NOTE: On Windows, statistics about system load and swap usage are currently not captured. +[id="{beatname_lc}-passing-credentials"] +==== Pass credentials + +:start-type: start +include::../../libbeat/docs/shared-passing-credentials-setup.asciidoc[] + ==== Test the Metricbeat installation To verify that your server's statistics are present in Elasticsearch, issue diff --git a/packetbeat/docs/gettingstarted.asciidoc b/packetbeat/docs/gettingstarted.asciidoc index 86c55b99e61..f540213eb1b 100644 --- a/packetbeat/docs/gettingstarted.asciidoc +++ b/packetbeat/docs/gettingstarted.asciidoc @@ -243,6 +243,8 @@ If you are sending output to Logstash, make sure you include::../../libbeat/docs/step-configure-kibana-endpoint.asciidoc[] +include::../../libbeat/docs/step-configure-credentials.asciidoc[] + :requires-sudo: yes include::../../libbeat/docs/step-test-config.asciidoc[] @@ -313,8 +315,13 @@ PS C:\Program Files\Packetbeat> Start-Service packetbeat By default the log files are stored in `C:\ProgramData\packetbeat\Logs`. -[float] -=== Test the Packetbeat installation +[id="{beatname_lc}-passing-credentials"] +==== Pass credentials + +:start-type: start +include::../../libbeat/docs/shared-passing-credentials-setup.asciidoc[] + +==== Test the Packetbeat installation Packetbeat is now ready to capture data from your network traffic. You can test that it works by creating a simple HTTP request. For example: diff --git a/winlogbeat/docs/getting-started.asciidoc b/winlogbeat/docs/getting-started.asciidoc index 927c985333a..a1426efc950 100644 --- a/winlogbeat/docs/getting-started.asciidoc +++ b/winlogbeat/docs/getting-started.asciidoc @@ -121,6 +121,8 @@ If you are sending output to Logstash, make sure you include::../../libbeat/docs/step-configure-kibana-endpoint.asciidoc[] +include::../../libbeat/docs/step-configure-credentials.asciidoc[] + . After you save your configuration file, test it with the following command. + [source,shell] @@ -167,6 +169,13 @@ this command: PS C:\Program Files\Winlogbeat> services.msc ---------------------------------------------------------------------- +[id="{beatname_lc}-passing-credentials"] +==== Pass credentials + +:start-type: start +include::../../libbeat/docs/shared-passing-credentials-setup.asciidoc[] + + ==== Stop Winlogbeat Stop the Winlogbeat service with the following command: From 573c31518956af9be96c51f8541b9b9a821eb802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Wed, 16 Aug 2017 13:04:41 +0200 Subject: [PATCH 083/139] filebeat: fix PostgreSQL dashboards (#4905) --- .../Filebeat-Postgresql-overview.json | 14 +++++++------- .../Filebeat-Postgresql-slowlogs.json | 18 +++++++++--------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-overview.json b/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-overview.json index c63dea005ff..51cafad690c 100644 --- a/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-overview.json +++ b/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-overview.json @@ -6,13 +6,13 @@ "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"filter\":[]}" }, - "savedSearchId": "ef9da9b0-776c-11e7-9e03-393c0d1aa325", + "savedSearchId": "PostgreSQL All Logs", "title": "PostgreSQL Log Level Count", "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", "version": 1, "visState": "{\"title\":\"PostgreSQL Log Level Count\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"postgresql.log.level\",\"size\":12,\"order\":\"desc\",\"orderBy\":\"1\"}}]}" }, - "id": "28563b50-776d-11e7-9e03-393c0d1aa325", + "id": "PostgreSQL Log Level Count", "type": "visualization", "version": 1 }, @@ -28,7 +28,7 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"a0b887a0-763d-11e7-9e03-393c0d1aa325\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"postgresql.log.level:*\",\"language\":\"lucene\"},\"filter\":[]}" + "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"postgresql.log.level:*\",\"language\":\"lucene\"},\"filter\":[]}" }, "sort": [ "@timestamp", @@ -37,7 +37,7 @@ "title": "PostgreSQL All Logs", "version": 1 }, - "id": "ef9da9b0-776c-11e7-9e03-393c0d1aa325", + "id": "PostgreSQL All Logs", "type": "search", "version": 1 }, @@ -49,16 +49,16 @@ "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"size_x\":6,\"size_y\":3,\"panelIndex\":1,\"type\":\"visualization\",\"id\":\"28563b50-776d-11e7-9e03-393c0d1aa325\",\"col\":1,\"row\":4},{\"size_x\":12,\"size_y\":3,\"panelIndex\":2,\"type\":\"search\",\"id\":\"ef9da9b0-776c-11e7-9e03-393c0d1aa325\",\"col\":1,\"row\":1,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.level\",\"postgresql.log.message\",\"postgresql.log.query\"],\"sort\":[\"@timestamp\",\"desc\"]}]", + "panelsJSON": "[{\"size_x\":6,\"size_y\":3,\"panelIndex\":1,\"type\":\"visualization\",\"id\":\"PostgreSQL Log Level Count\",\"col\":1,\"row\":4},{\"size_x\":12,\"size_y\":3,\"panelIndex\":2,\"type\":\"search\",\"id\":\"PostgreSQL All Logs\",\"col\":1,\"row\":1,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.level\",\"postgresql.log.message\",\"postgresql.log.query\"],\"sort\":[\"@timestamp\",\"desc\"]}]", "timeRestore": false, "title": "PostgreSQL All Logs", "uiStateJSON": "{\"P-1\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", "version": 1 }, - "id": "a21284c0-776e-11e7-9e03-393c0d1aa325", + "id": "PostgreSQL All Logs", "type": "dashboard", "version": 1 } ], "version": "6.0.0-beta1-SNAPSHOT" -} \ No newline at end of file +} diff --git a/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-slowlogs.json b/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-slowlogs.json index 6268c9a5cc8..2a300e6f6c0 100644 --- a/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-slowlogs.json +++ b/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-slowlogs.json @@ -6,13 +6,13 @@ "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\"}}" }, - "savedSearchId": "d338f1e0-776b-11e7-9e03-393c0d1aa325", + "savedSearchId": "PostgreSQL Query Durations", "title": "PostgreSQL Query Count and Duration", "uiStateJSON": "{\"vis\":{\"colors\":{\"Sum of query duration\":\"#6ED0E0\",\"Number of queries\":\"#0A437C\"},\"legendOpen\":true}}", "version": 1, "visState": "{\"title\":\"PostgreSQL Query Count and Duration\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{\"text\":\"@timestamp per minute\"}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"\"}}],\"seriesParams\":[{\"show\":true,\"mode\":\"normal\",\"type\":\"histogram\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"lineWidth\":2,\"data\":{\"id\":\"4\",\"label\":\"Number of queries\"},\"valueAxis\":\"ValueAxis-1\"},{\"show\":true,\"mode\":\"normal\",\"type\":\"histogram\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"lineWidth\":2,\"data\":{\"id\":\"2\",\"label\":\"Sum of query duration\"},\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"m\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Number of queries\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"sum\",\"schema\":\"metric\",\"params\":{\"field\":\"postgresql.log.duration\",\"customLabel\":\"Sum of query duration\"}}]}" }, - "id": "63bb6bd0-776c-11e7-9e03-393c0d1aa325", + "id": "PostgreSQL Query Count and Duration", "type": "visualization", "version": 2 }, @@ -27,7 +27,7 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"a0b887a0-763d-11e7-9e03-393c0d1aa325\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"postgresql.log.duration:\u003e30\",\"language\":\"lucene\"},\"filter\":[]}" + "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"postgresql.log.duration:\u003e30\",\"language\":\"lucene\"},\"filter\":[]}" }, "sort": [ "@timestamp", @@ -36,7 +36,7 @@ "title": "Slow PostgreSQL Queries", "version": 1 }, - "id": "653bbfb0-776b-11e7-9e03-393c0d1aa325", + "id": "Slow PostgreSQL Queries", "type": "search", "version": 3 }, @@ -51,7 +51,7 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"a0b887a0-763d-11e7-9e03-393c0d1aa325\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"postgresql.log.duration:*\",\"language\":\"lucene\"},\"filter\":[]}" + "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"postgresql.log.duration:*\",\"language\":\"lucene\"},\"filter\":[]}" }, "sort": [ "@timestamp", @@ -60,7 +60,7 @@ "title": "PostgreSQL Query Durations", "version": 1 }, - "id": "d338f1e0-776b-11e7-9e03-393c0d1aa325", + "id": "PostgreSQL Query Durations", "type": "search", "version": 2 }, @@ -72,16 +72,16 @@ "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"postgresql.log.query:*\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"63bb6bd0-776c-11e7-9e03-393c0d1aa325\",\"panelIndex\":1,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.duration\",\"postgresql.log.query\"],\"id\":\"653bbfb0-776b-11e7-9e03-393c0d1aa325\",\"panelIndex\":2,\"row\":1,\"size_x\":6,\"size_y\":3,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"size_x\":12,\"size_y\":3,\"panelIndex\":3,\"type\":\"search\",\"id\":\"d338f1e0-776b-11e7-9e03-393c0d1aa325\",\"col\":1,\"row\":4,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.duration\",\"postgresql.log.query\"],\"sort\":[\"@timestamp\",\"desc\"]}]", + "panelsJSON": "[{\"col\":1,\"id\":\"PostgreSQL Query Count and Duration\",\"panelIndex\":1,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.duration\",\"postgresql.log.query\"],\"id\":\"Slow PostgreSQL Queries\",\"panelIndex\":2,\"row\":1,\"size_x\":6,\"size_y\":3,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"size_x\":12,\"size_y\":3,\"panelIndex\":3,\"type\":\"search\",\"id\":\"PostgreSQL Query Durations\",\"col\":1,\"row\":4,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.duration\",\"postgresql.log.query\"],\"sort\":[\"@timestamp\",\"desc\"]}]", "timeRestore": false, "title": "PostgreSQL Query Duration Overview", "uiStateJSON": "{}", "version": 1 }, - "id": "92370770-776d-11e7-9e03-393c0d1aa325", + "id": "PostgreSQL Query Duration Overview", "type": "dashboard", "version": 1 } ], "version": "6.0.0-beta1-SNAPSHOT" -} \ No newline at end of file +} From 1495b3ad282d75cf0d527861501a171b1f484a38 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Wed, 16 Aug 2017 07:08:05 -0400 Subject: [PATCH 084/139] Update and reorganize system module config docs (#4909) Move configuration options from module page to their respective metricset pages. - Add `process.include_cpu_ticks` to reference config file (it was missing). - Rename Darwin to macOS in list of supported operating systems. - Add docs for `core.metrics` and `cpu.metrics`. --- metricbeat/docs/modules/system.asciidoc | 63 +------------ metricbeat/metricbeat.reference.yml | 4 + .../module/system/_meta/config.reference.yml | 4 + metricbeat/module/system/_meta/docs.asciidoc | 63 +------------ .../module/system/core/_meta/docs.asciidoc | 19 +++- .../module/system/cpu/_meta/docs.asciidoc | 18 +++- .../module/system/diskio/_meta/docs.asciidoc | 11 ++- .../system/filesystem/_meta/docs.asciidoc | 2 +- .../module/system/fsstat/_meta/docs.asciidoc | 2 +- .../module/system/load/_meta/docs.asciidoc | 13 ++- .../module/system/memory/_meta/docs.asciidoc | 7 +- .../module/system/network/_meta/docs.asciidoc | 23 +++-- .../module/system/process/_meta/docs.asciidoc | 93 +++++++++++++++---- .../process_summary/_meta/docs.asciidoc | 12 +++ .../module/system/socket/_meta/docs.asciidoc | 23 +++-- .../module/system/uptime/_meta/docs.asciidoc | 7 +- 16 files changed, 192 insertions(+), 172 deletions(-) diff --git a/metricbeat/docs/modules/system.asciidoc b/metricbeat/docs/modules/system.asciidoc index 1fb694e6c6c..7f3c48f776e 100644 --- a/metricbeat/docs/modules/system.asciidoc +++ b/metricbeat/docs/modules/system.asciidoc @@ -5,67 +5,8 @@ This file is generated! See scripts/docs_collector.py [[metricbeat-module-system]] == System module -The System module allows you to monitor your servers. Because the System module always applies to the local -server, the `hosts` config option is not needed. - -[float] -=== Module-specific configuration notes - -The System module has these additional config options: - -*`processes`*:: When the `process` metricset is enabled, you can use the `processes` option to define a list of -regexp expressions to filter the processes that are reported. For more complex filtering, you should use the `processors` configuration option. See <> for more information. -+ -The following example config returns metrics for all processes: -+ -[source,yaml] ----- -metricbeat.modules: -- module: system - metricsets: ["process"] - processes: ['.*'] ----- - -*`process.include_top_n`*:: These options allow you to filter out all processes -that are not in the top N by CPU or memory, in order to reduce the number of -documents created. If both the `by_cpu` and `by_memory` options are used, the -union of the two sets is included. - -*`process.include_top_n.enabled`*:: Set to false to disable the top N feature and -include all processes, regardless of the other options. The default is `true`, -but nothing is filtered unless one of the other options (`by_cpu` or `by_memory`) -is set to a non-zero value. - -*`process.include_top_n.by_cpu`*:: How many processes to include from the top -by CPU. The processes are sorted by the `system.process.cpu.total.pct` field. -The default is 0. - -*`process.include_top_n.by_memory`*:: How many processes to include from the top -by memory. The processes are sorted by the `system.process.memory.rss.bytes` -field. The default is 0. - -*`process.cgroups.enabled`*:: When the `process` metricset is enabled, you can -use this boolean configuration option to disable cgroup metrics. By default -cgroup metrics collection is enabled. -+ -The following example config disables cgroup metrics on Linux. -+ -[source,yaml] ----- -metricbeat.modules: -- module: system - metricsets: ["process"] - process.cgroups.enabled: false ----- -*`cpu_ticks`*:: When the `cpu` or `core` metricset is enabled, you can specify `cpu_ticks: true` to report CPU ticks in addition to CPU percentages stats. For example: -+ -[source,yaml] ----- -metricbeat.modules: -- module: system - metricsets: ["cpu", "core"] - cpu_ticks: true ----- +The System module allows you to monitor your servers. Because the System module +always applies to the local server, the `hosts` config option is not needed. [float] === Dashboard diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index bc24e9f98fe..fbce46e53dc 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -79,6 +79,10 @@ metricbeat.modules: # reported with the process metricset's events. Defaults to empty. #process.env.whitelist: [] + # Include the cumulative CPU tick values with the process metrics. Defaults + # to false. + #process.include_cpu_ticks: false + # Configure reverse DNS lookup on remote IP addresses in the socket metricset. #socket.reverse_lookup.enabled: false #socket.reverse_lookup.success_ttl: 60s diff --git a/metricbeat/module/system/_meta/config.reference.yml b/metricbeat/module/system/_meta/config.reference.yml index 099b2b1f36b..37df6615d08 100644 --- a/metricbeat/module/system/_meta/config.reference.yml +++ b/metricbeat/module/system/_meta/config.reference.yml @@ -47,6 +47,10 @@ # reported with the process metricset's events. Defaults to empty. #process.env.whitelist: [] + # Include the cumulative CPU tick values with the process metrics. Defaults + # to false. + #process.include_cpu_ticks: false + # Configure reverse DNS lookup on remote IP addresses in the socket metricset. #socket.reverse_lookup.enabled: false #socket.reverse_lookup.success_ttl: 60s diff --git a/metricbeat/module/system/_meta/docs.asciidoc b/metricbeat/module/system/_meta/docs.asciidoc index 2529e86b8d0..4a093d9ae1f 100644 --- a/metricbeat/module/system/_meta/docs.asciidoc +++ b/metricbeat/module/system/_meta/docs.asciidoc @@ -1,66 +1,7 @@ == System module -The System module allows you to monitor your servers. Because the System module always applies to the local -server, the `hosts` config option is not needed. - -[float] -=== Module-specific configuration notes - -The System module has these additional config options: - -*`processes`*:: When the `process` metricset is enabled, you can use the `processes` option to define a list of -regexp expressions to filter the processes that are reported. For more complex filtering, you should use the `processors` configuration option. See <> for more information. -+ -The following example config returns metrics for all processes: -+ -[source,yaml] ----- -metricbeat.modules: -- module: system - metricsets: ["process"] - processes: ['.*'] ----- - -*`process.include_top_n`*:: These options allow you to filter out all processes -that are not in the top N by CPU or memory, in order to reduce the number of -documents created. If both the `by_cpu` and `by_memory` options are used, the -union of the two sets is included. - -*`process.include_top_n.enabled`*:: Set to false to disable the top N feature and -include all processes, regardless of the other options. The default is `true`, -but nothing is filtered unless one of the other options (`by_cpu` or `by_memory`) -is set to a non-zero value. - -*`process.include_top_n.by_cpu`*:: How many processes to include from the top -by CPU. The processes are sorted by the `system.process.cpu.total.pct` field. -The default is 0. - -*`process.include_top_n.by_memory`*:: How many processes to include from the top -by memory. The processes are sorted by the `system.process.memory.rss.bytes` -field. The default is 0. - -*`process.cgroups.enabled`*:: When the `process` metricset is enabled, you can -use this boolean configuration option to disable cgroup metrics. By default -cgroup metrics collection is enabled. -+ -The following example config disables cgroup metrics on Linux. -+ -[source,yaml] ----- -metricbeat.modules: -- module: system - metricsets: ["process"] - process.cgroups.enabled: false ----- -*`cpu_ticks`*:: When the `cpu` or `core` metricset is enabled, you can specify `cpu_ticks: true` to report CPU ticks in addition to CPU percentages stats. For example: -+ -[source,yaml] ----- -metricbeat.modules: -- module: system - metricsets: ["cpu", "core"] - cpu_ticks: true ----- +The System module allows you to monitor your servers. Because the System module +always applies to the local server, the `hosts` config option is not needed. [float] === Dashboard diff --git a/metricbeat/module/system/core/_meta/docs.asciidoc b/metricbeat/module/system/core/_meta/docs.asciidoc index af39d109182..1ad4be81009 100644 --- a/metricbeat/module/system/core/_meta/docs.asciidoc +++ b/metricbeat/module/system/core/_meta/docs.asciidoc @@ -1,11 +1,26 @@ === System core metricset -The System `core` metricset provides load statistics for each CPU core. +The System `core` metricset provides usage statistics for each CPU core. This metricset is available on: -- Darwin - FreeBSD - Linux +- macOS - OpenBSD - Windows + +[float] +=== Configuration + +*`core.metrics`*:: This option controls what metrics are reported for each CPU +core. The value is a list and two metric types are supported - `percentages` and +`ticks`. The default value is `core.metrics: [percentages]`. ++ +[source,yaml] +---- +metricbeat.modules: +- module: system + metricsets: [core] + core.metrics: [percentages, ticks] +---- diff --git a/metricbeat/module/system/cpu/_meta/docs.asciidoc b/metricbeat/module/system/cpu/_meta/docs.asciidoc index 4d42a6f555f..12389f79119 100644 --- a/metricbeat/module/system/cpu/_meta/docs.asciidoc +++ b/metricbeat/module/system/cpu/_meta/docs.asciidoc @@ -4,8 +4,24 @@ The System `cpu` metricset provides CPU statistics. This metricset is available on: -- Darwin - FreeBSD - Linux +- macOS - OpenBSD - Windows + +[float] +=== Configuration + +*`cpu.metrics`*:: This option controls what CPU metrics are reported. The value +is a list and three metric types are supported - `percentages`, +`normalized_percentages`, and `ticks`. The default value is +`cpu.metrics: [percentages]`. ++ +[source,yaml] +---- +metricbeat.modules: +- module: system + metricsets: [core] + core.metrics: [percentages, normalized_percentages, ticks] +---- diff --git a/metricbeat/module/system/diskio/_meta/docs.asciidoc b/metricbeat/module/system/diskio/_meta/docs.asciidoc index edcb19e283e..fa19994e9c5 100644 --- a/metricbeat/module/system/diskio/_meta/docs.asciidoc +++ b/metricbeat/module/system/diskio/_meta/docs.asciidoc @@ -1,11 +1,16 @@ === System diskio metricset -The System `diskio` metricset provides disk IO metrics collected from the operating -system. One event is created for each disk mounted on the system. +The System `diskio` metricset provides disk IO metrics collected from the +operating system. One event is created for each disk mounted on the system. This metricset is available on: -- macOS (requires 10.10+) - Linux +- macOS (requires 10.10+) - Windows - FreeBSD (amd64) + +[float] +=== Configuration + +There are no configuration options for this metricset. diff --git a/metricbeat/module/system/filesystem/_meta/docs.asciidoc b/metricbeat/module/system/filesystem/_meta/docs.asciidoc index e3aa78f585f..d517e58ca11 100644 --- a/metricbeat/module/system/filesystem/_meta/docs.asciidoc +++ b/metricbeat/module/system/filesystem/_meta/docs.asciidoc @@ -5,9 +5,9 @@ system, one document is provided. This metricset is available on: -- Darwin - FreeBSD - Linux +- macOS - OpenBSD - Windows diff --git a/metricbeat/module/system/fsstat/_meta/docs.asciidoc b/metricbeat/module/system/fsstat/_meta/docs.asciidoc index 16cbe772f05..2751f5fc630 100644 --- a/metricbeat/module/system/fsstat/_meta/docs.asciidoc +++ b/metricbeat/module/system/fsstat/_meta/docs.asciidoc @@ -4,8 +4,8 @@ The System `fsstat` metricset provides overall file system statistics. This metricset is available on: -- Darwin - FreeBSD - Linux +- macOS - OpenBSD - Windows diff --git a/metricbeat/module/system/load/_meta/docs.asciidoc b/metricbeat/module/system/load/_meta/docs.asciidoc index ac54ecaba62..14685de5408 100644 --- a/metricbeat/module/system/load/_meta/docs.asciidoc +++ b/metricbeat/module/system/load/_meta/docs.asciidoc @@ -4,7 +4,12 @@ The System `load` metricset provides load statistics. This metricset is available on: - - Darwin - - FreeBSD - - Linux - - OpenBSD +- FreeBSD +- Linux +- macOS +- OpenBSD + +[float] +=== Configuration + +There are no configuration options for this metricset. diff --git a/metricbeat/module/system/memory/_meta/docs.asciidoc b/metricbeat/module/system/memory/_meta/docs.asciidoc index 400e83b0a07..a6ac7021e63 100644 --- a/metricbeat/module/system/memory/_meta/docs.asciidoc +++ b/metricbeat/module/system/memory/_meta/docs.asciidoc @@ -4,8 +4,13 @@ The System `memory` metricset provides memory statistics. This metricset is available on: -- Darwin - FreeBSD - Linux +- macOS - OpenBSD - Windows + +[float] +=== Configuration + +There are no configuration options for this metricset. diff --git a/metricbeat/module/system/network/_meta/docs.asciidoc b/metricbeat/module/system/network/_meta/docs.asciidoc index 5da1e75da7e..86cc92a8f60 100644 --- a/metricbeat/module/system/network/_meta/docs.asciidoc +++ b/metricbeat/module/system/network/_meta/docs.asciidoc @@ -3,9 +3,20 @@ The System `network` metricset provides network IO metrics collected from the operating system. One event is created for each network interface. -By default metrics are reported from all network interfaces. To select which -interfaces metrics are reported from, use the `interfaces` configuration -option. The value must be an array of interface names. For example: +This metricset is available on: + +- FreeBSD +- Linux +- macOS +- Windows + +[float] +=== Configuration + +*`interfaces`*:: By default metrics are reported from all network interfaces. +To select which interfaces metrics are reported from, use the `interfaces` +configuration option. The value must be an array of interface names. For +example: [source,yaml] ---------------------------- @@ -15,9 +26,3 @@ metricbeat.modules: interfaces: [eth0] ---------------------------- -This metricset is available on: - -- Darwin -- Linux -- Windows -- FreeBSD diff --git a/metricbeat/module/system/process/_meta/docs.asciidoc b/metricbeat/module/system/process/_meta/docs.asciidoc index 44d0888e435..602c9fbab66 100644 --- a/metricbeat/module/system/process/_meta/docs.asciidoc +++ b/metricbeat/module/system/process/_meta/docs.asciidoc @@ -5,35 +5,57 @@ provided for each process. This metricset is available on: -- Darwin - FreeBSD - Linux +- macOS - Windows [float] -=== Cache cmdline +=== Configuration -This metricset caches the command line args for a running process. This means if you alter -the command line for a process while this metricset is running, these changes are not detected. -This feature can be disabled by adding -`process.cmdline.cache.enabled: false` to the system module configuration. - -[float] -=== Control group (cgroup) metrics - -On Linux this metricset will collect metrics from any cgroups that the process -is a member of. This feature is enabled by default and can be disabled by adding -`process.cgroups.enabled: false` to the system module configuration. +*`processes`*:: When the `process` metricset is enabled, you can use the +`processes` option to define a list of regexp expressions to filter the +processes that are reported. For more complex filtering, you should use the +`processors` configuration option. See <> for more +information. ++ +The following example config returns metrics for all processes: ++ +[source,yaml] +---- +metricbeat.modules: +- module: system + metricsets: ["process"] + processes: ['.*'] +---- -[float] -=== Process environment variables +*`process.cgroups.enabled`*:: When the `process` metricset is enabled, you can +use this boolean configuration option to disable cgroup metrics. By default +cgroup metrics collection is enabled. ++ +The following example config disables cgroup metrics on Linux. ++ +[source,yaml] +---- +metricbeat.modules: +- module: system + metricsets: ["process"] + process.cgroups.enabled: false +---- -This metricset can collect the environment variables that were used to start the -process. This feature is available on Linux, Darwin, and FreeBSD. No environment -variables are collected by default because they could contain sensitive information. -You must configure the environment variables that you wish to collect by -specifying a list of regular expressions that match the variable name. +*`process.cmdline.cache.enabled`*:: This metricset caches the command line args +for a running process by default. This means if you alter the command line for a +process while this metricset is running, these changes are not detected. Caching +can be disabled by setting `process.cmdline.cache.enabled: false` in the +configuration. +*`process.env.whitelist`*:: This metricset can collect the environment variables +that were used to start the process. This feature is available on Linux, Darwin, +and FreeBSD. No environment variables are collected by default because they +could contain sensitive information. You must configure the environment +variables that you wish to collect by specifying a list of regular expressions +that match the variable name. ++ [source,yaml] ---- metricbeat.modules: @@ -43,3 +65,34 @@ metricbeat.modules: - '^PATH$' - '^SSH_.*' ---- + +*`process.include_cpu_ticks`*:: By default the cumulative CPU tick values +are not reported by this metricset (only percentages are reported). Setting +this option to true will enable the reporting of the raw CPU tick values +(for user, system, and total CPU time). ++ +[source,yaml] +---- +metricbeat.modules: +- module: system + metricsets: ["process"] + process.include_cpu_ticks: true +---- + +*`process.include_top_n`*:: These options allow you to filter out all processes +that are not in the top N by CPU or memory, in order to reduce the number of +documents created. If both the `by_cpu` and `by_memory` options are used, the +union of the two sets is included. + +*`process.include_top_n.enabled`*:: Set to false to disable the top N feature +and include all processes, regardless of the other options. The default is +`true`, but nothing is filtered unless one of the other options (`by_cpu` or +`by_memory`) is set to a non-zero value. + +*`process.include_top_n.by_cpu`*:: How many processes to include from the top +by CPU. The processes are sorted by the `system.process.cpu.total.pct` field. +The default is 0. + +*`process.include_top_n.by_memory`*:: How many processes to include from the top +by memory. The processes are sorted by the `system.process.memory.rss.bytes` +field. The default is 0. diff --git a/metricbeat/module/system/process_summary/_meta/docs.asciidoc b/metricbeat/module/system/process_summary/_meta/docs.asciidoc index faa96021b7c..0025d8874f5 100644 --- a/metricbeat/module/system/process_summary/_meta/docs.asciidoc +++ b/metricbeat/module/system/process_summary/_meta/docs.asciidoc @@ -2,3 +2,15 @@ The `process_summary` metricset collects high level statistics about the running processes. + +This metricset is available on: + +- FreeBSD +- Linux +- macOS +- Windows + +[float] +=== Configuration + +There are no configuration options for this metricset. diff --git a/metricbeat/module/system/socket/_meta/docs.asciidoc b/metricbeat/module/system/socket/_meta/docs.asciidoc index 23255ba5780..dfdf9e4afcb 100644 --- a/metricbeat/module/system/socket/_meta/docs.asciidoc +++ b/metricbeat/module/system/socket/_meta/docs.asciidoc @@ -27,13 +27,8 @@ The metricset reports the process that has the socket open. In order to provide this information, Metricbeat must be running as root. Root access is also required to read the file descriptor information of other processes. -You can configure the metricset to perform a reverse lookup on the remote IP, -and the returned hostname will be added to the event and cached. If a hostname -is found, then the eTLD+1 (effective top-level domain plus one level) value will -also be added to the event. Reverse lookups are disabled by default. - -The following example shows the full configuration for the metricset along with -the defaults. +[float] +=== Configuration [source,yaml] ---- @@ -43,3 +38,17 @@ the defaults. socket.reverse_lookup.success_ttl: 60s socket.reverse_lookup.failure_ttl: 60s ---- + +*`socket.reverse_lookup.enabled`*:: +You can configure the metricset to perform a reverse lookup on the remote IP, +and the returned hostname will be added to the event and cached. If a hostname +is found, then the eTLD+1 (effective top-level domain plus one level) value will +also be added to the event. Reverse lookups are disabled by default. + +*`socket.reverse_lookup.success_ttl`*:: +The results of successful reverse lookups are cached for the period of time +defined by this option. The default value is 60s. + +*`socket.reverse_lookup.failure_ttl`*:: +The results of failed reverse lookups are cached for the period of time +defined by this option. The default value is 60s. diff --git a/metricbeat/module/system/uptime/_meta/docs.asciidoc b/metricbeat/module/system/uptime/_meta/docs.asciidoc index f738283cb5a..34947b64180 100644 --- a/metricbeat/module/system/uptime/_meta/docs.asciidoc +++ b/metricbeat/module/system/uptime/_meta/docs.asciidoc @@ -4,7 +4,12 @@ The System `uptime` metricset provides the uptime of the host operating system. This metricset is available on: -- Darwin - Linux +- macOS - OpenBSD - Windows + +[float] +=== Configuration + +There are no configuration options for this metricset. From 7b56380967c5d9733015d90c1c1b1e4c7437b474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Wed, 16 Aug 2017 13:54:14 +0200 Subject: [PATCH 085/139] filebeat: add Kafka log module (#4885) This module is based on https://www.elastic.co/blog/monitoring-kafka-with-elastic-stack-1-filebeat --- CHANGELOG.asciidoc | 1 + filebeat/docs/fields.asciidoc | 90 ++ .../images/filebeat-kafka-logs-overview.png | Bin 0 -> 69319 bytes filebeat/docs/modules/kafka.asciidoc | 37 + filebeat/docs/modules_list.asciidoc | 2 + filebeat/filebeat.reference.yml | 15 + filebeat/module/kafka/_meta/config.yml | 13 + filebeat/module/kafka/_meta/docs.asciidoc | 24 + filebeat/module/kafka/_meta/fields.yml | 9 + .../dashboard/Filebeat-Kafka-overview.json | 85 ++ filebeat/module/kafka/log/_meta/fields.yml | 41 + filebeat/module/kafka/log/config/log.yml | 10 + .../module/kafka/log/ingest/pipeline.json | 66 ++ filebeat/module/kafka/log/manifest.yml | 14 + filebeat/module/kafka/log/test/controller.log | 20 + .../log/test/controller.log-expected.json | 961 ++++++++++++++++++ filebeat/module/kafka/log/test/server.log | 20 + .../kafka/log/test/server.log-expected.json | 961 ++++++++++++++++++ .../module/kafka/log/test/state-change.log | 1 + .../log/test/state-change.log-expected.json | 49 + filebeat/modules.d/kafka.yml.disabled | 13 + 21 files changed, 2432 insertions(+) create mode 100644 filebeat/docs/images/filebeat-kafka-logs-overview.png create mode 100644 filebeat/docs/modules/kafka.asciidoc create mode 100644 filebeat/module/kafka/_meta/config.yml create mode 100644 filebeat/module/kafka/_meta/docs.asciidoc create mode 100644 filebeat/module/kafka/_meta/fields.yml create mode 100644 filebeat/module/kafka/_meta/kibana/default/dashboard/Filebeat-Kafka-overview.json create mode 100644 filebeat/module/kafka/log/_meta/fields.yml create mode 100644 filebeat/module/kafka/log/config/log.yml create mode 100644 filebeat/module/kafka/log/ingest/pipeline.json create mode 100644 filebeat/module/kafka/log/manifest.yml create mode 100644 filebeat/module/kafka/log/test/controller.log create mode 100644 filebeat/module/kafka/log/test/controller.log-expected.json create mode 100644 filebeat/module/kafka/log/test/server.log create mode 100644 filebeat/module/kafka/log/test/server.log-expected.json create mode 100644 filebeat/module/kafka/log/test/state-change.log create mode 100644 filebeat/module/kafka/log/test/state-change.log-expected.json create mode 100644 filebeat/modules.d/kafka.yml.disabled diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 05e93e68425..0e360ce32a4 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -76,6 +76,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Filebeat* - Add PostgreSQL module with slowlog support. {pull}4763[4763] +- Add Kafka log module. {pull}4885[4885] *Heartbeat* diff --git a/filebeat/docs/fields.asciidoc b/filebeat/docs/fields.asciidoc index 4e1cf9673fc..0b677ee0073 100644 --- a/filebeat/docs/fields.asciidoc +++ b/filebeat/docs/fields.asciidoc @@ -18,6 +18,7 @@ grouped in the following categories: * <> * <> * <> +* <> * <> * <> * <> @@ -749,6 +750,95 @@ type: text The logged message. +[[exported-fields-kafka]] +== Kafka fields + +Kafka module + + + +[float] +== kafka fields + + + + +[float] +== log fields + +Kafka log lines. + + + +[float] +=== `kafka.log.timestamp` + +The timestamp from the log line. + + +[float] +=== `kafka.log.level` + +example: WARN + +The log level. + + +[float] +=== `kafka.log.message` + +type: text + +The logged message. + + +[float] +=== `kafka.log.component` + +type: keyword + +Component the log is coming from. + + +[float] +=== `kafka.log.class` + +type: text + +Java class the log is coming from. + + +[float] +== trace fields + +Trace in the log line. + + + +[float] +=== `kafka.log.trace.class` + +type: keyword + +Java class the trace is coming from. + + +[float] +=== `kafka.log.trace.message` + +type: text + +Message part of the trace. + + +[float] +=== `kafka.log.trace.full` + +type: text + +The full trace in the log line. + + [[exported-fields-kubernetes-processor]] == Kubernetes fields diff --git a/filebeat/docs/images/filebeat-kafka-logs-overview.png b/filebeat/docs/images/filebeat-kafka-logs-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..b04697a4b338c64a715fac0797132ef7f3af8254 GIT binary patch literal 69319 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

    X6TiX!ntzCoQU2S@ReQp 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 literal 0 HcmV?d00001 diff --git a/filebeat/docs/modules/kafka.asciidoc b/filebeat/docs/modules/kafka.asciidoc new file mode 100644 index 00000000000..36a13dc8ae5 --- /dev/null +++ b/filebeat/docs/modules/kafka.asciidoc @@ -0,0 +1,37 @@ +//// +This file is generated! See scripts/docs_collector.py +//// + +[[filebeat-module-kafka]] +== Kafka module + +This module collects and parses the logs created by https://kafka.apache.org/[Kafka]. + +[float] +=== Compatibility + +The Kafka module was tested with logs from versions 2.11. + +[float] +=== Dashboard + +This module comes with a sample dashboard to see Kafka logs and stacktraces. + +image::./images/filebeat-kafka-logs-overview.png[] + +[float] +=== Logs fileset settings + +[float] +==== var.paths + +An array of paths where to look for the log files. If left empty, Filebeat +will choose the paths depending on your operating systems. + + +[float] +=== Fields + +For a description of each field in the metricset, see the +<> section. + diff --git a/filebeat/docs/modules_list.asciidoc b/filebeat/docs/modules_list.asciidoc index 1dd62900250..52dca849789 100644 --- a/filebeat/docs/modules_list.asciidoc +++ b/filebeat/docs/modules_list.asciidoc @@ -6,6 +6,7 @@ This file is generated! See scripts/docs_collector.py * <> * <> * <> + * <> * <> * <> * <> @@ -19,6 +20,7 @@ include::modules-overview.asciidoc[] include::modules/apache2.asciidoc[] include::modules/auditd.asciidoc[] include::modules/icinga.asciidoc[] +include::modules/kafka.asciidoc[] include::modules/mysql.asciidoc[] include::modules/nginx.asciidoc[] include::modules/postgresql.asciidoc[] diff --git a/filebeat/filebeat.reference.yml b/filebeat/filebeat.reference.yml index 37c52fa679e..058d4d88dee 100644 --- a/filebeat/filebeat.reference.yml +++ b/filebeat/filebeat.reference.yml @@ -114,6 +114,21 @@ filebeat.modules: # can be added under this section. #prospector: +#-------------------------------- Kafka Module ------------------------------- +- module: kafka + # All logs + log: + enabled: true + + # Set custom paths for Kafka. If left empty, + # Filebeat will look under /opt. + #var.kafka_home: + + # Set custom paths for the log files. If left empty, + # Filebeat will choose the paths depending on your OS. + #var.paths: + + #-------------------------------- MySQL Module ------------------------------- #- module: mysql # Error logs diff --git a/filebeat/module/kafka/_meta/config.yml b/filebeat/module/kafka/_meta/config.yml new file mode 100644 index 00000000000..fe568e8e562 --- /dev/null +++ b/filebeat/module/kafka/_meta/config.yml @@ -0,0 +1,13 @@ +- module: kafka + # All logs + log: + enabled: true + + # Set custom paths for Kafka. If left empty, + # Filebeat will look under /opt. + #var.kafka_home: + + # Set custom paths for the log files. If left empty, + # Filebeat will choose the paths depending on your OS. + #var.paths: + diff --git a/filebeat/module/kafka/_meta/docs.asciidoc b/filebeat/module/kafka/_meta/docs.asciidoc new file mode 100644 index 00000000000..fc2ea722bb5 --- /dev/null +++ b/filebeat/module/kafka/_meta/docs.asciidoc @@ -0,0 +1,24 @@ +== Kafka module + +This module collects and parses the logs created by https://kafka.apache.org/[Kafka]. + +[float] +=== Compatibility + +The Kafka module was tested with logs from versions 2.11. + +[float] +=== Dashboard + +This module comes with a sample dashboard to see Kafka logs and stacktraces. + +image::./images/filebeat-kafka-logs-overview.png[] + +[float] +=== Logs fileset settings + +[float] +==== var.paths + +An array of paths where to look for the log files. If left empty, Filebeat +will choose the paths depending on your operating systems. diff --git a/filebeat/module/kafka/_meta/fields.yml b/filebeat/module/kafka/_meta/fields.yml new file mode 100644 index 00000000000..5469c535e71 --- /dev/null +++ b/filebeat/module/kafka/_meta/fields.yml @@ -0,0 +1,9 @@ +- key: kafka + title: "Kafka" + description: > + Kafka module + fields: + - name: kafka + type: group + description: > + fields: diff --git a/filebeat/module/kafka/_meta/kibana/default/dashboard/Filebeat-Kafka-overview.json b/filebeat/module/kafka/_meta/kibana/default/dashboard/Filebeat-Kafka-overview.json new file mode 100644 index 00000000000..7b5d03e48ee --- /dev/null +++ b/filebeat/module/kafka/_meta/kibana/default/dashboard/Filebeat-Kafka-overview.json @@ -0,0 +1,85 @@ +{ + "objects": [ + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "Kafka stacktraces", + "title": "Number of Kafka stracktraces by class", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Number of Kafka stracktraces by class\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{\"text\":\"@timestamp per 30 minutes\"}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"kafka.log.trace.class\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\"}}]}" + }, + "id": "Number of Kafka stracktraces by class", + "type": "visualization", + "version": 1 + }, + { + "attributes": { + "columns": [ + "kafka.log.class", + "kafka.log.trace.class", + "kafka.log.trace.full" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"_exists_:kafka.log.trace.class\",\"language\":\"lucene\"},\"filter\":[]}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "Kafka stacktraces", + "version": 1 + }, + "id": "Kafka stacktraces", + "type": "search", + "version": 1 + }, + { + "attributes": { + "columns": [ + "kafka.log.level", + "kafka.log.component", + "kafka.log.message" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"kafka.log.level:*\",\"language\":\"lucene\"},\"filter\":[]}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "All Kafka logs", + "version": 1 + }, + "id": "All Kafka logs", + "type": "search", + "version": 1 + }, + { + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" + }, + "optionsJSON": "{\"darkTheme\":false}", + "panelsJSON": "[{\"col\":1,\"id\":\"Number of Kafka stracktraces by class\",\"panelIndex\":1,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"columns\":[\"kafka.log.class\",\"kafka.log.trace.class\",\"kafka.log.trace.full\"],\"id\":\"Kafka stacktraces\",\"panelIndex\":2,\"row\":1,\"size_x\":6,\"size_y\":3,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"size_x\":12,\"size_y\":3,\"panelIndex\":3,\"type\":\"search\",\"id\":\"All Kafka logs\",\"col\":1,\"row\":4,\"columns\":[\"kafka.log.level\",\"kafka.log.component\",\"kafka.log.message\"],\"sort\":[\"@timestamp\",\"desc\"]}]", + "timeRestore": false, + "title": "Kafka logs overview", + "uiStateJSON": "{}", + "version": 1 + }, + "id": "Kafka logs overview", + "type": "dashboard", + "version": 1 + } + ], + "version": "6.0.0-beta1-SNAPSHOT" +} diff --git a/filebeat/module/kafka/log/_meta/fields.yml b/filebeat/module/kafka/log/_meta/fields.yml new file mode 100644 index 00000000000..e9d234cb625 --- /dev/null +++ b/filebeat/module/kafka/log/_meta/fields.yml @@ -0,0 +1,41 @@ +- name: log + type: group + description: > + Kafka log lines. + fields: + - name: timestamp + description: > + The timestamp from the log line. + - name: level + example: "WARN" + description: > + The log level. + - name: message + type: text + description: > + The logged message. + - name: component + type: keyword + description: > + Component the log is coming from. + - name: class + type: text + description: > + Java class the log is coming from. + - name: trace + type: group + description: > + Trace in the log line. + fields: + - name: class + type: keyword + description: > + Java class the trace is coming from. + - name: message + type: text + description: > + Message part of the trace. + - name: full + type: text + description: > + The full trace in the log line. diff --git a/filebeat/module/kafka/log/config/log.yml b/filebeat/module/kafka/log/config/log.yml new file mode 100644 index 00000000000..98c684ef52f --- /dev/null +++ b/filebeat/module/kafka/log/config/log.yml @@ -0,0 +1,10 @@ +type: log +paths: +{{ range $i, $path := .paths }} + - {{$path}} +{{ end }} +exclude_files: [".gz$"] +multiline: + pattern: '^\[' + negate: true + match: after diff --git a/filebeat/module/kafka/log/ingest/pipeline.json b/filebeat/module/kafka/log/ingest/pipeline.json new file mode 100644 index 00000000000..1c5149f5a51 --- /dev/null +++ b/filebeat/module/kafka/log/ingest/pipeline.json @@ -0,0 +1,66 @@ +{ + "description": "Pipeline for parsing Kafka log messages", + "processors": [ + { + "grok": { + "field": "message", + "trace_match": true, + "patterns": [ + "(?m)%{TIMESTAMP_ISO8601:kafka.log.timestamp}. %{LOGLEVEL:kafka.log.level} +%{JAVALOGMESSAGE:kafka.log.message} \\(%{JAVACLASS:kafka.log.class}\\)$[ \\n]*(?'kafka.log.trace.full'.*)" + ] + } + }, + { + "grok": { + "field": "kafka.log.message", + "patterns": [ + "\\[%{DATA:kafka.log.component}\\][,:. ] +%{JAVALOGMESSAGE:kafka.log.message}" + ], + "on_failure": [ + { + "set": { + "field": "kafka.log.component", + "value": "unknown" + } + } + ] + } + }, + { + "grok": { + "field": "kafka.log.trace.full", + "ignore_missing": true, + "patterns": [ + "%{JAVACLASS:kafka.log.trace.class}:\\s*%{JAVALOGMESSAGE:kafka.log.trace.message}" + ], + "on_failure": [ + { + "remove": { + "field": "kafka.log.trace" + } + } + ] + } + }, + { + "rename": { + "field": "@timestamp", + "target_field": "beat.read_time" + } + }, + { + "date": { + "field": "kafka.log.timestamp", + "target_field": "@timestamp", + "formats": ["yyyy-MM-dd HH:mm:ss,SSS"] + } + }, + {"remove": {"field": "kafka.log.timestamp" }} + ], + "on_failure" : [{ + "set" : { + "field" : "error.log", + "value" : "{{ _ingest.on_failure_message }}" + } + }] +} diff --git a/filebeat/module/kafka/log/manifest.yml b/filebeat/module/kafka/log/manifest.yml new file mode 100644 index 00000000000..fb7916d9536 --- /dev/null +++ b/filebeat/module/kafka/log/manifest.yml @@ -0,0 +1,14 @@ +module_version: 1.0 + +var: + - name: kafka_home + default: /opt/kafka* + - name: paths + default: + - "{{.kafka_home}}/logs/controller.log*" + - "{{.kafka_home}}/logs/server.log*" + - "{{.kafka_home}}/logs/state-change.log*" + - "{{.kafka_home}}/logs/kafka-*.log*" + +ingest_pipeline: ingest/pipeline.json +prospector: config/log.yml diff --git a/filebeat/module/kafka/log/test/controller.log b/filebeat/module/kafka/log/test/controller.log new file mode 100644 index 00000000000..39cd4b97043 --- /dev/null +++ b/filebeat/module/kafka/log/test/controller.log @@ -0,0 +1,20 @@ +[2017-08-04 10:48:21,048] INFO [controller-event-thread]: Starting (kafka.controller.ControllerEventManager$ControllerEventThread) +[2017-08-04 10:48:21,063] INFO [Controller 0]: 0 successfully elected as the controller (kafka.controller.KafkaController) +[2017-08-04 10:48:21,064] INFO [Controller 0]: Broker 0 starting become controller state transition (kafka.controller.KafkaController) +[2017-08-04 10:48:21,082] INFO [Controller 0]: Controller 0 incremented epoch to 1 (kafka.controller.KafkaController) +[2017-08-04 10:48:21,085] DEBUG [Controller 0]: Registering IsrChangeNotificationListener (kafka.controller.KafkaController) +[2017-08-04 10:48:21,154] INFO [Replica state machine on controller 0]: Started replica state machine with initial state -> Map() (kafka.controller.ReplicaStateMachine) +[2017-08-04 10:48:21,156] INFO [Partition state machine on Controller 0]: Started partition state machine with initial state -> Map() (kafka.controller.PartitionStateMachine) +[2017-08-04 10:48:21,157] INFO [Controller 0]: Broker 0 is ready to serve as the new controller with epoch 1 (kafka.controller.KafkaController) +[2017-08-04 10:48:21,165] INFO [Partition state machine on Controller 0]: Invoking state change to OnlinePartition for partitions (kafka.controller.PartitionStateMachine) +[2017-08-04 11:44:22,588] DEBUG [Controller 0]: Live brokers: (kafka.controller.KafkaController) +[2017-08-04 11:44:25,094] INFO [controller-event-thread]: Shutting down (kafka.controller.ControllerEventManager$ControllerEventThread) +[2017-08-04 11:44:25,095] INFO [controller-event-thread]: Stopped (kafka.controller.ControllerEventManager$ControllerEventThread) +[2017-08-04 11:44:25,097] INFO [controller-event-thread]: Shutdown completed (kafka.controller.ControllerEventManager$ControllerEventThread) +[2017-08-04 11:44:25,099] DEBUG [Controller 0]: Controller resigning, broker id 0 (kafka.controller.KafkaController) +[2017-08-04 11:44:25,100] DEBUG [Controller 0]: De-registering IsrChangeNotificationListener (kafka.controller.KafkaController) +[2017-08-04 11:44:25,105] INFO [Partition state machine on Controller 0]: Stopped partition state machine (kafka.controller.PartitionStateMachine) +[2017-08-04 11:44:25,111] INFO [Replica state machine on controller 0]: Stopped replica state machine (kafka.controller.ReplicaStateMachine) +[2017-08-04 11:44:25,112] INFO [Controller-0-to-broker-0-send-thread]: Shutting down (kafka.controller.RequestSendThread) +[2017-08-04 11:44:25,112] INFO [Controller-0-to-broker-0-send-thread]: Stopped (kafka.controller.RequestSendThread) +[2017-08-04 11:44:25,113] INFO [Controller-0-to-broker-0-send-thread]: Shutdown completed (kafka.controller.RequestSendThread) diff --git a/filebeat/module/kafka/log/test/controller.log-expected.json b/filebeat/module/kafka/log/test/controller.log-expected.json new file mode 100644 index 00000000000..b3453298e43 --- /dev/null +++ b/filebeat/module/kafka/log/test/controller.log-expected.json @@ -0,0 +1,961 @@ +[ + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "wItR0l0Bed9fOYVUjezS", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T11:44:25.113Z", + "offset": 2695, + "kafka": { + "log": { + "component": "Controller-0-to-broker-0-send-thread", + "level": "INFO", + "message": "Shutdown completed", + "class": "kafka.controller.RequestSendThread" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.376Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "fileset": { + "module": "kafka", + "name": "log" + }, + "message": "[2017-08-04 11:44:25,113] INFO [Controller-0-to-broker-0-send-thread]: Shutdown completed (kafka.controller.RequestSendThread)" + }, + "fields": { + "@timestamp": [ + "2017-08-04T11:44:25.113Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501847065113 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "notR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T11:44:25.112Z", + "offset": 2452, + "kafka": { + "log": { + "component": "Controller-0-to-broker-0-send-thread", + "level": "INFO", + "message": "Shutting down", + "class": "kafka.controller.RequestSendThread" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.374Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "message": "[2017-08-04 11:44:25,112] INFO [Controller-0-to-broker-0-send-thread]: Shutting down (kafka.controller.RequestSendThread)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T11:44:25.112Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501847065112 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "n4tR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T11:44:25.112Z", + "offset": 2568, + "kafka": { + "log": { + "component": "Controller-0-to-broker-0-send-thread", + "level": "INFO", + "message": "Stopped", + "class": "kafka.controller.RequestSendThread" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.376Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "message": "[2017-08-04 11:44:25,112] INFO [Controller-0-to-broker-0-send-thread]: Stopped (kafka.controller.RequestSendThread)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T11:44:25.112Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501847065112 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "nYtR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T11:44:25.111Z", + "offset": 2330, + "kafka": { + "log": { + "component": "Replica state machine on controller 0", + "level": "INFO", + "message": "Stopped replica state machine", + "class": "kafka.controller.ReplicaStateMachine" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.373Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "fileset": { + "module": "kafka", + "name": "log" + }, + "message": "[2017-08-04 11:44:25,111] INFO [Replica state machine on controller 0]: Stopped replica state machine (kafka.controller.ReplicaStateMachine)" + }, + "fields": { + "@timestamp": [ + "2017-08-04T11:44:25.111Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501847065111 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "nItR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T11:44:25.105Z", + "offset": 2189, + "kafka": { + "log": { + "component": "Partition state machine on Controller 0", + "level": "INFO", + "message": "Stopped partition state machine", + "class": "kafka.controller.PartitionStateMachine" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.372Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "fileset": { + "module": "kafka", + "name": "log" + }, + "message": "[2017-08-04 11:44:25,105] INFO [Partition state machine on Controller 0]: Stopped partition state machine (kafka.controller.PartitionStateMachine)" + }, + "fields": { + "@timestamp": [ + "2017-08-04T11:44:25.105Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501847065105 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "m4tR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T11:44:25.100Z", + "offset": 2042, + "kafka": { + "log": { + "component": "Controller 0", + "level": "DEBUG", + "message": "De-registering IsrChangeNotificationListener", + "class": "kafka.controller.KafkaController" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.372Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "message": "[2017-08-04 11:44:25,100] DEBUG [Controller 0]: De-registering IsrChangeNotificationListener (kafka.controller.KafkaController)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T11:44:25.100Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501847065100 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "motR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T11:44:25.099Z", + "offset": 1914, + "kafka": { + "log": { + "component": "Controller 0", + "level": "DEBUG", + "message": "Controller resigning, broker id 0", + "class": "kafka.controller.KafkaController" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.372Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "message": "[2017-08-04 11:44:25,099] DEBUG [Controller 0]: Controller resigning, broker id 0 (kafka.controller.KafkaController)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T11:44:25.099Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501847065099 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "mYtR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T11:44:25.097Z", + "offset": 1797, + "kafka": { + "log": { + "component": "controller-event-thread", + "level": "INFO", + "message": "Shutdown completed", + "class": "kafka.controller.ControllerEventManager$ControllerEventThread" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.370Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "fileset": { + "module": "kafka", + "name": "log" + }, + "message": "[2017-08-04 11:44:25,097] INFO [controller-event-thread]: Shutdown completed (kafka.controller.ControllerEventManager$ControllerEventThread)" + }, + "fields": { + "@timestamp": [ + "2017-08-04T11:44:25.097Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501847065097 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "mItR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T11:44:25.095Z", + "offset": 1656, + "kafka": { + "log": { + "component": "controller-event-thread", + "level": "INFO", + "message": "Stopped", + "class": "kafka.controller.ControllerEventManager$ControllerEventThread" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.369Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "message": "[2017-08-04 11:44:25,095] INFO [controller-event-thread]: Stopped (kafka.controller.ControllerEventManager$ControllerEventThread)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T11:44:25.095Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501847065095 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "l4tR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T11:44:25.094Z", + "offset": 1526, + "kafka": { + "log": { + "component": "controller-event-thread", + "level": "INFO", + "message": "Shutting down", + "class": "kafka.controller.ControllerEventManager$ControllerEventThread" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.367Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "message": "[2017-08-04 11:44:25,094] INFO [controller-event-thread]: Shutting down (kafka.controller.ControllerEventManager$ControllerEventThread)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T11:44:25.094Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501847065094 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "lotR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T11:44:22.588Z", + "offset": 1390, + "kafka": { + "log": { + "component": "Controller 0", + "level": "DEBUG", + "message": "Live brokers: ", + "class": "kafka.controller.KafkaController" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.365Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "message": "[2017-08-04 11:44:22,588] DEBUG [Controller 0]: Live brokers: (kafka.controller.KafkaController)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T11:44:22.588Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501847062588 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "lYtR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.165Z", + "offset": 1292, + "kafka": { + "log": { + "component": "Partition state machine on Controller 0", + "level": "INFO", + "message": "Invoking state change to OnlinePartition for partitions ", + "class": "kafka.controller.PartitionStateMachine" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.364Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "message": "[2017-08-04 10:48:21,165] INFO [Partition state machine on Controller 0]: Invoking state change to OnlinePartition for partitions (kafka.controller.PartitionStateMachine)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.165Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701165 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "lItR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.157Z", + "offset": 1120, + "kafka": { + "log": { + "component": "Controller 0", + "level": "INFO", + "message": "Broker 0 is ready to serve as the new controller with epoch 1", + "class": "kafka.controller.KafkaController" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.363Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "fileset": { + "module": "kafka", + "name": "log" + }, + "message": "[2017-08-04 10:48:21,157] INFO [Controller 0]: Broker 0 is ready to serve as the new controller with epoch 1 (kafka.controller.KafkaController)" + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.157Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701157 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "k4tR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.156Z", + "offset": 976, + "kafka": { + "log": { + "component": "Partition state machine on Controller 0", + "level": "INFO", + "message": "Started partition state machine with initial state -> Map()", + "class": "kafka.controller.PartitionStateMachine" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.362Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "message": "[2017-08-04 10:48:21,156] INFO [Partition state machine on Controller 0]: Started partition state machine with initial state -> Map() (kafka.controller.PartitionStateMachine)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.156Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701156 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "kotR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.154Z", + "offset": 801, + "kafka": { + "log": { + "component": "Replica state machine on controller 0", + "level": "INFO", + "message": "Started replica state machine with initial state -> Map()", + "class": "kafka.controller.ReplicaStateMachine" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.361Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "message": "[2017-08-04 10:48:21,154] INFO [Replica state machine on controller 0]: Started replica state machine with initial state -> Map() (kafka.controller.ReplicaStateMachine)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.154Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701154 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "kYtR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.085Z", + "offset": 632, + "kafka": { + "log": { + "component": "Controller 0", + "level": "DEBUG", + "message": "Registering IsrChangeNotificationListener", + "class": "kafka.controller.KafkaController" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.360Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "fileset": { + "module": "kafka", + "name": "log" + }, + "message": "[2017-08-04 10:48:21,085] DEBUG [Controller 0]: Registering IsrChangeNotificationListener (kafka.controller.KafkaController)" + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.085Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701085 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "kItR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.082Z", + "offset": 507, + "kafka": { + "log": { + "component": "Controller 0", + "level": "INFO", + "message": "Controller 0 incremented epoch to 1", + "class": "kafka.controller.KafkaController" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.358Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "message": "[2017-08-04 10:48:21,082] INFO [Controller 0]: Controller 0 incremented epoch to 1 (kafka.controller.KafkaController)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.082Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701082 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "j4tR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.064Z", + "offset": 389, + "kafka": { + "log": { + "component": "Controller 0", + "level": "INFO", + "message": "Broker 0 starting become controller state transition", + "class": "kafka.controller.KafkaController" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.358Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "message": "[2017-08-04 10:48:21,064] INFO [Controller 0]: Broker 0 starting become controller state transition (kafka.controller.KafkaController)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.064Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701064 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "jotR0l0Bed9fOYVUfexP", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.063Z", + "offset": 254, + "kafka": { + "log": { + "component": "Controller 0", + "level": "INFO", + "message": "0 successfully elected as the controller", + "class": "kafka.controller.KafkaController" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.358Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "fileset": { + "module": "kafka", + "name": "log" + }, + "message": "[2017-08-04 10:48:21,063] INFO [Controller 0]: 0 successfully elected as the controller (kafka.controller.KafkaController)" + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.063Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701063 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "jYtR0l0Bed9fOYVUfOzU", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.048Z", + "offset": 131, + "kafka": { + "log": { + "component": "controller-event-thread", + "level": "INFO", + "message": "Starting", + "class": "kafka.controller.ControllerEventManager$ControllerEventThread" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.358Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log", + "fileset": { + "module": "kafka", + "name": "log" + }, + "message": "[2017-08-04 10:48:21,048] INFO [controller-event-thread]: Starting (kafka.controller.ControllerEventManager$ControllerEventThread)" + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.048Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/controller.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701048 + ] + } +] diff --git a/filebeat/module/kafka/log/test/server.log b/filebeat/module/kafka/log/test/server.log new file mode 100644 index 00000000000..8ebf66523d9 --- /dev/null +++ b/filebeat/module/kafka/log/test/server.log @@ -0,0 +1,20 @@ +[2017-08-04 10:48:20,377] INFO starting (kafka.server.KafkaServer) +[2017-08-04 10:48:20,379] INFO Connecting to zookeeper on localhost:2181 (kafka.server.KafkaServer) +[2017-08-04 10:48:20,400] INFO Client environment:java.io.tmpdir=/tmp (org.apache.zookeeper.ZooKeeper) +[2017-08-04 10:48:20,400] INFO Client environment:java.compiler= (org.apache.zookeeper.ZooKeeper) +[2017-08-04 10:48:20,401] INFO Initiating client connection, connectString=localhost:2181 sessionTimeout=6000 watcher=org.I0Itec.zkclient.ZkClient@5ffead27 (org.apache.zookeeper.ZooKeeper) +[2017-08-04 10:48:20,413] INFO Waiting for keeper state SyncConnected (org.I0Itec.zkclient.ZkClient) +[2017-08-04 10:48:20,415] INFO Opening socket connection to server localhost/0:0:0:0:0:0:0:1:2181. Will not attempt to authenticate using SASL (unknown error) (org.apache.zookeeper.ClientCnxn) +[2017-08-04 10:48:20,420] INFO Socket connection established to localhost/0:0:0:0:0:0:0:1:2181, initiating session (org.apache.zookeeper.ClientCnxn) +[2017-08-04 10:48:20,457] INFO Session establishment complete on server localhost/0:0:0:0:0:0:0:1:2181, sessionid = 0x15dabf8d4140000, negotiated timeout = 6000 (org.apache.zookeeper.ClientCnxn) +[2017-08-04 10:48:20,458] INFO zookeeper state changed (SyncConnected) (org.I0Itec.zkclient.ZkClient) +[2017-08-04 10:48:20,748] WARN No meta.properties file under dir /tmp/kafka-logs/meta.properties (kafka.server.BrokerMetadataCheckpoint) +[2017-08-04 10:48:20,800] INFO [ThrottledRequestReaper-Fetch]: Starting (kafka.server.ClientQuotaManager$ThrottledRequestReaper) +[2017-08-04 10:48:20,866] INFO Log directory '/tmp/kafka-logs' not found, creating it. (kafka.log.LogManager) +[2017-08-04 10:48:20,873] INFO Loading logs. (kafka.log.LogManager) +[2017-08-04 10:48:21,062] INFO [ExpirationReaper-0-Heartbeat]: Starting (kafka.server.DelayedOperationPurgatory$ExpiredOperationReaper) +[2017-08-04 10:48:21,063] INFO Result of znode creation is: OK (kafka.utils.ZKCheckedEphemeral) +[2017-08-04 10:48:21,095] INFO [Group Metadata Manager on Broker 0]: Removed 0 expired offsets in 1 milliseconds. (kafka.coordinator.group.GroupMetadataManager) +[2017-08-04 10:48:21,127] INFO [ProducerId Manager 0]: Acquired new producerId block (brokerId:0,blockStartProducerId:0,blockEndProducerId:999) by writing to Zk with path version 1 (kafka.coordinator.transaction.ProducerIdManager) +[2017-08-04 10:48:21,162] INFO [Transaction Coordinator 0]: Starting up. (kafka.coordinator.transaction.TransactionCoordinator) +[2017-08-04 10:48:21,167] INFO [Transaction Marker Channel Manager 0]: Starting (kafka.coordinator.transaction.TransactionMarkerChannelManager) diff --git a/filebeat/module/kafka/log/test/server.log-expected.json b/filebeat/module/kafka/log/test/server.log-expected.json new file mode 100644 index 00000000000..713942361b5 --- /dev/null +++ b/filebeat/module/kafka/log/test/server.log-expected.json @@ -0,0 +1,961 @@ +[ + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "wYtR0l0Bed9fOYVUjuwB", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.167Z", + "offset": 2641, + "kafka": { + "log": { + "component": "Transaction Marker Channel Manager 0", + "level": "INFO", + "message": "Starting", + "class": "kafka.coordinator.transaction.TransactionMarkerChannelManager" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.385Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "fileset": { + "module": "kafka", + "name": "log" + }, + "message": "[2017-08-04 10:48:21,167] INFO [Transaction Marker Channel Manager 0]: Starting (kafka.coordinator.transaction.TransactionMarkerChannelManager)" + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.167Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701167 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "sotR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.162Z", + "offset": 2497, + "kafka": { + "log": { + "component": "Transaction Coordinator 0", + "level": "INFO", + "message": "Starting up.", + "class": "kafka.coordinator.transaction.TransactionCoordinator" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.384Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "fileset": { + "module": "kafka", + "name": "log" + }, + "message": "[2017-08-04 10:48:21,162] INFO [Transaction Coordinator 0]: Starting up. (kafka.coordinator.transaction.TransactionCoordinator)" + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.162Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701162 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "sYtR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.127Z", + "offset": 2369, + "kafka": { + "log": { + "component": "ProducerId Manager 0", + "level": "INFO", + "message": "Acquired new producerId block (brokerId:0,blockStartProducerId:0,blockEndProducerId:999) by writing to Zk with path version 1", + "class": "kafka.coordinator.transaction.ProducerIdManager" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.384Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "fileset": { + "module": "kafka", + "name": "log" + }, + "message": "[2017-08-04 10:48:21,127] INFO [ProducerId Manager 0]: Acquired new producerId block (brokerId:0,blockStartProducerId:0,blockEndProducerId:999) by writing to Zk with path version 1 (kafka.coordinator.transaction.ProducerIdManager)" + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.127Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701127 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "sItR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.095Z", + "offset": 2138, + "kafka": { + "log": { + "component": "Group Metadata Manager on Broker 0", + "level": "INFO", + "message": "Removed 0 expired offsets in 1 milliseconds.", + "class": "kafka.coordinator.group.GroupMetadataManager" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.384Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "message": "[2017-08-04 10:48:21,095] INFO [Group Metadata Manager on Broker 0]: Removed 0 expired offsets in 1 milliseconds. (kafka.coordinator.group.GroupMetadataManager)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.095Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701095 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "r4tR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.063Z", + "offset": 1977, + "kafka": { + "log": { + "component": "unknown", + "level": "INFO", + "message": "Result of znode creation is: OK", + "class": "kafka.utils.ZKCheckedEphemeral" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.384Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "message": "[2017-08-04 10:48:21,063] INFO Result of znode creation is: OK (kafka.utils.ZKCheckedEphemeral)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.063Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701063 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "rotR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.062Z", + "offset": 1881, + "kafka": { + "log": { + "component": "ExpirationReaper-0-Heartbeat", + "level": "INFO", + "message": "Starting", + "class": "kafka.server.DelayedOperationPurgatory$ExpiredOperationReaper" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.381Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "message": "[2017-08-04 10:48:21,062] INFO [ExpirationReaper-0-Heartbeat]: Starting (kafka.server.DelayedOperationPurgatory$ExpiredOperationReaper)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.062Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701062 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "rYtR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:20.873Z", + "offset": 1745, + "kafka": { + "log": { + "component": "unknown", + "level": "INFO", + "message": "Loading logs.", + "class": "kafka.log.LogManager" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.381Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "message": "[2017-08-04 10:48:20,873] INFO Loading logs. (kafka.log.LogManager)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:20.873Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843700873 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "rItR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:20.866Z", + "offset": 1677, + "kafka": { + "log": { + "component": "unknown", + "level": "INFO", + "message": "Log directory '/tmp/kafka-logs' not found, creating it.", + "class": "kafka.log.LogManager" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.381Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "fileset": { + "module": "kafka", + "name": "log" + }, + "message": "[2017-08-04 10:48:20,866] INFO Log directory '/tmp/kafka-logs' not found, creating it. (kafka.log.LogManager)" + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:20.866Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843700866 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "q4tR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:20.800Z", + "offset": 1567, + "kafka": { + "log": { + "component": "ThrottledRequestReaper-Fetch", + "level": "INFO", + "message": "Starting", + "class": "kafka.server.ClientQuotaManager$ThrottledRequestReaper" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.380Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "message": "[2017-08-04 10:48:20,800] INFO [ThrottledRequestReaper-Fetch]: Starting (kafka.server.ClientQuotaManager$ThrottledRequestReaper)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:20.800Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843700800 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "qotR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:20.748Z", + "offset": 1438, + "kafka": { + "log": { + "component": "unknown", + "level": "WARN", + "message": "No meta.properties file under dir /tmp/kafka-logs/meta.properties", + "class": "kafka.server.BrokerMetadataCheckpoint" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.380Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "message": "[2017-08-04 10:48:20,748] WARN No meta.properties file under dir /tmp/kafka-logs/meta.properties (kafka.server.BrokerMetadataCheckpoint)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:20.748Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843700748 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "qYtR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:20.458Z", + "offset": 1301, + "kafka": { + "log": { + "component": "unknown", + "level": "INFO", + "message": "zookeeper state changed (SyncConnected)", + "class": "org.I0Itec.zkclient.ZkClient" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.379Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "fileset": { + "module": "kafka", + "name": "log" + }, + "message": "[2017-08-04 10:48:20,458] INFO zookeeper state changed (SyncConnected) (org.I0Itec.zkclient.ZkClient)" + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:20.458Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843700458 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "qItR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:20.457Z", + "offset": 1199, + "kafka": { + "log": { + "component": "unknown", + "level": "INFO", + "message": "Session establishment complete on server localhost/0:0:0:0:0:0:0:1:2181, sessionid = 0x15dabf8d4140000, negotiated timeout = 6000", + "class": "org.apache.zookeeper.ClientCnxn" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.379Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "message": "[2017-08-04 10:48:20,457] INFO Session establishment complete on server localhost/0:0:0:0:0:0:0:1:2181, sessionid = 0x15dabf8d4140000, negotiated timeout = 6000 (org.apache.zookeeper.ClientCnxn)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:20.457Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843700457 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "p4tR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:20.420Z", + "offset": 1004, + "kafka": { + "log": { + "component": "unknown", + "level": "INFO", + "message": "Socket connection established to localhost/0:0:0:0:0:0:0:1:2181, initiating session", + "class": "org.apache.zookeeper.ClientCnxn" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.379Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "message": "[2017-08-04 10:48:20,420] INFO Socket connection established to localhost/0:0:0:0:0:0:0:1:2181, initiating session (org.apache.zookeeper.ClientCnxn)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:20.420Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843700420 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "potR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:20.415Z", + "offset": 855, + "kafka": { + "log": { + "component": "unknown", + "level": "INFO", + "message": "Opening socket connection to server localhost/0:0:0:0:0:0:0:1:2181. Will not attempt to authenticate using SASL (unknown error)", + "class": "org.apache.zookeeper.ClientCnxn" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.379Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "message": "[2017-08-04 10:48:20,415] INFO Opening socket connection to server localhost/0:0:0:0:0:0:0:1:2181. Will not attempt to authenticate using SASL (unknown error) (org.apache.zookeeper.ClientCnxn)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:20.415Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843700415 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "pYtR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:20.413Z", + "offset": 662, + "kafka": { + "log": { + "component": "unknown", + "level": "INFO", + "message": "Waiting for keeper state SyncConnected", + "class": "org.I0Itec.zkclient.ZkClient" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.378Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "message": "[2017-08-04 10:48:20,413] INFO Waiting for keeper state SyncConnected (org.I0Itec.zkclient.ZkClient)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:20.413Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843700413 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "pItR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:20.401Z", + "offset": 561, + "kafka": { + "log": { + "component": "unknown", + "level": "INFO", + "message": "Initiating client connection, connectString=localhost:2181 sessionTimeout=6000 watcher=org.I0Itec.zkclient.ZkClient@5ffead27", + "class": "org.apache.zookeeper.ZooKeeper" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.378Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "message": "[2017-08-04 10:48:20,401] INFO Initiating client connection, connectString=localhost:2181 sessionTimeout=6000 watcher=org.I0Itec.zkclient.ZkClient@5ffead27 (org.apache.zookeeper.ZooKeeper)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:20.401Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843700401 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "o4tR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:20.400Z", + "offset": 372, + "kafka": { + "log": { + "component": "unknown", + "level": "INFO", + "message": "Client environment:java.compiler=", + "class": "org.apache.zookeeper.ZooKeeper" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.359Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "message": "[2017-08-04 10:48:20,400] INFO Client environment:java.compiler= (org.apache.zookeeper.ZooKeeper)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:20.400Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843700400 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "ootR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:20.400Z", + "offset": 270, + "kafka": { + "log": { + "component": "unknown", + "level": "INFO", + "message": "Client environment:java.io.tmpdir=/tmp", + "class": "org.apache.zookeeper.ZooKeeper" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.359Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "message": "[2017-08-04 10:48:20,400] INFO Client environment:java.io.tmpdir=/tmp (org.apache.zookeeper.ZooKeeper)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:20.400Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843700400 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "oYtR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:20.379Z", + "offset": 167, + "kafka": { + "log": { + "component": "unknown", + "level": "INFO", + "message": "Connecting to zookeeper on localhost:2181", + "class": "kafka.server.KafkaServer" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.359Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "message": "[2017-08-04 10:48:20,379] INFO Connecting to zookeeper on localhost:2181 (kafka.server.KafkaServer)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:20.379Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843700379 + ] + }, + + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "oItR0l0Bed9fOYVUfeyz", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:20.377Z", + "offset": 67, + "kafka": { + "log": { + "component": "unknown", + "level": "INFO", + "message": "starting", + "class": "kafka.server.KafkaServer" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.359Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log", + "fileset": { + "module": "kafka", + "name": "log" + }, + "message": "[2017-08-04 10:48:20,377] INFO starting (kafka.server.KafkaServer)" + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:20.377Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/server.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843700377 + ] + } +] diff --git a/filebeat/module/kafka/log/test/state-change.log b/filebeat/module/kafka/log/test/state-change.log new file mode 100644 index 00000000000..675a51dff72 --- /dev/null +++ b/filebeat/module/kafka/log/test/state-change.log @@ -0,0 +1 @@ +[2017-08-04 10:48:21,428] TRACE Controller 0 epoch 1 received response {error_code=0} for a request sent to broker baldur:9092 (id: 0 rack: null) (state.change.logger) diff --git a/filebeat/module/kafka/log/test/state-change.log-expected.json b/filebeat/module/kafka/log/test/state-change.log-expected.json new file mode 100644 index 00000000000..9d02b4d8869 --- /dev/null +++ b/filebeat/module/kafka/log/test/state-change.log-expected.json @@ -0,0 +1,49 @@ +[ + { + "_index": "filebeat-7.0.0-alpha1-2017.08.11", + "_type": "doc", + "_id": "v4tR0l0Bed9fOYVUjey6", + "_version": 1, + "_score": null, + "_source": { + "@timestamp": "2017-08-04T10:48:21.428Z", + "offset": 168, + "kafka": { + "log": { + "component": "unknown", + "level": "TRACE", + "message": "Controller 0 epoch 1 received response {error_code=0} for a request sent to broker baldur:9092 (id: 0 rack: null)", + "class": "state.change.logger" + } + }, + "beat": { + "hostname": "baldur", + "read_time": "2017-08-11T17:22:21.359Z", + "name": "baldur", + "version": "7.0.0-alpha1" + }, + "prospector": { + "type": "log" + }, + "source": "/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/state-change.log", + "message": "[2017-08-04 10:48:21,428] TRACE Controller 0 epoch 1 received response {error_code=0} for a request sent to broker baldur:9092 (id: 0 rack: null) (state.change.logger)", + "fileset": { + "module": "kafka", + "name": "log" + } + }, + "fields": { + "@timestamp": [ + "2017-08-04T10:48:21.428Z" + ] + }, + "highlight": { + "source": [ + "@kibana-highlighted-field@/home/n/go/src/github.com/elastic/beats/filebeat/module/kafka/log/test/state-change.log@/kibana-highlighted-field@" + ] + }, + "sort": [ + 1501843701428 + ] + } +] diff --git a/filebeat/modules.d/kafka.yml.disabled b/filebeat/modules.d/kafka.yml.disabled new file mode 100644 index 00000000000..fe568e8e562 --- /dev/null +++ b/filebeat/modules.d/kafka.yml.disabled @@ -0,0 +1,13 @@ +- module: kafka + # All logs + log: + enabled: true + + # Set custom paths for Kafka. If left empty, + # Filebeat will look under /opt. + #var.kafka_home: + + # Set custom paths for the log files. If left empty, + # Filebeat will choose the paths depending on your OS. + #var.paths: + From aa54a220e416bfe793641b607c5d50e91a29fcb0 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Wed, 16 Aug 2017 09:33:37 -0400 Subject: [PATCH 086/139] Add filesystem.ignore_types to ignore filesystem types (#4823) (#4906) * Add filesystem.ignore_types to ignore filesystem types Add `filesystem.ignore_types` to the system module for ignoring filesystems in the `filesystem` and `fsstat` metricsets. The new configuration option accepts a list of filesystem types. metricbeat.modules: - module: system metricsets: [filesystem, fsstat] filesystem.ignore_types: [nfs, smbfs, proc, cgroups] Closes #4685 (cherry picked from commit 70caf0e4d67fe7104b471c7b1f4630b7d5aa58a4) --- CHANGELOG.asciidoc | 1 + metricbeat/metricbeat.reference.yml | 5 +++ .../module/system/_meta/config.reference.yml | 5 +++ .../system/filesystem/_meta/docs.asciidoc | 28 ++++++++++++--- .../module/system/filesystem/filesystem.go | 11 ++++++ metricbeat/module/system/filesystem/helper.go | 36 +++++++++++++++++++ .../module/system/filesystem/helper_test.go | 17 +++++++++ .../module/system/fsstat/_meta/docs.asciidoc | 7 ++++ metricbeat/module/system/fsstat/fsstat.go | 11 ++++++ 9 files changed, 117 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 0e360ce32a4..593d0cc9ec5 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -87,6 +87,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Add http server metricset to support push metrics via http. {pull}4770[4770] - Make config object public for graphite and http server {pull}4820[4820] - Add system uptime metricset. {issue}[4848[4848] +- Add `filesystem.ignore_types` to system module for ignoring filesystem types. {issue}4685[4685] *Packetbeat* diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index fbce46e53dc..482c60539c0 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -52,6 +52,11 @@ metricbeat.modules: cpu.metrics: ["percentages"] # The other available options are normalized_percentages and ticks. core.metrics: ["percentages"] # The other available option is ticks. + # A list of filesystem types to ignore. The filesystem metricset will not + # collect data from filesystems matching any of the specified types, and + # fsstats will not include data from these filesystems in its summary stats. + #filesystem.ignore_types: [] + # These options allow you to filter out all processes that are not # in the top N by CPU or memory, in order to reduce the number of documents created. # If both the `by_cpu` and `by_memory` options are used, the union of the two sets diff --git a/metricbeat/module/system/_meta/config.reference.yml b/metricbeat/module/system/_meta/config.reference.yml index 37df6615d08..17dedccbe4c 100644 --- a/metricbeat/module/system/_meta/config.reference.yml +++ b/metricbeat/module/system/_meta/config.reference.yml @@ -20,6 +20,11 @@ cpu.metrics: ["percentages"] # The other available options are normalized_percentages and ticks. core.metrics: ["percentages"] # The other available option is ticks. + # A list of filesystem types to ignore. The filesystem metricset will not + # collect data from filesystems matching any of the specified types, and + # fsstats will not include data from these filesystems in its summary stats. + #filesystem.ignore_types: [] + # These options allow you to filter out all processes that are not # in the top N by CPU or memory, in order to reduce the number of documents created. # If both the `by_cpu` and `by_memory` options are used, the union of the two sets diff --git a/metricbeat/module/system/filesystem/_meta/docs.asciidoc b/metricbeat/module/system/filesystem/_meta/docs.asciidoc index d517e58ca11..d62584e466a 100644 --- a/metricbeat/module/system/filesystem/_meta/docs.asciidoc +++ b/metricbeat/module/system/filesystem/_meta/docs.asciidoc @@ -11,15 +11,35 @@ This metricset is available on: - OpenBSD - Windows +[float] +=== Configuration + +*`filesystem.ignore_types`* - A list of filesystem types to ignore. Metrics will +not be collected from filesystems matching these types. This setting also +affects the `fsstats` metricset. + [float] === Filtering Often there are mounted filesystems that you do not want Metricbeat to report -metrics on. A simple strategy to deal with these filesystems is to configure a -drop_event filter that matches the `mount_point` or `type` using a regular -expression. +metrics on. One option is to configure Metricbeat to ignore specific filesystem +types. This can be accomplished by configuring `filesystem.ignore_types` with +a list of filesystem types to ignore. In this example we are ignoring three +types of filesystems. + +[source,yaml] +---- +metricbeat.modules: + - module: system + period: 30s + metricsets: ["filesystem"] + filesystem.ignore_types: [nfs, smbfs, autofs] +---- -Below is an example. +Another strategy to deal with these filesystems is to configure a `drop_event` +filter that matches the `mount_point` using a regular expression. This type of +filtering occurs after the data has been collected so it can be less efficient +than the previous method. [source,yaml] ---- diff --git a/metricbeat/module/system/filesystem/filesystem.go b/metricbeat/module/system/filesystem/filesystem.go index 24426db8bb1..7bf133be8ab 100644 --- a/metricbeat/module/system/filesystem/filesystem.go +++ b/metricbeat/module/system/filesystem/filesystem.go @@ -22,12 +22,19 @@ func init() { // MetricSet for fetching filesystem metrics. type MetricSet struct { mb.BaseMetricSet + config Config } // New creates and returns a new instance of MetricSet. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + var config Config + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + return &MetricSet{ BaseMetricSet: base, + config: config, }, nil } @@ -39,6 +46,10 @@ func (m *MetricSet) Fetch() ([]common.MapStr, error) { return nil, errors.Wrap(err, "filesystem list") } + if len(m.config.IgnoreTypes) > 0 { + fss = Filter(fss, BuildTypeFilter(m.config.IgnoreTypes...)) + } + filesSystems := make([]common.MapStr, 0, len(fss)) for _, fs := range fss { fsStat, err := GetFileSystemStat(fs) diff --git a/metricbeat/module/system/filesystem/helper.go b/metricbeat/module/system/filesystem/helper.go index f5471f5df26..7f272e37373 100644 --- a/metricbeat/module/system/filesystem/helper.go +++ b/metricbeat/module/system/filesystem/helper.go @@ -13,6 +13,10 @@ import ( sigar "github.com/elastic/gosigar" ) +type Config struct { + IgnoreTypes []string `config:"filesystem.ignore_types"` +} + type FileSystemStat struct { sigar.FileSystemUsage DevName string `json:"device_name"` @@ -91,3 +95,35 @@ func GetFilesystemEvent(fsStat *FileSystemStat) common.MapStr { }, } } + +// Predicate is a function predicate for use with filesystems. It returns true +// if the argument matches the predicate. +type Predicate func(*sigar.FileSystem) bool + +// Filter returns a filtered list of filesystems. The in parameter +// is used as the backing storage for the returned slice and is therefore +// modified in this operation. +func Filter(in []sigar.FileSystem, p Predicate) []sigar.FileSystem { + out := in[:0] + for _, fs := range in { + if p(&fs) { + out = append(out, fs) + } + } + return out +} + +// BuildTypeFilter returns a predicate that returns false if the given +// filesystem has a type that matches one of the ignoreType values. +func BuildTypeFilter(ignoreType ...string) Predicate { + return func(fs *sigar.FileSystem) bool { + for _, fsType := range ignoreType { + // XXX (andrewkroh): SysTypeName appears to be used for non-Windows + // and TypeName is used exclusively for Windows. + if fs.SysTypeName == fsType || fs.TypeName == fsType { + return false + } + } + return true + } +} diff --git a/metricbeat/module/system/filesystem/helper_test.go b/metricbeat/module/system/filesystem/helper_test.go index c0e101b8c7a..6cc8805c77a 100644 --- a/metricbeat/module/system/filesystem/helper_test.go +++ b/metricbeat/module/system/filesystem/helper_test.go @@ -9,6 +9,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + + sigar "github.com/elastic/gosigar" ) func TestFileSystemList(t *testing.T) { @@ -44,3 +46,18 @@ func TestFileSystemList(t *testing.T) { } } } + +func TestFilter(t *testing.T) { + in := []sigar.FileSystem{ + {SysTypeName: "nfs"}, + {SysTypeName: "ext4"}, + {SysTypeName: "proc"}, + {SysTypeName: "smb"}, + } + + out := Filter(in, BuildTypeFilter("nfs", "smb", "proc")) + + if assert.Len(t, out, 1) { + assert.Equal(t, "ext4", out[0].SysTypeName) + } +} diff --git a/metricbeat/module/system/fsstat/_meta/docs.asciidoc b/metricbeat/module/system/fsstat/_meta/docs.asciidoc index 2751f5fc630..1f2f104c2d4 100644 --- a/metricbeat/module/system/fsstat/_meta/docs.asciidoc +++ b/metricbeat/module/system/fsstat/_meta/docs.asciidoc @@ -9,3 +9,10 @@ This metricset is available on: - macOS - OpenBSD - Windows + +[float] +=== Configuration + +*`filesystem.ignore_types`* - A list of filesystem types to ignore. Metrics will +not be collected from filesystems matching these types. This setting also +affects the `filesystem` metricset. diff --git a/metricbeat/module/system/fsstat/fsstat.go b/metricbeat/module/system/fsstat/fsstat.go index 21eb4870e15..aec4069f3f5 100644 --- a/metricbeat/module/system/fsstat/fsstat.go +++ b/metricbeat/module/system/fsstat/fsstat.go @@ -23,12 +23,19 @@ func init() { // MetricSet for fetching a summary of filesystem stats. type MetricSet struct { mb.BaseMetricSet + config filesystem.Config } // New creates and returns a new instance of MetricSet. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + var config filesystem.Config + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + return &MetricSet{ BaseMetricSet: base, + config: config, }, nil } @@ -40,6 +47,10 @@ func (m *MetricSet) Fetch() (common.MapStr, error) { return nil, errors.Wrap(err, "filesystem list") } + if len(m.config.IgnoreTypes) > 0 { + fss = filesystem.Filter(fss, filesystem.BuildTypeFilter(m.config.IgnoreTypes...)) + } + // These values are optional and could also be calculated by Kibana var totalFiles, totalSize, totalSizeFree, totalSizeUsed uint64 dict := map[string]bool{} From 80869fa486938deb96baf27914d58dfe83ad3f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20P=C3=A9rez-Aradros=20Herce?= Date: Wed, 16 Aug 2017 22:20:10 +0200 Subject: [PATCH 087/139] Add support for init contianers in `add_kubernetes_metadata` (#4890) --- CHANGELOG.asciidoc | 1 + libbeat/libbeat.full.yml | 647 ------------------ .../add_kubernetes_metadata/indexing.go | 35 +- .../add_kubernetes_metadata/indexing_test.go | 29 +- .../add_kubernetes_metadata/podwatcher.go | 2 +- .../add_kubernetes_metadata/types.go | 13 +- 6 files changed, 54 insertions(+), 673 deletions(-) delete mode 100644 libbeat/libbeat.full.yml diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 593d0cc9ec5..e088076532a 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -37,6 +37,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Fix go plugins not loaded when beat starts {pull}4799[4799] - Eliminate deprecated _default_ mapping in 6.x {pull}4864[4864] - Register kubernetes `field_format` matcher and remove logger in `Encode` API {pull}4888[4888] +- Add support for `initContainers` in `add_kubernetes_metadata` processor. {issue}4825[4825] *Auditbeat* diff --git a/libbeat/libbeat.full.yml b/libbeat/libbeat.full.yml deleted file mode 100644 index 1e9023a8247..00000000000 --- a/libbeat/libbeat.full.yml +++ /dev/null @@ -1,647 +0,0 @@ - -#================================ General ====================================== - -# The name of the shipper that publishes the network data. It can be used to group -# all the transactions sent by a single shipper in the web interface. -# If this options is not defined, the hostname is used. -#name: - -# The tags of the shipper are included in their own field with each -# transaction published. Tags make it easy to group servers by different -# logical properties. -#tags: ["service-X", "web-tier"] - -# Optional fields that you can specify to add additional information to the -# output. Fields can be scalar values, arrays, dictionaries, or any nested -# combination of these. -#fields: -# env: staging - -# If this option is set to true, the custom fields are stored as top-level -# fields in the output document instead of being grouped under a fields -# sub-dictionary. Default is false. -#fields_under_root: false - -# Internal queue size for single events in processing pipeline -#queue_size: 1000 - -# The internal queue size for bulk events in the processing pipeline. -# Do not modify this value. -#bulk_queue_size: 0 - -# Sets the maximum number of CPUs that can be executing simultaneously. The -# default is the number of logical CPUs available in the system. -#max_procs: - -#================================ Processors =================================== - -# Processors are used to reduce the number of fields in the exported event or to -# enhance the event with external metadata. This section defines a list of -# processors that are applied one by one and the first one receives the initial -# event: -# -# event -> filter1 -> event1 -> filter2 ->event2 ... -# -# The supported processors are drop_fields, drop_event, include_fields, and -# add_cloud_metadata. -# -# For example, you can use the following processors to keep the fields that -# contain CPU load percentages, but remove the fields that contain CPU ticks -# values: -# -#processors: -#- include_fields: -# fields: ["cpu"] -#- drop_fields: -# fields: ["cpu.user", "cpu.system"] -# -# The following example drops the events that have the HTTP response code 200: -# -#processors: -#- drop_event: -# when: -# equals: -# http.code: 200 -# -# The following example enriches each event with metadata from the cloud -# provider about the host machine. It works on EC2, GCE, and DigitalOcean. -# -#processors: -#- add_cloud_metadata: -# -# The following example enriches each event with the local timezone. -# -#processors: -#- add_locale: -# - -#================================ Outputs ====================================== - -# Configure what outputs to use when sending the data collected by the beat. -# Multiple outputs may be used. - -#-------------------------- Elasticsearch output ------------------------------- -output.elasticsearch: - # Boolean flag to enable or disable the output module. - #enabled: true - - # Array of hosts to connect to. - # Scheme and port can be left out and will be set to the default (http and 9200) - # In case you specify and additional path, the scheme is required: http://localhost:9200/path - # IPv6 addresses should always be defined as: https://[2001:db8::1]:9200 - hosts: ["localhost:9200"] - - # Set gzip compression level. - #compression_level: 0 - - # Optional protocol and basic auth credentials. - #protocol: "https" - #username: "elastic" - #password: "changeme" - - # Dictionary of HTTP parameters to pass within the url with index operations. - #parameters: - #param1: value1 - #param2: value2 - - # Number of workers per Elasticsearch host. - #worker: 1 - - # Optional index name. The default is "libbeat" plus date - # and generates [libbeat-]YYYY.MM.DD keys. - #index: "libbeat-%{[beat.version]}-%{+yyyy.MM.dd}" - - # Optional ingest node pipeline. By default no pipeline will be used. - #pipeline: "" - - # Optional HTTP Path - #path: "/elasticsearch" - - # Custom HTTP headers to add to each request - #headers: - # X-My-Header: Contents of the header - - # Proxy server url - #proxy_url: http://proxy:3128 - - # The number of times a particular Elasticsearch index operation is attempted. If - # the indexing operation doesn't succeed after this many retries, the events are - # dropped. The default is 3. - #max_retries: 3 - - # The maximum number of events to bulk in a single Elasticsearch bulk API index request. - # The default is 50. - #bulk_max_size: 50 - - # Configure http request timeout before failing an request to Elasticsearch. - #timeout: 90 - - # The number of seconds to wait for new events between two bulk API index requests. - # If `bulk_max_size` is reached before this interval expires, addition bulk index - # requests are made. - #flush_interval: 1s - - # Use SSL settings for HTTPS. Default is true. - #ssl.enabled: true - - # Configure SSL verification mode. If `none` is configured, all server hosts - # and certificates will be accepted. In this mode, SSL based connections are - # susceptible to man-in-the-middle attacks. Use only for testing. Default is - # `full`. - #ssl.verification_mode: full - - # List of supported/valid TLS versions. By default all TLS versions 1.0 up to - # 1.2 are enabled. - #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] - - # SSL configuration. By default is off. - # List of root certificates for HTTPS server verifications - #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - - # Certificate for SSL client authentication - #ssl.certificate: "/etc/pki/client/cert.pem" - - # Client Certificate Key - #ssl.key: "/etc/pki/client/cert.key" - - # Optional passphrase for decrypting the Certificate Key. - #ssl.key_passphrase: '' - - # Configure cipher suites to be used for SSL connections - #ssl.cipher_suites: [] - - # Configure curve types for ECDHE based cipher suites - #ssl.curve_types: [] - - -#----------------------------- Logstash output --------------------------------- -#output.logstash: - # Boolean flag to enable or disable the output module. - #enabled: true - - # The Logstash hosts - #hosts: ["localhost:5044"] - - # Number of workers per Logstash host. - #worker: 1 - - # Set gzip compression level. - #compression_level: 3 - - # Optional load balance the events between the Logstash hosts - #loadbalance: true - - # Number of batches to be send asynchronously to logstash while processing - # new batches. - #pipelining: 0 - - # Optional index name. The default index name is set to name of the beat - # in all lowercase. - #index: 'libbeat' - - # SOCKS5 proxy server URL - #proxy_url: socks5://user:password@socks5-server:2233 - - # Resolve names locally when using a proxy server. Defaults to false. - #proxy_use_local_resolver: false - - # Enable SSL support. SSL is automatically enabled, if any SSL setting is set. - #ssl.enabled: true - - # Configure SSL verification mode. If `none` is configured, all server hosts - # and certificates will be accepted. In this mode, SSL based connections are - # susceptible to man-in-the-middle attacks. Use only for testing. Default is - # `full`. - #ssl.verification_mode: full - - # List of supported/valid TLS versions. By default all TLS versions 1.0 up to - # 1.2 are enabled. - #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] - - # Optional SSL configuration options. SSL is off by default. - # List of root certificates for HTTPS server verifications - #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - - # Certificate for SSL client authentication - #ssl.certificate: "/etc/pki/client/cert.pem" - - # Client Certificate Key - #ssl.key: "/etc/pki/client/cert.key" - - # Optional passphrase for decrypting the Certificate Key. - #ssl.key_passphrase: '' - - # Configure cipher suites to be used for SSL connections - #ssl.cipher_suites: [] - - # Configure curve types for ECDHE based cipher suites - #ssl.curve_types: [] - -#------------------------------- Kafka output ---------------------------------- -#output.kafka: - # Boolean flag to enable or disable the output module. - #enabled: true - - # The list of Kafka broker addresses from where to fetch the cluster metadata. - # The cluster metadata contain the actual Kafka brokers events are published - # to. - #hosts: ["localhost:9092"] - - # The Kafka topic used for produced events. The setting can be a format string - # using any event field. To set the topic from document type use `%{[type]}`. - #topic: beats - - # The Kafka event key setting. Use format string to create unique event key. - # By default no event key will be generated. - #key: '' - - # The Kafka event partitioning strategy. Default hashing strategy is `hash` - # using the `output.kafka.key` setting or randomly distributes events if - # `output.kafka.key` is not configured. - #partition.hash: - # If enabled, events will only be published to partitions with reachable - # leaders. Default is false. - #reachable_only: false - - # Configure alternative event field names used to compute the hash value. - # If empty `output.kafka.key` setting will be used. - # Default value is empty list. - #hash: [] - - # Authentication details. Password is required if username is set. - #username: '' - #password: '' - - # Kafka version libbeat is assumed to run against. Defaults to the oldest - # supported stable version (currently version 0.8.2.0) - #version: 0.8.2 - - # Metadata update configuration. Metadata do contain leader information - # deciding which broker to use when publishing. - #metadata: - # Max metadata request retry attempts when cluster is in middle of leader - # election. Defaults to 3 retries. - #retry.max: 3 - - # Waiting time between retries during leader elections. Default is 250ms. - #retry.backoff: 250ms - - # Refresh metadata interval. Defaults to every 10 minutes. - #refresh_frequency: 10m - - # The number of concurrent load-balanced Kafka output workers. - #worker: 1 - - # The number of times to retry publishing an event after a publishing failure. - # After the specified number of retries, the events are typically dropped. - # Some Beats, such as Filebeat, ignore the max_retries setting and retry until - # all events are published. Set max_retries to a value less than 0 to retry - # until all events are published. The default is 3. - #max_retries: 3 - - # The maximum number of events to bulk in a single Kafka request. The default - # is 2048. - #bulk_max_size: 2048 - - # The number of seconds to wait for responses from the Kafka brokers before - # timing out. The default is 30s. - #timeout: 30s - - # The maximum duration a broker will wait for number of required ACKs. The - # default is 10s. - #broker_timeout: 10s - - # The number of messages buffered for each Kafka broker. The default is 256. - #channel_buffer_size: 256 - - # The keep-alive period for an active network connection. If 0s, keep-alives - # are disabled. The default is 0 seconds. - #keep_alive: 0 - - # Sets the output compression codec. Must be one of none, snappy and gzip. The - # default is gzip. - #compression: gzip - - # The maximum permitted size of JSON-encoded messages. Bigger messages will be - # dropped. The default value is 1000000 (bytes). This value should be equal to - # or less than the broker's message.max.bytes. - #max_message_bytes: 1000000 - - # The ACK reliability level required from broker. 0=no response, 1=wait for - # local commit, -1=wait for all replicas to commit. The default is 1. Note: - # If set to 0, no ACKs are returned by Kafka. Messages might be lost silently - # on error. - #required_acks: 1 - - # The number of seconds to wait for new events between two producer API calls. - #flush_interval: 1s - - # The configurable ClientID used for logging, debugging, and auditing - # purposes. The default is "beats". - #client_id: beats - - # Enable SSL support. SSL is automatically enabled, if any SSL setting is set. - #ssl.enabled: true - - # Optional SSL configuration options. SSL is off by default. - # List of root certificates for HTTPS server verifications - #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - - # Configure SSL verification mode. If `none` is configured, all server hosts - # and certificates will be accepted. In this mode, SSL based connections are - # susceptible to man-in-the-middle attacks. Use only for testing. Default is - # `full`. - #ssl.verification_mode: full - - # List of supported/valid TLS versions. By default all TLS versions 1.0 up to - # 1.2 are enabled. - #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] - - # Certificate for SSL client authentication - #ssl.certificate: "/etc/pki/client/cert.pem" - - # Client Certificate Key - #ssl.key: "/etc/pki/client/cert.key" - - # Optional passphrase for decrypting the Certificate Key. - #ssl.key_passphrase: '' - - # Configure cipher suites to be used for SSL connections - #ssl.cipher_suites: [] - - # Configure curve types for ECDHE based cipher suites - #ssl.curve_types: [] - -#------------------------------- Redis output ---------------------------------- -#output.redis: - # Boolean flag to enable or disable the output module. - #enabled: true - - # The list of Redis servers to connect to. If load balancing is enabled, the - # events are distributed to the servers in the list. If one server becomes - # unreachable, the events are distributed to the reachable servers only. - #hosts: ["localhost:6379"] - - # The Redis port to use if hosts does not contain a port number. The default - # is 6379. - #port: 6379 - - # The name of the Redis list or channel the events are published to. The - # default is libbeat. - #key: libbeat - - # The password to authenticate with. The default is no authentication. - #password: - - # The Redis database number where the events are published. The default is 0. - #db: 0 - - # The Redis data type to use for publishing events. If the data type is list, - # the Redis RPUSH command is used. If the data type is channel, the Redis - # PUBLISH command is used. The default value is list. - #datatype: list - - # The number of workers to use for each host configured to publish events to - # Redis. Use this setting along with the loadbalance option. For example, if - # you have 2 hosts and 3 workers, in total 6 workers are started (3 for each - # host). - #worker: 1 - - # If set to true and multiple hosts or workers are configured, the output - # plugin load balances published events onto all Redis hosts. If set to false, - # the output plugin sends all events to only one host (determined at random) - # and will switch to another host if the currently selected one becomes - # unreachable. The default value is true. - #loadbalance: true - - # The Redis connection timeout in seconds. The default is 5 seconds. - #timeout: 5s - - # The number of times to retry publishing an event after a publishing failure. - # After the specified number of retries, the events are typically dropped. - # Some Beats, such as Filebeat, ignore the max_retries setting and retry until - # all events are published. Set max_retries to a value less than 0 to retry - # until all events are published. The default is 3. - #max_retries: 3 - - # The maximum number of events to bulk in a single Redis request or pipeline. - # The default is 2048. - #bulk_max_size: 2048 - - # The URL of the SOCKS5 proxy to use when connecting to the Redis servers. The - # value must be a URL with a scheme of socks5://. - #proxy_url: - - # This option determines whether Redis hostnames are resolved locally when - # using a proxy. The default value is false, which means that name resolution - # occurs on the proxy server. - #proxy_use_local_resolver: false - - # Enable SSL support. SSL is automatically enabled, if any SSL setting is set. - #ssl.enabled: true - - # Configure SSL verification mode. If `none` is configured, all server hosts - # and certificates will be accepted. In this mode, SSL based connections are - # susceptible to man-in-the-middle attacks. Use only for testing. Default is - # `full`. - #ssl.verification_mode: full - - # List of supported/valid TLS versions. By default all TLS versions 1.0 up to - # 1.2 are enabled. - #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] - - # Optional SSL configuration options. SSL is off by default. - # List of root certificates for HTTPS server verifications - #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - - # Certificate for SSL client authentication - #ssl.certificate: "/etc/pki/client/cert.pem" - - # Client Certificate Key - #ssl.key: "/etc/pki/client/cert.key" - - # Optional passphrase for decrypting the Certificate Key. - #ssl.key_passphrase: '' - - # Configure cipher suites to be used for SSL connections - #ssl.cipher_suites: [] - - # Configure curve types for ECDHE based cipher suites - #ssl.curve_types: [] - - -#------------------------------- File output ----------------------------------- -#output.file: - # Boolean flag to enable or disable the output module. - #enabled: true - - # Path to the directory where to save the generated files. The option is - # mandatory. - #path: "/tmp/libbeat" - - # Name of the generated files. The default is `libbeat` and it generates - # files: `libbeat`, `libbeat.1`, `libbeat.2`, etc. - #filename: libbeat - - # Maximum size in kilobytes of each file. When this size is reached, and on - # every libbeat restart, the files are rotated. The default value is 10240 - # kB. - #rotate_every_kb: 10000 - - # Maximum number of files under path. When this number of files is reached, - # the oldest file is deleted and the rest are shifted from last to first. The - # default is 7 files. - #number_of_files: 7 - - -#----------------------------- Console output --------------------------------- -#output.console: - # Boolean flag to enable or disable the output module. - #enabled: true - - # Pretty print json event - #pretty: false - -#================================= Paths ====================================== - -# The home path for the libbeat installation. This is the default base path -# for all other path settings and for miscellaneous files that come with the -# distribution (for example, the sample dashboards). -# If not set by a CLI flag or in the configuration file, the default for the -# home path is the location of the binary. -#path.home: - -# The configuration path for the libbeat installation. This is the default -# base path for configuration files, including the main YAML configuration file -# and the Elasticsearch template file. If not set by a CLI flag or in the -# configuration file, the default for the configuration path is the home path. -#path.config: ${path.home} - -# The data path for the libbeat installation. This is the default base path -# for all the files in which libbeat needs to store its data. If not set by a -# CLI flag or in the configuration file, the default for the data path is a data -# subdirectory inside the home path. -#path.data: ${path.home}/data - -# The logs path for a libbeat installation. This is the default location for -# the Beat's log files. If not set by a CLI flag or in the configuration file, -# the default for the logs path is a logs subdirectory inside the home path. -#path.logs: ${path.home}/logs - -#============================== Dashboards ===================================== -# These settings control loading the sample dashboards to the Kibana index. Loading -# the dashboards is disabled by default and can be enabled either by setting the -# options here, or by using the `-setup` CLI flag. -#setup.dashboards.enabled: false - -# The URL from where to download the dashboards archive. By default this URL -# has a value which is computed based on the Beat name and version. For released -# versions, this URL points to the dashboard archive on the artifacts.elastic.co -# website. -#setup.dashboards.url: - -# The directory from where to read the dashboards. It is used instead of the URL -# when it has a value. -#setup.dashboards.directory: - -# The file archive (zip file) from where to read the dashboards. It is used instead -# of the URL when it has a value. -#setup.dashboards.file: - -# If this option is enabled, the snapshot URL is used instead of the default URL. -#setup.dashboards.snapshot: false - -# The URL from where to download the snapshot version of the dashboards. By default -# this has a value which is computed based on the Beat name and version. -#setup.dashboards.snapshot_url - -# In case the archive contains the dashboards from multiple Beats, this lets you -# select which one to load. You can load all the dashboards in the archive by -# setting this to the empty string. -#setup.dashboards.beat: libbeat - -# The name of the Kibana index to use for setting the configuration. Default is ".kibana" -#setup.dashboards.kibana_index: .kibana - -# The Elasticsearch index name. This overwrites the index name defined in the -# dashboards and index pattern. Example: testbeat-* -#setup.dashboards.index: - -#============================== Template ===================================== - -# A template is used to set the mapping in Elasticsearch -# By default template loading is enabled and the template is loaded. -# These settings can be adjusted to load your own template or overwrite existing ones. - -# Set to false to disable template loading. -#setup.template.enabled: true - -# Template name. By default the template name is libbeat. -# The version of the beat will always be appended to the given name -# so the final name is libbeat-%{[beat.version]}. -#setup.template.name: "libbeat" - -# Path to fields.yml file to generate the template -#setup.template.fields: "${path.config}/fields.yml" - -# Overwrite existing template -#setup.template.overwrite: false - - -#================================ HTTP Endpoint ====================================== -# Each beat can expose internal data points through a http endpoint. For security -# reason the endpoint is disabled by default. This feature is currently in beta. - -# Defines if http endpoint is enabled -#http.enabled: false - -# Host to expose the http endpoint to. It is recommended to use only localhost. -#http.host: localhost - -# Port on which the http endpoint is exposed. Default is 5066 -#http.port: 5066 - -#================================ Logging ====================================== -# There are three options for the log output: syslog, file, stderr. -# Under Windows systems, the log files are per default sent to the file output, -# under all other system per default to syslog. - -# Sets log level. The default log level is info. -# Available log levels are: critical, error, warning, info, debug -#logging.level: info - -# Enable debug output for selected components. To enable all selectors use ["*"] -# Other available selectors are "beat", "publish", "service" -# Multiple selectors can be chained. -#logging.selectors: [ ] - -# Send all logging output to syslog. The default is false. -#logging.to_syslog: true - -# If enabled, libbeat periodically logs its internal metrics that have changed -# in the last period. For each metric that changed, the delta from the value at -# the beginning of the period is logged. Also, the total values for -# all non-zero internal metrics are logged on shutdown. The default is true. -#logging.metrics.enabled: true - -# The period after which to log the internal metrics. The default is 30s. -#logging.metrics.period: 30s - -# Logging to rotating files files. Set logging.to_files to false to disable logging to -# files. -logging.to_files: true -logging.files: - # Configure the path where the logs are written. The default is the logs directory - # under the home path (the binary location). - #path: /var/log/libbeat - - # The name of the files where the logs are written to. - #name: libbeat - - # Configure log file size limit. If limit is reached, log file will be - # automatically rotated - #rotateeverybytes: 10485760 # = 10MB - - # Number of rotated log files to keep. Oldest files will be deleted first. - #keepfiles: 7 - diff --git a/libbeat/processors/add_kubernetes_metadata/indexing.go b/libbeat/processors/add_kubernetes_metadata/indexing.go index 06ecce7ae42..ccb9c35d098 100644 --- a/libbeat/processors/add_kubernetes_metadata/indexing.go +++ b/libbeat/processors/add_kubernetes_metadata/indexing.go @@ -271,15 +271,19 @@ func NewContainerIndexer(_ common.Config, genMeta GenMeta) (Indexer, error) { func (c *ContainerIndexer) GetMetadata(pod *Pod) []MetadataIndex { commonMeta := c.genMeta.GenerateMetaData(pod) - containers := c.GetIndexes(pod) var metadata []MetadataIndex - for i := 0; i < len(containers); i++ { + for _, status := range append(pod.Status.ContainerStatuses, pod.Status.InitContainerStatuses...) { + cID := containerID(status) + if cID == "" { + continue + } + containerMeta := commonMeta.Clone() containerMeta["container"] = common.MapStr{ - "name": pod.Status.ContainerStatuses[i].Name, + "name": status.Name, } metadata = append(metadata, MetadataIndex{ - Index: containers[i], + Index: cID, Data: containerMeta, }) } @@ -289,18 +293,27 @@ func (c *ContainerIndexer) GetMetadata(pod *Pod) []MetadataIndex { func (c *ContainerIndexer) GetIndexes(pod *Pod) []string { var containers []string - for _, status := range pod.Status.ContainerStatuses { - cID := status.ContainerID - if cID != "" { - parts := strings.Split(cID, "//") - if len(parts) == 2 { - containers = append(containers, parts[1]) - } + for _, status := range append(pod.Status.ContainerStatuses, pod.Status.InitContainerStatuses...) { + cID := containerID(status) + if cID == "" { + continue } + containers = append(containers, cID) } return containers } +func containerID(status PodContainerStatus) string { + cID := status.ContainerID + if cID != "" { + parts := strings.Split(cID, "//") + if len(parts) == 2 { + return parts[1] + } + } + return "" +} + type FieldMatcher struct { MatchFields []string } diff --git a/libbeat/processors/add_kubernetes_metadata/indexing_test.go b/libbeat/processors/add_kubernetes_metadata/indexing_test.go index 9a36fc4868a..657d8c31e2a 100644 --- a/libbeat/processors/add_kubernetes_metadata/indexing_test.go +++ b/libbeat/processors/add_kubernetes_metadata/indexing_test.go @@ -60,6 +60,7 @@ func TestContainerIndexer(t *testing.T) { podName := "testpod" ns := "testns" container := "container" + initContainer := "initcontainer" pod := Pod{ Metadata: ObjectMeta{ @@ -70,7 +71,8 @@ func TestContainerIndexer(t *testing.T) { }, }, Status: PodStatus{ - ContainerStatuses: make([]PodContainerStatus, 0), + ContainerStatuses: make([]PodContainerStatus, 0), + InitContainerStatuses: make([]PodContainerStatus, 0), }, } @@ -88,27 +90,38 @@ func TestContainerIndexer(t *testing.T) { }, } - cid := "docker://abcde" - pod.Status.ContainerStatuses = []PodContainerStatus{ { Name: container, - ContainerID: cid, + ContainerID: "docker://abcde", }, } - expected["container"] = common.MapStr{ - "name": container, + pod.Status.InitContainerStatuses = []PodContainerStatus{ + { + Name: initContainer, + ContainerID: "docker://fghij", + }, } indexers = conIndexer.GetMetadata(&pod) - assert.Equal(t, len(indexers), 1) + assert.Equal(t, len(indexers), 2) assert.Equal(t, indexers[0].Index, "abcde") + assert.Equal(t, indexers[1].Index, "fghij") indices = conIndexer.GetIndexes(&pod) - assert.Equal(t, len(indices), 1) + assert.Equal(t, len(indices), 2) assert.Equal(t, indices[0], "abcde") + assert.Equal(t, indices[1], "fghij") + expected["container"] = common.MapStr{ + "name": container, + } assert.Equal(t, expected.String(), indexers[0].Data.String()) + + expected["container"] = common.MapStr{ + "name": initContainer, + } + assert.Equal(t, expected.String(), indexers[1].Data.String()) } func TestFieldMatcher(t *testing.T) { diff --git a/libbeat/processors/add_kubernetes_metadata/podwatcher.go b/libbeat/processors/add_kubernetes_metadata/podwatcher.go index bc25327efe8..2d0ef0e2fca 100644 --- a/libbeat/processors/add_kubernetes_metadata/podwatcher.go +++ b/libbeat/processors/add_kubernetes_metadata/podwatcher.go @@ -84,7 +84,7 @@ func (p *PodWatcher) watchPods() { if err != nil { //watch pod failures should be logged and gracefully failed over as metadata retrieval //should never stop. - logp.Err("kubernetes: Watching API eror %v", err) + logp.Err("kubernetes: Watching API error %v", err) time.Sleep(time.Second) continue } diff --git a/libbeat/processors/add_kubernetes_metadata/types.go b/libbeat/processors/add_kubernetes_metadata/types.go index d3bec7c7cfa..6337d2d5ea5 100644 --- a/libbeat/processors/add_kubernetes_metadata/types.go +++ b/libbeat/processors/add_kubernetes_metadata/types.go @@ -82,12 +82,13 @@ type PodContainerStatus struct { } type PodStatus struct { - Conditions []PodStatusCondition `json:"conditions"` - ContainerStatuses []PodContainerStatus `json:"containerStatuses"` - HostIP string `json:"hostIP"` - Phase string `json:"phase"` - PodIP string `json:"podIP"` - StartTime string `json:"startTime"` + Conditions []PodStatusCondition `json:"conditions"` + ContainerStatuses []PodContainerStatus `json:"containerStatuses"` + InitContainerStatuses []PodContainerStatus `json:"initContainerStatuses"` + HostIP string `json:"hostIP"` + Phase string `json:"phase"` + PodIP string `json:"podIP"` + StartTime string `json:"startTime"` } type Pod struct { From c8fc8171393474c6d942765d8b058ba7ba8cd623 Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Wed, 16 Aug 2017 23:36:05 +0200 Subject: [PATCH 088/139] Update latest testing environment to 6.0.0-beta1 (#4911) --- testing/environments/latest.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/testing/environments/latest.yml b/testing/environments/latest.yml index 65dffee4b84..854ba41654d 100644 --- a/testing/environments/latest.yml +++ b/testing/environments/latest.yml @@ -1,9 +1,9 @@ -# This is the latest stable release environment. +# This is the latest released environment. version: '2.1' services: elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:5.4.1 + image: docker.elastic.co/elasticsearch/elasticsearch:6.0.0-beta1 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9200"] environment: @@ -18,13 +18,13 @@ services: context: docker/logstash dockerfile: Dockerfile args: - ELASTIC_VERSION: 5.4.1 + ELASTIC_VERSION: 6.0.0-beta1 DOWNLOAD_URL: https://artifacts.elastic.co/downloads environment: - ES_HOST=elasticsearch kibana: - image: docker.elastic.co/kibana/kibana:5.4.1 + image: docker.elastic.co/kibana/kibana:6.0.0-beta1 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:5601"] retries: 6 From de1e51015505802fcc65fbaebb6a9a49fde1aa0f Mon Sep 17 00:00:00 2001 From: DeDe Morton Date: Mon, 14 Aug 2017 18:30:05 -0700 Subject: [PATCH 089/139] [Docs] Add module config reload docs --- filebeat/docs/reload-configuration.asciidoc | 89 +++++++++++++++++---- 1 file changed, 74 insertions(+), 15 deletions(-) diff --git a/filebeat/docs/reload-configuration.asciidoc b/filebeat/docs/reload-configuration.asciidoc index 4244910c22f..be624086941 100644 --- a/filebeat/docs/reload-configuration.asciidoc +++ b/filebeat/docs/reload-configuration.asciidoc @@ -3,34 +3,49 @@ beta[] -You can configure Filebeat to dynamically reload prospector configuration files -when there are changes. To do this, you specify a path -(https://golang.org/pkg/path/filepath/#Glob[Glob]) to watch for prospector -configuration changes. When the files found by the Glob change, new prospectors -are started/stopped according to changes in the configuration files. +You can configure Filebeat to dynamically reload configuration files when there +are changes. This feature is available for prospector and module configuration +files only. + +To configure this feature, you specify a path +(https://golang.org/pkg/path/filepath/#Glob[Glob]) to watch for configuration +changes. When the files found by the Glob change, new prospectors and/or +modules are started and stopped according to changes in the configuration files. This feature is especially useful in container environments where one container is used to tail logs for services running in other containers on the same host. -To enable dynamic config reloading, you specify the `path` and `reload` options -in the `filebeat.config.prospectors` section of the main `filebeat.yml` config -file. For example: +To enable dynamic config reloading, you specify the following options under +`filebeat.config.prospectors` (for prospector configs) or +`filebeat.config.modules` (for module configs): + +`path`:: A Glob that defines the files to check for changes. +`reload.enabled`:: When set to `true`, enables dynamic config reload. +`reload.period`:: Specifies how often the files are checked for changes. Do not +set the `period` to less than 1s because the modification time of files is often +stored in seconds. Setting the `period` to less than 1s will result in +unnecessary overhead. + +See <> and <> for examples. + + +[float] +[[reload-prospector-config]] +=== Prospector config + +For prospector configurations, you specify reload options in the +`filebeat.config.prospectors` section of the +{beatname_lc}.yml+ file. For +example: [source,yaml] ------------------------------------------------------------------------------ filebeat.config.prospectors: + enabled: true path: configs/*.yml reload.enabled: true reload.period: 10s ------------------------------------------------------------------------------ -`path`:: A Glob that defines the files to check for changes. -`reload.enabled`:: When set to `true`, enables dynamic config reload. -`reload.period`:: Specifies how often the files are checked for changes. Do not -set the `period` to less than 1s because the modification time of files is often -stored in seconds. Setting the `period` to less than 1s will result in -unnecessary overhead. - Each file found by the Glob must contain a list of one or more prospector definitions. For example: @@ -47,6 +62,50 @@ definitions. For example: scan_frequency: 5s ------------------------------------------------------------------------------ + WARNING: It is critical that two running prospectors DO NOT have overlapping file paths defined. If more than one prospector harvests the same file at the same time, it can lead to unexpected behaviour. + +[float] +[[reload-module-config]] +=== Module config + +For module configurations, you specify reload options in the +`filebeat.config.modules` section of the +{beatname_lc}.yml+ file. For example: + +[source,yaml] +------------------------------------------------------------------------------ +filebeat.config.modules: + enabled: true + path: configs/*.yml + reload.enabled: true + reload.period: 10s +------------------------------------------------------------------------------ + +TIP: If you are using the <> command to enable and +disable configurations, you can enable config reloading for the `modules.d` +directory by specifying `path: ${path.config}/modules.d/*.yml`. + +Each file found by the Glob must contain a list of one or more module +definitions. For example: + +//REVIEWERS: I got an error when I tried to have an empty line before the -module: mysql entry below. Shouldn't whitespace be allowed there? + +[source,yaml] +------------------------------------------------------------------------------ +- module: apache2 + access: + enabled: true + var.paths: [/var/log/apache2/access.log*] + error: + enabled: true + var.paths: [/var/log/apache2/error.log*] +- module: mysql + error: + enabled: true + var.paths: [/var/log/mysql/error.log*] + slowlog: + enabled: true + var.paths: [/var/log/mysql/mysql-slow.log*] +------------------------------------------------------------------------------ From 1039e28c728d8fab58841b1f5267ec875e11735f Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Thu, 17 Aug 2017 15:08:06 +0200 Subject: [PATCH 090/139] Beats testing guide (#4866) * Beats testing guide Add a first version of the beats testing guide. The devguide was not built by our doc build in the past. Several changes were made to the build_docs script so it can also be used for the devguide. * docs_build.sh was moved out of `libbeat/scripts` as it belongs more to the framework part and was moved under `script`.all * Add review feedback, fix build --- docs/devguide/contributing.asciidoc | 2 + docs/devguide/testing.asciidoc | 67 +++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 docs/devguide/testing.asciidoc diff --git a/docs/devguide/contributing.asciidoc b/docs/devguide/contributing.asciidoc index 592915cf743..56d5118eea3 100644 --- a/docs/devguide/contributing.asciidoc +++ b/docs/devguide/contributing.asciidoc @@ -112,6 +112,8 @@ Running the testsuite has the following requirements: * Docker >= {docker} * Docker-compose >= {docker-compose} +For more details check the <> guide. + [float] [[documentation]] diff --git a/docs/devguide/testing.asciidoc b/docs/devguide/testing.asciidoc new file mode 100644 index 00000000000..caa0a8f7d88 --- /dev/null +++ b/docs/devguide/testing.asciidoc @@ -0,0 +1,67 @@ +[[testing]] +=== Testing + +Beats has a various sets of tests. This guide should help to understand how the different test suites work, how they are used and new tests are added. + +In general there are two major test suites: + +* Tests written in Golang +* Tests written in Python + +The tests written in Golang use the https://golang.org/pkg/testing/[Golang Testing package]. The tests written in Python depend on http://nose.readthedocs.io/en/latest/[nosetests] and require a compiled and executable binary from the Golang code. The python test run a beat with a specific config and params and either check if the output is as expected or if the correct things show up in the logs. + +For both of the above test suites so called integration tests exists. Integration tests in Beats are tests which require an external system like Elasticsearch to test if the integration with this service works as expected. Beats provides in its testsuite docker containers and docker-compose files to start these environments but a developer can run the required services also locally. + +==== Running Golang Tests + +The golang tests can be executed in each Golang package by running `go test .`. This will execute all tests which don't don't require an external service to be running. To also run the Golang integration tests run `go test -tags=integration .`. It will require you to run the expected services on localhost. + +To run all non integration tests for a beat run `make unit`. This will execute all the tests which are not inside a `vendor` directory. If you want to have a coverage report for the tests which were run use `make unit-tests`. A coverage report will be generated under `build/coverage` directory. + +All Golang tests are in the same package as the tested code itself and have the postfix `_test` in the file name. Most of the tests are in the same package as the rest of the code. Some of the tests which should be sepearate from the rest of the code or should not use private variables go under `{packagename}_test`. + + +==== Running Python Tests + +The system tests require a testing binary to be available and the python environment to be set up. To create the testing binary run `make {beatname}.test`. This will create the test binary in the beat directory. To setup the testing environment `make python-env` can be run which will use `virtualenv` to load the dependencies. Then `nosetests` has to be run inside `tests/system`. + +To automate all these steps into one `make system-tests` can be run. This creates the binary, the environment and runs all tests which do not require and external service. + +For the tests which require an external service like Elasticsearch to be running use `INTEGRATION_TESTS=1 make system-tests`. This will assume the services are running on localhost. + +To run the tests without the services running locally, the command `make system-tests-environment` can be used. This will start up the required environment in docker and will run all tests including the testing binary inside the docker environment. + +All Python tests are under `tests/system` directory. + +==== Test commands + +This is a quick summary of the available test commands: + +* `unit`: Golang tests +* `unit-tests`: Golang tests with coverage reports +* `integration-tests`: Golang tests with services in local docker +* `integration-tests-environment`: Golang tests inside docker with service in docker +* `fast-system-tests`: Python tests +* `system-tests`: Python tests with coverage report +* `INTEGRATION_TESTS=1 system-tests`: Python tests with local services +* `system-tests-environment`: Python tests inside docker with service in docker +* `testsuite`: Complete test suite in docker environment is run +* `test`: Runs testsuite without environment + +There are two experimental test commands: + +* `benchmark-tests`: Running golang tests with `-bench` flag +* `load-tests`: Running system tests with `LOAD_TESTS=1` flag + + +==== Coverage report + +If the tests were run to create a test coverage, the coverage report files can be found under `build/docs`. To create a more human readable file out of the `.cov` file `make coverage-report` can be used. It creates a `.html` file for each report and a `full.html` as summary of all reports together in the directory `build/coverage`. + +==== Race detection + +All tests can be run with the Golang race detector enabled by setting the environment variable `RACE_DETECTOR=1`. This applies to tests in Golang and Python. For Python the test binary has to be recompile when the flag is changed. Having the race detection enabled will slow down the tests. + +==== Docker environment + +Running the tests inside the docker environment is useful to not have to setup all services locally. It has the disadvantage that also the binary is run inside the docker container and not on the local machine. From 3f50a041f5533c6d51ae591ab75b1de059c429ee Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Thu, 17 Aug 2017 20:17:34 +0200 Subject: [PATCH 091/139] Rename the beatname.sh script to beatname (#4933) This makes it a bit less weird when using the commands on Debian/Centos systems. --- CHANGELOG.asciidoc | 3 ++- dev-tools/packer/platforms/centos/run.sh.j2 | 2 +- dev-tools/packer/platforms/debian/run.sh.j2 | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index e088076532a..598bbaccdd4 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -16,6 +16,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - The log directory (`path.log`) for Windows services is now set to `C:\ProgramData\[beatname]\logs`. {issue}4764[4764] - Fail if removed setting output.X.flush_interval is explicitly configured. +- Rename the `/usr/bin/beatname.sh` script (e.g. `metricbeat.sh`) to `/usr/bin/beatname`. {pull}4933[4933] *Auditbeat* @@ -89,7 +90,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Make config object public for graphite and http server {pull}4820[4820] - Add system uptime metricset. {issue}[4848[4848] - Add `filesystem.ignore_types` to system module for ignoring filesystem types. {issue}4685[4685] - + *Packetbeat* *Winlogbeat* diff --git a/dev-tools/packer/platforms/centos/run.sh.j2 b/dev-tools/packer/platforms/centos/run.sh.j2 index 3ac232ce569..2077ae1d24f 100644 --- a/dev-tools/packer/platforms/centos/run.sh.j2 +++ b/dev-tools/packer/platforms/centos/run.sh.j2 @@ -33,7 +33,7 @@ FPM_ARGS=( --after-install /tmp/systemd-daemon-reload.sh --config-files /etc/{{.beat_name}}/{{.beat_name}}.yml homedir/=/usr/share/{{.beat_name}} - beatname-${RUNID}.sh=/usr/bin/{{.beat_name}}.sh + beatname-${RUNID}.sh=/usr/bin/{{.beat_name}} {{.beat_name}}-linux-{{.arch}}=/usr/share/{{.beat_name}}/bin/{{.beat_name}} {{.beat_name}}-linux.yml=/etc/{{.beat_name}}/{{.beat_name}}.yml {{.beat_name}}-linux.reference.yml=/etc/{{.beat_name}}/{{.beat_name}}.reference.yml diff --git a/dev-tools/packer/platforms/debian/run.sh.j2 b/dev-tools/packer/platforms/debian/run.sh.j2 index 11f88d0cc7b..46fdc0f86d0 100644 --- a/dev-tools/packer/platforms/debian/run.sh.j2 +++ b/dev-tools/packer/platforms/debian/run.sh.j2 @@ -30,7 +30,7 @@ FPM_ARGS=( --after-install /tmp/systemd-daemon-reload.sh --config-files /etc/{{.beat_name}}/{{.beat_name}}.yml homedir/=/usr/share/{{.beat_name}} - beatname-${RUNID}.sh=/usr/bin/{{.beat_name}}.sh + beatname-${RUNID}.sh=/usr/bin/{{.beat_name}} {{.beat_name}}-linux-{{.arch}}=/usr/share/{{.beat_name}}/bin/{{.beat_name}} {{.beat_name}}-linux.yml=/etc/{{.beat_name}}/{{.beat_name}}.yml {{.beat_name}}-linux.reference.yml=/etc/{{.beat_name}}/{{.beat_name}}.reference.yml From d424b1083e080e8e24dcd7becdfa7177daaa4a98 Mon Sep 17 00:00:00 2001 From: Max Jonas Werner Date: Thu, 17 Aug 2017 20:30:06 +0200 Subject: [PATCH 092/139] Add kafkabeat to community beats doc (#4935) --- libbeat/docs/communitybeats.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbeat/docs/communitybeats.asciidoc b/libbeat/docs/communitybeats.asciidoc index e977a9c441d..ae554ba814b 100644 --- a/libbeat/docs/communitybeats.asciidoc +++ b/libbeat/docs/communitybeats.asciidoc @@ -47,7 +47,7 @@ https://github.com/icinga/icingabeat[icingabeat]:: Icingabeat ships events and s https://github.com/devopsmakers/iobeat[iobeat]:: Reads IO stats from /proc/diskstats on Linux. https://github.com/radoondas/jmxproxybeat[jmxproxybeat]:: Reads Tomcat JMX metrics exposed over 'JMX Proxy Servlet' to HTTP. https://github.com/mheese/journalbeat[journalbeat]:: Used for log shipping from systemd/journald based Linux systems. -https://github.com/dearcode/kafkabeat[kafkabeat]:: read data from kafka with Consumer-groups. +https://github.com/justsocialapps/kafkabeat[kafkabeat]:: Reads data from Kafka topics. https://github.com/eskibars/lmsensorsbeat[lmsensorsbeat]:: Collects data from lm-sensors (such as CPU temperatures, fan speeds, and voltages from i2c and smbus). https://github.com/consulthys/logstashbeat[logstashbeat]:: Collects data from Logstash monitoring API (v5 onwards) and indexes them in Elasticsearch. https://github.com/yedamao/mcqbeat[mcqbeat]:: Reads the status of queues from memcacheq. From 04387ca7a577f2cdb6785ae03b3d021c287fe5fa Mon Sep 17 00:00:00 2001 From: DeDe Morton Date: Thu, 17 Aug 2017 16:56:17 -0700 Subject: [PATCH 093/139] [Docs] Add udp prospector to list of types --- filebeat/docs/filebeat-options.asciidoc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/filebeat/docs/filebeat-options.asciidoc b/filebeat/docs/filebeat-options.asciidoc index 8458096de10..7bfdcfd8bd2 100644 --- a/filebeat/docs/filebeat-options.asciidoc +++ b/filebeat/docs/filebeat-options.asciidoc @@ -32,9 +32,10 @@ filebeat.prospectors: One of the following input types: - * log: Reads every line of the log file (default) - * stdin: Reads the standard in - * redis: Reads slow log entries from redis (experimental) + * log: Reads every line of the log file (default). + * stdin: Reads the standard in. + * redis: Reads slow log entries from redis (experimental). + * udp: Reads events over UDP. Also see <>. The value that you specify here is used as the `type` for each event published to Logstash and Elasticsearch. @@ -492,3 +493,9 @@ by assigning a higher limit of harvesters. The `enabled` option can be used with each prospector to define if a prospector is enabled or not. By default, enabled is set to true. +[float] +[[max-message-size]] +==== `max_message_size` + +When used with `type: udp`, specifies the maximum size of the message received over UDP. The default is 10240. + From 7aefcb1cdac88a7bcbea36371b563a9c8e723105 Mon Sep 17 00:00:00 2001 From: DeDe Morton Date: Thu, 17 Aug 2017 17:38:40 -0700 Subject: [PATCH 094/139] [Docs] Adding missing review changes --- filebeat/docs/reload-configuration.asciidoc | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/filebeat/docs/reload-configuration.asciidoc b/filebeat/docs/reload-configuration.asciidoc index be624086941..00242b2cddd 100644 --- a/filebeat/docs/reload-configuration.asciidoc +++ b/filebeat/docs/reload-configuration.asciidoc @@ -78,20 +78,17 @@ For module configurations, you specify reload options in the ------------------------------------------------------------------------------ filebeat.config.modules: enabled: true - path: configs/*.yml + path: prospectors.d/*.yml <1> reload.enabled: true reload.period: 10s ------------------------------------------------------------------------------ - -TIP: If you are using the <> command to enable and -disable configurations, you can enable config reloading for the `modules.d` -directory by specifying `path: ${path.config}/modules.d/*.yml`. +<1> If you change the path setting to look for config changes in a different +directory, you will not be able to use the <> command +to enable and disable module configurations. Each file found by the Glob must contain a list of one or more module definitions. For example: -//REVIEWERS: I got an error when I tried to have an empty line before the -module: mysql entry below. Shouldn't whitespace be allowed there? - [source,yaml] ------------------------------------------------------------------------------ - module: apache2 @@ -101,11 +98,4 @@ definitions. For example: error: enabled: true var.paths: [/var/log/apache2/error.log*] -- module: mysql - error: - enabled: true - var.paths: [/var/log/mysql/error.log*] - slowlog: - enabled: true - var.paths: [/var/log/mysql/mysql-slow.log*] ------------------------------------------------------------------------------ From 33c08979481273ed0af431105bf2366a9f82debf Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Fri, 18 Aug 2017 13:09:43 +0200 Subject: [PATCH 095/139] Remove _all fields settings from the 5.x template (#4928) Part of #4901. The removal of the `norms: false` _all setting results in a storage increase of one byte per doc, but this smooths the upgrade experience. --- libbeat/template/template.go | 2 +- testing/environments/5x.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libbeat/template/template.go b/libbeat/template/template.go index 26233bd655b..1bdc1904e42 100644 --- a/libbeat/template/template.go +++ b/libbeat/template/template.go @@ -135,7 +135,7 @@ func (t *Template) generate(properties common.MapStr, dynamicTemplates []common. basicStructure.Put("template", t.GetName()+"-*") } - if t.esVersion.IsMajor(2) || t.esVersion.IsMajor(5) { + if t.esVersion.IsMajor(2) { basicStructure.Put("mappings._default_._all.norms.enabled", false) } diff --git a/testing/environments/5x.yml b/testing/environments/5x.yml index 27868c90079..a45c8382d8c 100644 --- a/testing/environments/5x.yml +++ b/testing/environments/5x.yml @@ -3,7 +3,7 @@ version: '2.1' services: elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:5.4.1 + image: docker.elastic.co/elasticsearch/elasticsearch:5.5.1 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9200"] environment: @@ -18,13 +18,13 @@ services: context: docker/logstash dockerfile: Dockerfile args: - ELASTIC_VERSION: 5.4.1 + ELASTIC_VERSION: 5.5.1 DOWNLOAD_URL: https://artifacts.elastic.co/downloads environment: - ES_HOST=elasticsearch kibana: - image: docker.elastic.co/kibana/kibana:5.4.1 + image: docker.elastic.co/kibana/kibana:5.5.1 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:5601"] retries: 6 From 654eafe90479e7e1eab03df3ed6c1639284029fe Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Fri, 18 Aug 2017 13:50:36 +0200 Subject: [PATCH 096/139] Let docs build fail if not index.asciidoc found (#4945) Currently if the index.asciidoc is not found, the doc build just carries on without an error. With this change in case the index file is missing, the doc build will fail. This should not be a problem as all beats have the index file. * Fix link to beats devguide --- Makefile | 2 +- script/build_docs.sh | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 4a63e5d63df..578d46609b1 100644 --- a/Makefile +++ b/Makefile @@ -95,7 +95,7 @@ beats-dashboards: .PHONY: docs docs: @$(foreach var,$(PROJECTS),BUILD_DIR=${BUILD_DIR} $(MAKE) -C $(var) docs || exit 1;) - sh ./script/build_docs.sh dev-guide github.com/elastic/beats/docs/dev-guide ${BUILD_DIR} + sh ./script/build_docs.sh dev-guide github.com/elastic/beats/docs/devguide ${BUILD_DIR} .PHONY: package package: update beats-dashboards diff --git a/script/build_docs.sh b/script/build_docs.sh index 9a77fa53608..b5e29fbdece 100755 --- a/script/build_docs.sh +++ b/script/build_docs.sh @@ -20,13 +20,14 @@ fi index="${GOPATH%%:*}/src/${path}/index.asciidoc" -if [ -f "$index" ]; then - echo "Building docs for ${name}..." - dest_dir="$html_dir/${name}" - mkdir -p "$dest_dir" - params="" - if [ "$PREVIEW" = "1" ]; then - params="--chunk=1 -open chunk=1 -open" - fi - $docs_dir/build_docs.pl $params --doc "$index" -out "$dest_dir" +echo "Building docs for ${name}..." +echo "Index document: ${index}" + +dest_dir="$html_dir/${name}" +mkdir -p "$dest_dir" +params="" +if [ "$PREVIEW" = "1" ]; then + params="--chunk=1 -open chunk=1 -open" fi +$docs_dir/build_docs.pl $params --doc "$index" -out "$dest_dir" + From cb5e05dd10739e96d0c513ad3d760b4bc009bee8 Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Fri, 18 Aug 2017 13:54:27 +0200 Subject: [PATCH 097/139] Cleanup iostats field naming (#4900) * Cleanup iostats field naming Align naming with other metricsets. --- metricbeat/docs/fields.asciidoc | 20 ++++++---- .../module/system/diskio/_meta/fields.yml | 18 +++++---- metricbeat/module/system/diskio/diskio.go | 38 +++++++++++++------ metricbeat/tests/system/test_system.py | 4 +- 4 files changed, 51 insertions(+), 29 deletions(-) diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index cf12c65ebbc..8258d3dddd3 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -8773,7 +8773,7 @@ The total number of of milliseconds spent doing I/Os. [float] -=== `system.diskio.iostat.read_request_merged_per_sec` +=== `system.diskio.iostat.read.request.merges_per_sec` type: float @@ -8781,7 +8781,7 @@ The number of read requests merged per second that were queued to the device. [float] -=== `system.diskio.iostat.write_request_merged_per_sec` +=== `system.diskio.iostat.write.request.merges_per_sec` type: float @@ -8789,7 +8789,7 @@ The number of write requests merged per second that were queued to the device. [float] -=== `system.diskio.iostat.read_request_per_sec` +=== `system.diskio.iostat.read.request.per_sec` type: float @@ -8797,7 +8797,7 @@ The number of read requests that were issued to the device per second [float] -=== `system.diskio.iostat.write_request_per_sec` +=== `system.diskio.iostat.write.request.per_sec` type: float @@ -8805,23 +8805,27 @@ The number of write requests that were issued to the device per second [float] -=== `system.diskio.iostat.read_byte_per_sec` +=== `system.diskio.iostat.read.per_sec.bytes` type: float +format: bytes + The number of Bytes read from the device per second. [float] -=== `system.diskio.iostat.write_byte_per_sec` +=== `system.diskio.iostat.write.per_sec.bytes` type: float +format: bytes + The number of Bytes write from the device per second. [float] -=== `system.diskio.iostat.avg_request_size` +=== `system.diskio.iostat.request.avg_size` type: float @@ -8829,7 +8833,7 @@ The average size (in sectors) of the requests that were issued to the device. [float] -=== `system.diskio.iostat.avg_queue_size` +=== `system.diskio.iostat.queue.avg_size` type: float diff --git a/metricbeat/module/system/diskio/_meta/fields.yml b/metricbeat/module/system/diskio/_meta/fields.yml index 57f34696505..fa098d82e32 100644 --- a/metricbeat/module/system/diskio/_meta/fields.yml +++ b/metricbeat/module/system/diskio/_meta/fields.yml @@ -55,42 +55,44 @@ description: > The total number of of milliseconds spent doing I/Os. - - name: iostat.read_request_merged_per_sec + - name: iostat.read.request.merges_per_sec type: float description: > The number of read requests merged per second that were queued to the device. - - name: iostat.write_request_merged_per_sec + - name: iostat.write.request.merges_per_sec type: float description: > The number of write requests merged per second that were queued to the device. - - name: iostat.read_request_per_sec + - name: iostat.read.request.per_sec type: float description: > The number of read requests that were issued to the device per second - - name: iostat.write_request_per_sec + - name: iostat.write.request.per_sec type: float description: > The number of write requests that were issued to the device per second - - name: iostat.read_byte_per_sec + - name: iostat.read.per_sec.bytes type: float description: > The number of Bytes read from the device per second. + format: bytes - - name: iostat.write_byte_per_sec + - name: iostat.write.per_sec.bytes type: float description: > The number of Bytes write from the device per second. + format: bytes - - name: iostat.avg_request_size + - name: iostat.request.avg_size type: float description: > The average size (in sectors) of the requests that were issued to the device. - - name: iostat.avg_queue_size + - name: iostat.queue.avg_size type: float description: > The average queue length of the requests that were issued to the device. diff --git a/metricbeat/module/system/diskio/diskio.go b/metricbeat/module/system/diskio/diskio.go index 765a9ae4f8b..a0a8444dc8c 100644 --- a/metricbeat/module/system/diskio/diskio.go +++ b/metricbeat/module/system/diskio/diskio.go @@ -65,17 +65,33 @@ func (m *MetricSet) Fetch() ([]common.MapStr, error) { extraMetrics, err := m.statistics.CalIOStatistics(counters) if err == nil { event["iostat"] = common.MapStr{ - "read_request_merged_per_sec": extraMetrics.ReadRequestMergeCountPerSec, - "write_request_merged_per_sec": extraMetrics.WriteRequestMergeCountPerSec, - "read_request_per_sec": extraMetrics.ReadRequestCountPerSec, - "write_request_per_sec": extraMetrics.WriteRequestCountPerSec, - "read_byte_per_sec": extraMetrics.ReadBytesPerSec, - "write_byte_per_sec": extraMetrics.WriteBytesPerSec, - "avg_request_size": extraMetrics.AvgRequestSize, - "avg_queue_size": extraMetrics.AvgQueueSize, - "await": extraMetrics.AvgAwaitTime, - "service_time": extraMetrics.AvgServiceTime, - "busy": extraMetrics.BusyPct, + "read": common.MapStr{ + "request": common.MapStr{ + "merges_per_sec": extraMetrics.ReadRequestMergeCountPerSec, + "per_sec": extraMetrics.ReadRequestCountPerSec, + }, + "per_sec": common.MapStr{ + "bytes": extraMetrics.ReadBytesPerSec, + }, + }, + "write": common.MapStr{ + "request": common.MapStr{ + "merges_per_sec": extraMetrics.WriteRequestMergeCountPerSec, + "per_sec": extraMetrics.WriteRequestCountPerSec, + }, + "per_sec": common.MapStr{ + "bytes": extraMetrics.WriteBytesPerSec, + }, + }, + "queue": common.MapStr{ + "avg_size": extraMetrics.AvgQueueSize, + }, + "request": common.MapStr{ + "avg_size": extraMetrics.AvgRequestSize, + }, + "await": extraMetrics.AvgAwaitTime, + "service_time": extraMetrics.AvgServiceTime, + "busy": extraMetrics.BusyPct, } } diff --git a/metricbeat/tests/system/test_system.py b/metricbeat/tests/system/test_system.py index 582cc3078f5..10c4b046f04 100644 --- a/metricbeat/tests/system/test_system.py +++ b/metricbeat/tests/system/test_system.py @@ -29,8 +29,8 @@ SYSTEM_DISKIO_FIELDS_LINUX = ["name", "read.count", "write.count", "read.bytes", "write.bytes", "read.time", "write.time", "io.time", - "iostat.read_request_merged_per_sec", "iostat.write_request_merged_per_sec", "iostat.read_request_per_sec", "iostat.write_request_per_sec", "iostat.read_byte_per_sec", "iostat.write_byte_per_sec" - "iostat.avg_request_size", "iostat.avg_queue_size", "iostat.await", "iostat.service_time", "iostat.busy"] + "iostat.read.request.merges_per_sec", "iostat.write.request.merges_per_sec", "iostat.read.request.per_sec", "iostat.write.request.per_sec", "iostat.read.per_sec.bytes", "iostat.write.per_sec.bytes" + "iostat.request.avg_size", "iostat.queue.avg_size", "iostat.await", "iostat.service_time", "iostat.busy"] SYSTEM_FILESYSTEM_FIELDS = ["available", "device_name", "type", "files", "free", "free_files", "mount_point", "total", "used.bytes", From 4302f53aed46421ffc759f56b386beb647ae76d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Berfin=20Sar=C4=B1?= Date: Fri, 18 Aug 2017 17:26:32 +0300 Subject: [PATCH 098/139] Add etcdbeat to the community beats (#4915) --- libbeat/docs/communitybeats.asciidoc | 1 + 1 file changed, 1 insertion(+) diff --git a/libbeat/docs/communitybeats.asciidoc b/libbeat/docs/communitybeats.asciidoc index ae554ba814b..da6a31e8a7e 100644 --- a/libbeat/docs/communitybeats.asciidoc +++ b/libbeat/docs/communitybeats.asciidoc @@ -32,6 +32,7 @@ https://github.com/Pravoru/consulbeat[consulbeat]:: Reads services health checks https://github.com/Ingensi/dockbeat[dockbeat]:: Reads Docker container statistics and indexes them in Elasticsearch. https://github.com/radoondas/elasticbeat[elasticbeat]:: Reads status from an Elasticsearch cluster and indexes them in Elasticsearch. +https://github.com/gamegos/etcdbeat[etcdbeat]:: Reads stats from the Etcd v2 API and indexes them into Elasticsearch. https://github.com/christiangalsterer/execbeat[execbeat]:: Periodically executes shell commands and sends the standard output and standard error to Logstash or Elasticsearch. https://github.com/jarpy/factbeat[factbeat]:: Collects facts from https://puppetlabs.com/facter[Facter]. From d20e58a545cc000a3b8a28c85539df2c4ab8cc86 Mon Sep 17 00:00:00 2001 From: Vijay Samuel Date: Fri, 18 Aug 2017 11:05:30 -0700 Subject: [PATCH 099/139] Move TCP UDP start up into server.Start() (#4903) --- CHANGELOG.asciidoc | 1 + metricbeat/helper/server/http/http.go | 3 ++- metricbeat/helper/server/server.go | 2 +- metricbeat/helper/server/tcp/tcp.go | 25 ++++++++++++-------- metricbeat/helper/server/tcp/tcp_test.go | 14 +++++------ metricbeat/helper/server/udp/udp.go | 26 +++++++++++++-------- metricbeat/helper/server/udp/udp_test.go | 12 +++++----- metricbeat/module/graphite/server/server.go | 10 +++++++- 8 files changed, 57 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 598bbaccdd4..13a1373bbe3 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -69,6 +69,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Update init scripts to use the `test config` subcommand instead of the deprecated `-configtest` flag. {issue}4600[4600] - Get by default the credentials for connecting to Kibana from the Elasticsearch output configuration. {pull}4867[4867] +- Move TCP UDP start up into `server.Start()` {pull}4903[4903] *Auditbeat* diff --git a/metricbeat/helper/server/http/http.go b/metricbeat/helper/server/http/http.go index 9346d4e473b..e6aee784e9c 100644 --- a/metricbeat/helper/server/http/http.go +++ b/metricbeat/helper/server/http/http.go @@ -57,7 +57,7 @@ func NewHttpServer(mb mb.BaseMetricSet) (server.Server, error) { return h, nil } -func (h *HttpServer) Start() { +func (h *HttpServer) Start() error { go func() { logp.Info("Starting http server on %s", h.server.Addr) @@ -67,6 +67,7 @@ func (h *HttpServer) Start() { } }() + return nil } func (h *HttpServer) Stop() { diff --git a/metricbeat/helper/server/server.go b/metricbeat/helper/server/server.go index cac93797589..c10f560c5fc 100644 --- a/metricbeat/helper/server/server.go +++ b/metricbeat/helper/server/server.go @@ -11,7 +11,7 @@ const ( // Server is an interface that can be used to implement servers which can accept data. type Server interface { // Start is used to start the server at a well defined port. - Start() + Start() error // Stop the server. Stop() // Get a channel of events. diff --git a/metricbeat/helper/server/tcp/tcp.go b/metricbeat/helper/server/tcp/tcp.go index a2ea7819779..81431676282 100644 --- a/metricbeat/helper/server/tcp/tcp.go +++ b/metricbeat/helper/server/tcp/tcp.go @@ -4,6 +4,8 @@ import ( "fmt" "net" + "github.com/pkg/errors" + "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/metricbeat/helper/server" @@ -11,6 +13,7 @@ import ( ) type TcpServer struct { + tcpAddr *net.TCPAddr listener *net.TCPListener receiveBufferSize int done chan struct{} @@ -42,25 +45,27 @@ func NewTcpServer(base mb.BaseMetricSet) (server.Server, error) { return nil, err } - listener, err := net.ListenTCP("tcp", addr) - if err != nil { - return nil, err - } - - logp.Info("Started listening for TCP on: %s:%d", config.Host, config.Port) return &TcpServer{ - listener: listener, + tcpAddr: addr, receiveBufferSize: config.ReceiveBufferSize, done: make(chan struct{}), eventQueue: make(chan server.Event), }, nil } -func (g *TcpServer) Start() { - go g.WatchMetrics() +func (g *TcpServer) Start() error { + listener, err := net.ListenTCP("tcp", g.tcpAddr) + if err != nil { + return errors.Wrap(err, "failed to start TCP server") + } + g.listener = listener + logp.Info("Started listening for TCP on: %s", g.tcpAddr.String()) + + go g.watchMetrics() + return nil } -func (g *TcpServer) WatchMetrics() { +func (g *TcpServer) watchMetrics() { buffer := make([]byte, g.receiveBufferSize) for { select { diff --git a/metricbeat/helper/server/tcp/tcp_test.go b/metricbeat/helper/server/tcp/tcp_test.go index 6fd1a55c5a7..a57848e22c9 100644 --- a/metricbeat/helper/server/tcp/tcp_test.go +++ b/metricbeat/helper/server/tcp/tcp_test.go @@ -20,14 +20,9 @@ func GetTestTcpServer(host string, port int) (server.Server, error) { return nil, err } - listener, err := net.ListenTCP("tcp", addr) - if err != nil { - return nil, err - } - logp.Info("Started listening for TCP on: %s:%d", host, port) return &TcpServer{ - listener: listener, + tcpAddr: addr, receiveBufferSize: 1024, done: make(chan struct{}), eventQueue: make(chan server.Event), @@ -43,7 +38,12 @@ func TestTcpServer(t *testing.T) { t.FailNow() } - svc.Start() + err = svc.Start() + if err != nil { + t.Error(err) + t.FailNow() + } + defer svc.Stop() writeToServer(t, "test1", host, port) msg := <-svc.GetEvents() diff --git a/metricbeat/helper/server/udp/udp.go b/metricbeat/helper/server/udp/udp.go index fc476b70207..124e4b0a502 100644 --- a/metricbeat/helper/server/udp/udp.go +++ b/metricbeat/helper/server/udp/udp.go @@ -4,6 +4,8 @@ import ( "fmt" "net" + "github.com/pkg/errors" + "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/metricbeat/helper/server" @@ -11,6 +13,7 @@ import ( ) type UdpServer struct { + udpaddr *net.UDPAddr listener *net.UDPConn receiveBufferSize int done chan struct{} @@ -43,25 +46,28 @@ func NewUdpServer(base mb.BaseMetricSet) (server.Server, error) { return nil, err } - listener, err := net.ListenUDP("udp", addr) - if err != nil { - return nil, err - } - - logp.Info("Started listening for UDP on: %s:%d", config.Host, config.Port) return &UdpServer{ - listener: listener, + udpaddr: addr, receiveBufferSize: config.ReceiveBufferSize, done: make(chan struct{}), eventQueue: make(chan server.Event), }, nil } -func (g *UdpServer) Start() { - go g.WatchMetrics() +func (g *UdpServer) Start() error { + listener, err := net.ListenUDP("udp", g.udpaddr) + if err != nil { + return errors.Wrap(err, "failed to start UDP server") + } + + logp.Info("Started listening for UDP on: %s", g.udpaddr.String()) + g.listener = listener + + go g.watchMetrics() + return nil } -func (g *UdpServer) WatchMetrics() { +func (g *UdpServer) watchMetrics() { buffer := make([]byte, g.receiveBufferSize) for { select { diff --git a/metricbeat/helper/server/udp/udp_test.go b/metricbeat/helper/server/udp/udp_test.go index 737f88dd4e5..bb2c0a10c6e 100644 --- a/metricbeat/helper/server/udp/udp_test.go +++ b/metricbeat/helper/server/udp/udp_test.go @@ -20,14 +20,9 @@ func GetTestUdpServer(host string, port int) (server.Server, error) { return nil, err } - listener, err := net.ListenUDP("udp", addr) - if err != nil { - return nil, err - } - logp.Info("Started listening for UDP on: %s:%d", host, port) return &UdpServer{ - listener: listener, + udpaddr: addr, receiveBufferSize: 1024, done: make(chan struct{}), eventQueue: make(chan server.Event), @@ -44,6 +39,11 @@ func TestUdpServer(t *testing.T) { } svc.Start() + if err != nil { + t.Error(err) + t.FailNow() + } + defer svc.Stop() writeToServer(t, "test1", host, port) msg := <-svc.GetEvents() diff --git a/metricbeat/module/graphite/server/server.go b/metricbeat/module/graphite/server/server.go index fac1154b507..e06fb3140bb 100644 --- a/metricbeat/module/graphite/server/server.go +++ b/metricbeat/module/graphite/server/server.go @@ -1,7 +1,10 @@ package server import ( + "github.com/pkg/errors" + "github.com/elastic/beats/libbeat/common/cfgwarn" + "github.com/elastic/beats/libbeat/logp" serverhelper "github.com/elastic/beats/metricbeat/helper/server" "github.com/elastic/beats/metricbeat/helper/server/tcp" "github.com/elastic/beats/metricbeat/helper/server/udp" @@ -61,7 +64,12 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // Run method provides the Graphite server with a reporter with which events can be reported. func (m *MetricSet) Run(reporter mb.PushReporter) { // Start event watcher - m.server.Start() + if err := m.server.Start(); err != nil { + err = errors.Wrap(err, "failed to start graphite server") + logp.Err("%v", err) + reporter.Error(err) + return + } for { select { From aba48f81023ed5113d2009ab244445e2c962cd3f Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Sat, 19 Aug 2017 14:30:42 -0700 Subject: [PATCH 100/139] Fixes #4950 - Remove mar.local queries from dashboards (#4953) --- .../5.x/visualization/System-Navigation.json | 14 +++++++------- .../dashboard/Metricbeat-host-overview.json | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/metricbeat/module/system/_meta/kibana/5.x/visualization/System-Navigation.json b/metricbeat/module/system/_meta/kibana/5.x/visualization/System-Navigation.json index 80e59adb254..6f4add5ec0b 100644 --- a/metricbeat/module/system/_meta/kibana/5.x/visualization/System-Navigation.json +++ b/metricbeat/module/system/_meta/kibana/5.x/visualization/System-Navigation.json @@ -1,10 +1,10 @@ { - "visState": "{\"title\":\"System Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"| [System Overview](#/dashboard/Metricbeat-system-overview) | [Hosts Overview (requires Kibana > 5.4)](#/dashboard/d1f1f9e0-1b1c-11e7-b09e-037021c4f8df) | [Host Overview (requires Kibana > 5.4)](#/dashboard/79ffd6e0-faa0-11e6-947f-177f697178b8) | [Load/CPU](#/dashboard/Metricbeat-cpu) | [Memory](#/dashboard/Metricbeat-memory) | [Processes](#/dashboard/Metricbeat-processes) | [Network](#/dashboard/Metricbeat-network) | [Filesystem](#/dashboard/Metricbeat-filesystem) | [Filesystem per Host](#/dashboard/Metricbeat-filesystem-per-Host) | [CPU/Memory per container](#/dashboard/CPU-slash-Memory-per-container) |\"},\"aggs\":[],\"listeners\":{}}", - "description": "", - "title": "System Navigation", - "uiStateJSON": "{}", - "version": 1, + "visState": "{\"title\":\"System Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"| [System Overview](#/dashboard/Metricbeat-system-overview) | [Hosts Overview (requires Kibana > 5.4)](#/dashboard/d1f1f9e0-1b1c-11e7-b09e-037021c4f8df) | [Host Overview (requires Kibana > 5.4)](#/dashboard/79ffd6e0-faa0-11e6-947f-177f697178b8) | [Load/CPU](#/dashboard/Metricbeat-cpu) | [Memory](#/dashboard/Metricbeat-memory) | [Processes](#/dashboard/Metricbeat-processes) | [Network](#/dashboard/Metricbeat-network) | [Filesystem](#/dashboard/Metricbeat-filesystem) | [Filesystem per Host](#/dashboard/Metricbeat-filesystem-per-Host) | [CPU/Memory per container](#/dashboard/CPU-slash-Memory-per-container) |\"},\"aggs\":[],\"listeners\":{}}", + "description": "", + "title": "System Navigation", + "uiStateJSON": "{}", + "version": 1, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[{\"meta\":{\"index\":\"metricbeat-*\",\"key\":\"beat.name\",\"value\":\"mar.local\",\"disabled\":false,\"negate\":false,\"alias\":null},\"query\":{\"match\":{\"beat.name\":{\"query\":\"mar.local\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}]}" + "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" } -} \ No newline at end of file +} diff --git a/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-host-overview.json b/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-host-overview.json index 43c3fd48255..a5b115a8d79 100644 --- a/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-host-overview.json +++ b/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-host-overview.json @@ -350,7 +350,7 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"beat.hostname:\\\"mar.local\\\"\"}}}],\"highlightAll\":true,\"version\":true}" + "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"\"}}}],\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", "panelsJSON": "[{\"col\":1,\"id\":\"6b7b9a40-faa1-11e6-86b1-cd7735ff7e23\",\"panelIndex\":1,\"row\":12,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"4d546850-1b15-11e7-b09e-037021c4f8df\",\"panelIndex\":2,\"row\":6,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"089b85d0-1b16-11e7-b09e-037021c4f8df\",\"panelIndex\":3,\"row\":12,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"bfa5e400-1b16-11e7-b09e-037021c4f8df\",\"panelIndex\":4,\"row\":9,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"e0f001c0-1b18-11e7-b09e-037021c4f8df\",\"panelIndex\":5,\"row\":15,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"2e224660-1b19-11e7-b09e-037021c4f8df\",\"panelIndex\":6,\"row\":15,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"ab2d1e90-1b1a-11e7-b09e-037021c4f8df\",\"panelIndex\":7,\"row\":6,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"4e4bb1e0-1b1b-11e7-b09e-037021c4f8df\",\"panelIndex\":8,\"row\":9,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"26732e20-1b91-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":9,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"83e12df0-1b91-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":10,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":3,\"id\":\"d3166e80-1b91-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":11,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":7,\"id\":\"522ee670-1b92-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":12,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":9,\"id\":\"1aae9140-1b93-11e7-8ada-3df93aab833e\",\"panelIndex\":13,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":9,\"id\":\"34f97ee0-1b96-11e7-8ada-3df93aab833e\",\"panelIndex\":14,\"row\":4,\"size_x\":4,\"size_y\":2,\"type\":\"visualization\"},{\"col\":10,\"id\":\"aa984970-1e0b-11e7-852e-cdcfcfdffddd\",\"panelIndex\":15,\"row\":1,\"size_x\":3,\"size_y\":1,\"type\":\"visualization\"},{\"col\":1,\"id\":\"System-Navigation\",\"panelIndex\":16,\"row\":1,\"size_x\":9,\"size_y\":1,\"type\":\"visualization\"},{\"col\":1,\"id\":\"19e123b0-4d5a-11e7-aee5-fdc812cc3bec\",\"panelIndex\":21,\"row\":4,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":3,\"id\":\"d2e80340-4d5c-11e7-aa29-87a97a796de6\",\"panelIndex\":22,\"row\":4,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":7,\"id\":\"825fdb80-4d1d-11e7-b5f2-2b7c1895bf32\",\"panelIndex\":23,\"row\":4,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":11,\"id\":\"96976150-4d5d-11e7-aa29-87a97a796de6\",\"panelIndex\":25,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"99381c80-4d60-11e7-9a4c-ed99bbcaa42b\",\"panelIndex\":27,\"row\":18,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"c5e3cf90-4d60-11e7-9a4c-ed99bbcaa42b\",\"panelIndex\":28,\"row\":18,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"590a60f0-5d87-11e7-8884-1bb4c3b890e4\",\"panelIndex\":29,\"row\":4,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"}]", @@ -372,4 +372,4 @@ } ], "version": "6.0.0-alpha3-SNAPSHOT" -} \ No newline at end of file +} From 38262803c227a923f587ad0e4bac86942f3f1eb4 Mon Sep 17 00:00:00 2001 From: Steffen Siering Date: Mon, 21 Aug 2017 11:05:18 +0200 Subject: [PATCH 101/139] Fix flow timestamp update (#4955) --- CHANGELOG.asciidoc | 2 ++ packetbeat/flows/table.go | 5 ++++- packetbeat/tests/system/test_0060_flows.py | 9 +++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 13a1373bbe3..611e2ccf8ad 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -61,6 +61,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Packetbeat* +- Update flow timestamp on each packet being received. {issue}4895[4895] + *Winlogbeat* ==== Added diff --git a/packetbeat/flows/table.go b/packetbeat/flows/table.go index c8c1bc49724..5c5c411ccd2 100644 --- a/packetbeat/flows/table.go +++ b/packetbeat/flows/table.go @@ -58,6 +58,8 @@ func (t *flowMetaTable) get(id *FlowID, counter *counterReg) Flow { } func (t *flowTable) get(id *FlowID, counter *counterReg) Flow { + ts := time.Now() + t.mutex.Lock() defer t.mutex.Unlock() @@ -66,13 +68,14 @@ func (t *flowTable) get(id *FlowID, counter *counterReg) Flow { if bf == nil || !bf.isAlive() { debugf("create new flow") - bf = newBiFlow(id.rawFlowID.clone(), time.Now(), id.dir) + bf = newBiFlow(id.rawFlowID.clone(), ts, id.dir) t.table[string(bf.id.flowID)] = bf t.flows.append(bf) } else if bf.dir != id.dir { dir = flowDirReversed } + bf.ts = ts stats := bf.stats[dir] if stats == nil { stats = newFlowStats(counter) diff --git a/packetbeat/tests/system/test_0060_flows.py b/packetbeat/tests/system/test_0060_flows.py index 6a4463768cf..e6d23780f53 100644 --- a/packetbeat/tests/system/test_0060_flows.py +++ b/packetbeat/tests/system/test_0060_flows.py @@ -1,5 +1,6 @@ from packetbeat import (BaseTest, FLOWS_REQUIRED_FIELDS) from pprint import PrettyPrinter +from datetime import datetime import six @@ -11,6 +12,10 @@ def check_fields(flow, fields): assert flow[k] == v +def parse_timestamp(ts): + return datetime.strptime(ts, "%Y-%m-%dT%H:%M:%S.%fZ") + + class Test(BaseTest): def test_mysql_flow(self): @@ -43,6 +48,10 @@ def test_mysql_flow(self): 'dest.stats.net_bytes_total': 181133, }) + start_ts = parse_timestamp(objs[0]['start_time']) + last_ts = parse_timestamp(objs[0]['last_time']) + assert last_ts > start_ts + def test_memcache_udp_flow(self): self.render_config_template( flows=True, From 4dfc9a7c8a4c8e0b9362238e98af292d4a861317 Mon Sep 17 00:00:00 2001 From: Monica Sarbu Date: Mon, 21 Aug 2017 14:04:59 +0200 Subject: [PATCH 102/139] Add 5.x and 6.x rabbitmq dashboards (#4912) --- .../5.x/dashboard/Metricbeat-Rabbitmq.json | 13 +++ .../5.x/search/Metricbeat-Rabbitmq.json | 14 +++ .../Rabbitmq-Erlang-Process-Usage.json | 11 ++ .../visualization/Rabbitmq-Memory-Usage.json | 11 ++ .../Rabbitmq-Number-of-Nodes.json | 11 ++ .../Rabbitmq-Queue-Index-Operations.json | 11 ++ .../dashboard/Metricbeat-Rabbitmq.json | 107 ++++++++++++++++++ 7 files changed, 178 insertions(+) create mode 100644 metricbeat/module/rabbitmq/_meta/kibana/5.x/dashboard/Metricbeat-Rabbitmq.json create mode 100644 metricbeat/module/rabbitmq/_meta/kibana/5.x/search/Metricbeat-Rabbitmq.json create mode 100644 metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Erlang-Process-Usage.json create mode 100644 metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Memory-Usage.json create mode 100644 metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Number-of-Nodes.json create mode 100644 metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Queue-Index-Operations.json create mode 100644 metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-Rabbitmq.json diff --git a/metricbeat/module/rabbitmq/_meta/kibana/5.x/dashboard/Metricbeat-Rabbitmq.json b/metricbeat/module/rabbitmq/_meta/kibana/5.x/dashboard/Metricbeat-Rabbitmq.json new file mode 100644 index 00000000000..605a68d2cdb --- /dev/null +++ b/metricbeat/module/rabbitmq/_meta/kibana/5.x/dashboard/Metricbeat-Rabbitmq.json @@ -0,0 +1,13 @@ +{ + "hits": 0, + "timeRestore": false, + "description": "", + "title": "Metricbeat-Rabbitmq", + "uiStateJSON": "{}", + "panelsJSON": "[{\"col\":1,\"id\":\"RabbitMQ-Memory-Usage\",\"panelIndex\":8,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":8,\"id\":\"Rabbitmq-Number-of-Nodes\",\"panelIndex\":2,\"row\":1,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"RabbitMQ-Erlang-Process-Usage\",\"panelIndex\":10,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"RabbitMQ-Queue-Index-Operations\",\"panelIndex\":9,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"}]", + "optionsJSON": "{\"darkTheme\":false}", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + } +} diff --git a/metricbeat/module/rabbitmq/_meta/kibana/5.x/search/Metricbeat-Rabbitmq.json b/metricbeat/module/rabbitmq/_meta/kibana/5.x/search/Metricbeat-Rabbitmq.json new file mode 100644 index 00000000000..860ba3b584c --- /dev/null +++ b/metricbeat/module/rabbitmq/_meta/kibana/5.x/search/Metricbeat-Rabbitmq.json @@ -0,0 +1,14 @@ +{ + "title": "Metricbeat-Rabbitmq", + "description": "", + "hits": 0, + "sort": [ + "@timestamp", + "desc" + ], + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": + "{\"index\":\"metricbeat-*\",\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:rabbitmq\",\"analyze_wildcard\":true}}}" + } +} diff --git a/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Erlang-Process-Usage.json b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Erlang-Process-Usage.json new file mode 100644 index 00000000000..3468f394488 --- /dev/null +++ b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Erlang-Process-Usage.json @@ -0,0 +1,11 @@ +{ + "title": "RabbitMQ Erlang Process Usage", + "visState": "{\"title\":\"RabbitMQ Erlang Process Usage\",\"type\":\"line\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"legendPosition\":\"top\",\"radiusRatio\":9,\"scale\":\"linear\",\"setYExtents\":false,\"shareYAxis\":true,\"showCircles\":false,\"smoothLines\":true,\"times\":[],\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.proc.used\",\"customLabel\":\"Used Process\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"rabbitmq.node.name.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Node name\"}}],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "savedSearchId": "Metricbeat-Rabbitmq", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + } +} diff --git a/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Memory-Usage.json b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Memory-Usage.json new file mode 100644 index 00000000000..6dde99da1a8 --- /dev/null +++ b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Memory-Usage.json @@ -0,0 +1,11 @@ +{ + "title": "RabbitMQ Memory Usage", + "visState": "{\"title\":\"RabbitMQ Memory Usage\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"showCircles\":false,\"smoothLines\":true,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":true,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.mem.used.bytes\",\"json\":\"\",\"customLabel\":\"Used memory\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"rabbitmq.node.name.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Node name\"}}],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "savedSearchId": "Metricbeat-Rabbitmq", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + } +} diff --git a/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Number-of-Nodes.json b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Number-of-Nodes.json new file mode 100644 index 00000000000..960525ecd99 --- /dev/null +++ b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Number-of-Nodes.json @@ -0,0 +1,11 @@ +{ + "title": "RabbitMQ Number of Nodes", + "visState": "{\n \"title\": \"Rabbitmq-Number-of-Nodes\",\n \"type\": \"metric\",\n \"params\": {\n \"handleNoResults\": true,\n \"fontSize\": 60\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"rabbitmq.node.name.keyword\",\n \"customLabel\": \"RabbitMQ Nodes\"\n }\n }\n ],\n \"listeners\": {}\n}", + "uiStateJSON": "{}", + "description": "", + "savedSearchId": "Metricbeat-Rabbitmq", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\n \"filter\": []\n}" + } +} diff --git a/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Queue-Index-Operations.json b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Queue-Index-Operations.json new file mode 100644 index 00000000000..76094a228c3 --- /dev/null +++ b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Queue-Index-Operations.json @@ -0,0 +1,11 @@ +{ + "title": "RabbitMQ Queue Index Operations", + "visState": "{\"title\":\"RabbitMQ Queue Index Operations\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"showCircles\":false,\"smoothLines\":false,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.read.count\",\"customLabel\":\"Queue Index Read\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.journal_write.count\",\"customLabel\":\"Queue Index Jornal Write\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.write.count\",\"customLabel\":\"Queue Index Write\"}}],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "savedSearchId": "Metricbeat-Rabbitmq", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + } +} diff --git a/metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-Rabbitmq.json b/metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-Rabbitmq.json new file mode 100644 index 00000000000..8e90a1b563f --- /dev/null +++ b/metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-Rabbitmq.json @@ -0,0 +1,107 @@ +{ + "objects": [ + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "Metricbeat-Rabbitmq", + "title": "RabbitMQ Memory Usage", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"RabbitMQ Memory Usage\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"showCircles\":false,\"smoothLines\":true,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":true,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.mem.used.bytes\",\"json\":\"\",\"customLabel\":\"Used memory\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"rabbitmq.node.name.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Node name\"}}],\"listeners\":{}}" + }, + "col": 1, + "id": "RabbitMQ-Memory-Usage", + "panelIndex": 8, + "row": 1, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 9 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\n \"filter\": []\n}" + }, + "savedSearchId": "Metricbeat-Rabbitmq", + "title": "RabbitMQ Number of Nodes", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\n \"title\": \"Rabbitmq-Number-of-Nodes\",\n \"type\": \"metric\",\n \"params\": {\n \"handleNoResults\": true,\n \"fontSize\": 60\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"rabbitmq.node.name.keyword\",\n \"customLabel\": \"RabbitMQ Nodes\"\n }\n }\n ],\n \"listeners\": {}\n}" + }, + "col": 8, + "id": "Rabbitmq-Number-of-Nodes", + "panelIndex": 2, + "row": 1, + "size_x": 3, + "size_y": 3, + "type": "visualization", + "version": 7 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "Metricbeat-Rabbitmq", + "title": "RabbitMQ Erlang Process Usage", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"RabbitMQ Erlang Process Usage\",\"type\":\"line\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"legendPosition\":\"top\",\"radiusRatio\":9,\"scale\":\"linear\",\"setYExtents\":false,\"shareYAxis\":true,\"showCircles\":false,\"smoothLines\":true,\"times\":[],\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.proc.used\",\"customLabel\":\"Used Process\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"rabbitmq.node.name.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Node name\"}}],\"listeners\":{}}" + }, + "col": 1, + "id": "RabbitMQ-Erlang-Process-Usage", + "panelIndex": 10, + "row": 4, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 6 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "Metricbeat-Rabbitmq", + "title": "RabbitMQ Queue Index Operations", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"RabbitMQ Queue Index Operations\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"showCircles\":false,\"smoothLines\":false,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.read.count\",\"customLabel\":\"Queue Index Read\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.journal_write.count\",\"customLabel\":\"Queue Index Jornal Write\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.write.count\",\"customLabel\":\"Queue Index Write\"}}],\"listeners\":{}}" + }, + "col": 7, + "id": "RabbitMQ-Queue-Index-Operations", + "panelIndex": 9, + "row": 4, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 5 + }, + { + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:rabbitmq\",\"analyze_wildcard\":true}}}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "Metricbeat-Rabbitmq", + "version": 1 + }, + "id": "Metricbeat-Rabbitmq", + "type": "search", + "version": 26 + } + ], + "version": "5.6.0-SNAPSHOT" +} \ No newline at end of file From ec6d0770176a462850eaba8acb83e65f673aba97 Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Mon, 21 Aug 2017 22:21:16 +0200 Subject: [PATCH 103/139] Fix typo in generate_notice.py script comment (#4963) --- dev-tools/generate_notice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/generate_notice.py b/dev-tools/generate_notice.py index 19b985db9a4..f2c764d655a 100644 --- a/dev-tools/generate_notice.py +++ b/dev-tools/generate_notice.py @@ -112,7 +112,7 @@ def write_notice_file(f, beat, copyright, dependencies): # it's an Apache License, so include only the NOTICE file f.write("Apache License 2.0\n\n") - # Skipe NOTICE files not needed + # Skip NOTICE files which are not needed if os.path.join(os.path.dirname(lib["license_file"])) in SKIP_NOTICE: continue From 02a59a1bd1f4c74f16fc069acbacdc5da0afe0da Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Tue, 22 Aug 2017 00:53:06 +0200 Subject: [PATCH 104/139] Allow template pattern to be overwritten (#4769) With the current template loading is was not possible to overload the pattern used as name and pattern were mixed. For example in the case where someone wanted to define pattern name `a` that applies to the indice `a` this was not possible because the pattern generated was `a-*` so it didn't apply to the index `a`. This change now allows to set pattern and name separately. To make sure index pattern and templates are in sync, the beat will not start in case the index pattern was modified but the template patterns not. We should figure out later some automated mechanisms here. We should find a better solution for 6.x to require less config options and also include dashboard generation in this. --- CHANGELOG.asciidoc | 1 + auditbeat/auditbeat.reference.yml | 13 +++- filebeat/filebeat.reference.yml | 13 +++- filebeat/tests/system/config/filebeat.yml.j2 | 5 ++ .../system/config/filebeat_modules.yml.j2 | 3 + filebeat/tests/system/test_modules.py | 5 +- heartbeat/heartbeat.reference.yml | 13 +++- libbeat/_meta/config.reference.yml | 13 +++- libbeat/cmd/export/template.go | 2 +- libbeat/cmd/instance/beat.go | 21 +++++- libbeat/template/config.go | 1 + libbeat/template/load.go | 5 +- libbeat/template/load_integration_test.go | 11 ++- libbeat/template/template.go | 64 ++++++++++++++-- libbeat/tests/system/beat/beat.py | 8 +- libbeat/tests/system/config/mockbeat.yml.j2 | 3 +- libbeat/tests/system/test_template.py | 74 +++++++++++++++++++ metricbeat/metricbeat.reference.yml | 13 +++- packetbeat/packetbeat.reference.yml | 13 +++- winlogbeat/winlogbeat.reference.yml | 13 +++- 20 files changed, 244 insertions(+), 50 deletions(-) create mode 100644 libbeat/tests/system/test_template.py diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 611e2ccf8ad..f10062d1b9a 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -17,6 +17,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - The log directory (`path.log`) for Windows services is now set to `C:\ProgramData\[beatname]\logs`. {issue}4764[4764] - Fail if removed setting output.X.flush_interval is explicitly configured. - Rename the `/usr/bin/beatname.sh` script (e.g. `metricbeat.sh`) to `/usr/bin/beatname`. {pull}4933[4933] +- Beat does not start if elasticsearch index pattern was modified but not the template name and pattern. {issue}4769[4769] *Auditbeat* diff --git a/auditbeat/auditbeat.reference.yml b/auditbeat/auditbeat.reference.yml index 049ba139cac..45c92fecc4c 100644 --- a/auditbeat/auditbeat.reference.yml +++ b/auditbeat/auditbeat.reference.yml @@ -209,6 +209,7 @@ output.elasticsearch: # Optional index name. The default is "auditbeat" plus date # and generates [auditbeat-]YYYY.MM.DD keys. + # In case you modify this pattern you must update setup.template.name and setup.template.pattern accordingly. #index: "auditbeat-%{[beat.version]}-%{+yyyy.MM.dd}" # Optional ingest node pipeline. By default no pipeline will be used. @@ -666,10 +667,14 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Template name. By default the template name is auditbeat. -# The version of the beat will always be appended to the given name -# so the final name is auditbeat-%{[beat.version]}. -#setup.template.name: "auditbeat" +# Template name. By default the template name is "auditbeat-%{[beat.version]}" +# The template name and pattern has to be set in case the elasticsearch index pattern is modified. +#setup.template.name: "auditbeat-%{[beat.version]}" + +# Template patttern. By default the template patter is "-%{[beat.version]}-*" to apply to the default index settings. +# The first part is the version of the beat and then -* is used to match all daily indicies. +# The template name and pattern has to be set in case the elasticsearch index pattern is modified. +#setup.template.pattern: "auditbeat-%{[beat.version]}-*" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" diff --git a/filebeat/filebeat.reference.yml b/filebeat/filebeat.reference.yml index 058d4d88dee..a3df4633cd1 100644 --- a/filebeat/filebeat.reference.yml +++ b/filebeat/filebeat.reference.yml @@ -629,6 +629,7 @@ output.elasticsearch: # Optional index name. The default is "filebeat" plus date # and generates [filebeat-]YYYY.MM.DD keys. + # In case you modify this pattern you must update setup.template.name and setup.template.pattern accordingly. #index: "filebeat-%{[beat.version]}-%{+yyyy.MM.dd}" # Optional ingest node pipeline. By default no pipeline will be used. @@ -1086,10 +1087,14 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Template name. By default the template name is filebeat. -# The version of the beat will always be appended to the given name -# so the final name is filebeat-%{[beat.version]}. -#setup.template.name: "filebeat" +# Template name. By default the template name is "filebeat-%{[beat.version]}" +# The template name and pattern has to be set in case the elasticsearch index pattern is modified. +#setup.template.name: "filebeat-%{[beat.version]}" + +# Template patttern. By default the template patter is "-%{[beat.version]}-*" to apply to the default index settings. +# The first part is the version of the beat and then -* is used to match all daily indicies. +# The template name and pattern has to be set in case the elasticsearch index pattern is modified. +#setup.template.pattern: "filebeat-%{[beat.version]}-*" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" diff --git a/filebeat/tests/system/config/filebeat.yml.j2 b/filebeat/tests/system/config/filebeat.yml.j2 index bf61fd1c244..7ab3e3115e7 100644 --- a/filebeat/tests/system/config/filebeat.yml.j2 +++ b/filebeat/tests/system/config/filebeat.yml.j2 @@ -133,6 +133,11 @@ geoip: ] {%- endif %} +{% if setup_template_name is not none %} +setup.template.name: setup_template_name +setup.template.pattern: setup_template_pattern +{%- endif %} + {%- if processors %} #================================ Filters ===================================== diff --git a/filebeat/tests/system/config/filebeat_modules.yml.j2 b/filebeat/tests/system/config/filebeat_modules.yml.j2 index 3e8083fc037..b62c9c293c9 100644 --- a/filebeat/tests/system/config/filebeat_modules.yml.j2 +++ b/filebeat/tests/system/config/filebeat_modules.yml.j2 @@ -2,3 +2,6 @@ filebeat.registry_file: {{ beat.working_dir + '/' }}{{ registryFile|default("reg output.elasticsearch.hosts: ["{{ elasticsearch_url }}"] output.elasticsearch.index: {{ index_name }} + +setup.template.name: {{ index_name }} +setup.template.pattern: {{ index_name }}* diff --git a/filebeat/tests/system/test_modules.py b/filebeat/tests/system/test_modules.py index 4b0f79bc59d..582a80b444e 100644 --- a/filebeat/tests/system/test_modules.py +++ b/filebeat/tests/system/test_modules.py @@ -46,7 +46,8 @@ def test_modules(self): template_name="filebeat_modules", output=cfgfile, index_name=self.index_name, - elasticsearch_url=self.elasticsearch_url) + elasticsearch_url=self.elasticsearch_url + ) for module in modules: path = os.path.join(self.modules_path, module) @@ -161,6 +162,8 @@ def test_prospector_pipeline_config(self): pipeline="estest", index=index_name), pipeline="test", + setup_template_name=index_name, + setup_template_pattern=index_name + "*", ) os.mkdir(self.working_dir + "/log/") diff --git a/heartbeat/heartbeat.reference.yml b/heartbeat/heartbeat.reference.yml index c3b0ebdce58..82d975ecc47 100644 --- a/heartbeat/heartbeat.reference.yml +++ b/heartbeat/heartbeat.reference.yml @@ -358,6 +358,7 @@ output.elasticsearch: # Optional index name. The default is "heartbeat" plus date # and generates [heartbeat-]YYYY.MM.DD keys. + # In case you modify this pattern you must update setup.template.name and setup.template.pattern accordingly. #index: "heartbeat-%{[beat.version]}-%{+yyyy.MM.dd}" # Optional ingest node pipeline. By default no pipeline will be used. @@ -815,10 +816,14 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Template name. By default the template name is heartbeat. -# The version of the beat will always be appended to the given name -# so the final name is heartbeat-%{[beat.version]}. -#setup.template.name: "heartbeat" +# Template name. By default the template name is "heartbeat-%{[beat.version]}" +# The template name and pattern has to be set in case the elasticsearch index pattern is modified. +#setup.template.name: "heartbeat-%{[beat.version]}" + +# Template patttern. By default the template patter is "-%{[beat.version]}-*" to apply to the default index settings. +# The first part is the version of the beat and then -* is used to match all daily indicies. +# The template name and pattern has to be set in case the elasticsearch index pattern is modified. +#setup.template.pattern: "heartbeat-%{[beat.version]}-*" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" diff --git a/libbeat/_meta/config.reference.yml b/libbeat/_meta/config.reference.yml index 478a48e97cc..6dd7c4b0c2b 100644 --- a/libbeat/_meta/config.reference.yml +++ b/libbeat/_meta/config.reference.yml @@ -144,6 +144,7 @@ output.elasticsearch: # Optional index name. The default is "beatname" plus date # and generates [beatname-]YYYY.MM.DD keys. + # In case you modify this pattern you must update setup.template.name and setup.template.pattern accordingly. #index: "beatname-%{[beat.version]}-%{+yyyy.MM.dd}" # Optional ingest node pipeline. By default no pipeline will be used. @@ -601,10 +602,14 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Template name. By default the template name is beatname. -# The version of the beat will always be appended to the given name -# so the final name is beatname-%{[beat.version]}. -#setup.template.name: "beatname" +# Template name. By default the template name is "beatname-%{[beat.version]}" +# The template name and pattern has to be set in case the elasticsearch index pattern is modified. +#setup.template.name: "beatname-%{[beat.version]}" + +# Template patttern. By default the template patter is "-%{[beat.version]}-*" to apply to the default index settings. +# The first part is the version of the beat and then -* is used to match all daily indicies. +# The template name and pattern has to be set in case the elasticsearch index pattern is modified. +#setup.template.pattern: "beatname-%{[beat.version]}-*" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" diff --git a/libbeat/cmd/export/template.go b/libbeat/cmd/export/template.go index 876690b6803..1403cf8b8cf 100644 --- a/libbeat/cmd/export/template.go +++ b/libbeat/cmd/export/template.go @@ -38,7 +38,7 @@ func GenTemplateConfigCmd(name, beatVersion string) *cobra.Command { } } - tmpl, err := template.New(b.Info.Version, version, index, cfg.Settings) + tmpl, err := template.New(b.Info.Version, index, version, cfg) if err != nil { fmt.Fprintf(os.Stderr, "Error generating template: %+v", err) os.Exit(1) diff --git a/libbeat/cmd/instance/beat.go b/libbeat/cmd/instance/beat.go index 22afc618bdf..6352895aedd 100644 --- a/libbeat/cmd/instance/beat.go +++ b/libbeat/cmd/instance/beat.go @@ -542,9 +542,11 @@ func (b *Beat) loadDashboards(force bool) error { // the elasticsearch output. It is important the the registration happens before // the publisher is created. func (b *Beat) registerTemplateLoading() error { + + var cfg template.TemplateConfig + // Check if outputting to file is enabled, and output to file if it is - if b.Config.Template != nil && b.Config.Template.Enabled() { - var cfg template.TemplateConfig + if b.Config.Template.Enabled() { err := b.Config.Template.Unpack(&cfg) if err != nil { return fmt.Errorf("unpacking template config fails: %v", err) @@ -553,7 +555,22 @@ func (b *Beat) registerTemplateLoading() error { // Loads template by default if esOutput is enabled if b.Config.Output.Name() == "elasticsearch" { + + // Get ES Index name for comparison + esCfg := struct { + Index string `config:"index"` + }{} + err := b.Config.Output.Config().Unpack(&esCfg) + if err != nil { + return err + } + + if esCfg.Index != "" && (cfg.Name == "" || cfg.Pattern == "") { + return fmt.Errorf("setup.template.name and setup.template.pattern have to be set if index name is modified.") + } + if b.Config.Template == nil || (b.Config.Template != nil && b.Config.Template.Enabled()) { + // load template through callback to make sure it is also loaded // on reconnecting callback, err := b.templateLoadingCallback() diff --git a/libbeat/template/config.go b/libbeat/template/config.go index 9aacc7e997a..eec7e6dab57 100644 --- a/libbeat/template/config.go +++ b/libbeat/template/config.go @@ -3,6 +3,7 @@ package template type TemplateConfig struct { Enabled bool `config:"enabled"` Name string `config:"name"` + Pattern string `config:"pattern"` Fields string `config:"fields"` Overwrite bool `config:"overwrite"` Settings TemplateSettings `config:"settings"` diff --git a/libbeat/template/load.go b/libbeat/template/load.go index b8648f809a0..07da99f3af2 100644 --- a/libbeat/template/load.go +++ b/libbeat/template/load.go @@ -42,11 +42,8 @@ func NewLoader(cfg *common.Config, client ESClient, beatInfo beat.Info) (*Loader // In case the template is not already loaded or overwriting is enabled, the // template is written to index func (l *Loader) Load() error { - if l.config.Name == "" { - l.config.Name = l.beatInfo.Beat - } - tmpl, err := New(l.beatInfo.Version, l.client.GetVersion(), l.config.Name, l.config.Settings) + tmpl, err := New(l.beatInfo.Version, l.beatInfo.Beat, l.client.GetVersion(), l.config) if err != nil { return fmt.Errorf("error creating template instance: %v", err) } diff --git a/libbeat/template/load_integration_test.go b/libbeat/template/load_integration_test.go index 827927a95e3..9e21e30036f 100644 --- a/libbeat/template/load_integration_test.go +++ b/libbeat/template/load_integration_test.go @@ -44,7 +44,7 @@ func TestLoadTemplate(t *testing.T) { fieldsPath := absPath + "/fields.yml" index := "testbeat" - tmpl, err := New(version.GetDefaultVersion(), client.GetVersion(), index, TemplateSettings{}) + tmpl, err := New(version.GetDefaultVersion(), index, client.GetVersion(), TemplateConfig{}) assert.NoError(t, err) content, err := tmpl.Load(fieldsPath) assert.NoError(t, err) @@ -132,7 +132,7 @@ func TestLoadBeatsTemplate(t *testing.T) { fieldsPath := absPath + "/fields.yml" index := beat - tmpl, err := New(version.GetDefaultVersion(), client.GetVersion(), index, TemplateSettings{}) + tmpl, err := New(version.GetDefaultVersion(), index, client.GetVersion(), TemplateConfig{}) assert.NoError(t, err) content, err := tmpl.Load(fieldsPath) assert.NoError(t, err) @@ -178,7 +178,10 @@ func TestTemplateSettings(t *testing.T) { "enabled": false, }, } - tmpl, err := New(version.GetDefaultVersion(), client.GetVersion(), "testbeat", settings) + config := TemplateConfig{ + Settings: settings, + } + tmpl, err := New(version.GetDefaultVersion(), "testbeat", client.GetVersion(), config) assert.NoError(t, err) content, err := tmpl.Load(fieldsPath) assert.NoError(t, err) @@ -335,7 +338,7 @@ func TestTemplateWithData(t *testing.T) { // Setup ES client := elasticsearch.GetTestingElasticsearch(t) - tmpl, err := New(version.GetDefaultVersion(), client.GetVersion(), "testindex", TemplateSettings{}) + tmpl, err := New(version.GetDefaultVersion(), "testindex", client.GetVersion(), TemplateConfig{}) assert.NoError(t, err) content, err := tmpl.Load(fieldsPath) assert.NoError(t, err) diff --git a/libbeat/template/template.go b/libbeat/template/template.go index 1bdc1904e42..97995d69a8e 100644 --- a/libbeat/template/template.go +++ b/libbeat/template/template.go @@ -2,8 +2,11 @@ package template import ( "fmt" + "time" + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/common/fmtstr" "github.com/elastic/go-ucfg/yaml" ) @@ -17,19 +20,58 @@ var ( ) type Template struct { - index string + name string + pattern string beatVersion common.Version esVersion common.Version settings TemplateSettings } // New creates a new template instance -func New(beatVersion string, esVersion string, index string, settings TemplateSettings) (*Template, error) { +func New(beatVersion string, beatName string, esVersion string, config TemplateConfig) (*Template, error) { bV, err := common.NewVersion(beatVersion) if err != nil { return nil, err } + name := config.Name + if name == "" { + name = fmt.Sprintf("%s-%s", beatName, bV.String()) + } + + pattern := config.Pattern + if pattern == "" { + pattern = name + "-*" + } + + event := &beat.Event{ + Fields: common.MapStr{ + "beat": common.MapStr{ + "name": beatName, + "version": bV.String(), + }, + }, + Timestamp: time.Now(), + } + + nameFormatter, err := fmtstr.CompileEvent(name) + if err != nil { + return nil, err + } + name, err = nameFormatter.Run(event) + if err != nil { + return nil, err + } + + patternFormatter, err := fmtstr.CompileEvent(pattern) + if err != nil { + return nil, err + } + pattern, err = patternFormatter.Run(event) + if err != nil { + return nil, err + } + // In case no esVersion is set, it is assumed the same as beat version if esVersion == "" { esVersion = beatVersion @@ -41,10 +83,11 @@ func New(beatVersion string, esVersion string, index string, settings TemplateSe } return &Template{ - index: index, + pattern: pattern, + name: name, beatVersion: *bV, esVersion: *esV, - settings: settings, + settings: config.Settings, }, nil } @@ -62,9 +105,14 @@ func (t *Template) Load(file string) (common.MapStr, error) { return output, nil } -// GetName returns the name of the template which is {index}-{version} +// GetName returns the name of the template func (t *Template) GetName() string { - return fmt.Sprintf("%s-%s", t.index, t.beatVersion.String()) + return t.name +} + +// GetPattern returns the pattern of the template +func (t *Template) GetPattern() string { + return t.pattern } // generate generates the full template @@ -130,9 +178,9 @@ func (t *Template) generate(properties common.MapStr, dynamicTemplates []common. // ES 6 moved from template to index_patterns: https://github.com/elastic/elasticsearch/pull/21009 if t.esVersion.Major >= 6 { - basicStructure.Put("index_patterns", []string{t.GetName() + "-*"}) + basicStructure.Put("index_patterns", []string{t.GetPattern()}) } else { - basicStructure.Put("template", t.GetName()+"-*") + basicStructure.Put("template", t.GetPattern()) } if t.esVersion.IsMajor(2) { diff --git a/libbeat/tests/system/beat/beat.py b/libbeat/tests/system/beat/beat.py index f1a99233bd9..988653d60ca 100644 --- a/libbeat/tests/system/beat/beat.py +++ b/libbeat/tests/system/beat/beat.py @@ -11,6 +11,7 @@ import yaml from datetime import datetime, timedelta + BEAT_REQUIRED_FIELDS = ["@timestamp", "beat.name", "beat.hostname", "beat.version"] @@ -168,7 +169,7 @@ def start_beat(self, "-test.coverprofile", os.path.join(self.working_dir, "coverage.cov"), "-path.home", os.path.normpath(self.working_dir), - "-c", os.path.join(self.working_dir, config) + "-c", os.path.join(self.working_dir, config), ] if logging_args: @@ -262,6 +263,11 @@ def setUp(self): shutil.rmtree(self.working_dir) os.makedirs(self.working_dir) + fields_yml = os.path.join(self.beat_path, "fields.yml") + # Only add it if it exists + if os.path.isfile(fields_yml): + shutil.copyfile(fields_yml, os.path.join(self.working_dir, "fields.yml")) + try: # update the last_run link if os.path.islink(self.build_path + "last_run"): diff --git a/libbeat/tests/system/config/mockbeat.yml.j2 b/libbeat/tests/system/config/mockbeat.yml.j2 index cd4081d33eb..03909dfb3ac 100644 --- a/libbeat/tests/system/config/mockbeat.yml.j2 +++ b/libbeat/tests/system/config/mockbeat.yml.j2 @@ -65,7 +65,8 @@ setup.template: settings: index.number_of_shards: 1 index.codec: best_compression - + name: {{ es_template_name }} + pattern: {{ es_template_pattern }} #================================ Logging ===================================== {% if metrics_period -%} diff --git a/libbeat/tests/system/test_template.py b/libbeat/tests/system/test_template.py new file mode 100644 index 00000000000..499f36ab3e4 --- /dev/null +++ b/libbeat/tests/system/test_template.py @@ -0,0 +1,74 @@ +from base import BaseTest + + +class Test(BaseTest): + + def test_index_modified(self): + """ + Test that beat stops in case elasticsearch index is modified and pattern not + """ + self.render_config_template( + elasticsearch={"index": "test"}, + ) + + exit_code = self.run_beat() + + assert exit_code == 1 + assert self.log_contains( + "setup.template.name and setup.template.pattern have to be set if index name is modified.") is True + + def test_index_not_modified(self): + """ + Test that beat starts running if elasticsearch output is set + """ + self.render_config_template( + elasticsearch={"hosts": "localhost:9200"}, + ) + + proc = self.start_beat() + self.wait_until(lambda: self.log_contains("mockbeat start running.")) + proc.check_kill_and_wait() + + def test_index_modified_no_pattern(self): + """ + Test that beat stops in case elasticsearch index is modified and pattern not + """ + self.render_config_template( + elasticsearch={"index": "test"}, + es_template_name="test", + ) + + exit_code = self.run_beat() + + assert exit_code == 1 + assert self.log_contains( + "setup.template.name and setup.template.pattern have to be set if index name is modified.") is True + + def test_index_modified_no_name(self): + """ + Test that beat stops in case elasticsearch index is modified and name not + """ + self.render_config_template( + elasticsearch={"index": "test"}, + es_template_pattern="test", + ) + + exit_code = self.run_beat() + + assert exit_code == 1 + assert self.log_contains( + "setup.template.name and setup.template.pattern have to be set if index name is modified.") is True + + def test_index_with_pattern_name(self): + """ + Test that beat starts running if elasticsearch output with modified index and pattern and name are set + """ + self.render_config_template( + elasticsearch={"hosts": "localhost:9200"}, + es_template_name="test", + es_template_pattern="test-*", + ) + + proc = self.start_beat() + self.wait_until(lambda: self.log_contains("mockbeat start running.")) + proc.check_kill_and_wait() diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index 482c60539c0..ebde2b5b23b 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -588,6 +588,7 @@ output.elasticsearch: # Optional index name. The default is "metricbeat" plus date # and generates [metricbeat-]YYYY.MM.DD keys. + # In case you modify this pattern you must update setup.template.name and setup.template.pattern accordingly. #index: "metricbeat-%{[beat.version]}-%{+yyyy.MM.dd}" # Optional ingest node pipeline. By default no pipeline will be used. @@ -1045,10 +1046,14 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Template name. By default the template name is metricbeat. -# The version of the beat will always be appended to the given name -# so the final name is metricbeat-%{[beat.version]}. -#setup.template.name: "metricbeat" +# Template name. By default the template name is "metricbeat-%{[beat.version]}" +# The template name and pattern has to be set in case the elasticsearch index pattern is modified. +#setup.template.name: "metricbeat-%{[beat.version]}" + +# Template patttern. By default the template patter is "-%{[beat.version]}-*" to apply to the default index settings. +# The first part is the version of the beat and then -* is used to match all daily indicies. +# The template name and pattern has to be set in case the elasticsearch index pattern is modified. +#setup.template.pattern: "metricbeat-%{[beat.version]}-*" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" diff --git a/packetbeat/packetbeat.reference.yml b/packetbeat/packetbeat.reference.yml index 58e72b6228c..e72d7386f8f 100644 --- a/packetbeat/packetbeat.reference.yml +++ b/packetbeat/packetbeat.reference.yml @@ -596,6 +596,7 @@ output.elasticsearch: # Optional index name. The default is "packetbeat" plus date # and generates [packetbeat-]YYYY.MM.DD keys. + # In case you modify this pattern you must update setup.template.name and setup.template.pattern accordingly. #index: "packetbeat-%{[beat.version]}-%{+yyyy.MM.dd}" # Optional ingest node pipeline. By default no pipeline will be used. @@ -1053,10 +1054,14 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Template name. By default the template name is packetbeat. -# The version of the beat will always be appended to the given name -# so the final name is packetbeat-%{[beat.version]}. -#setup.template.name: "packetbeat" +# Template name. By default the template name is "packetbeat-%{[beat.version]}" +# The template name and pattern has to be set in case the elasticsearch index pattern is modified. +#setup.template.name: "packetbeat-%{[beat.version]}" + +# Template patttern. By default the template patter is "-%{[beat.version]}-*" to apply to the default index settings. +# The first part is the version of the beat and then -* is used to match all daily indicies. +# The template name and pattern has to be set in case the elasticsearch index pattern is modified. +#setup.template.pattern: "packetbeat-%{[beat.version]}-*" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" diff --git a/winlogbeat/winlogbeat.reference.yml b/winlogbeat/winlogbeat.reference.yml index 668b3deac40..f38bd235a8f 100644 --- a/winlogbeat/winlogbeat.reference.yml +++ b/winlogbeat/winlogbeat.reference.yml @@ -173,6 +173,7 @@ output.elasticsearch: # Optional index name. The default is "winlogbeat" plus date # and generates [winlogbeat-]YYYY.MM.DD keys. + # In case you modify this pattern you must update setup.template.name and setup.template.pattern accordingly. #index: "winlogbeat-%{[beat.version]}-%{+yyyy.MM.dd}" # Optional ingest node pipeline. By default no pipeline will be used. @@ -630,10 +631,14 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Template name. By default the template name is winlogbeat. -# The version of the beat will always be appended to the given name -# so the final name is winlogbeat-%{[beat.version]}. -#setup.template.name: "winlogbeat" +# Template name. By default the template name is "winlogbeat-%{[beat.version]}" +# The template name and pattern has to be set in case the elasticsearch index pattern is modified. +#setup.template.name: "winlogbeat-%{[beat.version]}" + +# Template patttern. By default the template patter is "-%{[beat.version]}-*" to apply to the default index settings. +# The first part is the version of the beat and then -* is used to match all daily indicies. +# The template name and pattern has to be set in case the elasticsearch index pattern is modified. +#setup.template.pattern: "winlogbeat-%{[beat.version]}-*" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" From cc790d7a8cffbc19cda1f693a32f658c9d40b9b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Wed, 23 Aug 2017 12:18:31 +0200 Subject: [PATCH 105/139] Add new metrics to CPU metricset (#4969) * metricbeat: add cpu.total.pct && cpu.total.norm.pct Closes #4898 * fix system tests --- CHANGELOG.asciidoc | 1 + metricbeat/docs/fields.asciidoc | 20 +++++++++++++++++++ metricbeat/module/system/cpu/_meta/fields.yml | 13 ++++++++++++ metricbeat/module/system/cpu/cpu.go | 2 ++ metricbeat/module/system/util.go | 6 ++++++ metricbeat/module/system/util_test.go | 6 ++++++ metricbeat/tests/system/test_processors.py | 2 +- metricbeat/tests/system/test_system.py | 4 ++-- 8 files changed, 51 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index f10062d1b9a..b84ad52244b 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -59,6 +59,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Support `npipe` protocol (Windows) in Docker module. {pull}4751[4751] - Added missing mongodb configuration file to the `modules.d` folder. {pull}4870[4870] - Fix wrong MySQL CRUD queries timelion visualization {pull}4857[4857] +- Add new metrics to CPU metricsset {pull}4969[4969] *Packetbeat* diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 8258d3dddd3..cabf00631fa 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -8543,6 +8543,16 @@ format: percent The percentage of CPU time spent in involuntary wait by the virtual CPU while the hypervisor was servicing another processor. Available only on Unix. +[float] +=== `system.cpu.total.pct` + +type: scaled_float + +format: percent + +The percentage of CPU time spent in non-idle state. + + [float] === `system.cpu.user.norm.pct` @@ -8623,6 +8633,16 @@ format: percent The percentage of CPU time spent in involuntary wait by the virtual CPU while the hypervisor was servicing another processor. Available only on Unix. +[float] +=== `system.cpu.total.norm.pct` + +type: scaled_float + +format: percent + +The percentage of CPU time spent in non-idle state. + + [float] === `system.cpu.user.ticks` diff --git a/metricbeat/module/system/cpu/_meta/fields.yml b/metricbeat/module/system/cpu/_meta/fields.yml index 8747e6f5b41..b68af75bc39 100644 --- a/metricbeat/module/system/cpu/_meta/fields.yml +++ b/metricbeat/module/system/cpu/_meta/fields.yml @@ -64,6 +64,12 @@ was servicing another processor. Available only on Unix. + - name: total.pct + type: scaled_float + format: percent + description: > + The percentage of CPU time spent in non-idle state. + # Normalized Percentages - name: user.norm.pct type: scaled_float @@ -115,6 +121,13 @@ was servicing another processor. Available only on Unix. + - name: total.norm.pct + type: scaled_float + format: percent + description: > + The percentage of CPU time spent in non-idle state. + + # Ticks - name: user.ticks type: long diff --git a/metricbeat/module/system/cpu/cpu.go b/metricbeat/module/system/cpu/cpu.go index d9be2ca0b15..a088234f0e3 100644 --- a/metricbeat/module/system/cpu/cpu.go +++ b/metricbeat/module/system/cpu/cpu.go @@ -65,6 +65,7 @@ func (m *MetricSet) Fetch() (common.MapStr, error) { event.Put("nice.pct", pct.Nice) event.Put("softirq.pct", pct.SoftIRQ) event.Put("steal.pct", pct.Steal) + event.Put("total.pct", pct.Total) case normalizedPercentages: normalizedPct := sample.NormalizedPercentages() event.Put("user.norm.pct", normalizedPct.User) @@ -75,6 +76,7 @@ func (m *MetricSet) Fetch() (common.MapStr, error) { event.Put("nice.norm.pct", normalizedPct.Nice) event.Put("softirq.norm.pct", normalizedPct.SoftIRQ) event.Put("steal.norm.pct", normalizedPct.Steal) + event.Put("total.norm.pct", normalizedPct.Total) case ticks: ticks := sample.Ticks() event.Put("user.ticks", ticks.User) diff --git a/metricbeat/module/system/util.go b/metricbeat/module/system/util.go index 7e6eb895e11..87c87a36763 100644 --- a/metricbeat/module/system/util.go +++ b/metricbeat/module/system/util.go @@ -47,6 +47,7 @@ type CPUPercentages struct { Nice float64 SoftIRQ float64 Steal float64 + Total float64 } type CPUTicks struct { @@ -98,6 +99,10 @@ func cpuPercentages(s0, s1 *sigar.Cpu, numCPU int) CPUPercentages { return Round(pct * float64(numCPU)) } + calculateTotalPct := func() float64 { + return Round(float64(numCPU) - calculatePct(s0.Idle, s1.Idle)) + } + return CPUPercentages{ User: calculatePct(s0.User, s1.User), System: calculatePct(s0.Sys, s1.Sys), @@ -107,6 +112,7 @@ func cpuPercentages(s0, s1 *sigar.Cpu, numCPU int) CPUPercentages { Nice: calculatePct(s0.Nice, s1.Nice), SoftIRQ: calculatePct(s0.SoftIrq, s1.SoftIrq), Steal: calculatePct(s0.Stolen, s1.Stolen), + Total: calculateTotalPct(), } } diff --git a/metricbeat/module/system/util_test.go b/metricbeat/module/system/util_test.go index dadede272e3..41cf5ff86f3 100644 --- a/metricbeat/module/system/util_test.go +++ b/metricbeat/module/system/util_test.go @@ -52,6 +52,8 @@ func TestCPUCoresMonitorSample(t *testing.T) { assert.True(t, normPct.System <= 100) assert.True(t, normPct.Idle > 0) assert.True(t, normPct.Idle <= 100) + assert.True(t, normPct.Total > 0) + assert.True(t, normPct.Total <= 100) ticks := s.Ticks() assert.True(t, ticks.User > 0) @@ -110,10 +112,14 @@ func TestCPUMetricsPercentages(t *testing.T) { pct := sample.NormalizedPercentages() assert.EqualValues(t, .3, pct.User) assert.EqualValues(t, .7, pct.System) + assert.EqualValues(t, .0, pct.Idle) + assert.EqualValues(t, 1., pct.Total) pct = sample.Percentages() assert.EqualValues(t, .3*float64(NumCPU), pct.User) assert.EqualValues(t, .7*float64(NumCPU), pct.System) + assert.EqualValues(t, .0*float64(NumCPU), pct.Idle) + assert.EqualValues(t, 1.*float64(NumCPU), pct.Total) } func TestRound(t *testing.T) { diff --git a/metricbeat/tests/system/test_processors.py b/metricbeat/tests/system/test_processors.py index 40619e851eb..1c83e228840 100644 --- a/metricbeat/tests/system/test_processors.py +++ b/metricbeat/tests/system/test_processors.py @@ -41,7 +41,7 @@ def test_drop_fields(self): print(cpu.keys()) self.assertItemsEqual(self.de_dot([ "system", "cores", "user", "softirq", "iowait", - "idle", "irq", "steal", "nice" + "idle", "irq", "steal", "nice", "total" ]), cpu.keys()) def test_dropfields_with_condition(self): diff --git a/metricbeat/tests/system/test_system.py b/metricbeat/tests/system/test_system.py index 10c4b046f04..bd1d3dc58e5 100644 --- a/metricbeat/tests/system/test_system.py +++ b/metricbeat/tests/system/test_system.py @@ -7,12 +7,12 @@ import os SYSTEM_CPU_FIELDS = ["cores", "idle.pct", "iowait.pct", "irq.pct", "nice.pct", - "softirq.pct", "steal.pct", "system.pct", "user.pct"] + "softirq.pct", "steal.pct", "system.pct", "user.pct", "total.pct"] SYSTEM_CPU_FIELDS_ALL = ["cores", "idle.pct", "idle.ticks", "iowait.pct", "iowait.ticks", "irq.pct", "irq.ticks", "nice.pct", "nice.ticks", "softirq.pct", "softirq.ticks", "steal.pct", "steal.ticks", "system.pct", "system.ticks", "user.pct", "user.ticks", "idle.norm.pct", "iowait.norm.pct", "irq.norm.pct", "nice.norm.pct", "softirq.norm.pct", - "steal.norm.pct", "system.norm.pct", "user.norm.pct"] + "steal.norm.pct", "system.norm.pct", "user.norm.pct", "total.norm.pct"] SYSTEM_LOAD_FIELDS = ["cores", "1", "5", "15", "norm.1", "norm.5", "norm.15"] From bd6981df3e461c5ae34bf62516637f7c03701efd Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Wed, 23 Aug 2017 13:20:48 +0200 Subject: [PATCH 106/139] Added cloud.id and cloud.auth config settings (#4964) * Added cloud.id and cloud.auth config settings This adds two new configuration settings: `cloud.id` and `cloud.auth`. They can be used in the configuration file, or from the CLI like this: ``` ./metricbeat -e -E cloud.id= -E cloud.auth= ``` The ES/KB settings are changed via overwritting, but we display an INFO level message that the settings are changed by the cloud-id. Closes #4959. * goimports fix * aded more tests * added basic docs * changelog * addressed comments * Check that we're not enabling a second output * remove unused var * Addressed comments --- CHANGELOG.asciidoc | 1 + auditbeat/auditbeat.reference.yml | 13 ++ auditbeat/auditbeat.yml | 15 +- filebeat/filebeat.reference.yml | 13 ++ filebeat/filebeat.yml | 15 +- heartbeat/heartbeat.reference.yml | 13 ++ heartbeat/heartbeat.yml | 15 +- libbeat/_meta/config.reference.yml | 13 ++ libbeat/_meta/config.yml | 15 +- libbeat/cloudid/cloudid.go | 128 +++++++++++++++++ libbeat/cloudid/cloudid_test.go | 209 ++++++++++++++++++++++++++++ libbeat/cmd/instance/beat.go | 6 + libbeat/docs/outputconfig.asciidoc | 36 +++++ metricbeat/metricbeat.reference.yml | 13 ++ metricbeat/metricbeat.yml | 15 +- packetbeat/packetbeat.reference.yml | 13 ++ packetbeat/packetbeat.yml | 15 +- winlogbeat/winlogbeat.reference.yml | 13 ++ winlogbeat/winlogbeat.yml | 15 +- 19 files changed, 569 insertions(+), 7 deletions(-) create mode 100644 libbeat/cloudid/cloudid.go create mode 100644 libbeat/cloudid/cloudid_test.go diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index b84ad52244b..0f3a5b31ea0 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -74,6 +74,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Update init scripts to use the `test config` subcommand instead of the deprecated `-configtest` flag. {issue}4600[4600] - Get by default the credentials for connecting to Kibana from the Elasticsearch output configuration. {pull}4867[4867] - Move TCP UDP start up into `server.Start()` {pull}4903[4903] +- Added `cloud.id` and `cloud.auth` settings, for simplifying using Beats with the Elastic Cloud. {issue}4959[4959] *Auditbeat* diff --git a/auditbeat/auditbeat.reference.yml b/auditbeat/auditbeat.reference.yml index 45c92fecc4c..1ec15108741 100644 --- a/auditbeat/auditbeat.reference.yml +++ b/auditbeat/auditbeat.reference.yml @@ -175,6 +175,19 @@ auditbeat.modules: #processors: #- add_docker_metadata: ~ +#============================= Elastic Cloud ================================== + +# These settings simplify using auditbeat with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + #================================ Outputs ====================================== # Configure what outputs to use when sending the data collected by the beat. diff --git a/auditbeat/auditbeat.yml b/auditbeat/auditbeat.yml index 35fd3d040ee..fac44ac5471 100644 --- a/auditbeat/auditbeat.yml +++ b/auditbeat/auditbeat.yml @@ -59,7 +59,7 @@ auditbeat.modules: #============================== Kibana ===================================== -# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. +# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. # This requires a Kibana endpoint configuration. setup.kibana: @@ -69,6 +69,19 @@ setup.kibana: # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601 #host: "localhost:5601" +#============================= Elastic Cloud ================================== + +# These settings simplify using auditbeat with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + #================================ Outputs ===================================== # Configure what outputs to use when sending the data collected by the beat. diff --git a/filebeat/filebeat.reference.yml b/filebeat/filebeat.reference.yml index a3df4633cd1..344ca043ef7 100644 --- a/filebeat/filebeat.reference.yml +++ b/filebeat/filebeat.reference.yml @@ -595,6 +595,19 @@ filebeat.prospectors: #processors: #- add_docker_metadata: ~ +#============================= Elastic Cloud ================================== + +# These settings simplify using filebeat with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + #================================ Outputs ====================================== # Configure what outputs to use when sending the data collected by the beat. diff --git a/filebeat/filebeat.yml b/filebeat/filebeat.yml index a49d550f818..8650eb67824 100644 --- a/filebeat/filebeat.yml +++ b/filebeat/filebeat.yml @@ -105,7 +105,7 @@ filebeat.config.modules: #============================== Kibana ===================================== -# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. +# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. # This requires a Kibana endpoint configuration. setup.kibana: @@ -115,6 +115,19 @@ setup.kibana: # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601 #host: "localhost:5601" +#============================= Elastic Cloud ================================== + +# These settings simplify using filebeat with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + #================================ Outputs ===================================== # Configure what outputs to use when sending the data collected by the beat. diff --git a/heartbeat/heartbeat.reference.yml b/heartbeat/heartbeat.reference.yml index 82d975ecc47..564d15a73d8 100644 --- a/heartbeat/heartbeat.reference.yml +++ b/heartbeat/heartbeat.reference.yml @@ -324,6 +324,19 @@ heartbeat.scheduler: #processors: #- add_docker_metadata: ~ +#============================= Elastic Cloud ================================== + +# These settings simplify using heartbeat with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + #================================ Outputs ====================================== # Configure what outputs to use when sending the data collected by the beat. diff --git a/heartbeat/heartbeat.yml b/heartbeat/heartbeat.yml index 308b8105159..998d94863af 100644 --- a/heartbeat/heartbeat.yml +++ b/heartbeat/heartbeat.yml @@ -52,7 +52,7 @@ heartbeat.monitors: #============================== Kibana ===================================== -# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. +# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. # This requires a Kibana endpoint configuration. setup.kibana: @@ -62,6 +62,19 @@ setup.kibana: # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601 #host: "localhost:5601" +#============================= Elastic Cloud ================================== + +# These settings simplify using heartbeat with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + #================================ Outputs ===================================== # Configure what outputs to use when sending the data collected by the beat. diff --git a/libbeat/_meta/config.reference.yml b/libbeat/_meta/config.reference.yml index 6dd7c4b0c2b..456d184647f 100644 --- a/libbeat/_meta/config.reference.yml +++ b/libbeat/_meta/config.reference.yml @@ -110,6 +110,19 @@ #processors: #- add_docker_metadata: ~ +#============================= Elastic Cloud ================================== + +# These settings simplify using beatname with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + #================================ Outputs ====================================== # Configure what outputs to use when sending the data collected by the beat. diff --git a/libbeat/_meta/config.yml b/libbeat/_meta/config.yml index 5bc54c106d3..d3847a08aec 100644 --- a/libbeat/_meta/config.yml +++ b/libbeat/_meta/config.yml @@ -29,7 +29,7 @@ #============================== Kibana ===================================== -# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. +# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. # This requires a Kibana endpoint configuration. setup.kibana: @@ -39,6 +39,19 @@ setup.kibana: # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601 #host: "localhost:5601" +#============================= Elastic Cloud ================================== + +# These settings simplify using beatname with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + #================================ Outputs ===================================== # Configure what outputs to use when sending the data collected by the beat. diff --git a/libbeat/cloudid/cloudid.go b/libbeat/cloudid/cloudid.go new file mode 100644 index 00000000000..fc5b3b6a2df --- /dev/null +++ b/libbeat/cloudid/cloudid.go @@ -0,0 +1,128 @@ +// package cloudid contains functions for parsing the cloud.id and cloud.auth +// settings and modifying the configuration to take them into account. +package cloudid + +import ( + "encoding/base64" + "fmt" + "net/url" + "strings" + + "github.com/pkg/errors" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/logp" +) + +// OverwriteSettings modifies the received config object by overwriting the +// output.elasticsearch.hosts, output.elasticsearch.username, output.elasticsearch.password, +// setup.kibana.host settings based on values derived from the cloud.id and cloud.auth +// settings. +func OverwriteSettings(cfg *common.Config) error { + + cloudID, _ := cfg.String("cloud.id", -1) + cloudAuth, _ := cfg.String("cloud.auth", -1) + + if cloudID == "" && cloudAuth == "" { + // nothing to hack + return nil + } + + logp.Debug("cloudid", "cloud.id: %s, cloud.auth: %s", cloudID, cloudAuth) + if cloudID == "" { + return errors.New("cloud.auth specified but cloud.id is empty. Please specify both.") + } + + // cloudID overwrites + esURL, kibanaURL, err := decodeCloudID(cloudID) + if err != nil { + return errors.Errorf("Error decoding cloud.id: %v", err) + } + + logp.Info("Setting Elasticsearch and Kibana URLs based on the cloud id: output.elasticsearch.hosts=%s and setup.kibana.host=%s", esURL, kibanaURL) + + esURLConfig, err := common.NewConfigFrom([]string{esURL}) + if err != nil { + return err + } + + // Before enabling the ES output, check that no other output is enabled + tmp := struct { + Output common.ConfigNamespace `config:"output"` + }{} + if err := cfg.Unpack(&tmp); err != nil { + return err + } + if out := tmp.Output; out.IsSet() && out.Name() != "elasticsearch" { + return errors.Errorf("The cloud.id setting enables the Elasticsearch output, but you already have the %s output enabled in the config", out.Name()) + } + + err = cfg.SetChild("output.elasticsearch.hosts", -1, esURLConfig) + if err != nil { + return err + } + + err = cfg.SetString("setup.kibana.host", -1, kibanaURL) + if err != nil { + return err + } + + if cloudAuth != "" { + // cloudAuth overwrites + username, password, err := decodeCloudAuth(cloudAuth) + if err != nil { + return err + } + + err = cfg.SetString("output.elasticsearch.username", -1, username) + if err != nil { + return err + } + + err = cfg.SetString("output.elasticsearch.password", -1, password) + if err != nil { + return err + } + } + + return nil +} + +// decodeCloudID decodes the cloud.id into elasticsearch-URL and kibana-URL +func decodeCloudID(cloudID string) (string, string, error) { + + // 1. Ignore anything before `:`. + idx := strings.LastIndex(cloudID, ":") + if idx >= 0 { + cloudID = cloudID[idx+1:] + } + + // 2. base64 decode + decoded, err := base64.StdEncoding.DecodeString(cloudID) + if err != nil { + return "", "", errors.Wrapf(err, "base64 decoding failed on %s", cloudID) + } + + // 3. separate based on `$` + words := strings.Split(string(decoded), "$") + if len(words) < 3 { + return "", "", errors.Errorf("Expected at least 3 parts in %s", string(decoded)) + } + + // 4. form the URLs + esURL := url.URL{Scheme: "https", Host: fmt.Sprintf("%s.%s:443", words[1], words[0])} + kibanaURL := url.URL{Scheme: "https", Host: fmt.Sprintf("%s.%s:443", words[2], words[0])} + + return esURL.String(), kibanaURL.String(), nil +} + +// decodeCloudAuth splits the cloud.auth into username and password. +func decodeCloudAuth(cloudAuth string) (string, string, error) { + + idx := strings.Index(cloudAuth, ":") + if idx < 0 { + return "", "", errors.New("cloud.auth setting doesn't contain `:` to split between username and password") + } + + return cloudAuth[0:idx], cloudAuth[idx+1:], nil +} diff --git a/libbeat/cloudid/cloudid_test.go b/libbeat/cloudid/cloudid_test.go new file mode 100644 index 00000000000..68ef48e78de --- /dev/null +++ b/libbeat/cloudid/cloudid_test.go @@ -0,0 +1,209 @@ +package cloudid + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/libbeat/common" +) + +func TestDecode(t *testing.T) { + tests := []struct { + cloudID string + expectedEsURL string + expectedKibanaURL string + }{ + { + cloudID: "staging:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRjZWM2ZjI2MWE3NGJmMjRjZTMzYmI4ODExYjg0Mjk0ZiRjNmMyY2E2ZDA0MjI0OWFmMGNjN2Q3YTllOTYyNTc0Mw==", + expectedEsURL: "https://cec6f261a74bf24ce33bb8811b84294f.us-east-1.aws.found.io:443", + expectedKibanaURL: "https://c6c2ca6d042249af0cc7d7a9e9625743.us-east-1.aws.found.io:443", + }, + { + cloudID: "dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRjZWM2ZjI2MWE3NGJmMjRjZTMzYmI4ODExYjg0Mjk0ZiRjNmMyY2E2ZDA0MjI0OWFmMGNjN2Q3YTllOTYyNTc0Mw==", + expectedEsURL: "https://cec6f261a74bf24ce33bb8811b84294f.us-east-1.aws.found.io:443", + expectedKibanaURL: "https://c6c2ca6d042249af0cc7d7a9e9625743.us-east-1.aws.found.io:443", + }, + { + cloudID: ":dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRjZWM2ZjI2MWE3NGJmMjRjZTMzYmI4ODExYjg0Mjk0ZiRjNmMyY2E2ZDA0MjI0OWFmMGNjN2Q3YTllOTYyNTc0Mw==", + expectedEsURL: "https://cec6f261a74bf24ce33bb8811b84294f.us-east-1.aws.found.io:443", + expectedKibanaURL: "https://c6c2ca6d042249af0cc7d7a9e9625743.us-east-1.aws.found.io:443", + }, + { + cloudID: "gcp-cluster:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJDhhMDI4M2FmMDQxZjE5NWY3NzI5YmMwNGM2NmEwZmNlJDBjZDVjZDU2OGVlYmU1M2M4OWViN2NhZTViYWM4YjM3", + expectedEsURL: "https://8a0283af041f195f7729bc04c66a0fce.us-central1.gcp.cloud.es.io:443", + expectedKibanaURL: "https://0cd5cd568eebe53c89eb7cae5bac8b37.us-central1.gcp.cloud.es.io:443", + }, + } + + for _, test := range tests { + esURL, kbURL, err := decodeCloudID(test.cloudID) + assert.NoError(t, err, test.cloudID) + + assert.Equal(t, esURL, test.expectedEsURL, test.cloudID) + assert.Equal(t, kbURL, test.expectedKibanaURL, test.cloudID) + } +} + +func TestDecodeError(t *testing.T) { + tests := []struct { + cloudID string + errorMsg string + }{ + { + cloudID: "staging:garbagedXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRjZWM2ZjI2MWE3NGJmMjRjZTMzYmI4ODExYjg0Mjk0ZiRjNmMyY2E2ZDA0MjI0OWFmMGNjN2Q3YTllOTYyNTc0Mw==", + errorMsg: "base64 decoding failed", + }, + { + cloudID: "dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJDhhMDI4M2FmMDQxZjE5NWY3NzI5YmMwNGM2NmEwZg==", + errorMsg: "Expected at least 3 parts", + }, + } + + for _, test := range tests { + _, _, err := decodeCloudID(test.cloudID) + assert.Error(t, err, test.cloudID) + assert.Contains(t, err.Error(), test.errorMsg, test.cloudID) + } +} + +func TestOverwriteSettings(t *testing.T) { + tests := []struct { + name string + inCfg map[string]interface{} + outCfg map[string]interface{} + }{ + { + name: "No cloud-id specified, nothing should change", + inCfg: map[string]interface{}{ + "output.elasticsearch.hosts": "localhost:9200", + }, + outCfg: map[string]interface{}{ + "output.elasticsearch.hosts": "localhost:9200", + }, + }, + { + name: "cloudid realistic example", + inCfg: map[string]interface{}{ + "output.elasticsearch.hosts": "localhost:9200", + "cloud.id": "cloudidtest:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyQyNDlmM2FmMWY0ZWVlMjRhODRlM2I0MDFlNjhhMWIyYSRkNGFjNzU1OWQ0Njc0YjdjOTFhYmUxMDg1NmQ4NDMwNA==", + "cloud.auth": "elastic:changeme", + }, + outCfg: map[string]interface{}{ + "output.elasticsearch.hosts": []interface{}{"https://249f3af1f4eee24a84e3b401e68a1b2a.us-east-1.aws.found.io:443"}, + "output.elasticsearch.username": "elastic", + "output.elasticsearch.password": "changeme", + "setup.kibana.host": "https://d4ac7559d4674b7c91abe10856d84304.us-east-1.aws.found.io:443", + "cloud.id": "cloudidtest:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyQyNDlmM2FmMWY0ZWVlMjRhODRlM2I0MDFlNjhhMWIyYSRkNGFjNzU1OWQ0Njc0YjdjOTFhYmUxMDg1NmQ4NDMwNA==", + "cloud.auth": "elastic:changeme", + }, + }, + { + name: "only cloudid specified", + inCfg: map[string]interface{}{ + "output.elasticsearch.hosts": "localhost:9200", + "cloud.id": "cloudidtest:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyQyNDlmM2FmMWY0ZWVlMjRhODRlM2I0MDFlNjhhMWIyYSRkNGFjNzU1OWQ0Njc0YjdjOTFhYmUxMDg1NmQ4NDMwNA==", + }, + outCfg: map[string]interface{}{ + "output.elasticsearch.hosts": []interface{}{"https://249f3af1f4eee24a84e3b401e68a1b2a.us-east-1.aws.found.io:443"}, + "setup.kibana.host": "https://d4ac7559d4674b7c91abe10856d84304.us-east-1.aws.found.io:443", + "cloud.id": "cloudidtest:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyQyNDlmM2FmMWY0ZWVlMjRhODRlM2I0MDFlNjhhMWIyYSRkNGFjNzU1OWQ0Njc0YjdjOTFhYmUxMDg1NmQ4NDMwNA==", + }, + }, + { + name: "no output defined", + inCfg: map[string]interface{}{ + "cloud.id": "cloudidtest:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyQyNDlmM2FmMWY0ZWVlMjRhODRlM2I0MDFlNjhhMWIyYSRkNGFjNzU1OWQ0Njc0YjdjOTFhYmUxMDg1NmQ4NDMwNA==", + }, + outCfg: map[string]interface{}{ + "output.elasticsearch.hosts": []interface{}{"https://249f3af1f4eee24a84e3b401e68a1b2a.us-east-1.aws.found.io:443"}, + "setup.kibana.host": "https://d4ac7559d4674b7c91abe10856d84304.us-east-1.aws.found.io:443", + "cloud.id": "cloudidtest:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyQyNDlmM2FmMWY0ZWVlMjRhODRlM2I0MDFlNjhhMWIyYSRkNGFjNzU1OWQ0Njc0YjdjOTFhYmUxMDg1NmQ4NDMwNA==", + }, + }, + { + name: "multiple hosts to overwrite", + inCfg: map[string]interface{}{ + "output.elasticsearch.hosts": []string{"localhost:9200", "test", "test1"}, + "cloud.id": "cloudidtest:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyQyNDlmM2FmMWY0ZWVlMjRhODRlM2I0MDFlNjhhMWIyYSRkNGFjNzU1OWQ0Njc0YjdjOTFhYmUxMDg1NmQ4NDMwNA==", + }, + outCfg: map[string]interface{}{ + "output.elasticsearch.hosts": []interface{}{"https://249f3af1f4eee24a84e3b401e68a1b2a.us-east-1.aws.found.io:443"}, + "setup.kibana.host": "https://d4ac7559d4674b7c91abe10856d84304.us-east-1.aws.found.io:443", + "cloud.id": "cloudidtest:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyQyNDlmM2FmMWY0ZWVlMjRhODRlM2I0MDFlNjhhMWIyYSRkNGFjNzU1OWQ0Njc0YjdjOTFhYmUxMDg1NmQ4NDMwNA==", + }, + }, + } + + for _, test := range tests { + t.Logf("Executing test: %s", test.name) + + cfg, err := common.NewConfigFrom(test.inCfg) + assert.NoError(t, err) + + err = OverwriteSettings(cfg) + assert.NoError(t, err) + + var res map[string]interface{} + err = cfg.Unpack(&res) + assert.NoError(t, err) + + var expected map[string]interface{} + expectedCfg, err := common.NewConfigFrom(test.outCfg) + assert.NoError(t, err) + err = expectedCfg.Unpack(&expected) + assert.NoError(t, err) + + assert.Equal(t, res, expected) + } +} + +func TestOverwriteErrors(t *testing.T) { + tests := []struct { + name string + inCfg map[string]interface{} + errMsg string + }{ + { + name: "cloud.auth specified but cloud.id not", + inCfg: map[string]interface{}{ + "cloud.auth": "elastic:changeme", + }, + errMsg: "cloud.auth specified but cloud.id is empty", + }, + { + name: "invalid cloud.id", + inCfg: map[string]interface{}{ + "cloud.id": "blah", + }, + errMsg: "Error decoding cloud.id", + }, + { + name: "invalid cloud.auth", + inCfg: map[string]interface{}{ + "cloud.id": "cloudidtest:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyQyNDlmM2FmMWY0ZWVlMjRhODRlM2I0MDFlNjhhMWIyYSRkNGFjNzU1OWQ0Njc0YjdjOTFhYmUxMDg1NmQ4NDMwNA==", + "cloud.auth": "blah", + }, + errMsg: "cloud.auth setting doesn't contain `:`", + }, + { + name: "logstash output enabled", + inCfg: map[string]interface{}{ + "cloud.id": "cloudidtest:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyQyNDlmM2FmMWY0ZWVlMjRhODRlM2I0MDFlNjhhMWIyYSRkNGFjNzU1OWQ0Njc0YjdjOTFhYmUxMDg1NmQ4NDMwNA==", + "output.logstash.hosts": "localhost:544", + }, + errMsg: "The cloud.id setting enables the Elasticsearch output, but you already have the logstash output enabled", + }, + } + + for _, test := range tests { + t.Logf("Executing test: %s", test.name) + + cfg, err := common.NewConfigFrom(test.inCfg) + assert.NoError(t, err) + + err = OverwriteSettings(cfg) + assert.Error(t, err) + assert.Contains(t, err.Error(), test.errMsg) + } +} diff --git a/libbeat/cmd/instance/beat.go b/libbeat/cmd/instance/beat.go index 6352895aedd..02bb919c6bf 100644 --- a/libbeat/cmd/instance/beat.go +++ b/libbeat/cmd/instance/beat.go @@ -18,6 +18,7 @@ import ( "github.com/elastic/beats/libbeat/api" "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/cfgfile" + "github.com/elastic/beats/libbeat/cloudid" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/cfgwarn" "github.com/elastic/beats/libbeat/common/file" @@ -389,6 +390,11 @@ func (b *Beat) configure() error { return fmt.Errorf("error loading config file: %v", err) } + err = cloudid.OverwriteSettings(cfg) + if err != nil { + return err + } + b.RawConfig = cfg err = cfg.Unpack(&b.Config) if err != nil { diff --git a/libbeat/docs/outputconfig.asciidoc b/libbeat/docs/outputconfig.asciidoc index 61ba17df75a..49a4ed763e0 100644 --- a/libbeat/docs/outputconfig.asciidoc +++ b/libbeat/docs/outputconfig.asciidoc @@ -1093,3 +1093,39 @@ output.console: string: '%{[@timestamp]} %{[message]}' ------------------------------------------------------------------------------ +[[configure-cloud-id]] +=== Configure the output for the Elastic Cloud + +{beatname_uc} comes with two settings that simplify the output configuration +when used together with https://cloud.elastic.co/[Elastic Cloud]. When defined, +these setting overwrite settings from other parts in the configuration. + +Example: + +[source,yaml] +------------------------------------------------------------------------------ +cloud.id: "staging:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRjZWM2ZjI2MWE3NGJmMjRjZTMzYmI4ODExYjg0Mjk0ZiRjNmMyY2E2ZDA0MjI0OWFmMGNjN2Q3YTllOTYyNTc0Mw==" +cloud.auth: "elastic:changeme" +------------------------------------------------------------------------------ + +These settings can be also specified at the command line, like this: + + +["source","sh",subs="attributes,callouts"] +------------------------------------------------------------------------------ +{beatname_lc} -e -E cloud.id="" -E cloud.auth="" +------------------------------------------------------------------------------ + + +==== `cloud.id` + +The Cloud ID, which can be found in the Elastic Cloud web console, is used by +{beatname_uc} to resolve the Elasticsearch and Kibana URLs. This setting +overwrites the `output.elasticsearch.hosts` and `setup.kibana.host` settings. + +==== `cloud.auth` + +When specified, the `cloud.auth` overwrites the `output.elasticsearch.username` and +`output.elasticsearch.password` settings. Because the Kibana settings inherit +the username and password from the Elasticsearch output, this can also be used +to set the `setup.kibana.username` and `setup.kibana.password` options. diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index ebde2b5b23b..01944ee7de9 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -554,6 +554,19 @@ metricbeat.modules: #processors: #- add_docker_metadata: ~ +#============================= Elastic Cloud ================================== + +# These settings simplify using metricbeat with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + #================================ Outputs ====================================== # Configure what outputs to use when sending the data collected by the beat. diff --git a/metricbeat/metricbeat.yml b/metricbeat/metricbeat.yml index 63243270998..dcca623d820 100644 --- a/metricbeat/metricbeat.yml +++ b/metricbeat/metricbeat.yml @@ -54,7 +54,7 @@ setup.template.settings: #============================== Kibana ===================================== -# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. +# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. # This requires a Kibana endpoint configuration. setup.kibana: @@ -64,6 +64,19 @@ setup.kibana: # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601 #host: "localhost:5601" +#============================= Elastic Cloud ================================== + +# These settings simplify using metricbeat with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + #================================ Outputs ===================================== # Configure what outputs to use when sending the data collected by the beat. diff --git a/packetbeat/packetbeat.reference.yml b/packetbeat/packetbeat.reference.yml index e72d7386f8f..d5b82819825 100644 --- a/packetbeat/packetbeat.reference.yml +++ b/packetbeat/packetbeat.reference.yml @@ -562,6 +562,19 @@ packetbeat.protocols: #processors: #- add_docker_metadata: ~ +#============================= Elastic Cloud ================================== + +# These settings simplify using packetbeat with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + #================================ Outputs ====================================== # Configure what outputs to use when sending the data collected by the beat. diff --git a/packetbeat/packetbeat.yml b/packetbeat/packetbeat.yml index 9e5b1c3e61d..a4ce7c78b2d 100644 --- a/packetbeat/packetbeat.yml +++ b/packetbeat/packetbeat.yml @@ -123,7 +123,7 @@ packetbeat.protocols: #============================== Kibana ===================================== -# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. +# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. # This requires a Kibana endpoint configuration. setup.kibana: @@ -133,6 +133,19 @@ setup.kibana: # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601 #host: "localhost:5601" +#============================= Elastic Cloud ================================== + +# These settings simplify using packetbeat with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + #================================ Outputs ===================================== # Configure what outputs to use when sending the data collected by the beat. diff --git a/winlogbeat/winlogbeat.reference.yml b/winlogbeat/winlogbeat.reference.yml index f38bd235a8f..833e5640cad 100644 --- a/winlogbeat/winlogbeat.reference.yml +++ b/winlogbeat/winlogbeat.reference.yml @@ -139,6 +139,19 @@ winlogbeat.event_logs: #processors: #- add_docker_metadata: ~ +#============================= Elastic Cloud ================================== + +# These settings simplify using winlogbeat with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + #================================ Outputs ====================================== # Configure what outputs to use when sending the data collected by the beat. diff --git a/winlogbeat/winlogbeat.yml b/winlogbeat/winlogbeat.yml index ed162e15099..c3d495601e6 100644 --- a/winlogbeat/winlogbeat.yml +++ b/winlogbeat/winlogbeat.yml @@ -53,7 +53,7 @@ winlogbeat.event_logs: #============================== Kibana ===================================== -# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. +# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. # This requires a Kibana endpoint configuration. setup.kibana: @@ -63,6 +63,19 @@ setup.kibana: # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601 #host: "localhost:5601" +#============================= Elastic Cloud ================================== + +# These settings simplify using winlogbeat with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + #================================ Outputs ===================================== # Configure what outputs to use when sending the data collected by the beat. From 5613c5f7cf3d4c7d1ae26852051464c43cae5491 Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Wed, 23 Aug 2017 15:58:25 +0200 Subject: [PATCH 107/139] Move template and codec message to debug level (#4966) Both messages show up on startup of the Beat. I do not think they are required on the Info level, so they are moved to the Debug level. --- libbeat/outputs/codec/json/json.go | 3 --- libbeat/template/load.go | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/libbeat/outputs/codec/json/json.go b/libbeat/outputs/codec/json/json.go index b1ed32d0505..ea74a024305 100644 --- a/libbeat/outputs/codec/json/json.go +++ b/libbeat/outputs/codec/json/json.go @@ -9,7 +9,6 @@ import ( "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs/codec" ) @@ -41,8 +40,6 @@ func init() { } func New(pretty bool) *Encoder { - logp.Info("load json codec") - e := &Encoder{pretty: pretty} e.reset() return e diff --git a/libbeat/template/load.go b/libbeat/template/load.go index 07da99f3af2..a225b26f697 100644 --- a/libbeat/template/load.go +++ b/libbeat/template/load.go @@ -80,7 +80,7 @@ func (l *Loader) Load() error { // template if it exists. If you wish to not overwrite an existing template // then use CheckTemplate prior to calling this method. func (l *Loader) LoadTemplate(templateName string, template map[string]interface{}) error { - logp.Info("load template: %s", templateName) + logp.Debug("template", "Try loading template with name: %s", templateName) path := "/_template/" + templateName body, err := l.client.LoadJSON(path, template) if err != nil { From 807bc43c322703aaa3f82671156589f072a70659 Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Wed, 23 Aug 2017 23:24:03 +0200 Subject: [PATCH 108/139] Filebeat modules: Rename dashboards and visualization (#4952) * Renamed fields in Apache2 and Nginx modules * Renamed Filebeat Auditd dashboards and visualizations Also fixes #4595, there was a missing comma. * Rename the dashboards/viz for the system module This addresses in part #4567. * updated the icinga module dashboard. Also fixed the searches to not depend on the file names * Updated Kafka names This also uses a new ID for the Kafka dashboard (because the old one had spaces) and adds the `module.yml` file. * Updated mysql dashboard * PostgreSQL dashboards updated * Updated redis dashboard * Renamed one more postgres viz --- .../default/dashboard/Filebeat-apache2.json | 80 ++++++++-------- filebeat/module/apache2/module.yml | 4 + .../default/dashboard/Filebeat-auditd.json | 52 +++++------ filebeat/module/auditd/module.yml | 3 + .../dashboard/Filebeat-icinga-debug-log.json | 30 +++--- .../dashboard/Filebeat-icinga-main-log.json | 36 ++++---- .../Filebeat-icinga-startup-errors.json | 26 +++--- filebeat/module/icinga/module.yml | 12 +-- .../dashboard/Filebeat-Kafka-overview.json | 38 +++++--- filebeat/module/kafka/module.yml | 3 + .../default/dashboard/Filebeat-mysql.json | 52 +++++------ filebeat/module/mysql/module.yml | 3 + .../dashboard/Filebeat-nginx-overview.json | 56 ++++++------ ...nginx-access-remote-ip-count-explorer.json | 62 ++++++------- .../ml-nginx-remote-ip-url-explorer.json | 60 ++++++------ filebeat/module/nginx/module.yml | 12 +-- .../Filebeat-Postgresql-overview.json | 36 ++++++-- .../Filebeat-Postgresql-slowlogs.json | 24 ++--- filebeat/module/postgresql/module.yml | 5 + .../default/dashboard/Filebeat-redis.json | 44 ++++----- filebeat/module/redis/module.yml | 3 + .../Filebeat-auth-sudo-commands.json | 53 +++++++---- .../Filebeat-new-users-and-groups.json | 91 +++++++++++-------- .../Filebeat-ssh-login-attempts.json | 71 +++++++++------ .../default/dashboard/Filebeat-syslog.json | 47 ++++++---- filebeat/module/system/module.yml | 16 ++-- metricbeat/module/system/module.yml | 12 +-- 27 files changed, 522 insertions(+), 409 deletions(-) create mode 100644 filebeat/module/apache2/module.yml create mode 100644 filebeat/module/auditd/module.yml create mode 100644 filebeat/module/kafka/module.yml create mode 100644 filebeat/module/mysql/module.yml create mode 100644 filebeat/module/postgresql/module.yml create mode 100644 filebeat/module/redis/module.yml diff --git a/filebeat/module/apache2/_meta/kibana/default/dashboard/Filebeat-apache2.json b/filebeat/module/apache2/_meta/kibana/default/dashboard/Filebeat-apache2.json index de671b52dd4..aeca092d021 100644 --- a/filebeat/module/apache2/_meta/kibana/default/dashboard/Filebeat-apache2.json +++ b/filebeat/module/apache2/_meta/kibana/default/dashboard/Filebeat-apache2.json @@ -4,97 +4,97 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Apache2-access-logs", - "title": "Apache2 access unique IPs map", - "uiStateJSON": "{\"mapCenter\":[14.944784875088372,5.09765625]}", + "title": "Unique IPs map [Filebeat Apache2]", + "uiStateJSON": "{\n \"mapCenter\": [\n 14.944784875088372,\n 5.09765625\n ]\n}", "version": 1, - "visState": "{\"title\":\"Apache2 access unique IPs map\",\"type\":\"tile_map\",\"params\":{\"mapType\":\"Scaled Circle Markers\",\"isDesaturated\":true,\"addTooltip\":true,\"heatMaxZoom\":16,\"heatMinOpacity\":0.1,\"heatRadius\":25,\"heatBlur\":15,\"heatNormalizeData\":true,\"legendPosition\":\"bottomright\",\"mapZoom\":2,\"mapCenter\":[15,5],\"wms\":{\"enabled\":false,\"url\":\"https://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer\",\"options\":{\"version\":\"1.3.0\",\"layers\":\"0\",\"format\":\"image/png\",\"transparent\":true,\"attribution\":\"Maps provided by USGS\",\"styles\":\"\"}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"apache2.access.remote_ip\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"geohash_grid\",\"schema\":\"segment\",\"params\":{\"field\":\"apache2.access.geoip.location\",\"autoPrecision\":true}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Apache2 access unique IPs map\",\n \"type\": \"tile_map\",\n \"params\": {\n \"mapType\": \"Scaled Circle Markers\",\n \"isDesaturated\": true,\n \"addTooltip\": true,\n \"heatMaxZoom\": 16,\n \"heatMinOpacity\": 0.1,\n \"heatRadius\": 25,\n \"heatBlur\": 15,\n \"heatNormalizeData\": true,\n \"legendPosition\": \"bottomright\",\n \"mapZoom\": 2,\n \"mapCenter\": [\n 15,\n 5\n ],\n \"wms\": {\n \"enabled\": false,\n \"url\": \"https://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer\",\n \"options\": {\n \"version\": \"1.3.0\",\n \"layers\": \"0\",\n \"format\": \"image/png\",\n \"transparent\": true,\n \"attribution\": \"Maps provided by USGS\",\n \"styles\": \"\"\n }\n }\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache2.access.remote_ip\"\n }\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"geohash_grid\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"apache2.access.geoip.location\",\n \"autoPrecision\": true\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Apache2-access-unique-IPs-map", "type": "visualization", - "version": 4 + "version": 1 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Apache2-access-logs", - "title": "Apache2 response codes of top URLs", - "uiStateJSON": "{\"vis\":{\"colors\":{\"200\":\"#7EB26D\",\"404\":\"#EF843C\"}}}", + "title": "Top URLs by response code [Filebeat Apache2]", + "uiStateJSON": "{\n \"vis\": {\n \"colors\": {\n \"200\": \"#7EB26D\",\n \"404\": \"#EF843C\"\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"Apache2 response codes of top URLs\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"apache2.access.url\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"URL\",\"row\":false}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"apache2.access.response_code\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Apache2 response codes of top URLs\",\n \"type\": \"pie\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"isDonut\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"split\",\n \"params\": {\n \"field\": \"apache2.access.url\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"URL\",\n \"row\": false\n }\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"apache2.access.response_code\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Apache2-response-codes-of-top-URLs", "type": "visualization", - "version": 4 + "version": 1 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Apache2-access-logs", - "title": "Apache2 browsers", + "title": "Browsers breakdown [Filebeat Apache2]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Apache2 browsers\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"isDonut\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"apache2.access.remote_ip\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"apache2.access.user_agent.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"apache2.access.user_agent.major\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Apache2 browsers\",\n \"type\": \"pie\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"bottom\",\n \"isDonut\": true\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache2.access.remote_ip\"\n }\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"apache2.access.user_agent.name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"apache2.access.user_agent.major\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Apache2-browsers", "type": "visualization", - "version": 4 + "version": 1 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Apache2-access-logs", - "title": "Apache2 operating systems", + "title": "Operating systems breakdown [Filebeat Apache2]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Apache2 operating systems\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"isDonut\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"apache2.access.remote_ip\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"apache2.access.user_agent.os_name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"apache2.access.user_agent.os_major\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Apache2 operating systems\",\n \"type\": \"pie\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"bottom\",\n \"isDonut\": true\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache2.access.remote_ip\"\n }\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"apache2.access.user_agent.os_name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"apache2.access.user_agent.os_major\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Apache2-operating-systems", "type": "visualization", - "version": 4 + "version": 1 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Apache2-errors-log", - "title": "Apache2 error logs over time", + "title": "Error logs over time [Filebeat Apache2]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Apache2 error logs over time\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"apache2.error.level\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Apache2 error logs over time\",\n \"type\": \"histogram\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"apache2.error.level\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Apache2-error-logs-over-time", "type": "visualization", - "version": 4 + "version": 1 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Apache2-access-logs", - "title": "Apache2 response codes over time", - "uiStateJSON": "{\"vis\":{\"colors\":{\"200\":\"#629E51\",\"404\":\"#EF843C\"}}}", + "title": "Response codes over time [Filebeat Apache2]", + "uiStateJSON": "{\n \"vis\": {\n \"colors\": {\n \"200\": \"#629E51\",\n \"404\": \"#EF843C\"\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"Apache2 response codes over time\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"apache2.access.response_code\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Apache2 response codes over time\",\n \"type\": \"histogram\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"apache2.access.response_code\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Apache2-response-codes-over-time", "type": "visualization", - "version": 4 + "version": 1 }, { "attributes": { @@ -107,18 +107,18 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query_string\":{\"query\":\"_exists_:apache2.error\",\"analyze_wildcard\":true}},\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647}}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"_exists_:apache2.error\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": [],\n \"highlight\": {\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n }\n}" }, "sort": [ "@timestamp", "desc" ], - "title": "Apache2 errors log", + "title": "Apache errors log [Filebeat Apache2]", "version": 1 }, "id": "Apache2-errors-log", "type": "search", - "version": 8 + "version": 1 }, { "attributes": { @@ -131,37 +131,37 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query_string\":{\"query\":\"_exists_:apache2.access\",\"analyze_wildcard\":true}},\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647}}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"_exists_:apache2.access\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": [],\n \"highlight\": {\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n }\n}" }, "sort": [ "@timestamp", "desc" ], - "title": "Apache2 access logs", + "title": "Apache access logs [Filebeat Apache2]", "version": 1 }, "id": "Apache2-access-logs", "type": "search", - "version": 20 + "version": 1 }, { "attributes": { - "description": "", + "description": "Filebeat Apache2 module dashboard", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"default_field\":\"*\",\"query\":\"*\"}}},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"Apache2-access-unique-IPs-map\",\"panelIndex\":1,\"row\":1,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Apache2-response-codes-of-top-URLs\",\"panelIndex\":2,\"row\":6,\"size_x\":8,\"size_y\":3,\"type\":\"visualization\"},{\"col\":9,\"id\":\"Apache2-browsers\",\"panelIndex\":3,\"row\":6,\"size_x\":4,\"size_y\":3,\"type\":\"visualization\"},{\"col\":11,\"id\":\"Apache2-operating-systems\",\"panelIndex\":4,\"row\":4,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Apache2-error-logs-over-time\",\"panelIndex\":5,\"row\":9,\"size_x\":12,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Apache2-response-codes-over-time\",\"panelIndex\":6,\"row\":4,\"size_x\":10,\"size_y\":2,\"type\":\"visualization\"},{\"id\":\"Apache2-errors-log\",\"type\":\"search\",\"panelIndex\":7,\"size_x\":12,\"size_y\":3,\"col\":1,\"row\":11,\"columns\":[\"apache2.error.client\",\"apache2.error.level\",\"apache2.error.module\",\"apache2.error.message\"],\"sort\":[\"@timestamp\",\"desc\"]}]", + "panelsJSON": "[{\"col\":1,\"id\":\"Apache2-access-unique-IPs-map\",\"panelIndex\":1,\"row\":1,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Apache2-response-codes-of-top-URLs\",\"panelIndex\":2,\"row\":6,\"size_x\":8,\"size_y\":3,\"type\":\"visualization\"},{\"col\":9,\"id\":\"Apache2-browsers\",\"panelIndex\":3,\"row\":6,\"size_x\":4,\"size_y\":3,\"type\":\"visualization\"},{\"col\":11,\"id\":\"Apache2-operating-systems\",\"panelIndex\":4,\"row\":4,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Apache2-error-logs-over-time\",\"panelIndex\":5,\"row\":9,\"size_x\":12,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Apache2-response-codes-over-time\",\"panelIndex\":6,\"row\":4,\"size_x\":10,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"columns\":[\"apache2.error.client\",\"apache2.error.level\",\"apache2.error.module\",\"apache2.error.message\"],\"id\":\"Apache2-errors-log\",\"panelIndex\":7,\"row\":11,\"size_x\":12,\"size_y\":3,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"}]", "timeRestore": false, - "title": "Filebeat Apache2 Dashboard", - "uiStateJSON": "{\"P-1\":{\"mapCenter\":[40.713955826286046,-0.17578125]}}", + "title": "[Filebeat Apache2] Access and error logs", + "uiStateJSON": "{\"P-1\":{\"mapBounds\":{\"bottom_right\":{\"lat\":-3.864254615721396,\"lon\":205.3125},\"top_left\":{\"lat\":67.7427590666639,\"lon\":-205.6640625}},\"mapCenter\":[40.713955826286046,-0.17578125],\"mapCollar\":{\"top_left\":{\"lat\":90,\"lon\":-180},\"bottom_right\":{\"lat\":-39.667755,\"lon\":180},\"zoom\":2},\"mapZoom\":2}}", "version": 1 }, "id": "Filebeat-Apache2-Dashboard", "type": "dashboard", - "version": 4 + "version": 2 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/filebeat/module/apache2/module.yml b/filebeat/module/apache2/module.yml new file mode 100644 index 00000000000..0ac265bd256 --- /dev/null +++ b/filebeat/module/apache2/module.yml @@ -0,0 +1,4 @@ +dashboards: +- id: Filebeat-Apache2-Dashboard + file: Filebeat-apache2.json + diff --git a/filebeat/module/auditd/_meta/kibana/default/dashboard/Filebeat-auditd.json b/filebeat/module/auditd/_meta/kibana/default/dashboard/Filebeat-auditd.json index 2def2254c97..eae740e04bf 100644 --- a/filebeat/module/auditd/_meta/kibana/default/dashboard/Filebeat-auditd.json +++ b/filebeat/module/auditd/_meta/kibana/default/dashboard/Filebeat-auditd.json @@ -6,29 +6,29 @@ "kibanaSavedObjectMeta": { "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"*\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": []\n}" }, - "title": "Audit Event Types", + "title": "Event types breakdown [Filebeat Auditd]", "uiStateJSON": "{}", "version": 1, "visState": "{\n \"title\": \"Audit Event Types\",\n \"type\": \"pie\",\n \"params\": {\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"isDonut\": true\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"auditd.log.record_type\",\n \"size\": 50,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "6295bdd0-0a0e-11e7-825f-6748cda7d858", "type": "visualization", - "version": 4 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query_string\":{\"query\":\"auditd.log.record_type:EXECVE\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"auditd.log.record_type:EXECVE\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": []\n}" }, - "title": "Audit Top Exec Commands", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "title": "Top Exec Commands [Filebeat Auditd]", + "uiStateJSON": "{\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"Audit Top Exec Commands\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"auditd.log.a0\",\"size\":30,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Command (arg 0)\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Audit Top Exec Commands\",\n \"type\": \"table\",\n \"params\": {\n \"perPage\": 10,\n \"showPartialRows\": false,\n \"showMeticsAtAllLevels\": false,\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n },\n \"showTotal\": false,\n \"totalFunc\": \"sum\"\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"auditd.log.a0\",\n \"size\": 30,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Command (arg 0)\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "5ebdbe50-0a0f-11e7-825f-6748cda7d858", "type": "visualization", - "version": 4 + "version": 2 }, { "attributes": { @@ -36,44 +36,44 @@ "kibanaSavedObjectMeta": { "searchSourceJSON": "{}" }, - "title": "Audit Event Results", + "title": "Event Results [Filebeat Auditd]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"type\":\"timelion\",\"title\":\"Audit Event Results\",\"params\":{\"expression\":\".es(q=\\\"_exists_:auditd.log NOT auditd.log.res:failure\\\").label(\\\"Success\\\") .es(q=\\\"auditd.log.res:failed\\\").label(\\\"Failure\\\").title(\\\"Audit Event Results\\\")\",\"interval\":\"auto\"}}" + "visState": "{\"title\":\"Event Results [Filebeat Auditd]\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(q=\\\"_exists_:auditd.log NOT auditd.log.res:failure\\\").label(\\\"Success\\\"), .es(q=\\\"auditd.log.res:failed\\\").label(\\\"Failure\\\").title(\\\"Audit Event Results\\\")\",\"interval\":\"auto\"},\"aggs\":[]}" }, "id": "2bb0fa70-0a11-11e7-9e84-43da493ad0c7", "type": "visualization", - "version": 4 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"*\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": []\n}" }, - "title": "Audit Event Address Geo Location", + "title": "Event Address Geo Location [Filebeat Auditd]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Audit Event Address Geo Location\",\"type\":\"tile_map\",\"params\":{\"mapType\":\"Scaled Circle Markers\",\"isDesaturated\":true,\"addTooltip\":true,\"heatMaxZoom\":16,\"heatMinOpacity\":0.1,\"heatRadius\":25,\"heatBlur\":15,\"heatNormalizeData\":true,\"legendPosition\":\"bottomright\",\"mapZoom\":2,\"mapCenter\":[15,5],\"wms\":{\"enabled\":false,\"url\":\"https://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer\",\"options\":{\"version\":\"1.3.0\",\"layers\":\"0\",\"format\":\"image/png\",\"transparent\":true,\"attribution\":\"Maps provided by USGS\",\"styles\":\"\"}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"geohash_grid\",\"schema\":\"segment\",\"params\":{\"field\":\"auditd.log.geoip.location\",\"autoPrecision\":true,\"precision\":2}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Audit Event Address Geo Location\",\n \"type\": \"tile_map\",\n \"params\": {\n \"mapType\": \"Scaled Circle Markers\",\n \"isDesaturated\": true,\n \"addTooltip\": true,\n \"heatMaxZoom\": 16,\n \"heatMinOpacity\": 0.1,\n \"heatRadius\": 25,\n \"heatBlur\": 15,\n \"heatNormalizeData\": true,\n \"legendPosition\": \"bottomright\",\n \"mapZoom\": 2,\n \"mapCenter\": [\n 15,\n 5\n ],\n \"wms\": {\n \"enabled\": false,\n \"url\": \"https://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer\",\n \"options\": {\n \"version\": \"1.3.0\",\n \"layers\": \"0\",\n \"format\": \"image/png\",\n \"transparent\": true,\n \"attribution\": \"Maps provided by USGS\",\n \"styles\": \"\"\n }\n }\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"geohash_grid\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"auditd.log.geoip.location\",\n \"autoPrecision\": true,\n \"precision\": 2\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "d1726930-0a7f-11e7-8b04-eb22a5669f27", "type": "visualization", - "version": 4 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"*\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": []\n}" }, - "title": "Audit Event Account Tag Cloud", + "title": "Event Account Tag Cloud [Filebeat Auditd]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Audit Event Account Tag Cloud\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":15,\"maxFontSize\":42,\"hideLabel\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"auditd.log.acct\",\"size\":15,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Audit Event Account Tag Cloud\",\n \"type\": \"tagcloud\",\n \"params\": {\n \"scale\": \"linear\",\n \"orientation\": \"single\",\n \"minFontSize\": 15,\n \"maxFontSize\": 42,\n \"hideLabel\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"auditd.log.acct\",\n \"size\": 15,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "c5411910-0a87-11e7-8b04-eb22a5669f27", "type": "visualization", - "version": 4 + "version": 2 }, { "attributes": { @@ -85,31 +85,31 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query_string\":{\"query\":\"_exists_:auditd.log\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"highlightAll\": true,\n \"version\": true,\n \"query\": {\n \"query_string\": {\n \"query\": \"_exists_:auditd.log\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": []\n}" }, "sort": [ "@timestamp", "desc" ], - "title": "Audit Events", + "title": "Audit Events [Filebeat Auditd]", "version": 1 }, "id": "4ac0a370-0a11-11e7-8b04-eb22a5669f27", "type": "search", - "version": 4 + "version": 2 }, { "attributes": { - "description": "", + "description": "Dashboard for the Auditd Filebeat module", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}],\"highlightAll\":true,\"version\":true}" + "searchSourceJSON": "{\"filter\":[],\"highlightAll\":true,\"version\":true,\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\",\"default_field\":\"*\"}},\"language\":\"lucene\"}}" }, "optionsJSON": "{\"darkTheme\":false}", "panelsJSON": "[{\"col\":1,\"id\":\"6295bdd0-0a0e-11e7-825f-6748cda7d858\",\"panelIndex\":1,\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":9,\"id\":\"5ebdbe50-0a0f-11e7-825f-6748cda7d858\",\"panelIndex\":2,\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"2bb0fa70-0a11-11e7-9e84-43da493ad0c7\",\"panelIndex\":3,\"row\":5,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"d1726930-0a7f-11e7-8b04-eb22a5669f27\",\"panelIndex\":5,\"row\":5,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"c5411910-0a87-11e7-8b04-eb22a5669f27\",\"panelIndex\":6,\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"size_x\":12,\"size_y\":3,\"panelIndex\":7,\"type\":\"search\",\"id\":\"4ac0a370-0a11-11e7-8b04-eb22a5669f27\",\"col\":1,\"row\":8,\"columns\":[\"auditd.log.record_type\",\"auditd.log.sequence\",\"auditd.log.acct\"],\"sort\":[\"@timestamp\",\"desc\"]}]", "timeRestore": false, - "title": "Filebeat Auditd", - "uiStateJSON": "{\"P-2\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", + "title": "[Filebeat Auditd] Audit Events", + "uiStateJSON": "{\"P-2\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-5\":{\"mapZoom\":2,\"mapBounds\":{\"bottom_right\":{\"lat\":-43.580390855607845,\"lon\":102.65625},\"top_left\":{\"lat\":43.58039085560784,\"lon\":-102.3046875}},\"mapCollar\":{\"top_left\":{\"lat\":87.16078,\"lon\":-180},\"bottom_right\":{\"lat\":-87.16078,\"lon\":180},\"zoom\":2}}}", "version": 1 }, "id": "dfbb49f0-0a0f-11e7-8a62-2d05eaaac5cb", @@ -117,5 +117,5 @@ "version": 4 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/filebeat/module/auditd/module.yml b/filebeat/module/auditd/module.yml new file mode 100644 index 00000000000..d7f9dd13eb6 --- /dev/null +++ b/filebeat/module/auditd/module.yml @@ -0,0 +1,3 @@ +dashboards: +- id: dfbb49f0-0a0f-11e7-8a62-2d05eaaac5cb + file: Filebeat-auditd.json diff --git a/filebeat/module/icinga/_meta/kibana/default/dashboard/Filebeat-icinga-debug-log.json b/filebeat/module/icinga/_meta/kibana/default/dashboard/Filebeat-icinga-debug-log.json index 7d258fd01c1..10db7b372a5 100644 --- a/filebeat/module/icinga/_meta/kibana/default/dashboard/Filebeat-icinga-debug-log.json +++ b/filebeat/module/icinga/_meta/kibana/default/dashboard/Filebeat-icinga-debug-log.json @@ -4,13 +4,13 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "c876e6a0-2418-11e7-a83b-d5f4cebac9ff", - "title": "Icinga Debuglog Facility", + "title": "Debuglog Facility [Filebeat Icinga]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Icinga Debuglog Facility\",\"type\":\"histogram\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"icinga.debug.facility\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Icinga Debuglog Facility\",\n \"type\": \"histogram\",\n \"params\": {\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"icinga.debug.facility\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "0bc34b60-2419-11e7-a83b-d5f4cebac9ff", "type": "visualization", @@ -20,13 +20,13 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "c876e6a0-2418-11e7-a83b-d5f4cebac9ff", - "title": "Icinga Debuglog Severity", - "uiStateJSON": "{\"vis\":{\"colors\":{\"information\":\"#629E51\",\"warning\":\"#E5AC0E\",\"debug\":\"#BA43A9\",\"notice\":\"#6ED0E0\"}}}", + "title": "Debuglog Severity [Filebeat Icinga]", + "uiStateJSON": "{\n \"vis\": {\n \"colors\": {\n \"information\": \"#629E51\",\n \"warning\": \"#E5AC0E\",\n \"debug\": \"#BA43A9\",\n \"notice\": \"#6ED0E0\"\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"Icinga Debuglog Severity\",\"type\":\"histogram\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"icinga.debug.severity\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Icinga Debuglog Severity\",\n \"type\": \"histogram\",\n \"params\": {\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"icinga.debug.severity\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "fb09d4b0-2418-11e7-a83b-d5f4cebac9ff", "type": "visualization", @@ -42,30 +42,30 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"query\":{\"query_string\":{\"query\":\"source:*icinga2\\\\/debug.log\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"query\":{\"query\":\"*\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"index\":\"filebeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"fileset.module\",\"value\":\"icinga\",\"params\":{\"query\":\"icinga\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"fileset.module\":{\"query\":\"icinga\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}},{\"meta\":{\"index\":\"filebeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"fileset.name\",\"value\":\"debug\",\"params\":{\"query\":\"debug\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"fileset.name\":{\"query\":\"debug\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"version\":true}" }, "sort": [ "@timestamp", "desc" ], - "title": "Icinga Debug Log", + "title": "Debug Log [Filebeat Icinga]", "version": 1 }, "id": "c876e6a0-2418-11e7-a83b-d5f4cebac9ff", "type": "search", - "version": 4 + "version": 2 }, { "attributes": { - "description": "", + "description": "Filebeat Icinga module dashboard for the debug logs", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"default_field\":\"*\",\"query\":\"*\"}}},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"size_x\":6,\"size_y\":3,\"panelIndex\":1,\"type\":\"visualization\",\"id\":\"0bc34b60-2419-11e7-a83b-d5f4cebac9ff\",\"col\":1,\"row\":1},{\"size_x\":6,\"size_y\":3,\"panelIndex\":2,\"type\":\"visualization\",\"id\":\"fb09d4b0-2418-11e7-a83b-d5f4cebac9ff\",\"col\":7,\"row\":1},{\"size_x\":12,\"size_y\":29,\"panelIndex\":3,\"type\":\"search\",\"id\":\"c876e6a0-2418-11e7-a83b-d5f4cebac9ff\",\"col\":1,\"row\":4,\"columns\":[\"icinga.debug.facility\",\"icinga.debug.severity\",\"icinga.debug.message\"],\"sort\":[\"@timestamp\",\"desc\"]}]", + "panelsJSON": "[{\"col\":1,\"id\":\"0bc34b60-2419-11e7-a83b-d5f4cebac9ff\",\"panelIndex\":1,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"fb09d4b0-2418-11e7-a83b-d5f4cebac9ff\",\"panelIndex\":2,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"columns\":[\"icinga.debug.facility\",\"icinga.debug.severity\",\"icinga.debug.message\"],\"id\":\"c876e6a0-2418-11e7-a83b-d5f4cebac9ff\",\"panelIndex\":3,\"row\":4,\"size_x\":12,\"size_y\":29,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"}]", "timeRestore": false, - "title": "Icinga Debug Log", + "title": "[Filebeat Icinga] Debug Log", "uiStateJSON": "{}", "version": 1 }, @@ -74,5 +74,5 @@ "version": 2 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/filebeat/module/icinga/_meta/kibana/default/dashboard/Filebeat-icinga-main-log.json b/filebeat/module/icinga/_meta/kibana/default/dashboard/Filebeat-icinga-main-log.json index bc9893d6f8c..fc3cb86eac6 100644 --- a/filebeat/module/icinga/_meta/kibana/default/dashboard/Filebeat-icinga-main-log.json +++ b/filebeat/module/icinga/_meta/kibana/default/dashboard/Filebeat-icinga-main-log.json @@ -4,17 +4,17 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "ffaf5a30-2413-11e7-a0d9-39604d45ca7f", - "title": "Icinga Mainlog Severity", - "uiStateJSON": "{\"vis\":{\"colors\":{\"warning\":\"#E5AC0E\",\"critical\":\"#BF1B00\"}}}", + "title": "Mainlog Severity [Filebeat Icinga]", + "uiStateJSON": "{\n \"vis\": {\n \"colors\": {\n \"warning\": \"#E5AC0E\",\n \"critical\": \"#BF1B00\"\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"Icinga Mainlog Severity\",\"type\":\"histogram\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"icinga.main.severity\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Icinga Mainlog Severity\",\n \"type\": \"histogram\",\n \"params\": {\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"icinga.main.severity\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "d8e5dc40-2417-11e7-a83b-d5f4cebac9ff", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { @@ -26,53 +26,53 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"query\":{\"query_string\":{\"query\":\"source:*icinga2.log\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"index\":\"filebeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"fileset.module\",\"value\":\"icinga\",\"params\":{\"query\":\"icinga\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"fileset.module\":{\"query\":\"icinga\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}},{\"meta\":{\"index\":\"filebeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"fileset.name\",\"value\":\"main\",\"params\":{\"query\":\"main\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"fileset.name\":{\"query\":\"main\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"version\":true}" }, "sort": [ "@timestamp", "desc" ], - "title": "Icinga Main Log", + "title": "Main Log [Filebeat Icinga]", "version": 1 }, "id": "ffaf5a30-2413-11e7-a0d9-39604d45ca7f", "type": "search", - "version": 3 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "ffaf5a30-2413-11e7-a0d9-39604d45ca7f", - "title": "Icinga Mainlog Facility", + "title": "Mainlog Facility [Filebeat Icinga]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Icinga Mainlog Facility\",\"type\":\"histogram\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"icinga.main.facility\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Icinga Mainlog Facility\",\n \"type\": \"histogram\",\n \"params\": {\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"icinga.main.facility\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "2cf77780-2418-11e7-a83b-d5f4cebac9ff", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { - "description": "", + "description": "Filebeat Icinga module dashboard for the main log files", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"default_field\":\"*\",\"query\":\"*\"}}},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":7,\"id\":\"d8e5dc40-2417-11e7-a83b-d5f4cebac9ff\",\"panelIndex\":1,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"columns\":[\"icinga.main.facility\",\"icinga.main.severity\",\"icinga.main.message\"],\"id\":\"ffaf5a30-2413-11e7-a0d9-39604d45ca7f\",\"panelIndex\":2,\"row\":4,\"size_x\":12,\"size_y\":25,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"size_x\":6,\"size_y\":3,\"panelIndex\":3,\"type\":\"visualization\",\"id\":\"2cf77780-2418-11e7-a83b-d5f4cebac9ff\",\"col\":1,\"row\":1}]", + "panelsJSON": "[{\"col\":7,\"id\":\"d8e5dc40-2417-11e7-a83b-d5f4cebac9ff\",\"panelIndex\":1,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"columns\":[\"icinga.main.facility\",\"icinga.main.severity\",\"icinga.main.message\"],\"id\":\"ffaf5a30-2413-11e7-a0d9-39604d45ca7f\",\"panelIndex\":2,\"row\":4,\"size_x\":12,\"size_y\":25,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"col\":1,\"id\":\"2cf77780-2418-11e7-a83b-d5f4cebac9ff\",\"panelIndex\":3,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"}]", "timeRestore": false, - "title": "Icinga Main Log", + "title": "[Filebeat Icinga] Main Log", "uiStateJSON": "{}", "version": 1 }, "id": "f693d260-2417-11e7-a83b-d5f4cebac9ff", "type": "dashboard", - "version": 1 + "version": 4 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/filebeat/module/icinga/_meta/kibana/default/dashboard/Filebeat-icinga-startup-errors.json b/filebeat/module/icinga/_meta/kibana/default/dashboard/Filebeat-icinga-startup-errors.json index 06e267a558b..c83e64028bd 100644 --- a/filebeat/module/icinga/_meta/kibana/default/dashboard/Filebeat-icinga-startup-errors.json +++ b/filebeat/module/icinga/_meta/kibana/default/dashboard/Filebeat-icinga-startup-errors.json @@ -4,17 +4,17 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "710043e0-2417-11e7-a83b-d5f4cebac9ff", - "title": "Icinga Startup Errors", - "uiStateJSON": "{\"vis\":{\"colors\":{\"Count\":\"#BF1B00\"}}}", + "title": "Startup Errors [Filebeat Icinga]", + "uiStateJSON": "{\n \"vis\": {\n \"colors\": {\n \"Count\": \"#BF1B00\"\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"Icinga Startup Errors\",\"type\":\"histogram\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Icinga Startup Errors\",\n \"type\": \"histogram\",\n \"params\": {\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "a59b5e00-2417-11e7-a83b-d5f4cebac9ff", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { @@ -26,13 +26,13 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"query\":{\"query_string\":{\"query\":\"icinga.startup.severity:critical\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"query\":{\"query\":{\"query_string\":{\"query\":\"icinga.startup.severity:critical\",\"analyze_wildcard\":true,\"default_field\":\"*\"}},\"language\":\"lucene\"},\"filter\":[],\"version\":true}" }, "sort": [ "@timestamp", "desc" ], - "title": "Icinga Startup Errors", + "title": "Startup Errors [Filebeat Icinga]", "version": 1 }, "id": "710043e0-2417-11e7-a83b-d5f4cebac9ff", @@ -41,22 +41,22 @@ }, { "attributes": { - "description": "", + "description": "Filebeat Icinga module dashboard for startup errors", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"default_field\":\"*\",\"query\":\"*\"}}},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"size_x\":12,\"size_y\":2,\"panelIndex\":1,\"type\":\"visualization\",\"id\":\"a59b5e00-2417-11e7-a83b-d5f4cebac9ff\",\"col\":1,\"row\":1},{\"size_x\":12,\"size_y\":13,\"panelIndex\":2,\"type\":\"search\",\"id\":\"710043e0-2417-11e7-a83b-d5f4cebac9ff\",\"col\":1,\"row\":3,\"columns\":[\"icinga.startup.facility\",\"icinga.startup.severity\",\"icinga.startup.message\"],\"sort\":[\"@timestamp\",\"desc\"]}]", + "panelsJSON": "[{\"col\":1,\"id\":\"a59b5e00-2417-11e7-a83b-d5f4cebac9ff\",\"panelIndex\":1,\"row\":1,\"size_x\":12,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"columns\":[\"icinga.startup.facility\",\"icinga.startup.severity\",\"icinga.startup.message\"],\"id\":\"710043e0-2417-11e7-a83b-d5f4cebac9ff\",\"panelIndex\":2,\"row\":3,\"size_x\":12,\"size_y\":13,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"}]", "timeRestore": false, - "title": "Icinga Startup Errors", + "title": "[Filebeat Icinga] Startup Errors", "uiStateJSON": "{}", "version": 1 }, "id": "b9163ea0-2417-11e7-a83b-d5f4cebac9ff", "type": "dashboard", - "version": 1 + "version": 2 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/filebeat/module/icinga/module.yml b/filebeat/module/icinga/module.yml index 714fb6cf3a7..c5b53d65b2b 100644 --- a/filebeat/module/icinga/module.yml +++ b/filebeat/module/icinga/module.yml @@ -1,10 +1,10 @@ dashboards: - - id: 26309570-2419-11e7-a83b-d5f4cebac9ff - file: Filebeat-icinga-debug-log.json +- id: 26309570-2419-11e7-a83b-d5f4cebac9ff + file: Filebeat-icinga-debug-log.json - - id: b9163ea0-2417-11e7-a83b-d5f4cebac9ff - file: Filebeat-icinga-startup-errors.json +- id: b9163ea0-2417-11e7-a83b-d5f4cebac9ff + file: Filebeat-icinga-startup-errors.json - - id: f693d260-2417-11e7-a83b-d5f4cebac9ff - file: Filebeat-icinga-main-log.json +- id: f693d260-2417-11e7-a83b-d5f4cebac9ff + file: Filebeat-icinga-main-log.json diff --git a/filebeat/module/kafka/_meta/kibana/default/dashboard/Filebeat-Kafka-overview.json b/filebeat/module/kafka/_meta/kibana/default/dashboard/Filebeat-Kafka-overview.json index 7b5d03e48ee..c21c9c2ac80 100644 --- a/filebeat/module/kafka/_meta/kibana/default/dashboard/Filebeat-Kafka-overview.json +++ b/filebeat/module/kafka/_meta/kibana/default/dashboard/Filebeat-Kafka-overview.json @@ -4,17 +4,17 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Kafka stacktraces", - "title": "Number of Kafka stracktraces by class", + "title": "Number of stracktraces by class [Filebeat Kafka]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Number of Kafka stracktraces by class\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{\"text\":\"@timestamp per 30 minutes\"}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"kafka.log.trace.class\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\"}}]}" + "visState": "{\n \"title\": \"Number of Kafka stracktraces by class\",\n \"type\": \"histogram\",\n \"params\": {\n \"type\": \"histogram\",\n \"grid\": {\n \"categoryLines\": false,\n \"style\": {\n \"color\": \"#eee\"\n }\n },\n \"categoryAxes\": [\n {\n \"id\": \"CategoryAxis-1\",\n \"type\": \"category\",\n \"position\": \"bottom\",\n \"show\": true,\n \"style\": {},\n \"scale\": {\n \"type\": \"linear\"\n },\n \"labels\": {\n \"show\": true,\n \"truncate\": 100\n },\n \"title\": {\n \"text\": \"@timestamp per 30 minutes\"\n }\n }\n ],\n \"valueAxes\": [\n {\n \"id\": \"ValueAxis-1\",\n \"name\": \"LeftAxis-1\",\n \"type\": \"value\",\n \"position\": \"left\",\n \"show\": true,\n \"style\": {},\n \"scale\": {\n \"type\": \"linear\",\n \"mode\": \"normal\"\n },\n \"labels\": {\n \"show\": true,\n \"rotate\": 0,\n \"filter\": false,\n \"truncate\": 100\n },\n \"title\": {\n \"text\": \"Count\"\n }\n }\n ],\n \"seriesParams\": [\n {\n \"show\": \"true\",\n \"type\": \"histogram\",\n \"mode\": \"stacked\",\n \"data\": {\n \"label\": \"Count\",\n \"id\": \"1\"\n },\n \"valueAxis\": \"ValueAxis-1\",\n \"drawLinesBetweenPoints\": true,\n \"showCircles\": true\n }\n ],\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"times\": [],\n \"addTimeMarker\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"kafka.log.trace.class\",\n \"size\": 10,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ]\n}" }, "id": "Number of Kafka stracktraces by class", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { @@ -32,7 +32,7 @@ "@timestamp", "desc" ], - "title": "Kafka stacktraces", + "title": "Stacktraces [Filebeat Kafka]", "version": 1 }, "id": "Kafka stacktraces", @@ -49,13 +49,13 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"kafka.log.level:*\",\"language\":\"lucene\"},\"filter\":[]}" + "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"*\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"index\":\"filebeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"fileset.module\",\"value\":\"kafka\",\"params\":{\"query\":\"kafka\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"fileset.module\":{\"query\":\"kafka\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}},{\"meta\":{\"index\":\"filebeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"fileset.name\",\"value\":\"log\",\"params\":{\"query\":\"log\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"fileset.name\":{\"query\":\"log\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}]}" }, "sort": [ "@timestamp", "desc" ], - "title": "All Kafka logs", + "title": "All logs [Filebeat Kafka]", "version": 1 }, "id": "All Kafka logs", @@ -65,21 +65,37 @@ { "attributes": { "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "All Kafka logs", + "title": "Log levels over time [Filebeat Kafka]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Log levels over time [Filebeat Kafka]\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{\"text\":\"@timestamp per day\"}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"kafka.log.level\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Log Level\"}}]}" + }, + "id": "3f7c33c0-87ee-11e7-ad9c-db80de0bf8d3", + "type": "visualization", + "version": 1 + }, + { + "attributes": { + "description": "Filebeat Kafka module dashboard", "hits": 0, "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"Number of Kafka stracktraces by class\",\"panelIndex\":1,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"columns\":[\"kafka.log.class\",\"kafka.log.trace.class\",\"kafka.log.trace.full\"],\"id\":\"Kafka stacktraces\",\"panelIndex\":2,\"row\":1,\"size_x\":6,\"size_y\":3,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"size_x\":12,\"size_y\":3,\"panelIndex\":3,\"type\":\"search\",\"id\":\"All Kafka logs\",\"col\":1,\"row\":4,\"columns\":[\"kafka.log.level\",\"kafka.log.component\",\"kafka.log.message\"],\"sort\":[\"@timestamp\",\"desc\"]}]", + "panelsJSON": "[{\"col\":1,\"id\":\"Number of Kafka stracktraces by class\",\"panelIndex\":1,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"columns\":[\"kafka.log.class\",\"kafka.log.trace.class\",\"kafka.log.trace.full\"],\"id\":\"Kafka stacktraces\",\"panelIndex\":2,\"row\":1,\"size_x\":6,\"size_y\":3,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"col\":1,\"columns\":[\"kafka.log.level\",\"kafka.log.component\",\"kafka.log.message\"],\"id\":\"All Kafka logs\",\"panelIndex\":3,\"row\":6,\"size_x\":12,\"size_y\":5,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"size_x\":12,\"size_y\":2,\"panelIndex\":4,\"type\":\"visualization\",\"id\":\"3f7c33c0-87ee-11e7-ad9c-db80de0bf8d3\",\"col\":1,\"row\":4}]", "timeRestore": false, - "title": "Kafka logs overview", + "title": "[Filebeat Kafka] Overview", "uiStateJSON": "{}", "version": 1 }, - "id": "Kafka logs overview", + "id": "943caca0-87ee-11e7-ad9c-db80de0bf8d3", "type": "dashboard", "version": 1 } ], "version": "6.0.0-beta1-SNAPSHOT" -} +} \ No newline at end of file diff --git a/filebeat/module/kafka/module.yml b/filebeat/module/kafka/module.yml new file mode 100644 index 00000000000..1e307dc3bf5 --- /dev/null +++ b/filebeat/module/kafka/module.yml @@ -0,0 +1,3 @@ +dashboards: +- id: 943caca0-87ee-11e7-ad9c-db80de0bf8d3 + file: Filebeat-Kafka-overview.json diff --git a/filebeat/module/mysql/_meta/kibana/default/dashboard/Filebeat-mysql.json b/filebeat/module/mysql/_meta/kibana/default/dashboard/Filebeat-mysql.json index 29d19fe7a1c..c370205c440 100644 --- a/filebeat/module/mysql/_meta/kibana/default/dashboard/Filebeat-mysql.json +++ b/filebeat/module/mysql/_meta/kibana/default/dashboard/Filebeat-mysql.json @@ -7,14 +7,14 @@ "searchSourceJSON": "{\"filter\":[]}" }, "savedSearchId": "Filebeat-MySQL-Slow-log", - "title": "MySQL slowest queries", + "title": "Top slowest queries [Filebeat MySQL]", "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", "version": 1, - "visState": "{\"title\":\"MySQL slowest queries\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"mysql.slowlog.query_time.sec\",\"customLabel\":\"Query time\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"mysql.slowlog.query\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Query\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"mysql.slowlog.user\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"User\"}}],\"listeners\":{}}" + "visState": "{\"title\":\"Top slowest queries [Filebeat MySQL]\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"mysql.slowlog.query_time.sec\",\"customLabel\":\"Query time\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"mysql.slowlog.query\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Query\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"mysql.slowlog.user\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"User\"}}]}" }, "id": "MySQL-slowest-queries", "type": "visualization", - "version": 4 + "version": 1 }, { "attributes": { @@ -23,14 +23,14 @@ "searchSourceJSON": "{\"filter\":[]}" }, "savedSearchId": "Filebeat-MySQL-Slow-log", - "title": "MySQL Slow queries over time", + "title": "Slow queries over time [Filebeat MySQL]", "uiStateJSON": "{\"vis\":{\"colors\":{\"Slow queries\":\"#EF843C\"}}}", "version": 1, - "visState": "{\"title\":\"MySQL Slow queries over time\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Slow queries\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" + "visState": "{\"title\":\"Slow queries over time [Filebeat MySQL]\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{},\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{\"text\":\"@timestamp per 30 seconds\"}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Slow queries\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Slow queries\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Slow queries\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}]}" }, "id": "MySQL-Slow-queries-over-time", "type": "visualization", - "version": 4 + "version": 1 }, { "attributes": { @@ -39,14 +39,14 @@ "searchSourceJSON": "{\"filter\":[]}" }, "savedSearchId": "Filebeat-MySQL-error-log", - "title": "MySQL error logs", + "title": "Error logs over time [Filebeat MySQL]", "uiStateJSON": "{\"vis\":{\"colors\":{\"Count\":\"#447EBC\",\"Error logs\":\"#1F78C1\"}}}", "version": 1, - "visState": "{\"title\":\"MySQL error logs\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Error logs\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" + "visState": "{\"title\":\"Error logs over time [Filebeat MySQL]\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{},\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{\"text\":\"@timestamp per 30 seconds\"}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Error logs\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Error logs\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Error logs\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}]}" }, "id": "MySQL-error-logs", "type": "visualization", - "version": 4 + "version": 1 }, { "attributes": { @@ -57,18 +57,18 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query_string\":{\"query\":\"_exists_:mysql.error\",\"analyze_wildcard\":true}},\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647}}" + "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query\":\"*\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"index\":\"filebeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"fileset.module\",\"value\":\"mysql\",\"params\":{\"query\":\"mysql\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"fileset.module\":{\"query\":\"mysql\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}},{\"meta\":{\"index\":\"filebeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"fileset.name\",\"value\":\"error\",\"params\":{\"query\":\"error\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"fileset.name\":{\"query\":\"error\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"highlightAll\":true,\"version\":true}" }, "sort": [ "@timestamp", "desc" ], - "title": "Filebeat MySQL error log", + "title": "Error logs [Filebeat MySQL]", "version": 1 }, "id": "Filebeat-MySQL-error-log", "type": "search", - "version": 12 + "version": 1 }, { "attributes": { @@ -77,14 +77,14 @@ "searchSourceJSON": "{\"filter\":[]}" }, "savedSearchId": "Filebeat-MySQL-error-log", - "title": "MySQL Error logs levels", + "title": "Error logs levels breakdown [Filebeat MySQL]", "uiStateJSON": "{\"vis\":{\"colors\":{\"Note\":\"#9AC48A\",\"Warning\":\"#F9934E\",\"ERROR\":\"#E24D42\"}}}", "version": 1, - "visState": "{\"title\":\"MySQL Error logs levels\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"mysql.error.level\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\"title\":\"Error logs levels breakdown [Filebeat MySQL]\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"isDonut\":false,\"type\":\"pie\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"mysql.error.level\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}" }, "id": "MySQL-Error-logs-levels", "type": "visualization", - "version": 4 + "version": 1 }, { "attributes": { @@ -93,14 +93,14 @@ "searchSourceJSON": "{\"filter\":[]}" }, "savedSearchId": "Filebeat-MySQL-Slow-log", - "title": "MySQL Slow logs by count", + "title": "Slow logs breakdown [Filebeat MySQL]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"MySQL Slow logs by count\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"mysql.slowlog.query\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\"title\":\"Slow logs breakdown [Filebeat MySQL]\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"isDonut\":false,\"type\":\"pie\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"mysql.slowlog.query\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}" }, "id": "MySQL-Slow-logs-by-count", "type": "visualization", - "version": 4 + "version": 1 }, { "attributes": { @@ -110,37 +110,37 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"_exists_:mysql.slowlog\"}},\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647}}" + "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query\":\"*\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"index\":\"filebeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"fileset.module\",\"value\":\"mysql\",\"params\":{\"query\":\"mysql\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"fileset.module\":{\"query\":\"mysql\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}},{\"meta\":{\"index\":\"filebeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"fileset.name\",\"value\":\"slowlog\",\"params\":{\"query\":\"slowlog\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"fileset.name\":{\"query\":\"slowlog\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"highlightAll\":true,\"version\":true}" }, "sort": [ "@timestamp", "desc" ], - "title": "Filebeat MySQL Slow log", + "title": "Slow logs [Filebeat MySQL]", "version": 1 }, "id": "Filebeat-MySQL-Slow-log", "type": "search", - "version": 12 + "version": 1 }, { "attributes": { - "description": "", + "description": "Overview dashboard for the Filebeat MySQL module", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\",\"default_field\":\"*\"}},\"language\":\"lucene\"},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", "panelsJSON": "[{\"col\":1,\"id\":\"MySQL-slowest-queries\",\"panelIndex\":1,\"row\":8,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"MySQL-Slow-queries-over-time\",\"panelIndex\":2,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"MySQL-error-logs\",\"panelIndex\":3,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"columns\":[\"mysql.error.level\",\"mysql.error.message\"],\"id\":\"Filebeat-MySQL-error-log\",\"panelIndex\":4,\"row\":8,\"size_x\":6,\"size_y\":5,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"col\":7,\"id\":\"MySQL-Error-logs-levels\",\"panelIndex\":5,\"row\":4,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"MySQL-Slow-logs-by-count\",\"panelIndex\":6,\"row\":4,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"}]", "timeRestore": false, - "title": "Filebeat MySQL Dashboard", + "title": "[Filebeat MySQL] Overview", "uiStateJSON": "{\"P-1\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", "version": 1 }, "id": "Filebeat-MySQL-Dashboard", "type": "dashboard", - "version": 4 + "version": 2 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/filebeat/module/mysql/module.yml b/filebeat/module/mysql/module.yml new file mode 100644 index 00000000000..48dbd6d3076 --- /dev/null +++ b/filebeat/module/mysql/module.yml @@ -0,0 +1,3 @@ +dashboards: +- id: Filebeat-MySQL-Dashboard + file: Filebeat-mysql.json diff --git a/filebeat/module/nginx/_meta/kibana/default/dashboard/Filebeat-nginx-overview.json b/filebeat/module/nginx/_meta/kibana/default/dashboard/Filebeat-nginx-overview.json index 59e53a9ff1d..da29df38743 100644 --- a/filebeat/module/nginx/_meta/kibana/default/dashboard/Filebeat-nginx-overview.json +++ b/filebeat/module/nginx/_meta/kibana/default/dashboard/Filebeat-nginx-overview.json @@ -6,7 +6,7 @@ "kibanaSavedObjectMeta": { "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"*\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": []\n}" }, - "title": "Nginx Errors over time", + "title": "Errors over time [Filebeat Nginx]", "uiStateJSON": "{}", "version": 1, "visState": "{\n \"title\": \"Errors over time\",\n \"type\": \"area\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"smoothLines\": false,\n \"scale\": \"linear\",\n \"interpolate\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"nginx.error.level\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" @@ -19,12 +19,12 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"*\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": []\n}" }, - "title": "Nginx Access Browsers", + "title": "Browsers breakdown [Filebeat Nginx]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Nginx Access Browsers\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"isDonut\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"nginx.access.user_agent.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"nginx.access.user_agent.major\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Nginx Access Browsers\",\n \"type\": \"pie\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"bottom\",\n \"isDonut\": true\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"nginx.access.user_agent.name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"nginx.access.user_agent.major\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Nginx-Access-Browsers", "type": "visualization", @@ -34,12 +34,12 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"*\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": []\n}" }, - "title": "Nginx Access OSes", + "title": "Operating systems breakdown [Filebeat Nginx]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Nginx Access OSes\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"isDonut\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"nginx.access.user_agent.os_name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"nginx.access.user_agent.os_major\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Nginx Access OSes\",\n \"type\": \"pie\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"bottom\",\n \"isDonut\": true\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"nginx.access.user_agent.os_name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"nginx.access.user_agent.os_major\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Nginx-Access-OSes", "type": "visualization", @@ -52,7 +52,7 @@ "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Filebeat-Nginx-module", - "title": "Nginx Access over time", + "title": "Response codes over time [Filebeat Nginx]", "uiStateJSON": "{\n \"vis\": {\n \"colors\": {\n \"200\": \"#7EB26D\",\n \"404\": \"#614D93\"\n }\n }\n}", "version": 1, "visState": "{\n \"title\": \"New Visualization\",\n \"type\": \"histogram\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"nginx.access.response_code\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" @@ -65,12 +65,12 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"*\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": []\n}" }, - "title": "Nginx Access Response codes by top URLs", - "uiStateJSON": "{\"vis\":{\"colors\":{\"200\":\"#629E51\",\"404\":\"#0A50A1\"}}}", + "title": "Response codes by top URLs [Filebeat Nginx]", + "uiStateJSON": "{\n \"vis\": {\n \"colors\": {\n \"200\": \"#629E51\",\n \"404\": \"#0A50A1\"\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"Nginx Access Response codes by top URLs\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"nginx.access.url\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"row\":false}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"nginx.access.response_code\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Nginx Access Response codes by top URLs\",\n \"type\": \"pie\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"isDonut\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"split\",\n \"params\": {\n \"field\": \"nginx.access.url\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"row\": false\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"nginx.access.response_code\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Nginx-Access-Response-codes-by-top-URLs", "type": "visualization", @@ -82,7 +82,7 @@ "kibanaSavedObjectMeta": { "searchSourceJSON": "{\n \"filter\": [],\n \"index\": \"filebeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"_exists_:nginx.access\",\n \"analyze_wildcard\": true\n }\n },\n \"highlight\": {\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n }\n}" }, - "title": "Nginx Sent Byte Size", + "title": "Sent Byte Size [Filebeat Nginx]", "uiStateJSON": "{}", "version": 1, "visState": "{\n \"title\": \"Sent sizes\",\n \"type\": \"line\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"showCircles\": true,\n \"smoothLines\": true,\n \"interpolate\": \"linear\",\n \"scale\": \"linear\",\n \"drawLinesBetweenPoints\": true,\n \"radiusRatio\": \"17\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"sum\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"nginx.access.body_sent.bytes\",\n \"customLabel\": \"Data sent\"\n }\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"radius\",\n \"params\": {}\n }\n ],\n \"listeners\": {}\n}" @@ -95,13 +95,13 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Filebeat-Nginx-module", - "title": "Nginx Access Map", - "uiStateJSON": "{\"mapCenter\":[12.039320557540572,-0.17578125]}", + "title": "Access Map [Filebeat Nginx]", + "uiStateJSON": "{\n \"mapCenter\": [\n 12.039320557540572,\n -0.17578125\n ]\n}", "version": 1, - "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{},\"schema\":\"metric\",\"type\":\"count\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"autoPrecision\":true,\"field\":\"nginx.access.geoip.location\"},\"schema\":\"segment\",\"type\":\"geohash_grid\"}],\"listeners\":{},\"params\":{\"addTooltip\":true,\"heatBlur\":15,\"heatMaxZoom\":16,\"heatMinOpacity\":0.1,\"heatNormalizeData\":true,\"heatRadius\":25,\"isDesaturated\":true,\"legendPosition\":\"bottomright\",\"mapCenter\":[15,5],\"mapType\":\"Scaled Circle Markers\",\"mapZoom\":2,\"wms\":{\"enabled\":false,\"options\":{\"attribution\":\"Maps provided by USGS\",\"format\":\"image/png\",\"layers\":\"0\",\"styles\":\"\",\"transparent\":true,\"version\":\"1.3.0\"},\"url\":\"https://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer\"}},\"title\":\"Nginx Access Map\",\"type\":\"tile_map\"}" + "visState": "{\n \"aggs\": [\n {\n \"enabled\": true,\n \"id\": \"1\",\n \"params\": {},\n \"schema\": \"metric\",\n \"type\": \"count\"\n },\n {\n \"enabled\": true,\n \"id\": \"2\",\n \"params\": {\n \"autoPrecision\": true,\n \"field\": \"nginx.access.geoip.location\"\n },\n \"schema\": \"segment\",\n \"type\": \"geohash_grid\"\n }\n ],\n \"listeners\": {},\n \"params\": {\n \"addTooltip\": true,\n \"heatBlur\": 15,\n \"heatMaxZoom\": 16,\n \"heatMinOpacity\": 0.1,\n \"heatNormalizeData\": true,\n \"heatRadius\": 25,\n \"isDesaturated\": true,\n \"legendPosition\": \"bottomright\",\n \"mapCenter\": [\n 15,\n 5\n ],\n \"mapType\": \"Scaled Circle Markers\",\n \"mapZoom\": 2,\n \"wms\": {\n \"enabled\": false,\n \"options\": {\n \"attribution\": \"Maps provided by USGS\",\n \"format\": \"image/png\",\n \"layers\": \"0\",\n \"styles\": \"\",\n \"transparent\": true,\n \"version\": \"1.3.0\"\n },\n \"url\": \"https://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer\"\n }\n },\n \"title\": \"Nginx Access Map\",\n \"type\": \"tile_map\"\n}" }, "id": "Nginx-Access-Map", "type": "visualization", @@ -115,37 +115,37 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query_string\":{\"query\":\"_exists_:nginx\",\"analyze_wildcard\":true}},\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647}}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"_exists_:nginx\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": [],\n \"highlight\": {\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n }\n}" }, "sort": [ "@timestamp", "desc" ], - "title": "Filebeat Nginx module", + "title": "Nginx logs [Filebeat Nginx]", "version": 1 }, "id": "Filebeat-Nginx-module", "type": "search", - "version": 3 + "version": 2 }, { "attributes": { - "description": "", + "description": "Dashboard for the Filebeat Nginx module", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\n \"filter\": [\n {\n \"query\": {\n \"query_string\": {\n \"analyze_wildcard\": true,\n \"query\": \"*\"\n }\n }\n }\n ]\n}" }, - "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":9,\"id\":\"Errors-over-time\",\"panelIndex\":2,\"row\":4,\"size_x\":4,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Nginx-Access-Browsers\",\"panelIndex\":3,\"row\":10,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":5,\"id\":\"Nginx-Access-OSes\",\"panelIndex\":4,\"row\":10,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"New-Visualization\",\"panelIndex\":5,\"row\":4,\"size_x\":8,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Nginx-Access-Response-codes-by-top-URLs\",\"panelIndex\":6,\"row\":7,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":9,\"id\":\"Sent-sizes\",\"panelIndex\":7,\"row\":10,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"id\":\"Nginx-Access-Map\",\"type\":\"visualization\",\"panelIndex\":8,\"size_x\":12,\"size_y\":3,\"col\":1,\"row\":1}]", + "optionsJSON": "{\n \"darkTheme\": false\n}", + "panelsJSON": "[\n {\n \"col\": 9,\n \"id\": \"Errors-over-time\",\n \"panelIndex\": 2,\n \"row\": 4,\n \"size_x\": 4,\n \"size_y\": 3,\n \"type\": \"visualization\"\n },\n {\n \"col\": 1,\n \"id\": \"Nginx-Access-Browsers\",\n \"panelIndex\": 3,\n \"row\": 10,\n \"size_x\": 4,\n \"size_y\": 4,\n \"type\": \"visualization\"\n },\n {\n \"col\": 5,\n \"id\": \"Nginx-Access-OSes\",\n \"panelIndex\": 4,\n \"row\": 10,\n \"size_x\": 4,\n \"size_y\": 4,\n \"type\": \"visualization\"\n },\n {\n \"col\": 1,\n \"id\": \"New-Visualization\",\n \"panelIndex\": 5,\n \"row\": 4,\n \"size_x\": 8,\n \"size_y\": 3,\n \"type\": \"visualization\"\n },\n {\n \"col\": 1,\n \"id\": \"Nginx-Access-Response-codes-by-top-URLs\",\n \"panelIndex\": 6,\n \"row\": 7,\n \"size_x\": 12,\n \"size_y\": 3,\n \"type\": \"visualization\"\n },\n {\n \"col\": 9,\n \"id\": \"Sent-sizes\",\n \"panelIndex\": 7,\n \"row\": 10,\n \"size_x\": 4,\n \"size_y\": 4,\n \"type\": \"visualization\"\n },\n {\n \"id\": \"Nginx-Access-Map\",\n \"type\": \"visualization\",\n \"panelIndex\": 8,\n \"size_x\": 12,\n \"size_y\": 3,\n \"col\": 1,\n \"row\": 1\n }\n]", "timeRestore": false, - "title": "Filebeat Nginx Dashboard", - "uiStateJSON": "{\"P-4\":{\"vis\":{\"legendOpen\":true}},\"P-8\":{\"mapCenter\":[50.51342652633956,-0.17578125]}}", + "title": "[Filebeat Nginx] Access and error logs", + "uiStateJSON": "{\n \"P-4\": {\n \"vis\": {\n \"legendOpen\": true\n }\n },\n \"P-8\": {\n \"mapCenter\": [\n 50.51342652633956,\n -0.17578125\n ]\n }\n}", "version": 1 }, "id": "Filebeat-Nginx-Dashboard", "type": "dashboard", - "version": 2 + "version": 3 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/filebeat/module/nginx/_meta/kibana/default/dashboard/ml-nginx-access-remote-ip-count-explorer.json b/filebeat/module/nginx/_meta/kibana/default/dashboard/ml-nginx-access-remote-ip-count-explorer.json index 991232f1249..f9b270a0e4d 100644 --- a/filebeat/module/nginx/_meta/kibana/default/dashboard/ml-nginx-access-remote-ip-count-explorer.json +++ b/filebeat/module/nginx/_meta/kibana/default/dashboard/ml-nginx-access-remote-ip-count-explorer.json @@ -7,30 +7,30 @@ "searchSourceJSON": "{}" }, "savedSearchId": "ML-Filebeat-Nginx-Access", - "title": "ML Nginx Access Remote IP Timechart", - "uiStateJSON": "{\"vis\":{\"legendOpen\":false}}", + "title": "Remote IP Timechart [Filebeat Nginx] [ML]", + "uiStateJSON": "{\n \"vis\": {\n \"legendOpen\": false\n }\n}", "version": 1, - "visState": "{\"title\":\"ML Nginx Access Remote IP Timechart\",\"type\":\"area\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"@timestamp per 5 minutes\"},\"type\":\"category\"}],\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"interpolate\":\"linear\",\"legendPosition\":\"right\",\"radiusRatio\":9,\"scale\":\"linear\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"mode\":\"stacked\",\"show\":\"true\",\"showCircles\":true,\"type\":\"area\",\"valueAxis\":\"ValueAxis-1\"}],\"setYExtents\":false,\"showCircles\":true,\"times\":[],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{},\"type\":\"value\"}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"nginx.access.remote_ip\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"ML Nginx Access Remote IP Timechart\",\n \"type\": \"area\",\n \"params\": {\n \"addLegend\": true,\n \"addTimeMarker\": false,\n \"addTooltip\": true,\n \"categoryAxes\": [\n {\n \"id\": \"CategoryAxis-1\",\n \"labels\": {\n \"show\": true,\n \"truncate\": 100\n },\n \"position\": \"bottom\",\n \"scale\": {\n \"type\": \"linear\"\n },\n \"show\": true,\n \"style\": {},\n \"title\": {\n \"text\": \"@timestamp per 5 minutes\"\n },\n \"type\": \"category\"\n }\n ],\n \"defaultYExtents\": false,\n \"drawLinesBetweenPoints\": true,\n \"grid\": {\n \"categoryLines\": false,\n \"style\": {\n \"color\": \"#eee\"\n }\n },\n \"interpolate\": \"linear\",\n \"legendPosition\": \"right\",\n \"radiusRatio\": 9,\n \"scale\": \"linear\",\n \"seriesParams\": [\n {\n \"data\": {\n \"id\": \"1\",\n \"label\": \"Count\"\n },\n \"drawLinesBetweenPoints\": true,\n \"interpolate\": \"linear\",\n \"mode\": \"stacked\",\n \"show\": \"true\",\n \"showCircles\": true,\n \"type\": \"area\",\n \"valueAxis\": \"ValueAxis-1\"\n }\n ],\n \"setYExtents\": false,\n \"showCircles\": true,\n \"times\": [],\n \"valueAxes\": [\n {\n \"id\": \"ValueAxis-1\",\n \"labels\": {\n \"filter\": false,\n \"rotate\": 0,\n \"show\": true,\n \"truncate\": 100\n },\n \"name\": \"LeftAxis-1\",\n \"position\": \"left\",\n \"scale\": {\n \"mode\": \"normal\",\n \"type\": \"linear\"\n },\n \"show\": true,\n \"style\": {},\n \"title\": {},\n \"type\": \"value\"\n }\n ]\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"nginx.access.remote_ip\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "ML-Nginx-Access-Remote-IP-Timechart", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "ML-Filebeat-Nginx-Access", - "title": "ML Nginx Access Response Code Timechart", + "title": "Response Code Timechart [Filebeat Nginx] [ML]", "uiStateJSON": "{\n \"vis\": {\n \"colors\": {\n \"200\": \"#7EB26D\",\n \"404\": \"#614D93\"\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"ML Nginx Access Response Code Timechart\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"nginx.access.response_code\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"ML Nginx Access Response Code Timechart\",\n \"type\": \"histogram\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"nginx.access.response_code\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "ML-Nginx-Access-Response-Code-Timechart", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { @@ -39,30 +39,30 @@ "searchSourceJSON": "{}" }, "savedSearchId": "ML-Filebeat-Nginx-Access", - "title": "ML Nginx Access Top Remote IPs Table", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "title": "Top Remote IPs [Filebeat Nginx] [ML]", + "uiStateJSON": "{\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"ML Nginx Access Top Remote IPs Table\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"nginx.access.remote_ip\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"ML Nginx Access Top Remote IPs Table\",\n \"type\": \"table\",\n \"params\": {\n \"perPage\": 10,\n \"showPartialRows\": false,\n \"showMeticsAtAllLevels\": false,\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n },\n \"showTotal\": false,\n \"totalFunc\": \"sum\"\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"nginx.access.remote_ip\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "ML-Nginx-Access-Top-Remote-IPs-Table", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "ML-Filebeat-Nginx-Access", - "title": "ML Nginx Access Map", + "title": "Access Map [Filebeat Nginx] [ML]", "uiStateJSON": "{\n \"mapCenter\": [\n 12.039320557540572,\n -0.17578125\n ]\n}", "version": 1, - "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{},\"schema\":\"metric\",\"type\":\"count\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"autoPrecision\":true,\"field\":\"nginx.access.geoip.location\"},\"schema\":\"segment\",\"type\":\"geohash_grid\"}],\"listeners\":{},\"params\":{\"addTooltip\":true,\"heatBlur\":15,\"heatMaxZoom\":16,\"heatMinOpacity\":0.1,\"heatNormalizeData\":true,\"heatRadius\":25,\"isDesaturated\":true,\"legendPosition\":\"bottomright\",\"mapCenter\":[15,5],\"mapType\":\"Scaled Circle Markers\",\"mapZoom\":2,\"wms\":{\"enabled\":false,\"options\":{\"attribution\":\"Maps provided by USGS\",\"format\":\"image/png\",\"layers\":\"0\",\"styles\":\"\",\"transparent\":true,\"version\":\"1.3.0\"},\"url\":\"https://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer\"}},\"title\":\"ML Nginx Access Map\",\"type\":\"tile_map\"}" + "visState": "{\n \"aggs\": [\n {\n \"enabled\": true,\n \"id\": \"1\",\n \"params\": {},\n \"schema\": \"metric\",\n \"type\": \"count\"\n },\n {\n \"enabled\": true,\n \"id\": \"2\",\n \"params\": {\n \"autoPrecision\": true,\n \"field\": \"nginx.access.geoip.location\"\n },\n \"schema\": \"segment\",\n \"type\": \"geohash_grid\"\n }\n ],\n \"listeners\": {},\n \"params\": {\n \"addTooltip\": true,\n \"heatBlur\": 15,\n \"heatMaxZoom\": 16,\n \"heatMinOpacity\": 0.1,\n \"heatNormalizeData\": true,\n \"heatRadius\": 25,\n \"isDesaturated\": true,\n \"legendPosition\": \"bottomright\",\n \"mapCenter\": [\n 15,\n 5\n ],\n \"mapType\": \"Scaled Circle Markers\",\n \"mapZoom\": 2,\n \"wms\": {\n \"enabled\": false,\n \"options\": {\n \"attribution\": \"Maps provided by USGS\",\n \"format\": \"image/png\",\n \"layers\": \"0\",\n \"styles\": \"\",\n \"transparent\": true,\n \"version\": \"1.3.0\"\n },\n \"url\": \"https://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer\"\n }\n },\n \"title\": \"ML Nginx Access Map\",\n \"type\": \"tile_map\"\n}" }, "id": "ML-Nginx-Access-Map", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { @@ -71,14 +71,14 @@ "searchSourceJSON": "{}" }, "savedSearchId": "ML-Filebeat-Nginx-Access", - "title": "ML Nginx Access Top URLs Table", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "title": "Top URLs [Filebeat Nginx] [ML]", + "uiStateJSON": "{\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"ML Nginx Access Top URLs Table\",\"type\":\"table\",\"params\":{\"perPage\":100,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"nginx.access.url\",\"size\":1000,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"ML Nginx Access Top URLs Table\",\n \"type\": \"table\",\n \"params\": {\n \"perPage\": 100,\n \"showPartialRows\": false,\n \"showMeticsAtAllLevels\": false,\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n },\n \"showTotal\": false,\n \"totalFunc\": \"sum\"\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"nginx.access.url\",\n \"size\": 1000,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "ML-Nginx-Access-Top-URLs-Table", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { @@ -88,37 +88,37 @@ "description": "Filebeat Nginx Access Data", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query_string\":{\"query\":\"_exists_:nginx.access\",\"analyze_wildcard\":true}},\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647}}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"_exists_:nginx.access\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": [],\n \"highlight\": {\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n }\n}" }, "sort": [ "@timestamp", "desc" ], - "title": "ML Nginx Access Data", + "title": "ML Access Data [Filebeat Nginx]", "version": 1 }, "id": "ML-Filebeat-Nginx-Access", "type": "search", - "version": 1 + "version": 3 }, { "attributes": { - "description": "", + "description": "Machine learning dashboard, for the Filebeat Nginx module", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}],\"highlightAll\":true,\"version\":true}" + "searchSourceJSON": "{\n \"filter\": [\n {\n \"query\": {\n \"query_string\": {\n \"analyze_wildcard\": true,\n \"query\": \"*\"\n }\n }\n }\n ],\n \"highlightAll\": true,\n \"version\": true\n}" }, - "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"size_x\":6,\"size_y\":3,\"panelIndex\":1,\"type\":\"visualization\",\"id\":\"ML-Nginx-Access-Remote-IP-Timechart\",\"col\":1,\"row\":1},{\"size_x\":6,\"size_y\":3,\"panelIndex\":2,\"type\":\"visualization\",\"id\":\"ML-Nginx-Access-Response-Code-Timechart\",\"col\":7,\"row\":1},{\"size_x\":6,\"size_y\":3,\"panelIndex\":3,\"type\":\"visualization\",\"id\":\"ML-Nginx-Access-Top-Remote-IPs-Table\",\"col\":1,\"row\":4},{\"size_x\":6,\"size_y\":3,\"panelIndex\":4,\"type\":\"visualization\",\"id\":\"ML-Nginx-Access-Map\",\"col\":7,\"row\":4},{\"size_x\":12,\"size_y\":9,\"panelIndex\":5,\"type\":\"visualization\",\"id\":\"ML-Nginx-Access-Top-URLs-Table\",\"col\":1,\"row\":7}]", + "optionsJSON": "{\n \"darkTheme\": false\n}", + "panelsJSON": "[\n {\n \"size_x\": 6,\n \"size_y\": 3,\n \"panelIndex\": 1,\n \"type\": \"visualization\",\n \"id\": \"ML-Nginx-Access-Remote-IP-Timechart\",\n \"col\": 1,\n \"row\": 1\n },\n {\n \"size_x\": 6,\n \"size_y\": 3,\n \"panelIndex\": 2,\n \"type\": \"visualization\",\n \"id\": \"ML-Nginx-Access-Response-Code-Timechart\",\n \"col\": 7,\n \"row\": 1\n },\n {\n \"size_x\": 6,\n \"size_y\": 3,\n \"panelIndex\": 3,\n \"type\": \"visualization\",\n \"id\": \"ML-Nginx-Access-Top-Remote-IPs-Table\",\n \"col\": 1,\n \"row\": 4\n },\n {\n \"size_x\": 6,\n \"size_y\": 3,\n \"panelIndex\": 4,\n \"type\": \"visualization\",\n \"id\": \"ML-Nginx-Access-Map\",\n \"col\": 7,\n \"row\": 4\n },\n {\n \"size_x\": 12,\n \"size_y\": 9,\n \"panelIndex\": 5,\n \"type\": \"visualization\",\n \"id\": \"ML-Nginx-Access-Top-URLs-Table\",\n \"col\": 1,\n \"row\": 7\n }\n]", "timeRestore": false, - "title": "ML Nginx Access Remote IP Count Explorer", - "uiStateJSON": "{\"P-3\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-5\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", + "title": "[Filebeat Nginx] [ML] Remote IP Count Explorer", + "uiStateJSON": "{\n \"P-3\": {\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n },\n \"P-5\": {\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n }\n}", "version": 1 }, "id": "ML-Nginx-Access-Remote-IP-Count-Explorer", "type": "dashboard", - "version": 1 + "version": 3 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/filebeat/module/nginx/_meta/kibana/default/dashboard/ml-nginx-remote-ip-url-explorer.json b/filebeat/module/nginx/_meta/kibana/default/dashboard/ml-nginx-remote-ip-url-explorer.json index 97d67683167..911a53334d9 100644 --- a/filebeat/module/nginx/_meta/kibana/default/dashboard/ml-nginx-remote-ip-url-explorer.json +++ b/filebeat/module/nginx/_meta/kibana/default/dashboard/ml-nginx-remote-ip-url-explorer.json @@ -7,30 +7,30 @@ "searchSourceJSON": "{}" }, "savedSearchId": "ML-Filebeat-Nginx-Access", - "title": "ML Nginx Access Unique Count URL Timechart", + "title": "Unique Count URL Timechart [Filebeat Nginx] [ML]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"ML Nginx Access Unique Count URL Timechart\",\"type\":\"line\",\"params\":{\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{\"text\":\"@timestamp per day\"}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Unique count of nginx.access.url\"}}],\"seriesParams\":[{\"show\":true,\"mode\":\"normal\",\"type\":\"line\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"lineWidth\":2,\"data\":{\"id\":\"1\",\"label\":\"Unique count of nginx.access.url\"},\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"showCircles\":true,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"nginx.access.url\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"ML Nginx Access Unique Count URL Timechart\",\n \"type\": \"line\",\n \"params\": {\n \"grid\": {\n \"categoryLines\": false,\n \"style\": {\n \"color\": \"#eee\"\n }\n },\n \"categoryAxes\": [\n {\n \"id\": \"CategoryAxis-1\",\n \"type\": \"category\",\n \"position\": \"bottom\",\n \"show\": true,\n \"style\": {},\n \"scale\": {\n \"type\": \"linear\"\n },\n \"labels\": {\n \"show\": true,\n \"truncate\": 100\n },\n \"title\": {\n \"text\": \"@timestamp per day\"\n }\n }\n ],\n \"valueAxes\": [\n {\n \"id\": \"ValueAxis-1\",\n \"name\": \"LeftAxis-1\",\n \"type\": \"value\",\n \"position\": \"left\",\n \"show\": true,\n \"style\": {},\n \"scale\": {\n \"type\": \"linear\",\n \"mode\": \"normal\"\n },\n \"labels\": {\n \"show\": true,\n \"rotate\": 0,\n \"filter\": false,\n \"truncate\": 100\n },\n \"title\": {\n \"text\": \"Unique count of nginx.access.url\"\n }\n }\n ],\n \"seriesParams\": [\n {\n \"show\": true,\n \"mode\": \"normal\",\n \"type\": \"line\",\n \"drawLinesBetweenPoints\": true,\n \"showCircles\": true,\n \"interpolate\": \"linear\",\n \"lineWidth\": 2,\n \"data\": {\n \"id\": \"1\",\n \"label\": \"Unique count of nginx.access.url\"\n },\n \"valueAxis\": \"ValueAxis-1\"\n }\n ],\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"showCircles\": true,\n \"interpolate\": \"linear\",\n \"scale\": \"linear\",\n \"drawLinesBetweenPoints\": true,\n \"radiusRatio\": 9,\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"nginx.access.url\"\n }\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "ML-Nginx-Access-Unique-Count-URL-Timechart", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "ML-Filebeat-Nginx-Access", - "title": "ML Nginx Access Response Code Timechart", + "title": "Response Code Timechart [Filebeat Nginx] [ML]", "uiStateJSON": "{\n \"vis\": {\n \"colors\": {\n \"200\": \"#7EB26D\",\n \"404\": \"#614D93\"\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"ML Nginx Access Response Code Timechart\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"nginx.access.response_code\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"ML Nginx Access Response Code Timechart\",\n \"type\": \"histogram\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"nginx.access.response_code\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "ML-Nginx-Access-Response-Code-Timechart", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { @@ -39,30 +39,30 @@ "searchSourceJSON": "{}" }, "savedSearchId": "ML-Filebeat-Nginx-Access", - "title": "ML Nginx Access Top Remote IPs Table", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "title": "Top Remote IPs [Filebeat Nginx] [ML]", + "uiStateJSON": "{\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"ML Nginx Access Top Remote IPs Table\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"nginx.access.remote_ip\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"ML Nginx Access Top Remote IPs Table\",\n \"type\": \"table\",\n \"params\": {\n \"perPage\": 10,\n \"showPartialRows\": false,\n \"showMeticsAtAllLevels\": false,\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n },\n \"showTotal\": false,\n \"totalFunc\": \"sum\"\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"nginx.access.remote_ip\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "ML-Nginx-Access-Top-Remote-IPs-Table", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "ML-Filebeat-Nginx-Access", - "title": "ML Nginx Access Map", + "title": "Access Map [Filebeat Nginx] [ML]", "uiStateJSON": "{\n \"mapCenter\": [\n 12.039320557540572,\n -0.17578125\n ]\n}", "version": 1, - "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{},\"schema\":\"metric\",\"type\":\"count\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"autoPrecision\":true,\"field\":\"nginx.access.geoip.location\"},\"schema\":\"segment\",\"type\":\"geohash_grid\"}],\"listeners\":{},\"params\":{\"addTooltip\":true,\"heatBlur\":15,\"heatMaxZoom\":16,\"heatMinOpacity\":0.1,\"heatNormalizeData\":true,\"heatRadius\":25,\"isDesaturated\":true,\"legendPosition\":\"bottomright\",\"mapCenter\":[15,5],\"mapType\":\"Scaled Circle Markers\",\"mapZoom\":2,\"wms\":{\"enabled\":false,\"options\":{\"attribution\":\"Maps provided by USGS\",\"format\":\"image/png\",\"layers\":\"0\",\"styles\":\"\",\"transparent\":true,\"version\":\"1.3.0\"},\"url\":\"https://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer\"}},\"title\":\"ML Nginx Access Map\",\"type\":\"tile_map\"}" + "visState": "{\n \"aggs\": [\n {\n \"enabled\": true,\n \"id\": \"1\",\n \"params\": {},\n \"schema\": \"metric\",\n \"type\": \"count\"\n },\n {\n \"enabled\": true,\n \"id\": \"2\",\n \"params\": {\n \"autoPrecision\": true,\n \"field\": \"nginx.access.geoip.location\"\n },\n \"schema\": \"segment\",\n \"type\": \"geohash_grid\"\n }\n ],\n \"listeners\": {},\n \"params\": {\n \"addTooltip\": true,\n \"heatBlur\": 15,\n \"heatMaxZoom\": 16,\n \"heatMinOpacity\": 0.1,\n \"heatNormalizeData\": true,\n \"heatRadius\": 25,\n \"isDesaturated\": true,\n \"legendPosition\": \"bottomright\",\n \"mapCenter\": [\n 15,\n 5\n ],\n \"mapType\": \"Scaled Circle Markers\",\n \"mapZoom\": 2,\n \"wms\": {\n \"enabled\": false,\n \"options\": {\n \"attribution\": \"Maps provided by USGS\",\n \"format\": \"image/png\",\n \"layers\": \"0\",\n \"styles\": \"\",\n \"transparent\": true,\n \"version\": \"1.3.0\"\n },\n \"url\": \"https://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer\"\n }\n },\n \"title\": \"ML Nginx Access Map\",\n \"type\": \"tile_map\"\n}" }, "id": "ML-Nginx-Access-Map", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { @@ -71,14 +71,14 @@ "searchSourceJSON": "{}" }, "savedSearchId": "ML-Filebeat-Nginx-Access", - "title": "ML Nginx Access Top URLs Table", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "title": "Top URLs [Filebeat Nginx] [ML]", + "uiStateJSON": "{\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"ML Nginx Access Top URLs Table\",\"type\":\"table\",\"params\":{\"perPage\":100,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"nginx.access.url\",\"size\":1000,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"ML Nginx Access Top URLs Table\",\n \"type\": \"table\",\n \"params\": {\n \"perPage\": 100,\n \"showPartialRows\": false,\n \"showMeticsAtAllLevels\": false,\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n },\n \"showTotal\": false,\n \"totalFunc\": \"sum\"\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"nginx.access.url\",\n \"size\": 1000,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "ML-Nginx-Access-Top-URLs-Table", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { @@ -88,37 +88,37 @@ "description": "Filebeat Nginx Access Data", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"query\":{\"query_string\":{\"query\":\"_exists_:nginx.access\",\"analyze_wildcard\":true}},\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647}}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"_exists_:nginx.access\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": [],\n \"highlight\": {\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n }\n}" }, "sort": [ "@timestamp", "desc" ], - "title": "ML Nginx Access Data", + "title": "ML Access Data [Filebeat Nginx]", "version": 1 }, "id": "ML-Filebeat-Nginx-Access", "type": "search", - "version": 1 + "version": 3 }, { "attributes": { - "description": "", + "description": "Machine Learning dashboard for the Filebeat Nginx module", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}],\"highlightAll\":true,\"version\":true}" + "searchSourceJSON": "{\n \"filter\": [\n {\n \"query\": {\n \"query_string\": {\n \"analyze_wildcard\": true,\n \"query\": \"*\"\n }\n }\n }\n ],\n \"highlightAll\": true,\n \"version\": true\n}" }, - "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"ML-Nginx-Access-Unique-Count-URL-Timechart\",\"panelIndex\":1,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"ML-Nginx-Access-Response-Code-Timechart\",\"panelIndex\":2,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"ML-Nginx-Access-Top-Remote-IPs-Table\",\"panelIndex\":3,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"ML-Nginx-Access-Map\",\"panelIndex\":4,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"size_x\":12,\"size_y\":8,\"panelIndex\":5,\"type\":\"visualization\",\"id\":\"ML-Nginx-Access-Top-URLs-Table\",\"col\":1,\"row\":7}]", + "optionsJSON": "{\n \"darkTheme\": false\n}", + "panelsJSON": "[\n {\n \"col\": 1,\n \"id\": \"ML-Nginx-Access-Unique-Count-URL-Timechart\",\n \"panelIndex\": 1,\n \"row\": 1,\n \"size_x\": 6,\n \"size_y\": 3,\n \"type\": \"visualization\"\n },\n {\n \"col\": 7,\n \"id\": \"ML-Nginx-Access-Response-Code-Timechart\",\n \"panelIndex\": 2,\n \"row\": 1,\n \"size_x\": 6,\n \"size_y\": 3,\n \"type\": \"visualization\"\n },\n {\n \"col\": 1,\n \"id\": \"ML-Nginx-Access-Top-Remote-IPs-Table\",\n \"panelIndex\": 3,\n \"row\": 4,\n \"size_x\": 6,\n \"size_y\": 3,\n \"type\": \"visualization\"\n },\n {\n \"col\": 7,\n \"id\": \"ML-Nginx-Access-Map\",\n \"panelIndex\": 4,\n \"row\": 4,\n \"size_x\": 6,\n \"size_y\": 3,\n \"type\": \"visualization\"\n },\n {\n \"size_x\": 12,\n \"size_y\": 8,\n \"panelIndex\": 5,\n \"type\": \"visualization\",\n \"id\": \"ML-Nginx-Access-Top-URLs-Table\",\n \"col\": 1,\n \"row\": 7\n }\n]", "timeRestore": false, - "title": "ML Nginx Access Remote IP URL Explorer", - "uiStateJSON": "{\"P-2\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-3\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-5\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", + "title": "[Filebeat Nginx] [ML] Remote IP URL Explorer", + "uiStateJSON": "{\n \"P-2\": {\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n },\n \"P-3\": {\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n },\n \"P-5\": {\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n }\n}", "version": 1 }, "id": "ML-Nginx-Remote-IP-URL-Explorer", "type": "dashboard", - "version": 1 + "version": 4 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/filebeat/module/nginx/module.yml b/filebeat/module/nginx/module.yml index c4b35dc8179..3fa0c0290b6 100644 --- a/filebeat/module/nginx/module.yml +++ b/filebeat/module/nginx/module.yml @@ -1,9 +1,9 @@ dashboards: - - id: Filebeat-Nginx-Dashboard - file: Filebeat-nginx-overview.json +- id: Filebeat-Nginx-Dashboard + file: Filebeat-nginx-overview.json - - id: ML-Nginx-Access-Remote-IP-Count-Explorer - file: ml-nginx-access-remote-ip-count-explorer.json +- id: ML-Nginx-Access-Remote-IP-Count-Explorer + file: ml-nginx-access-remote-ip-count-explorer.json - - id: ML-Nginx-Remote-IP-URL-Explorer - file: ml-nginx-remote-ip-url-explorer.json +- id: ML-Nginx-Remote-IP-URL-Explorer + file: ml-nginx-remote-ip-url-explorer.json diff --git a/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-overview.json b/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-overview.json index 51cafad690c..8536a63f6c1 100644 --- a/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-overview.json +++ b/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-overview.json @@ -7,14 +7,14 @@ "searchSourceJSON": "{\"filter\":[]}" }, "savedSearchId": "PostgreSQL All Logs", - "title": "PostgreSQL Log Level Count", + "title": "Log Level Count [Filebeat PostgreSQL]", "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", "version": 1, - "visState": "{\"title\":\"PostgreSQL Log Level Count\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"postgresql.log.level\",\"size\":12,\"order\":\"desc\",\"orderBy\":\"1\"}}]}" + "visState": "{\"title\":\"Log Level Count [Filebeat PostgreSQL]\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"postgresql.log.level\",\"size\":12,\"order\":\"desc\",\"orderBy\":\"1\"}}]}" }, "id": "PostgreSQL Log Level Count", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { @@ -28,13 +28,13 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"postgresql.log.level:*\",\"language\":\"lucene\"},\"filter\":[]}" + "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"*\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"index\":\"filebeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"fileset.module\",\"value\":\"postgresql\",\"params\":{\"query\":\"postgresql\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"fileset.module\":{\"query\":\"postgresql\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}]}" }, "sort": [ "@timestamp", "desc" ], - "title": "PostgreSQL All Logs", + "title": "All Logs [Filebeat PostgreSQL]", "version": 1 }, "id": "PostgreSQL All Logs", @@ -44,21 +44,37 @@ { "attributes": { "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "PostgreSQL All Logs", + "title": "Logs by level over time [Filebeat PostgreSQL]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Logs by level over time [Filebeat PostgreSQL]\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{\"text\":\"@timestamp per month\"}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"postgresql.log.level\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}" + }, + "id": "3dbd5370-87f3-11e7-ad9c-db80de0bf8d3", + "type": "visualization", + "version": 1 + }, + { + "attributes": { + "description": "Overview dashboard for the Filebeat PostgreSQL module", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" + "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"size_x\":6,\"size_y\":3,\"panelIndex\":1,\"type\":\"visualization\",\"id\":\"PostgreSQL Log Level Count\",\"col\":1,\"row\":4},{\"size_x\":12,\"size_y\":3,\"panelIndex\":2,\"type\":\"search\",\"id\":\"PostgreSQL All Logs\",\"col\":1,\"row\":1,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.level\",\"postgresql.log.message\",\"postgresql.log.query\"],\"sort\":[\"@timestamp\",\"desc\"]}]", + "panelsJSON": "[{\"col\":1,\"id\":\"PostgreSQL Log Level Count\",\"panelIndex\":1,\"row\":1,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.level\",\"postgresql.log.message\",\"postgresql.log.query\"],\"id\":\"PostgreSQL All Logs\",\"panelIndex\":2,\"row\":4,\"size_x\":12,\"size_y\":6,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"size_x\":9,\"size_y\":3,\"panelIndex\":3,\"type\":\"visualization\",\"id\":\"3dbd5370-87f3-11e7-ad9c-db80de0bf8d3\",\"col\":4,\"row\":1}]", "timeRestore": false, - "title": "PostgreSQL All Logs", + "title": "[Filebeat PostgreSQL] Overview", "uiStateJSON": "{\"P-1\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", "version": 1 }, - "id": "PostgreSQL All Logs", + "id": "158be870-87f4-11e7-ad9c-db80de0bf8d3", "type": "dashboard", "version": 1 } ], "version": "6.0.0-beta1-SNAPSHOT" -} +} \ No newline at end of file diff --git a/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-slowlogs.json b/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-slowlogs.json index 2a300e6f6c0..b3a32c5e97c 100644 --- a/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-slowlogs.json +++ b/filebeat/module/postgresql/_meta/kibana/default/dashboard/Filebeat-Postgresql-slowlogs.json @@ -7,14 +7,14 @@ "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\"}}" }, "savedSearchId": "PostgreSQL Query Durations", - "title": "PostgreSQL Query Count and Duration", + "title": "Query count and cumulated duration [Filebeat PostgreSQL]", "uiStateJSON": "{\"vis\":{\"colors\":{\"Sum of query duration\":\"#6ED0E0\",\"Number of queries\":\"#0A437C\"},\"legendOpen\":true}}", "version": 1, - "visState": "{\"title\":\"PostgreSQL Query Count and Duration\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{\"text\":\"@timestamp per minute\"}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"\"}}],\"seriesParams\":[{\"show\":true,\"mode\":\"normal\",\"type\":\"histogram\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"lineWidth\":2,\"data\":{\"id\":\"4\",\"label\":\"Number of queries\"},\"valueAxis\":\"ValueAxis-1\"},{\"show\":true,\"mode\":\"normal\",\"type\":\"histogram\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"lineWidth\":2,\"data\":{\"id\":\"2\",\"label\":\"Sum of query duration\"},\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"m\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Number of queries\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"sum\",\"schema\":\"metric\",\"params\":{\"field\":\"postgresql.log.duration\",\"customLabel\":\"Sum of query duration\"}}]}" + "visState": "{\"title\":\"Query count and cumulated duration [Filebeat PostgreSQL]\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{\"text\":\"@timestamp per 3 hours\"}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"\"}}],\"seriesParams\":[{\"show\":true,\"mode\":\"normal\",\"type\":\"histogram\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"lineWidth\":2,\"data\":{\"id\":\"4\",\"label\":\"Number of queries\"},\"valueAxis\":\"ValueAxis-1\"},{\"show\":true,\"mode\":\"normal\",\"type\":\"histogram\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"lineWidth\":2,\"data\":{\"id\":\"2\",\"label\":\"Sum of query duration\"},\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Number of queries\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"sum\",\"schema\":\"metric\",\"params\":{\"field\":\"postgresql.log.duration\",\"customLabel\":\"Sum of query duration\"}}]}" }, "id": "PostgreSQL Query Count and Duration", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -33,12 +33,12 @@ "@timestamp", "desc" ], - "title": "Slow PostgreSQL Queries", + "title": "Slow Queries [Filebeat PostgreSQL]", "version": 1 }, "id": "Slow PostgreSQL Queries", "type": "search", - "version": 3 + "version": 1 }, { "attributes": { @@ -57,31 +57,31 @@ "@timestamp", "desc" ], - "title": "PostgreSQL Query Durations", + "title": "Query Durations [Filebeat PostgreSQL]", "version": 1 }, "id": "PostgreSQL Query Durations", "type": "search", - "version": 2 + "version": 1 }, { "attributes": { - "description": "", + "description": "Dashboard for analyzing the query durations of the Filebeat PostgreSQL module", "hits": 0, "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"postgresql.log.query:*\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"PostgreSQL Query Count and Duration\",\"panelIndex\":1,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.duration\",\"postgresql.log.query\"],\"id\":\"Slow PostgreSQL Queries\",\"panelIndex\":2,\"row\":1,\"size_x\":6,\"size_y\":3,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"size_x\":12,\"size_y\":3,\"panelIndex\":3,\"type\":\"search\",\"id\":\"PostgreSQL Query Durations\",\"col\":1,\"row\":4,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.duration\",\"postgresql.log.query\"],\"sort\":[\"@timestamp\",\"desc\"]}]", + "panelsJSON": "[{\"col\":1,\"id\":\"PostgreSQL Query Count and Duration\",\"panelIndex\":1,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.duration\",\"postgresql.log.query\"],\"id\":\"Slow PostgreSQL Queries\",\"panelIndex\":2,\"row\":1,\"size_x\":6,\"size_y\":3,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"col\":1,\"columns\":[\"postgresql.log.user\",\"postgresql.log.database\",\"postgresql.log.duration\",\"postgresql.log.query\"],\"id\":\"PostgreSQL Query Durations\",\"panelIndex\":3,\"row\":4,\"size_x\":12,\"size_y\":5,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"}]", "timeRestore": false, - "title": "PostgreSQL Query Duration Overview", + "title": "[Filebeat PostgreSQL] Query Duration Overview", "uiStateJSON": "{}", "version": 1 }, - "id": "PostgreSQL Query Duration Overview", + "id": "e4c5f230-87f3-11e7-ad9c-db80de0bf8d3", "type": "dashboard", "version": 1 } ], "version": "6.0.0-beta1-SNAPSHOT" -} +} \ No newline at end of file diff --git a/filebeat/module/postgresql/module.yml b/filebeat/module/postgresql/module.yml new file mode 100644 index 00000000000..881ddf4b634 --- /dev/null +++ b/filebeat/module/postgresql/module.yml @@ -0,0 +1,5 @@ +dashboards: +- id: 158be870-87f4-11e7-ad9c-db80de0bf8d3 + file: Filebeat-Postgresql-overview.json +- id: e4c5f230-87f3-11e7-ad9c-db80de0bf8d3 + file: Filebeat-Postgresql-slowlogs.json diff --git a/filebeat/module/redis/_meta/kibana/default/dashboard/Filebeat-redis.json b/filebeat/module/redis/_meta/kibana/default/dashboard/Filebeat-redis.json index a73f2897fb6..8b610881e60 100644 --- a/filebeat/module/redis/_meta/kibana/default/dashboard/Filebeat-redis.json +++ b/filebeat/module/redis/_meta/kibana/default/dashboard/Filebeat-redis.json @@ -4,31 +4,31 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[],\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query_string\":{\"query\":\"_exists_:redis.log\",\"analyze_wildcard\":true}}}" + "searchSourceJSON": "{\"filter\":[],\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":{\"query_string\":{\"query\":\"_exists_:redis.log\",\"analyze_wildcard\":true,\"default_field\":\"*\"}},\"language\":\"lucene\"}}" }, - "title": "Redis log levels and roles", + "title": "Log levels and roles breakdown [Filebeat Redis]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Redis log levels and roles\",\"type\":\"pie\",\"params\":{\"addLegend\":true,\"addTooltip\":true,\"isDonut\":false,\"legendPosition\":\"bottom\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"redis.log.role\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"redis.log.level\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Log level\"}}],\"listeners\":{}}" + "visState": "{\"title\":\"Log levels and roles breakdown [Filebeat Redis]\",\"type\":\"pie\",\"params\":{\"addLegend\":true,\"addTooltip\":true,\"isDonut\":false,\"legendPosition\":\"bottom\",\"type\":\"pie\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"redis.log.role\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"redis.log.level\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Log level\"}}]}" }, "id": "78b9afe0-478f-11e7-b1f0-cb29bac6bf8b", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[],\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query_string\":{\"query\":\"_exists_:redis.log\",\"analyze_wildcard\":true}}}" + "searchSourceJSON": "{\"filter\":[],\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":{\"query_string\":{\"query\":\"_exists_:redis.log\",\"analyze_wildcard\":true,\"default_field\":\"*\"}},\"language\":\"lucene\"}}" }, - "title": "Redis logs over time", + "title": "Logs over time [Filebeat Redis]", "uiStateJSON": "{\"vis\":{\"colors\":{\"notice\":\"#629E51\",\"warning\":\"#EF843C\"}}}", "version": 1, - "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{},\"schema\":\"metric\",\"type\":\"count\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"customInterval\":\"2h\",\"extended_bounds\":{},\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1},\"schema\":\"segment\",\"type\":\"date_histogram\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"field\":\"redis.log.level\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":5},\"schema\":\"group\",\"type\":\"terms\"}],\"listeners\":{},\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"@timestamp per week\"},\"type\":\"category\"}],\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"interpolate\":\"linear\",\"legendPosition\":\"right\",\"radiusRatio\":9,\"scale\":\"linear\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"mode\":\"stacked\",\"show\":\"true\",\"showCircles\":true,\"type\":\"histogram\",\"valueAxis\":\"ValueAxis-1\"}],\"setYExtents\":false,\"showCircles\":true,\"times\":[],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{},\"type\":\"value\"}]},\"title\":\"Redis logs over time\",\"type\":\"histogram\"}" + "visState": "{\"title\":\"Logs over time [Filebeat Redis]\",\"type\":\"histogram\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"@timestamp per month\"},\"type\":\"category\"}],\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"interpolate\":\"linear\",\"legendPosition\":\"right\",\"radiusRatio\":9,\"scale\":\"linear\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"mode\":\"stacked\",\"show\":\"true\",\"showCircles\":true,\"type\":\"histogram\",\"valueAxis\":\"ValueAxis-1\"}],\"setYExtents\":false,\"showCircles\":true,\"times\":[],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Count\"},\"type\":\"value\"}],\"type\":\"histogram\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"redis.log.level\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}" }, "id": "d2864600-478f-11e7-be88-2ddb32f3df97", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { @@ -41,18 +41,18 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query_string\":{\"query\":\"_exists_:redis.log\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"*\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"index\":\"filebeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"fileset.module\",\"value\":\"redis\",\"params\":{\"query\":\"redis\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"fileset.module\":{\"query\":\"redis\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}},{\"meta\":{\"index\":\"filebeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"fileset.name\",\"value\":\"log\",\"params\":{\"query\":\"log\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"fileset.name\":{\"query\":\"log\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}]}" }, "sort": [ "@timestamp", "desc" ], - "title": "Filebeat Redis logs", + "title": "Logs [Filebeat Redis]", "version": 1 }, "id": "73613570-4791-11e7-be88-2ddb32f3df97", "type": "search", - "version": 1 + "version": 2 }, { "attributes": { @@ -61,14 +61,14 @@ "searchSourceJSON": "{\"filter\":[]}" }, "savedSearchId": "0ab87b80-478e-11e7-b1f0-cb29bac6bf8b", - "title": "Redis slowest commands", + "title": "Top slowest commands [Filebeat Redis]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Redis slowest commands\",\"type\":\"histogram\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":200},\"position\":\"left\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Duration (microseconds)\"},\"type\":\"category\"}],\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"interpolate\":\"linear\",\"legendPosition\":\"right\",\"radiusRatio\":9,\"scale\":\"linear\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Command\"},\"drawLinesBetweenPoints\":true,\"mode\":\"normal\",\"show\":true,\"showCircles\":true,\"type\":\"histogram\",\"valueAxis\":\"ValueAxis-1\"}],\"setYExtents\":false,\"showCircles\":true,\"times\":[],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":true,\"rotate\":75,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"bottom\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Command\"},\"type\":\"value\"}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.slowlog.duration.us\",\"customLabel\":\"Command\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"redis.slowlog.cmd\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Duration (microseconds)\"}}],\"listeners\":{}}" + "visState": "{\"title\":\"Top slowest commands [Filebeat Redis]\",\"type\":\"histogram\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":200},\"position\":\"left\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Duration (microseconds)\"},\"type\":\"category\"}],\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"interpolate\":\"linear\",\"legendPosition\":\"right\",\"radiusRatio\":9,\"scale\":\"linear\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Command\"},\"drawLinesBetweenPoints\":true,\"mode\":\"normal\",\"show\":true,\"showCircles\":true,\"type\":\"histogram\",\"valueAxis\":\"ValueAxis-1\"}],\"setYExtents\":false,\"showCircles\":true,\"times\":[],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":true,\"rotate\":75,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"bottom\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Command\"},\"type\":\"value\"}],\"type\":\"histogram\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.slowlog.duration.us\",\"customLabel\":\"Command\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"redis.slowlog.cmd\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Duration (microseconds)\"}}]}" }, "id": "dcccaa80-4791-11e7-be88-2ddb32f3df97", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { @@ -81,13 +81,13 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query_string\":{\"query\":\"_exists_:redis.slowlog\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"_exists_:redis.slowlog\",\"default_field\":\"*\"}}},\"filter\":[]}" }, "sort": [ "@timestamp", "desc" ], - "title": "Filebeat Redis slowlog", + "title": "Slow logs [Filebeat Redis]", "version": 1 }, "id": "0ab87b80-478e-11e7-b1f0-cb29bac6bf8b", @@ -96,22 +96,22 @@ }, { "attributes": { - "description": "", + "description": "Overview dashboard for the FIlebeat Redis module", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}],\"highlightAll\":true,\"version\":true}" + "searchSourceJSON": "{\"filter\":[],\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"default_field\":\"*\",\"query\":\"*\"}}}}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"78b9afe0-478f-11e7-b1f0-cb29bac6bf8b\",\"panelIndex\":2,\"row\":5,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":4,\"id\":\"d2864600-478f-11e7-be88-2ddb32f3df97\",\"panelIndex\":3,\"row\":5,\"size_x\":9,\"size_y\":3,\"type\":\"visualization\"},{\"size_x\":12,\"size_y\":4,\"panelIndex\":4,\"type\":\"search\",\"id\":\"73613570-4791-11e7-be88-2ddb32f3df97\",\"col\":1,\"row\":8,\"columns\":[\"beat.name\",\"redis.log.level\",\"redis.log.role\",\"redis.log.message\"],\"sort\":[\"@timestamp\",\"desc\"]},{\"size_x\":6,\"size_y\":4,\"panelIndex\":5,\"type\":\"visualization\",\"id\":\"dcccaa80-4791-11e7-be88-2ddb32f3df97\",\"col\":7,\"row\":1},{\"size_x\":6,\"size_y\":4,\"panelIndex\":6,\"type\":\"search\",\"id\":\"0ab87b80-478e-11e7-b1f0-cb29bac6bf8b\",\"col\":1,\"row\":1,\"columns\":[\"beat.name\",\"message\",\"redis.slowlog.duration.us\",\"redis.slowlog.key\"],\"sort\":[\"@timestamp\",\"desc\"]}]", + "panelsJSON": "[{\"col\":1,\"id\":\"78b9afe0-478f-11e7-b1f0-cb29bac6bf8b\",\"panelIndex\":2,\"row\":5,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":4,\"id\":\"d2864600-478f-11e7-be88-2ddb32f3df97\",\"panelIndex\":3,\"row\":5,\"size_x\":9,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"columns\":[\"beat.name\",\"redis.log.level\",\"redis.log.role\",\"redis.log.message\"],\"id\":\"73613570-4791-11e7-be88-2ddb32f3df97\",\"panelIndex\":4,\"row\":8,\"size_x\":12,\"size_y\":4,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"col\":7,\"id\":\"dcccaa80-4791-11e7-be88-2ddb32f3df97\",\"panelIndex\":5,\"row\":1,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"columns\":[\"beat.name\",\"message\",\"redis.slowlog.duration.us\",\"redis.slowlog.key\"],\"id\":\"0ab87b80-478e-11e7-b1f0-cb29bac6bf8b\",\"panelIndex\":6,\"row\":1,\"size_x\":6,\"size_y\":4,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"}]", "timeRestore": false, - "title": "Filebeat Redis", + "title": "[Filebeat Redis] Overview", "uiStateJSON": "{\"P-5\":{\"vis\":{\"legendOpen\":false}}}", "version": 1 }, "id": "7fea2930-478e-11e7-b1f0-cb29bac6bf8b", "type": "dashboard", - "version": 1 + "version": 4 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/filebeat/module/redis/module.yml b/filebeat/module/redis/module.yml new file mode 100644 index 00000000000..29c9a121d93 --- /dev/null +++ b/filebeat/module/redis/module.yml @@ -0,0 +1,3 @@ +dashboards: +- id: 7fea2930-478e-11e7-b1f0-cb29bac6bf8b + file: Filebeat-redis.json diff --git a/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-auth-sudo-commands.json b/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-auth-sudo-commands.json index a3dfa348a34..fa3c2c49c87 100644 --- a/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-auth-sudo-commands.json +++ b/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-auth-sudo-commands.json @@ -4,13 +4,13 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "b6f321e0-fa25-11e6-bbd3-29c986c96e5a", - "title": "Sudo commands by user", + "title": "Sudo commands by user [Filebeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Sudo commands by user\",\"type\":\"histogram\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"system.auth.user\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Sudo commands by user\",\n \"type\": \"histogram\",\n \"params\": {\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"system.auth.user\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "5c7af030-fa2a-11e6-bbd3-29c986c96e5a", "type": "visualization", @@ -20,12 +20,12 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[],\"index\":\"filebeat-*\",\"highlightAll\":true,\"query\":{\"query_string\":{\"query\":\"_exists_:system.auth.sudo.error\",\"analyze_wildcard\":true}}}" + "searchSourceJSON": "{\n \"filter\": [],\n \"index\": \"filebeat-*\",\n \"highlightAll\": true,\n \"query\": {\n \"query_string\": {\n \"query\": \"_exists_:system.auth.sudo.error\",\n \"analyze_wildcard\": true\n }\n }\n}" }, - "title": "Sudo errors", + "title": "Sudo errors [Filebeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Sudo errors\",\"type\":\"histogram\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"system.auth.sudo.error\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Sudo errors\",\n \"type\": \"histogram\",\n \"params\": {\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"system.auth.sudo.error\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "51164310-fa2b-11e6-bbd3-29c986c96e5a", "type": "visualization", @@ -35,18 +35,33 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "b6f321e0-fa25-11e6-bbd3-29c986c96e5a", - "title": "Top sudo commands", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "title": "Top sudo commands [Filebeat System]", + "uiStateJSON": "{\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"Top sudo commands\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.auth.sudo.command\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.auth.user\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Top sudo commands\",\n \"type\": \"table\",\n \"params\": {\n \"perPage\": 10,\n \"showPartialRows\": false,\n \"showMeticsAtAllLevels\": false,\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n },\n \"showTotal\": false,\n \"totalFunc\": \"sum\"\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"system.auth.sudo.command\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"system.auth.user\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "dc589770-fa2b-11e6-bbd3-29c986c96e5a", "type": "visualization", "version": 2 }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{}" + }, + "title": "Dashboards [Filebeat System]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Dashboards [Filebeat System]\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"markdown\":\"[Syslog](#/dashboard/Filebeat-syslog-dashboard) | [Sudo commands](#/dashboard/277876d0-fa2c-11e6-bbd3-29c986c96e5a) | [SSH logins](#/dashboard/5517a150-f9ce-11e6-8115-a7c18106d86a) | [New users and groups](#/dashboard/0d3f2380-fa78-11e6-ae9b-81e5311e8cab)\"},\"aggs\":[]}" + }, + "id": "327417e0-8462-11e7-bab8-bd2f0fb42c54", + "type": "visualization", + "version": 1 + }, { "attributes": { "columns": [ @@ -58,37 +73,37 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"query\":{\"query_string\":{\"query\":\"_exists_:system.auth.sudo\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"highlightAll\": true,\n \"query\": {\n \"query_string\": {\n \"query\": \"_exists_:system.auth.sudo\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": []\n}" }, "sort": [ "@timestamp", "desc" ], - "title": "Sudo commands", + "title": "Sudo commands [Filebeat System]", "version": 1 }, "id": "b6f321e0-fa25-11e6-bbd3-29c986c96e5a", "type": "search", - "version": 3 + "version": 2 }, { "attributes": { - "description": "", + "description": "Sudo commands dashboard from the Filebeat System module", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\",\"default_field\":\"*\"}},\"language\":\"lucene\"},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"5c7af030-fa2a-11e6-bbd3-29c986c96e5a\",\"panelIndex\":1,\"row\":5,\"size_x\":12,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"51164310-fa2b-11e6-bbd3-29c986c96e5a\",\"panelIndex\":2,\"row\":9,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"dc589770-fa2b-11e6-bbd3-29c986c96e5a\",\"panelIndex\":3,\"row\":1,\"size_x\":12,\"size_y\":4,\"type\":\"visualization\"}]", + "panelsJSON": "[{\"col\":1,\"id\":\"5c7af030-fa2a-11e6-bbd3-29c986c96e5a\",\"panelIndex\":1,\"row\":6,\"size_x\":12,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"51164310-fa2b-11e6-bbd3-29c986c96e5a\",\"panelIndex\":2,\"row\":10,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"dc589770-fa2b-11e6-bbd3-29c986c96e5a\",\"panelIndex\":3,\"row\":2,\"size_x\":12,\"size_y\":4,\"type\":\"visualization\"},{\"size_x\":12,\"size_y\":1,\"panelIndex\":4,\"type\":\"visualization\",\"id\":\"327417e0-8462-11e7-bab8-bd2f0fb42c54\",\"col\":1,\"row\":1}]", "timeRestore": false, - "title": "Filebeat Auth - Sudo commands", + "title": "[Filebeat System] Sudo commands", "uiStateJSON": "{\"P-3\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", "version": 1 }, "id": "277876d0-fa2c-11e6-bbd3-29c986c96e5a", "type": "dashboard", - "version": 2 + "version": 6 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-new-users-and-groups.json b/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-new-users-and-groups.json index c0fbe9634b2..c4a209acad1 100644 --- a/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-new-users-and-groups.json +++ b/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-new-users-and-groups.json @@ -4,96 +4,111 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "8030c1b0-fa77-11e6-ae9b-81e5311e8cab", - "title": "New users", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "title": "New users [Filebeat System]", + "uiStateJSON": "{\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"New users\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.auth.hostname\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Host\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.auth.useradd.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"User\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.auth.useradd.uid\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"UID\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.auth.useradd.gid\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"GID\"}},{\"id\":\"6\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.auth.useradd.home\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Home\"}},{\"id\":\"7\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.auth.useradd.shell\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Shell\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"New users\",\n \"type\": \"table\",\n \"params\": {\n \"perPage\": 10,\n \"showPartialRows\": false,\n \"showMeticsAtAllLevels\": false,\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n },\n \"showTotal\": false,\n \"totalFunc\": \"sum\"\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"system.auth.hostname\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Host\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"system.auth.useradd.name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"User\"\n }\n },\n {\n \"id\": \"4\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"system.auth.useradd.uid\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"UID\"\n }\n },\n {\n \"id\": \"5\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"system.auth.useradd.gid\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"GID\"\n }\n },\n {\n \"id\": \"6\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"system.auth.useradd.home\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Home\"\n }\n },\n {\n \"id\": \"7\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"system.auth.useradd.shell\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Shell\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "f398d2f0-fa77-11e6-ae9b-81e5311e8cab", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "8030c1b0-fa77-11e6-ae9b-81e5311e8cab", - "title": "New users over time", + "title": "New users over time [Filebeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"New users over time\",\"type\":\"histogram\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"system.auth.useradd.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"New users over time\",\n \"type\": \"histogram\",\n \"params\": {\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"bottom\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"system.auth.useradd.name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "5dd15c00-fa78-11e6-ae9b-81e5311e8cab", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "8030c1b0-fa77-11e6-ae9b-81e5311e8cab", - "title": "New users by shell", - "uiStateJSON": "{\"vis\":{\"colors\":{\"/bin/bash\":\"#E24D42\",\"/bin/false\":\"#508642\",\"/sbin/nologin\":\"#7EB26D\"},\"legendOpen\":true}}", + "title": "New users by shell [Filebeat System]", + "uiStateJSON": "{\n \"vis\": {\n \"colors\": {\n \"/bin/bash\": \"#E24D42\",\n \"/bin/false\": \"#508642\",\n \"/sbin/nologin\": \"#7EB26D\"\n },\n \"legendOpen\": true\n }\n}", "version": 1, - "visState": "{\"title\":\"New users by shell\",\"type\":\"pie\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"system.auth.useradd.shell\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"system.auth.useradd.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"New users by shell\",\n \"type\": \"pie\",\n \"params\": {\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"isDonut\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"system.auth.useradd.shell\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"system.auth.useradd.name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "e121b140-fa78-11e6-a1df-a78bd7504d38", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "8030c1b0-fa77-11e6-ae9b-81e5311e8cab", - "title": "New users by home directory", - "uiStateJSON": "{\"vis\":{\"colors\":{\"/bin/bash\":\"#E24D42\",\"/bin/false\":\"#508642\",\"/sbin/nologin\":\"#7EB26D\",\"/nonexistent\":\"#629E51\"},\"legendOpen\":true}}", + "title": "New users by home directory [Filebeat System]", + "uiStateJSON": "{\n \"vis\": {\n \"colors\": {\n \"/bin/bash\": \"#E24D42\",\n \"/bin/false\": \"#508642\",\n \"/sbin/nologin\": \"#7EB26D\",\n \"/nonexistent\": \"#629E51\"\n },\n \"legendOpen\": true\n }\n}", "version": 1, - "visState": "{\"title\":\"New users by home directory\",\"type\":\"pie\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"system.auth.useradd.home\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"system.auth.useradd.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"New users by home directory\",\n \"type\": \"pie\",\n \"params\": {\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"isDonut\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"system.auth.useradd.home\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"system.auth.useradd.name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "d56ee420-fa79-11e6-a1df-a78bd7504d38", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "eb0039f0-fa7f-11e6-a1df-a78bd7504d38", - "title": "New groups", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "title": "New groups [Filebeat System]", + "uiStateJSON": "{\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"New groups\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.auth.groupadd.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.auth.groupadd.gid\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"New groups\",\n \"type\": \"table\",\n \"params\": {\n \"perPage\": 10,\n \"showPartialRows\": false,\n \"showMeticsAtAllLevels\": false,\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n },\n \"showTotal\": false,\n \"totalFunc\": \"sum\"\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"system.auth.groupadd.name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"system.auth.groupadd.gid\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "12667040-fa80-11e6-a1df-a78bd7504d38", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "eb0039f0-fa7f-11e6-a1df-a78bd7504d38", - "title": "New groups over time", + "title": "New groups over time [Filebeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"New groups over time\",\"type\":\"histogram\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"system.auth.groupadd.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"New groups over time\",\n \"type\": \"histogram\",\n \"params\": {\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"bottom\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"system.auth.groupadd.name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "346bb290-fa80-11e6-a1df-a78bd7504d38", "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{}" + }, + "title": "Dashboards [Filebeat System]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Dashboards [Filebeat System]\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"markdown\":\"[Syslog](#/dashboard/Filebeat-syslog-dashboard) | [Sudo commands](#/dashboard/277876d0-fa2c-11e6-bbd3-29c986c96e5a) | [SSH logins](#/dashboard/5517a150-f9ce-11e6-8115-a7c18106d86a) | [New users and groups](#/dashboard/0d3f2380-fa78-11e6-ae9b-81e5311e8cab)\"},\"aggs\":[]}" + }, + "id": "327417e0-8462-11e7-bab8-bd2f0fb42c54", + "type": "visualization", "version": 1 }, { @@ -108,18 +123,18 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"_exists_:system.auth.useradd\"}},\"filter\":[]}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"highlightAll\": true,\n \"query\": {\n \"query_string\": {\n \"analyze_wildcard\": true,\n \"query\": \"_exists_:system.auth.useradd\"\n }\n },\n \"filter\": []\n}" }, "sort": [ "@timestamp", "desc" ], - "title": "useradd logs", + "title": "useradd logs [Filebeat System]", "version": 1 }, "id": "8030c1b0-fa77-11e6-ae9b-81e5311e8cab", "type": "search", - "version": 4 + "version": 2 }, { "attributes": { @@ -130,13 +145,13 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"query\":{\"query_string\":{\"query\":\"_exists_:system.auth.groupadd\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"highlightAll\": true,\n \"query\": {\n \"query_string\": {\n \"query\": \"_exists_:system.auth.groupadd\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": []\n}" }, "sort": [ "@timestamp", "desc" ], - "title": "groupadd logs", + "title": "groupadd logs [Filebeat System]", "version": 1 }, "id": "eb0039f0-fa7f-11e6-a1df-a78bd7504d38", @@ -145,22 +160,22 @@ }, { "attributes": { - "description": "", + "description": "New users and groups dashboard for the System module in Filebeat", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"default_field\":\"*\",\"query\":\"*\"}}},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"f398d2f0-fa77-11e6-ae9b-81e5311e8cab\",\"panelIndex\":1,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"5dd15c00-fa78-11e6-ae9b-81e5311e8cab\",\"panelIndex\":2,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"e121b140-fa78-11e6-a1df-a78bd7504d38\",\"panelIndex\":3,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"d56ee420-fa79-11e6-a1df-a78bd7504d38\",\"panelIndex\":4,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"12667040-fa80-11e6-a1df-a78bd7504d38\",\"panelIndex\":5,\"row\":7,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"size_x\":6,\"size_y\":3,\"panelIndex\":6,\"type\":\"visualization\",\"id\":\"346bb290-fa80-11e6-a1df-a78bd7504d38\",\"col\":7,\"row\":7}]", + "panelsJSON": "[{\"col\":1,\"id\":\"f398d2f0-fa77-11e6-ae9b-81e5311e8cab\",\"panelIndex\":1,\"row\":2,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"5dd15c00-fa78-11e6-ae9b-81e5311e8cab\",\"panelIndex\":2,\"row\":2,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"e121b140-fa78-11e6-a1df-a78bd7504d38\",\"panelIndex\":3,\"row\":5,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"d56ee420-fa79-11e6-a1df-a78bd7504d38\",\"panelIndex\":4,\"row\":5,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"12667040-fa80-11e6-a1df-a78bd7504d38\",\"panelIndex\":5,\"row\":8,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"346bb290-fa80-11e6-a1df-a78bd7504d38\",\"panelIndex\":6,\"row\":8,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"size_x\":12,\"size_y\":1,\"panelIndex\":7,\"type\":\"visualization\",\"id\":\"327417e0-8462-11e7-bab8-bd2f0fb42c54\",\"col\":1,\"row\":1}]", "timeRestore": false, - "title": "Filebeat New users and groups", + "title": "[Filebeat System] New users and groups", "uiStateJSON": "{\"P-1\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-5\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", "version": 1 }, "id": "0d3f2380-fa78-11e6-ae9b-81e5311e8cab", "type": "dashboard", - "version": 1 + "version": 6 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-ssh-login-attempts.json b/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-ssh-login-attempts.json index 96d6377eeb8..bbeacf37219 100644 --- a/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-ssh-login-attempts.json +++ b/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-ssh-login-attempts.json @@ -4,61 +4,61 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[],\"index\":\"filebeat-*\",\"highlightAll\":true,\"query\":{\"query_string\":{\"query\":\"system.auth.ssh.event:Accepted\",\"analyze_wildcard\":true}}}" + "searchSourceJSON": "{\n \"filter\": [],\n \"index\": \"filebeat-*\",\n \"highlightAll\": true,\n \"query\": {\n \"query_string\": {\n \"query\": \"system.auth.ssh.event:Accepted\",\n \"analyze_wildcard\": true\n }\n }\n}" }, - "title": "Successful SSH logins", - "uiStateJSON": "{\"vis\":{\"colors\":{\"Accepted\":\"#3F6833\",\"Failed\":\"#F9934E\",\"Invalid\":\"#447EBC\",\"publickey\":\"#629E51\",\"password\":\"#BF1B00\"}}}", + "title": "Successful SSH logins [Filebeat System]", + "uiStateJSON": "{\n \"vis\": {\n \"colors\": {\n \"Accepted\": \"#3F6833\",\n \"Failed\": \"#F9934E\",\n \"Invalid\": \"#447EBC\",\n \"publickey\": \"#629E51\",\n \"password\": \"#BF1B00\"\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"Successful SSH logins\",\"type\":\"histogram\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"system.auth.ssh.method\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Successful SSH logins\",\n \"type\": \"histogram\",\n \"params\": {\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"system.auth.ssh.method\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "d16bb400-f9cc-11e6-8115-a7c18106d86a", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[],\"index\":\"filebeat-*\",\"highlightAll\":true}" + "searchSourceJSON": "{\n \"filter\": [],\n \"index\": \"filebeat-*\",\n \"highlightAll\": true\n}" }, - "title": "SSH login attempts", - "uiStateJSON": "{\"vis\":{\"colors\":{\"Accepted\":\"#3F6833\",\"Failed\":\"#F9934E\",\"Invalid\":\"#447EBC\"}}}", + "title": "SSH login attempts [Filebeat System]", + "uiStateJSON": "{\n \"vis\": {\n \"colors\": {\n \"Accepted\": \"#3F6833\",\n \"Failed\": \"#F9934E\",\n \"Invalid\": \"#447EBC\"\n }\n }\n}", "version": 1, - "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{},\"schema\":\"metric\",\"type\":\"count\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"customInterval\":\"2h\",\"extended_bounds\":{},\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1},\"schema\":\"segment\",\"type\":\"date_histogram\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"field\":\"system.auth.ssh.event\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":5},\"schema\":\"group\",\"type\":\"terms\"}],\"listeners\":{},\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"legendPosition\":\"right\",\"mode\":\"stacked\",\"scale\":\"linear\",\"setYExtents\":false,\"times\":[]},\"title\":\"SSH login attempts\",\"type\":\"histogram\"}" + "visState": "{\n \"aggs\": [\n {\n \"enabled\": true,\n \"id\": \"1\",\n \"params\": {},\n \"schema\": \"metric\",\n \"type\": \"count\"\n },\n {\n \"enabled\": true,\n \"id\": \"2\",\n \"params\": {\n \"customInterval\": \"2h\",\n \"extended_bounds\": {},\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"min_doc_count\": 1\n },\n \"schema\": \"segment\",\n \"type\": \"date_histogram\"\n },\n {\n \"enabled\": true,\n \"id\": \"3\",\n \"params\": {\n \"field\": \"system.auth.ssh.event\",\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"size\": 5\n },\n \"schema\": \"group\",\n \"type\": \"terms\"\n }\n ],\n \"listeners\": {},\n \"params\": {\n \"addLegend\": true,\n \"addTimeMarker\": false,\n \"addTooltip\": true,\n \"defaultYExtents\": false,\n \"legendPosition\": \"right\",\n \"mode\": \"stacked\",\n \"scale\": \"linear\",\n \"setYExtents\": false,\n \"times\": []\n },\n \"title\": \"SSH login attempts\",\n \"type\": \"histogram\"\n}" }, "id": "78b74f30-f9cd-11e6-8115-a7c18106d86a", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[],\"index\":\"filebeat-*\",\"highlightAll\":true,\"query\":{\"query_string\":{\"query\":\"system.auth.ssh.event:Failed OR system.auth.ssh.event:Invalid\",\"analyze_wildcard\":true}}}" + "searchSourceJSON": "{\n \"filter\": [],\n \"index\": \"filebeat-*\",\n \"highlightAll\": true,\n \"query\": {\n \"query_string\": {\n \"query\": \"system.auth.ssh.event:Failed OR system.auth.ssh.event:Invalid\",\n \"analyze_wildcard\": true\n }\n }\n}" }, - "title": "SSH users of failed login attempts", + "title": "SSH users of failed login attempts [Filebeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"SSH users of failed login attempts\",\"type\":\"tagcloud\",\"params\":{\"maxFontSize\":72,\"minFontSize\":18,\"orientation\":\"single\",\"scale\":\"linear\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"system.auth.user\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"SSH users of failed login attempts\",\n \"type\": \"tagcloud\",\n \"params\": {\n \"maxFontSize\": 72,\n \"minFontSize\": 18,\n \"orientation\": \"single\",\n \"scale\": \"linear\"\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"system.auth.user\",\n \"size\": 50,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "341ffe70-f9ce-11e6-8115-a7c18106d86a", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[],\"index\":\"filebeat-*\",\"highlightAll\":true,\"query\":{\"query_string\":{\"query\":\"system.auth.ssh.event:Failed OR system.auth.ssh.event:Invalid\",\"analyze_wildcard\":true}}}" + "searchSourceJSON": "{\n \"filter\": [],\n \"index\": \"filebeat-*\",\n \"highlightAll\": true,\n \"query\": {\n \"query_string\": {\n \"query\": \"system.auth.ssh.event:Failed OR system.auth.ssh.event:Invalid\",\n \"analyze_wildcard\": true\n }\n }\n}" }, - "title": "SSH failed login attempts source locations", - "uiStateJSON": "{\"mapZoom\":2,\"mapCenter\":[17.602139123350838,69.697265625]}", + "title": "SSH failed login attempts source locations [Filebeat System]", + "uiStateJSON": "{\n \"mapZoom\": 2,\n \"mapCenter\": [\n 17.602139123350838,\n 69.697265625\n ]\n}", "version": 1, - "visState": "{\"title\":\"SSH failed login attempts source locations\",\"type\":\"tile_map\",\"params\":{\"mapType\":\"Shaded Circle Markers\",\"isDesaturated\":true,\"addTooltip\":true,\"heatMaxZoom\":16,\"heatMinOpacity\":0.1,\"heatRadius\":25,\"heatBlur\":15,\"heatNormalizeData\":true,\"legendPosition\":\"bottomright\",\"mapZoom\":2,\"mapCenter\":[15,5],\"wms\":{\"enabled\":false,\"url\":\"https://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer\",\"options\":{\"version\":\"1.3.0\",\"layers\":\"0\",\"format\":\"image/png\",\"transparent\":true,\"attribution\":\"Maps provided by USGS\",\"styles\":\"\"}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"geohash_grid\",\"schema\":\"segment\",\"params\":{\"field\":\"system.auth.ssh.geoip.location\",\"autoPrecision\":true,\"precision\":2}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"SSH failed login attempts source locations\",\n \"type\": \"tile_map\",\n \"params\": {\n \"mapType\": \"Shaded Circle Markers\",\n \"isDesaturated\": true,\n \"addTooltip\": true,\n \"heatMaxZoom\": 16,\n \"heatMinOpacity\": 0.1,\n \"heatRadius\": 25,\n \"heatBlur\": 15,\n \"heatNormalizeData\": true,\n \"legendPosition\": \"bottomright\",\n \"mapZoom\": 2,\n \"mapCenter\": [\n 15,\n 5\n ],\n \"wms\": {\n \"enabled\": false,\n \"url\": \"https://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer\",\n \"options\": {\n \"version\": \"1.3.0\",\n \"layers\": \"0\",\n \"format\": \"image/png\",\n \"transparent\": true,\n \"attribution\": \"Maps provided by USGS\",\n \"styles\": \"\"\n }\n }\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"geohash_grid\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"system.auth.ssh.geoip.location\",\n \"autoPrecision\": true,\n \"precision\": 2\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "3cec3eb0-f9d3-11e6-8a3e-2b904044ea1d", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { @@ -72,37 +72,52 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"highlightAll\":true,\"query\":{\"query_string\":{\"query\":\"_exists_:system.auth.ssh.event\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"highlightAll\": true,\n \"query\": {\n \"query_string\": {\n \"query\": \"_exists_:system.auth.ssh.event\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": []\n}" }, "sort": [ "@timestamp", "desc" ], - "title": "SSH login attempts", + "title": "SSH login attempts [Filebeat System]", "version": 1 }, "id": "62439dc0-f9c9-11e6-a747-6121780e0414", "type": "search", - "version": 1 + "version": 2 }, { "attributes": { "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{}" + }, + "title": "Dashboards [Filebeat System]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Dashboards [Filebeat System]\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"markdown\":\"[Syslog](#/dashboard/Filebeat-syslog-dashboard) | [Sudo commands](#/dashboard/277876d0-fa2c-11e6-bbd3-29c986c96e5a) | [SSH logins](#/dashboard/5517a150-f9ce-11e6-8115-a7c18106d86a) | [New users and groups](#/dashboard/0d3f2380-fa78-11e6-ae9b-81e5311e8cab)\"},\"aggs\":[]}" + }, + "id": "327417e0-8462-11e7-bab8-bd2f0fb42c54", + "type": "visualization", + "version": 1 + }, + { + "attributes": { + "description": "SSH dashboard for the System module in Filebeat", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\",\"default_field\":\"*\"}},\"language\":\"lucene\"},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"d16bb400-f9cc-11e6-8115-a7c18106d86a\",\"panelIndex\":1,\"row\":4,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"78b74f30-f9cd-11e6-8115-a7c18106d86a\",\"panelIndex\":2,\"row\":1,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"341ffe70-f9ce-11e6-8115-a7c18106d86a\",\"panelIndex\":3,\"row\":7,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":7,\"id\":\"3cec3eb0-f9d3-11e6-8a3e-2b904044ea1d\",\"panelIndex\":4,\"row\":7,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"size_x\":12,\"size_y\":3,\"panelIndex\":5,\"type\":\"search\",\"id\":\"62439dc0-f9c9-11e6-a747-6121780e0414\",\"col\":1,\"row\":11,\"columns\":[\"system.auth.ssh.event\",\"system.auth.ssh.method\",\"system.auth.user\",\"system.auth.ssh.ip\",\"system.auth.ssh.geoip.country_iso_code\"],\"sort\":[\"@timestamp\",\"desc\"]}]", + "panelsJSON": "[{\"col\":1,\"id\":\"d16bb400-f9cc-11e6-8115-a7c18106d86a\",\"panelIndex\":1,\"row\":5,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"78b74f30-f9cd-11e6-8115-a7c18106d86a\",\"panelIndex\":2,\"row\":2,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"341ffe70-f9ce-11e6-8115-a7c18106d86a\",\"panelIndex\":3,\"row\":8,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":7,\"id\":\"3cec3eb0-f9d3-11e6-8a3e-2b904044ea1d\",\"panelIndex\":4,\"row\":8,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"size_x\":12,\"size_y\":3,\"panelIndex\":5,\"type\":\"search\",\"id\":\"62439dc0-f9c9-11e6-a747-6121780e0414\",\"col\":1,\"row\":12,\"columns\":[\"system.auth.ssh.event\",\"system.auth.ssh.method\",\"system.auth.user\",\"system.auth.ssh.ip\",\"system.auth.ssh.geoip.country_iso_code\"],\"sort\":[\"@timestamp\",\"desc\"]},{\"size_x\":12,\"size_y\":1,\"panelIndex\":6,\"type\":\"visualization\",\"id\":\"327417e0-8462-11e7-bab8-bd2f0fb42c54\",\"col\":1,\"row\":1}]", "timeRestore": false, - "title": "Filebeat SSH login attempts", - "uiStateJSON": "{\"P-4\":{\"mapCenter\":[39.774769485295465,23.203125],\"mapZoom\":3}}", + "title": "[Filebeat System] SSH login attempts", + "uiStateJSON": "{\"P-4\":{\"mapCenter\":[39.774769485295465,23.203125],\"mapZoom\":3,\"mapBounds\":{\"bottom_right\":{\"lat\":10.31491928581316,\"lon\":74.53125},\"top_left\":{\"lat\":60.50052541051131,\"lon\":-27.94921875}},\"mapCollar\":{\"top_left\":{\"lat\":85.593335,\"lon\":-79.189455},\"bottom_right\":{\"lat\":-14.777884999999998,\"lon\":125.771485},\"zoom\":3}}}", "version": 1 }, "id": "5517a150-f9ce-11e6-8115-a7c18106d86a", "type": "dashboard", - "version": 1 + "version": 7 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-syslog.json b/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-syslog.json index 6562d08a723..393fcfd616d 100644 --- a/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-syslog.json +++ b/filebeat/module/system/_meta/kibana/default/dashboard/Filebeat-syslog.json @@ -4,33 +4,33 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Syslog-system-logs", - "title": "Syslog events by hostname", + "title": "Syslog events by hostname [Filebeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Syslog events by hostname\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"system.syslog.hostname\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Syslog events by hostname\",\n \"type\": \"histogram\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"system.syslog.hostname\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Syslog-events-by-hostname", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Syslog-system-logs", - "title": "Syslog hostnames and processes", + "title": "Syslog hostnames and processes [Filebeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Syslog hostnames and processes\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"isDonut\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"system.syslog.hostname\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"system.syslog.program\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Syslog hostnames and processes\",\n \"type\": \"pie\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"bottom\",\n \"isDonut\": true\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"system.syslog.hostname\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"system.syslog.program\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Syslog-hostnames-and-processes", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { @@ -42,37 +42,52 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"filebeat-*\",\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"_exists_:system.syslog\",\"analyze_wildcard\":true}},\"highlightAll\":true}" + "searchSourceJSON": "{\n \"index\": \"filebeat-*\",\n \"filter\": [],\n \"highlight\": {\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n },\n \"query\": {\n \"query_string\": {\n \"query\": \"_exists_:system.syslog\",\n \"analyze_wildcard\": true\n }\n },\n \"highlightAll\": true\n}" }, "sort": [ "@timestamp", "desc" ], - "title": "Syslog system logs", + "title": "Syslog logs [Filebeat System]", "version": 1 }, "id": "Syslog-system-logs", "type": "search", - "version": 3 + "version": 2 }, { "attributes": { "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{}" + }, + "title": "Dashboards [Filebeat System]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Dashboards [Filebeat System]\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"markdown\":\"[Syslog](#/dashboard/Filebeat-syslog-dashboard) | [Sudo commands](#/dashboard/277876d0-fa2c-11e6-bbd3-29c986c96e5a) | [SSH logins](#/dashboard/5517a150-f9ce-11e6-8115-a7c18106d86a) | [New users and groups](#/dashboard/0d3f2380-fa78-11e6-ae9b-81e5311e8cab)\"},\"aggs\":[]}" + }, + "id": "327417e0-8462-11e7-bab8-bd2f0fb42c54", + "type": "visualization", + "version": 1 + }, + { + "attributes": { + "description": "Syslog dashboard from the Filebeat System module", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true,\"default_field\":\"*\"}},\"language\":\"lucene\"},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"id\":\"Syslog-events-by-hostname\",\"type\":\"visualization\",\"panelIndex\":1,\"size_x\":8,\"size_y\":4,\"col\":1,\"row\":1},{\"id\":\"Syslog-hostnames-and-processes\",\"type\":\"visualization\",\"panelIndex\":2,\"size_x\":4,\"size_y\":4,\"col\":9,\"row\":1},{\"id\":\"Syslog-system-logs\",\"type\":\"search\",\"panelIndex\":3,\"size_x\":12,\"size_y\":7,\"col\":1,\"row\":5,\"columns\":[\"system.syslog.hostname\",\"system.syslog.program\",\"system.syslog.message\"],\"sort\":[\"@timestamp\",\"desc\"]}]", + "panelsJSON": "[{\"id\":\"Syslog-events-by-hostname\",\"type\":\"visualization\",\"panelIndex\":1,\"size_x\":8,\"size_y\":4,\"col\":1,\"row\":2},{\"id\":\"Syslog-hostnames-and-processes\",\"type\":\"visualization\",\"panelIndex\":2,\"size_x\":4,\"size_y\":4,\"col\":9,\"row\":2},{\"id\":\"Syslog-system-logs\",\"type\":\"search\",\"panelIndex\":3,\"size_x\":12,\"size_y\":7,\"col\":1,\"row\":6,\"columns\":[\"system.syslog.hostname\",\"system.syslog.program\",\"system.syslog.message\"],\"sort\":[\"@timestamp\",\"desc\"]},{\"size_x\":12,\"size_y\":1,\"panelIndex\":4,\"type\":\"visualization\",\"id\":\"327417e0-8462-11e7-bab8-bd2f0fb42c54\",\"col\":1,\"row\":1}]", "timeRestore": false, - "title": "Filebeat syslog dashboard", + "title": "[Filebeat System] Syslog dashboard", "uiStateJSON": "{}", "version": 1 }, "id": "Filebeat-syslog-dashboard", "type": "dashboard", - "version": 1 + "version": 6 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/filebeat/module/system/module.yml b/filebeat/module/system/module.yml index b566c0a15b9..624c7e31809 100644 --- a/filebeat/module/system/module.yml +++ b/filebeat/module/system/module.yml @@ -1,12 +1,12 @@ dashboards: - - id: 0d3f2380-fa78-11e6-ae9b-81e5311e8cab - file: Filebeat-new-users-and-groups.json +- id: 0d3f2380-fa78-11e6-ae9b-81e5311e8cab + file: Filebeat-new-users-and-groups.json - - id: 277876d0-fa2c-11e6-bbd3-29c986c96e5a - file: Filebeat-auth-sudo-commands.json +- id: 277876d0-fa2c-11e6-bbd3-29c986c96e5a + file: Filebeat-auth-sudo-commands.json - - id: 5517a150-f9ce-11e6-8115-a7c18106d86a - file: Filebeat-ssh-login-attempts.json +- id: 5517a150-f9ce-11e6-8115-a7c18106d86a + file: Filebeat-ssh-login-attempts.json - - id: Filebeat-syslog-dashboard - file: Filebeat-syslog.json +- id: Filebeat-syslog-dashboard + file: Filebeat-syslog.json diff --git a/metricbeat/module/system/module.yml b/metricbeat/module/system/module.yml index 6da75ba8139..f047e9ee2a1 100644 --- a/metricbeat/module/system/module.yml +++ b/metricbeat/module/system/module.yml @@ -1,10 +1,10 @@ dashboards: - - id: Metricbeat-system-overview - file: Metricbeat-system-overview.json +- id: Metricbeat-system-overview + file: Metricbeat-system-overview.json - - id: 79ffd6e0-faa0-11e6-947f-177f697178b8 - file: Metricbeat-host-overview.json +- id: 79ffd6e0-faa0-11e6-947f-177f697178b8 + file: Metricbeat-host-overview.json - - id: CPU-slash-Memory-per-container - file: Metricbeat-docker-overview.json +- id: CPU-slash-Memory-per-container + file: Metricbeat-docker-overview.json From ea5f940204e2e038734708b13e4c1f42308ae04c Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Thu, 24 Aug 2017 10:48:07 +0200 Subject: [PATCH 109/139] Fix typo in reference config file (#4987) --- auditbeat/auditbeat.reference.yml | 2 +- filebeat/filebeat.reference.yml | 2 +- heartbeat/heartbeat.reference.yml | 2 +- libbeat/_meta/config.reference.yml | 2 +- metricbeat/metricbeat.reference.yml | 2 +- packetbeat/packetbeat.reference.yml | 2 +- winlogbeat/winlogbeat.reference.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/auditbeat/auditbeat.reference.yml b/auditbeat/auditbeat.reference.yml index 1ec15108741..64c83f7bb63 100644 --- a/auditbeat/auditbeat.reference.yml +++ b/auditbeat/auditbeat.reference.yml @@ -684,7 +684,7 @@ output.elasticsearch: # The template name and pattern has to be set in case the elasticsearch index pattern is modified. #setup.template.name: "auditbeat-%{[beat.version]}" -# Template patttern. By default the template patter is "-%{[beat.version]}-*" to apply to the default index settings. +# Template patttern. By default the template pattern is "-%{[beat.version]}-*" to apply to the default index settings. # The first part is the version of the beat and then -* is used to match all daily indicies. # The template name and pattern has to be set in case the elasticsearch index pattern is modified. #setup.template.pattern: "auditbeat-%{[beat.version]}-*" diff --git a/filebeat/filebeat.reference.yml b/filebeat/filebeat.reference.yml index 344ca043ef7..0271ea399ff 100644 --- a/filebeat/filebeat.reference.yml +++ b/filebeat/filebeat.reference.yml @@ -1104,7 +1104,7 @@ output.elasticsearch: # The template name and pattern has to be set in case the elasticsearch index pattern is modified. #setup.template.name: "filebeat-%{[beat.version]}" -# Template patttern. By default the template patter is "-%{[beat.version]}-*" to apply to the default index settings. +# Template patttern. By default the template pattern is "-%{[beat.version]}-*" to apply to the default index settings. # The first part is the version of the beat and then -* is used to match all daily indicies. # The template name and pattern has to be set in case the elasticsearch index pattern is modified. #setup.template.pattern: "filebeat-%{[beat.version]}-*" diff --git a/heartbeat/heartbeat.reference.yml b/heartbeat/heartbeat.reference.yml index 564d15a73d8..bbf555c33c6 100644 --- a/heartbeat/heartbeat.reference.yml +++ b/heartbeat/heartbeat.reference.yml @@ -833,7 +833,7 @@ output.elasticsearch: # The template name and pattern has to be set in case the elasticsearch index pattern is modified. #setup.template.name: "heartbeat-%{[beat.version]}" -# Template patttern. By default the template patter is "-%{[beat.version]}-*" to apply to the default index settings. +# Template patttern. By default the template pattern is "-%{[beat.version]}-*" to apply to the default index settings. # The first part is the version of the beat and then -* is used to match all daily indicies. # The template name and pattern has to be set in case the elasticsearch index pattern is modified. #setup.template.pattern: "heartbeat-%{[beat.version]}-*" diff --git a/libbeat/_meta/config.reference.yml b/libbeat/_meta/config.reference.yml index 456d184647f..4e80099b540 100644 --- a/libbeat/_meta/config.reference.yml +++ b/libbeat/_meta/config.reference.yml @@ -619,7 +619,7 @@ output.elasticsearch: # The template name and pattern has to be set in case the elasticsearch index pattern is modified. #setup.template.name: "beatname-%{[beat.version]}" -# Template patttern. By default the template patter is "-%{[beat.version]}-*" to apply to the default index settings. +# Template patttern. By default the template pattern is "-%{[beat.version]}-*" to apply to the default index settings. # The first part is the version of the beat and then -* is used to match all daily indicies. # The template name and pattern has to be set in case the elasticsearch index pattern is modified. #setup.template.pattern: "beatname-%{[beat.version]}-*" diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index 01944ee7de9..22180766a24 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -1063,7 +1063,7 @@ output.elasticsearch: # The template name and pattern has to be set in case the elasticsearch index pattern is modified. #setup.template.name: "metricbeat-%{[beat.version]}" -# Template patttern. By default the template patter is "-%{[beat.version]}-*" to apply to the default index settings. +# Template patttern. By default the template pattern is "-%{[beat.version]}-*" to apply to the default index settings. # The first part is the version of the beat and then -* is used to match all daily indicies. # The template name and pattern has to be set in case the elasticsearch index pattern is modified. #setup.template.pattern: "metricbeat-%{[beat.version]}-*" diff --git a/packetbeat/packetbeat.reference.yml b/packetbeat/packetbeat.reference.yml index d5b82819825..676ab18cf98 100644 --- a/packetbeat/packetbeat.reference.yml +++ b/packetbeat/packetbeat.reference.yml @@ -1071,7 +1071,7 @@ output.elasticsearch: # The template name and pattern has to be set in case the elasticsearch index pattern is modified. #setup.template.name: "packetbeat-%{[beat.version]}" -# Template patttern. By default the template patter is "-%{[beat.version]}-*" to apply to the default index settings. +# Template patttern. By default the template pattern is "-%{[beat.version]}-*" to apply to the default index settings. # The first part is the version of the beat and then -* is used to match all daily indicies. # The template name and pattern has to be set in case the elasticsearch index pattern is modified. #setup.template.pattern: "packetbeat-%{[beat.version]}-*" diff --git a/winlogbeat/winlogbeat.reference.yml b/winlogbeat/winlogbeat.reference.yml index 833e5640cad..f3e130aa563 100644 --- a/winlogbeat/winlogbeat.reference.yml +++ b/winlogbeat/winlogbeat.reference.yml @@ -648,7 +648,7 @@ output.elasticsearch: # The template name and pattern has to be set in case the elasticsearch index pattern is modified. #setup.template.name: "winlogbeat-%{[beat.version]}" -# Template patttern. By default the template patter is "-%{[beat.version]}-*" to apply to the default index settings. +# Template patttern. By default the template pattern is "-%{[beat.version]}-*" to apply to the default index settings. # The first part is the version of the beat and then -* is used to match all daily indicies. # The template name and pattern has to be set in case the elasticsearch index pattern is modified. #setup.template.pattern: "winlogbeat-%{[beat.version]}-*" From 66097bdc21b216b40851231a686ddc3b3cb367e8 Mon Sep 17 00:00:00 2001 From: Steffen Siering Date: Thu, 24 Aug 2017 11:14:41 +0200 Subject: [PATCH 110/139] Adapt packetbeat tcp protocol generator to new publisher pipeline (#4956) --- packetbeat/scripts/tcp-protocol/README.md | 30 +++++++++++-------- .../tcp-protocol/{protocol}/pub.go.tmpl | 25 +++++++++------- .../{protocol}/{protocol}.go.tmpl | 5 ++-- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/packetbeat/scripts/tcp-protocol/README.md b/packetbeat/scripts/tcp-protocol/README.md index 8f931ec053a..28c7c679b30 100644 --- a/packetbeat/scripts/tcp-protocol/README.md +++ b/packetbeat/scripts/tcp-protocol/README.md @@ -102,11 +102,13 @@ func echo(sock net.Conn) { Create analyzer skeleton from code generator template. ``` - $ cd ${GOPATH}/src/github.com/elastic/beats/packetbeat/protos - $ python ${GOPATH}/src/github.com/elastic/beats/packetbeat/script/create_tcp_protocol.py + $ cd ${GOPATH}/src/github.com/elastic/beats/packetbeat + $ python ${GOPATH}/src/github.com/elastic/beats/packetbeat/scripts/create_tcp_protocol.py ``` -Load plugin into packetbeat by adding `_ "github.com/elastic/beats/packetbeat/protos/echo"` to packetbeat import list in `$GOPATH/src/github.com/elastic/beats/packetbeat/main.go` +Load plugin into packetbeat by running `make update`. Or add `_ +"github.com/elastic/beats/packetbeat/protos/echo"` to the import list in +`$GOPATH/src/github.com/elastic/beats/packetbeat/include/list.go`. ### 2.2 Standalone beat with protocol analyzer (echo): @@ -114,7 +116,7 @@ Use packetbeat as framework to build custom beat (e.g. for testing) with selected protocol plugins only. A protocol plugin can still be added to packetbeat later by copying the final plugin to `$GOPATH/src/github.com/elastic/beats/packetbeat/protos` and importing module in -`$GOPATH/src/github.com/elastic/beats/packetbeat/main.go`. +`$GOPATH/src/github.com/elastic/beats/packetbeat/include/list.go`. Create custom beat (e.g. github.com//pb_echo): @@ -134,7 +136,7 @@ import ( "github.com/elastic/beats/packetbeat/beater" // import supported protocol modules - _ "github.com/urso/pb_echo/protos/echo" + _ "github.com/urso/pb_echo/protos/echo" ) var Name = "pb_echo" @@ -152,7 +154,7 @@ Create protocol analyzer module (use name ‘echo’ for new protocol): ``` $ mkdir proto $ cd proto -$ python ${GOPATH}/src/github.com/elastic/beats/packetbeat/script/create_tcp_protocol.py +$ python ${GOPATH}/src/github.com/elastic/beats/packetbeat/scripts/create_tcp_protocol.py ``` ### 3 Implement application layer analyzer @@ -226,7 +228,7 @@ If possible you can use third-party libraries for parsing messages. This might r ### 3.2 Add additional fields to transaction event ``` -func (pub *transPub) createEvent(requ, resp *message) common.MapStr { +func (pub *transPub) createEvent(requ, resp *message) beat.Event { status := common.OK_STATUS if resp.failed { status = common.ERROR_STATUS @@ -246,8 +248,7 @@ func (pub *transPub) createEvent(requ, resp *message) common.MapStr { Proc: string(requ.CmdlineTuple.Dst), } - event := common.MapStr{ - "@timestamp": common.Time(requ.Ts), + fields := common.MapStr{ "type": "echo", "status": status, "responsetime": responseTime, @@ -259,17 +260,20 @@ func (pub *transPub) createEvent(requ, resp *message) common.MapStr { // add processing notes/errors to event if len(requ.Notes)+len(resp.Notes) > 0 { - event["notes"] = append(requ.Notes, resp.Notes...) + fields["notes"] = append(requ.Notes, resp.Notes...) } if pub.sendRequest { - event["request"] = requ.content + fields["request"] = requ.content } if pub.sendResponse { - event["response"] = requ.content + fields["response"] = requ.content } - return event + return beat.Event{ + Timestamp: requ.Ts, + Fields: fields, + } } ``` diff --git a/packetbeat/scripts/tcp-protocol/{protocol}/pub.go.tmpl b/packetbeat/scripts/tcp-protocol/{protocol}/pub.go.tmpl index 0eec39662eb..a6cdb7ff73e 100644 --- a/packetbeat/scripts/tcp-protocol/{protocol}/pub.go.tmpl +++ b/packetbeat/scripts/tcp-protocol/{protocol}/pub.go.tmpl @@ -1,8 +1,10 @@ package {protocol} import ( + "github.com/elastic/beats/libbeat/beat" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/packetbeat/publish" + + "github.com/elastic/beats/packetbeat/protos" ) // Transaction Publisher. @@ -10,7 +12,7 @@ type transPub struct { sendRequest bool sendResponse bool - results publish.Transactions + results protos.Reporter } func (pub *transPub) onTransaction(requ, resp *message) error { @@ -18,12 +20,11 @@ func (pub *transPub) onTransaction(requ, resp *message) error { return nil } - event := pub.createEvent(requ, resp) - pub.results.PublishTransaction(event) + pub.results(pub.createEvent(requ, resp)) return nil } -func (pub *transPub) createEvent(requ, resp *message) common.MapStr { +func (pub *transPub) createEvent(requ, resp *message) beat.Event { status := common.OK_STATUS // resp_time in milliseconds @@ -40,8 +41,7 @@ func (pub *transPub) createEvent(requ, resp *message) common.MapStr { Proc: string(requ.CmdlineTuple.Dst), } - event := common.MapStr{ - "@timestamp": common.Time(requ.Ts), + fields := common.MapStr{ "type": "{protocol}", "status": status, "responsetime": responseTime, @@ -53,15 +53,18 @@ func (pub *transPub) createEvent(requ, resp *message) common.MapStr { // add processing notes/errors to event if len(requ.Notes)+len(resp.Notes) > 0 { - event["notes"] = append(requ.Notes, resp.Notes...) + fields["notes"] = append(requ.Notes, resp.Notes...) } if pub.sendRequest { - // event["request"] = + // fields["request"] = } if pub.sendResponse { - // event["response"] = + // fields["response"] = } - return event + return beat.Event{ + Timestamp: requ.Ts, + Fields: fields, + } } diff --git a/packetbeat/scripts/tcp-protocol/{protocol}/{protocol}.go.tmpl b/packetbeat/scripts/tcp-protocol/{protocol}/{protocol}.go.tmpl index 5bd703f54bb..ed40c7a0497 100644 --- a/packetbeat/scripts/tcp-protocol/{protocol}/{protocol}.go.tmpl +++ b/packetbeat/scripts/tcp-protocol/{protocol}/{protocol}.go.tmpl @@ -8,7 +8,6 @@ import ( "github.com/elastic/beats/packetbeat/protos" "github.com/elastic/beats/packetbeat/protos/tcp" - "github.com/elastic/beats/packetbeat/publish" ) // {plugin_type} application level protocol analyzer plugin @@ -45,7 +44,7 @@ func init() { // New create and initializes a new {protocol} protocol analyzer instance. func New( testMode bool, - results publish.Transactions, + results protos.Reporter, cfg *common.Config, ) (protos.Plugin, error) { p := &{plugin_type}{} @@ -62,7 +61,7 @@ func New( return p, nil } -func ({plugin_var} *{plugin_type}) init(results publish.Transactions, config *{protocol}Config) error { +func ({plugin_var} *{plugin_type}) init(results protos.Reporter, config *{protocol}Config) error { if err := {plugin_var}.setFromConfig(config); err != nil { return err } From c2360d08da718c2ebeca9757f9e0895d39e921c1 Mon Sep 17 00:00:00 2001 From: Steffen Siering Date: Thu, 24 Aug 2017 11:53:35 +0200 Subject: [PATCH 111/139] Add option to enable/disable LS output slow start (#4972) * Add option to enable/disable LS output slow start - add support to disable slow start in LS output - disable slow start by default. LS with java rewrite returns some kind of heartbeat every few seconds, so beats can tell the batch is still actively processed. With this change in LS, the original purpose of limiting batch sizes has become somewhat superfluous and is not really required anymore. -> We disable slow start and windowing by default, but keep the setting in case we find it's still required (e.g. when sending to older LS instances). * Update docs and reference configs * Remove unused method * Update changelog * review --- CHANGELOG.asciidoc | 1 + auditbeat/auditbeat.reference.yml | 5 ++++ filebeat/filebeat.reference.yml | 5 ++++ heartbeat/heartbeat.reference.yml | 5 ++++ libbeat/_meta/config.reference.yml | 5 ++++ libbeat/docs/outputconfig.asciidoc | 8 +++++ libbeat/outputs/logstash/async.go | 45 +++++++++++++++++------------ libbeat/outputs/logstash/config.go | 2 ++ libbeat/outputs/logstash/sync.go | 36 +++++++++++++++++------ libbeat/outputs/logstash/window.go | 6 ++++ metricbeat/metricbeat.reference.yml | 5 ++++ packetbeat/packetbeat.reference.yml | 5 ++++ winlogbeat/winlogbeat.reference.yml | 5 ++++ 13 files changed, 106 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 0f3a5b31ea0..1409a2b4adf 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -71,6 +71,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Affecting all Beats* +- Add setting to enable/disable the slow start in logstash output. {pull}4972[4972] - Update init scripts to use the `test config` subcommand instead of the deprecated `-configtest` flag. {issue}4600[4600] - Get by default the credentials for connecting to Kibana from the Elasticsearch output configuration. {pull}4867[4867] - Move TCP UDP start up into `server.Start()` {pull}4903[4903] diff --git a/auditbeat/auditbeat.reference.yml b/auditbeat/auditbeat.reference.yml index 64c83f7bb63..2e3a127379c 100644 --- a/auditbeat/auditbeat.reference.yml +++ b/auditbeat/auditbeat.reference.yml @@ -311,6 +311,11 @@ output.elasticsearch: # new batches. #pipelining: 5 + # If enabled only a subset of events in a batch of events is transfered per + # transaction. The number of events to sent increases up to `bulk_max_size` + # if no error is encountered. + #slow_start: false + # Optional index name. The default index name is set to name of the beat # in all lowercase. #index: 'auditbeat' diff --git a/filebeat/filebeat.reference.yml b/filebeat/filebeat.reference.yml index 0271ea399ff..1bd319ca0fc 100644 --- a/filebeat/filebeat.reference.yml +++ b/filebeat/filebeat.reference.yml @@ -731,6 +731,11 @@ output.elasticsearch: # new batches. #pipelining: 5 + # If enabled only a subset of events in a batch of events is transfered per + # transaction. The number of events to sent increases up to `bulk_max_size` + # if no error is encountered. + #slow_start: false + # Optional index name. The default index name is set to name of the beat # in all lowercase. #index: 'filebeat' diff --git a/heartbeat/heartbeat.reference.yml b/heartbeat/heartbeat.reference.yml index bbf555c33c6..e17e962120e 100644 --- a/heartbeat/heartbeat.reference.yml +++ b/heartbeat/heartbeat.reference.yml @@ -460,6 +460,11 @@ output.elasticsearch: # new batches. #pipelining: 5 + # If enabled only a subset of events in a batch of events is transfered per + # transaction. The number of events to sent increases up to `bulk_max_size` + # if no error is encountered. + #slow_start: false + # Optional index name. The default index name is set to name of the beat # in all lowercase. #index: 'heartbeat' diff --git a/libbeat/_meta/config.reference.yml b/libbeat/_meta/config.reference.yml index 4e80099b540..28bf014bbb4 100644 --- a/libbeat/_meta/config.reference.yml +++ b/libbeat/_meta/config.reference.yml @@ -246,6 +246,11 @@ output.elasticsearch: # new batches. #pipelining: 5 + # If enabled only a subset of events in a batch of events is transfered per + # transaction. The number of events to sent increases up to `bulk_max_size` + # if no error is encountered. + #slow_start: false + # Optional index name. The default index name is set to name of the beat # in all lowercase. #index: 'beatname' diff --git a/libbeat/docs/outputconfig.asciidoc b/libbeat/docs/outputconfig.asciidoc index 49a4ed763e0..c07e0037a2b 100644 --- a/libbeat/docs/outputconfig.asciidoc +++ b/libbeat/docs/outputconfig.asciidoc @@ -532,6 +532,14 @@ Beats that publish single events (such as Packetbeat) send each event directly t Elasticsearch. Beats that publish data in batches (such as Filebeat) send events in batches based on the spooler size. +===== `slow_start` + +If enabled only a subset of events in a batch of events is transfered per transaction. +The number of events to be sent increases up to `bulk_max_size` if no error is encountered. +On error the number of events per transaction is reduced again. + +The default is `false`. + [[kafka-output]] === Configure the Kafka output diff --git a/libbeat/outputs/logstash/async.go b/libbeat/outputs/logstash/async.go index 92b9ea3813a..10c0ed1fe23 100644 --- a/libbeat/outputs/logstash/async.go +++ b/libbeat/outputs/logstash/async.go @@ -16,7 +16,7 @@ type asyncClient struct { *transport.Client stats *outputs.Stats client *v2.AsyncClient - win window + win *window connect func() error } @@ -36,10 +36,14 @@ func newAsyncClient( stats *outputs.Stats, config *Config, ) (*asyncClient, error) { - c := &asyncClient{} - c.Client = conn - c.stats = stats - c.win.init(defaultStartMaxWindowSize, config.BulkMaxSize) + c := &asyncClient{ + Client: conn, + stats: stats, + } + + if config.SlowStart { + c.win = newWindower(defaultStartMaxWindowSize, config.BulkMaxSize) + } if config.TTL != 0 { logp.Warn(`The async Logstash client does not support the "ttl" option`) @@ -99,10 +103,6 @@ func (c *asyncClient) Close() error { return c.Client.Close() } -func (c *asyncClient) BatchSize() int { - return c.win.get() -} - func (c *asyncClient) Publish(batch publisher.Batch) error { st := c.stats events := batch.Events() @@ -113,24 +113,29 @@ func (c *asyncClient) Publish(batch publisher.Batch) error { return nil } - window := make([]interface{}, len(events)) - for i := range events { - window[i] = &events[i] - } - ref := &msgRef{ client: c, count: atomic.MakeUint32(1), batch: batch, slice: events, batchSize: len(events), - win: &c.win, + win: c.win, err: nil, } defer ref.dec() for len(events) > 0 { - n, err := c.publishWindowed(ref, events) + var ( + n int + err error + ) + + if c.win == nil { + n = len(events) + err = c.sendEvents(ref, events) + } else { + n, err = c.publishWindowed(ref, events) + } debugf("%v events out of %v events sent to logstash. Continue sending", n, len(events)) @@ -188,7 +193,9 @@ func (r *msgRef) callback(seq uint32, err error) { func (r *msgRef) done(n uint32) { r.client.stats.Acked(int(n)) r.slice = r.slice[n:] - r.win.tryGrowWindow(r.batchSize) + if r.win != nil { + r.win.tryGrowWindow(r.batchSize) + } r.dec() } @@ -197,7 +204,9 @@ func (r *msgRef) fail(n uint32, err error) { r.err = err } r.slice = r.slice[n:] - r.win.shrinkWindow() + if r.win != nil { + r.win.shrinkWindow() + } r.client.stats.Acked(int(n)) diff --git a/libbeat/outputs/logstash/config.go b/libbeat/outputs/logstash/config.go index 6e8e1feb5e8..5bb6fcc69b5 100644 --- a/libbeat/outputs/logstash/config.go +++ b/libbeat/outputs/logstash/config.go @@ -12,6 +12,7 @@ type Config struct { Port int `config:"port"` LoadBalance bool `config:"loadbalance"` BulkMaxSize int `config:"bulk_max_size"` + SlowStart bool `config:"slow_start"` Timeout time.Duration `config:"timeout"` TTL time.Duration `config:"ttl" validate:"min=0"` Pipelining int `config:"pipelining" validate:"min=0"` @@ -32,6 +33,7 @@ var defaultConfig = Config{ LoadBalance: false, Pipelining: 5, BulkMaxSize: 2048, + SlowStart: false, CompressionLevel: 3, Timeout: 30 * time.Second, MaxRetries: 3, diff --git a/libbeat/outputs/logstash/sync.go b/libbeat/outputs/logstash/sync.go index 9caf46cf495..4bf2bdbd98b 100644 --- a/libbeat/outputs/logstash/sync.go +++ b/libbeat/outputs/logstash/sync.go @@ -14,7 +14,7 @@ type syncClient struct { *transport.Client client *v2.SyncClient stats *outputs.Stats - win window + win *window ttl time.Duration ticker *time.Ticker } @@ -24,11 +24,15 @@ func newSyncClient( stats *outputs.Stats, config *Config, ) (*syncClient, error) { - c := &syncClient{} - c.Client = conn - c.ttl = config.TTL - c.stats = stats - c.win.init(defaultStartMaxWindowSize, config.BulkMaxSize) + c := &syncClient{ + Client: conn, + stats: stats, + ttl: config.TTL, + } + + if config.SlowStart { + c.win = newWindower(defaultStartMaxWindowSize, config.BulkMaxSize) + } if c.ttl > 0 { c.ticker = time.NewTicker(c.ttl) } @@ -95,13 +99,25 @@ func (c *syncClient) Publish(batch publisher.Batch) error { batch.Retry() return err } + // reset window size on reconnect - c.win.windowSize = int32(defaultStartMaxWindowSize) + if c.win != nil { + c.win.windowSize = int32(defaultStartMaxWindowSize) + } default: } } - n, err := c.publishWindowed(events) + var ( + n int + err error + ) + + if c.win == nil { + n, err = c.sendEvents(events) + } else { + n, err = c.publishWindowed(events) + } events = events[n:] st.Acked(n) @@ -112,7 +128,9 @@ func (c *syncClient) Publish(batch publisher.Batch) error { // return batch to pipeline before reporting/counting error batch.RetryEvents(events) - c.win.shrinkWindow() + if c.win != nil { + c.win.shrinkWindow() + } _ = c.Close() logp.Err("Failed to publish events caused by: %v", err) diff --git a/libbeat/outputs/logstash/window.go b/libbeat/outputs/logstash/window.go index 1786c53662f..df7ff1cd4dd 100644 --- a/libbeat/outputs/logstash/window.go +++ b/libbeat/outputs/logstash/window.go @@ -11,6 +11,12 @@ type window struct { maxWindowSize int } +func newWindower(start, max int) *window { + w := &window{} + w.init(start, max) + return w +} + func (w *window) init(start, max int) { *w = window{ windowSize: int32(start), diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index 22180766a24..12766fa9a2b 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -690,6 +690,11 @@ output.elasticsearch: # new batches. #pipelining: 5 + # If enabled only a subset of events in a batch of events is transfered per + # transaction. The number of events to sent increases up to `bulk_max_size` + # if no error is encountered. + #slow_start: false + # Optional index name. The default index name is set to name of the beat # in all lowercase. #index: 'metricbeat' diff --git a/packetbeat/packetbeat.reference.yml b/packetbeat/packetbeat.reference.yml index 676ab18cf98..0beec09d542 100644 --- a/packetbeat/packetbeat.reference.yml +++ b/packetbeat/packetbeat.reference.yml @@ -698,6 +698,11 @@ output.elasticsearch: # new batches. #pipelining: 5 + # If enabled only a subset of events in a batch of events is transfered per + # transaction. The number of events to sent increases up to `bulk_max_size` + # if no error is encountered. + #slow_start: false + # Optional index name. The default index name is set to name of the beat # in all lowercase. #index: 'packetbeat' diff --git a/winlogbeat/winlogbeat.reference.yml b/winlogbeat/winlogbeat.reference.yml index f3e130aa563..4454e8b44d7 100644 --- a/winlogbeat/winlogbeat.reference.yml +++ b/winlogbeat/winlogbeat.reference.yml @@ -275,6 +275,11 @@ output.elasticsearch: # new batches. #pipelining: 5 + # If enabled only a subset of events in a batch of events is transfered per + # transaction. The number of events to sent increases up to `bulk_max_size` + # if no error is encountered. + #slow_start: false + # Optional index name. The default index name is set to name of the beat # in all lowercase. #index: 'winlogbeat' From c9a40eb14c9432412ad1baee0605bb092f8305df Mon Sep 17 00:00:00 2001 From: Steffen Siering Date: Thu, 24 Aug 2017 12:24:20 +0200 Subject: [PATCH 112/139] Event ACK callbacks only report the events private field (#4978) * Event ACK callbacks only report the events private field * Only store file.State in beat.Event.Private - only store file state, such that events actual content can be GC'ed more early - tighten types interfaces to better match actual use * Update winlogbeat --- filebeat/beater/acker.go | 25 +++---- filebeat/beater/channels.go | 15 ++--- filebeat/channel/outlet.go | 2 +- filebeat/registrar/registrar.go | 30 ++++----- libbeat/beat/pipeline.go | 13 ++-- libbeat/publisher/pipeline/acker.go | 34 +++++----- libbeat/publisher/pipeline/client_ack.go | 6 +- libbeat/publisher/pipeline/pipeline_ack.go | 78 +++++++++++----------- winlogbeat/beater/winlogbeat.go | 16 ++--- 9 files changed, 101 insertions(+), 118 deletions(-) diff --git a/filebeat/beater/acker.go b/filebeat/beater/acker.go index 290ca0ec5e1..3c39c551917 100644 --- a/filebeat/beater/acker.go +++ b/filebeat/beater/acker.go @@ -1,9 +1,7 @@ package beater import ( - "github.com/elastic/beats/libbeat/beat" - - "github.com/elastic/beats/filebeat/util" + "github.com/elastic/beats/filebeat/input/file" ) // eventAcker handles publisher pipeline ACKs and forwards @@ -13,30 +11,29 @@ type eventACKer struct { } type successLogger interface { - Published(events []*util.Data) bool + Published(states []file.State) } func newEventACKer(out successLogger) *eventACKer { return &eventACKer{out: out} } -func (a *eventACKer) ackEvents(events []beat.Event) { - data := make([]*util.Data, 0, len(events)) - for _, event := range events { - p := event.Private - if p == nil { +func (a *eventACKer) ackEvents(data []interface{}) { + states := make([]file.State, 0, len(data)) + for _, datum := range data { + if datum == nil { continue } - datum, ok := p.(*util.Data) - if !ok || !datum.HasState() { + st, ok := datum.(file.State) + if !ok { continue } - data = append(data, datum) + states = append(states, st) } - if len(data) > 0 { - a.out.Published(data) + if len(states) > 0 { + a.out.Published(states) } } diff --git a/filebeat/beater/channels.go b/filebeat/beater/channels.go index 7e6c80042f7..7657ab2379d 100644 --- a/filebeat/beater/channels.go +++ b/filebeat/beater/channels.go @@ -3,14 +3,14 @@ package beater import ( "sync" + "github.com/elastic/beats/filebeat/input/file" "github.com/elastic/beats/filebeat/registrar" - "github.com/elastic/beats/filebeat/util" "github.com/elastic/beats/libbeat/monitoring" ) type registrarLogger struct { done chan struct{} - ch chan<- []*util.Data + ch chan<- []file.State } type finishedLogger struct { @@ -32,7 +32,7 @@ func newRegistrarLogger(reg *registrar.Registrar) *registrarLogger { } func (l *registrarLogger) Close() { close(l.done) } -func (l *registrarLogger) Published(events []*util.Data) bool { +func (l *registrarLogger) Published(states []file.State) { select { case <-l.done: // set ch to nil, so no more events will be send after channel close signal @@ -40,9 +40,7 @@ func (l *registrarLogger) Published(events []*util.Data) bool { // Note: nil channels will block, so only done channel will be actively // report 'closed'. l.ch = nil - return false - case l.ch <- events: - return true + case l.ch <- states: } } @@ -50,11 +48,10 @@ func newFinishedLogger(wg *eventCounter) *finishedLogger { return &finishedLogger{wg} } -func (l *finishedLogger) Published(events []*util.Data) bool { - for range events { +func (l *finishedLogger) Published(n int) bool { + for i := 0; i < n; i++ { l.wg.Done() } - return true } diff --git a/filebeat/channel/outlet.go b/filebeat/channel/outlet.go index 7794731793d..078789d24c4 100644 --- a/filebeat/channel/outlet.go +++ b/filebeat/channel/outlet.go @@ -36,7 +36,7 @@ func (o *outlet) OnEvent(d *util.Data) bool { event := d.GetEvent() if d.HasState() { - event.Private = d + event.Private = d.GetState() } if o.wg != nil { diff --git a/filebeat/registrar/registrar.go b/filebeat/registrar/registrar.go index 5bee242c32c..4b535e221ea 100644 --- a/filebeat/registrar/registrar.go +++ b/filebeat/registrar/registrar.go @@ -8,7 +8,6 @@ import ( "sync" "github.com/elastic/beats/filebeat/input/file" - "github.com/elastic/beats/filebeat/util" helper "github.com/elastic/beats/libbeat/common/file" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/monitoring" @@ -16,7 +15,7 @@ import ( ) type Registrar struct { - Channel chan []*util.Data + Channel chan []file.State out successLogger done chan struct{} registryFile string // Path to the Registry File @@ -25,7 +24,7 @@ type Registrar struct { } type successLogger interface { - Published(events []*util.Data) bool + Published(n int) bool } var ( @@ -40,7 +39,7 @@ func New(registryFile string, out successLogger) (*Registrar, error) { registryFile: registryFile, done: make(chan struct{}), states: file.NewStates(), - Channel: make(chan []*util.Data, 1), + Channel: make(chan []file.State, 1), out: out, wg: sync.WaitGroup{}, } @@ -155,15 +154,15 @@ func (r *Registrar) Run() { case <-r.done: logp.Info("Ending Registrar") return - case events := <-r.Channel: - r.onEvents(events) + case states := <-r.Channel: + r.onEvents(states) } } } // onEvents processes events received from the publisher pipeline -func (r *Registrar) onEvents(events []*util.Data) { - r.processEventStates(events) +func (r *Registrar) onEvents(states []file.State) { + r.processEventStates(states) beforeCount := r.states.Count() cleanedStates := r.states.Cleanup() @@ -178,21 +177,16 @@ func (r *Registrar) onEvents(events []*util.Data) { } if r.out != nil { - r.out.Published(events) + r.out.Published(len(states)) } } // processEventStates gets the states from the events and writes them to the registrar state -func (r *Registrar) processEventStates(events []*util.Data) { - logp.Debug("registrar", "Processing %d events", len(events)) +func (r *Registrar) processEventStates(states []file.State) { + logp.Debug("registrar", "Processing %d events", len(states)) - for _, data := range events { - - // skip events without state - if !data.HasState() { - continue - } - r.states.Update(data.GetState()) + for i := range states { + r.states.Update(states[i]) statesUpdate.Add(1) } } diff --git a/libbeat/beat/pipeline.go b/libbeat/beat/pipeline.go index 86023601fa3..2b5bf5389c1 100644 --- a/libbeat/beat/pipeline.go +++ b/libbeat/beat/pipeline.go @@ -58,13 +58,14 @@ type ClientConfig struct { // by the pipeline. ACKCount func(int) - // ACKEvents reports the events recently acknowledged by the pipeline. + // ACKEvents reports the events private data of recently acknowledged events. // Note: The slice passed must be copied if the events are to be processed // after the handler returns. - ACKEvents func([]Event) + ACKEvents func([]interface{}) // ACKLastEvent reports the last ACKed event out of a batch of ACKed events only. - ACKLastEvent func(Event) + // Only the events 'Private' field will be reported. + ACKLastEvent func(interface{}) } // ClientEventer provides access to internal client events. @@ -84,10 +85,12 @@ type PipelineACKHandler struct { ACKCount func(int) // ACKEvents reports the events recently acknowledged by the pipeline. - ACKEvents func([]Event) + // Only the events 'Private' field will be reported. + ACKEvents func([]interface{}) // ACKLastEvent reports the last ACKed event per pipeline client. - ACKLastEvents func([]Event) + // Only the events 'Private' field will be reported. + ACKLastEvents func([]interface{}) } type ProcessorList interface { diff --git a/libbeat/publisher/pipeline/acker.go b/libbeat/publisher/pipeline/acker.go index fc07a019976..f7e0891fd12 100644 --- a/libbeat/publisher/pipeline/acker.go +++ b/libbeat/publisher/pipeline/acker.go @@ -304,27 +304,27 @@ func (a *boundGapCountACK) onACK(total, acked int) { a.fn(total, acked) } -// eventACK reports all dropped and ACKed events. -// An instance of eventACK requires a counting ACKer (boundGapCountACK or countACK), +// eventDataACK reports all dropped and ACKed events private fields. +// An instance of eventDataACK requires a counting ACKer (boundGapCountACK or countACK), // for accounting for potentially dropped events. -type eventACK struct { +type eventDataACK struct { mutex sync.Mutex acker acker pipeline *Pipeline // TODO: replace with more efficient dynamic sized ring-buffer? - events []beat.Event - fn func(events []beat.Event, acked int) + data []interface{} + fn func(data []interface{}, acked int) } func newEventACK( pipeline *Pipeline, canDrop bool, sema *sema, - fn func([]beat.Event, int), -) *eventACK { - a := &eventACK{pipeline: pipeline, fn: fn} + fn func([]interface{}, int), +) *eventDataACK { + a := &eventDataACK{pipeline: pipeline, fn: fn} a.acker = makeCountACK(pipeline, canDrop, sema, a.onACK) return a @@ -337,15 +337,15 @@ func makeCountACK(pipeline *Pipeline, canDrop bool, sema *sema, fn func(int, int return newCountACK(fn) } -func (a *eventACK) close() { +func (a *eventDataACK) close() { a.acker.close() } -func (a *eventACK) addEvent(event beat.Event, published bool) bool { +func (a *eventDataACK) addEvent(event beat.Event, published bool) bool { a.mutex.Lock() active := a.pipeline.ackActive.Load() if active { - a.events = append(a.events, event) + a.data = append(a.data, event.Private) } a.mutex.Unlock() @@ -355,17 +355,17 @@ func (a *eventACK) addEvent(event beat.Event, published bool) bool { return false } -func (a *eventACK) ackEvents(n int) { a.acker.ackEvents(n) } -func (a *eventACK) onACK(total, acked int) { +func (a *eventDataACK) ackEvents(n int) { a.acker.ackEvents(n) } +func (a *eventDataACK) onACK(total, acked int) { n := total a.mutex.Lock() - events := a.events[:n] - a.events = a.events[n:] + data := a.data[:n] + a.data = a.data[n:] a.mutex.Unlock() - if len(events) > 0 && a.pipeline.ackActive.Load() { - a.fn(events, acked) + if len(data) > 0 && a.pipeline.ackActive.Load() { + a.fn(data, acked) } } diff --git a/libbeat/publisher/pipeline/client_ack.go b/libbeat/publisher/pipeline/client_ack.go index b882b3c2cca..f5d3749e721 100644 --- a/libbeat/publisher/pipeline/client_ack.go +++ b/libbeat/publisher/pipeline/client_ack.go @@ -44,8 +44,8 @@ func (p *Pipeline) makeACKer( return newWaitACK(acker, waitClose) } -func lastEventACK(fn func(beat.Event)) func([]beat.Event) { - return func(events []beat.Event) { +func lastEventACK(fn func(interface{})) func([]interface{}) { + return func(events []interface{}) { fn(events[len(events)-1]) } } @@ -91,7 +91,7 @@ func buildClientEventACK( pipeline *Pipeline, canDrop bool, sema *sema, - mk func(*clientACKer) func([]beat.Event, int), + mk func(*clientACKer) func([]interface{}, int), ) acker { guard := &clientACKer{} guard.lift(newEventACK(pipeline, canDrop, sema, mk(guard))) diff --git a/libbeat/publisher/pipeline/pipeline_ack.go b/libbeat/publisher/pipeline/pipeline_ack.go index 0d5a1d236b5..1fd39f411ec 100644 --- a/libbeat/publisher/pipeline/pipeline_ack.go +++ b/libbeat/publisher/pipeline/pipeline_ack.go @@ -9,7 +9,7 @@ import ( type ackBuilder interface { createPipelineACKer(canDrop bool, sema *sema) acker createCountACKer(canDrop bool, sema *sema, fn func(int)) acker - createEventACKer(canDrop bool, sema *sema, fn func([]beat.Event)) acker + createEventACKer(canDrop bool, sema *sema, fn func([]interface{})) acker } type pipelineEmptyACK struct { @@ -33,10 +33,10 @@ func (b *pipelineEmptyACK) createCountACKer(canDrop bool, sema *sema, fn func(in func (b *pipelineEmptyACK) createEventACKer( canDrop bool, sema *sema, - fn func([]beat.Event), + fn func([]interface{}), ) acker { - return buildClientEventACK(b.pipeline, canDrop, sema, func(guard *clientACKer) func([]beat.Event, int) { - return func(events []beat.Event, acked int) { + return buildClientEventACK(b.pipeline, canDrop, sema, func(guard *clientACKer) func([]interface{}, int) { + return func(events []interface{}, acked int) { if guard.Active() { fn(events) } @@ -67,13 +67,13 @@ func (b *pipelineCountACK) createCountACKer(canDrop bool, sema *sema, fn func(in func (b *pipelineCountACK) createEventACKer( canDrop bool, sema *sema, - fn func([]beat.Event), + fn func([]interface{}), ) acker { - return buildClientEventACK(b.pipeline, canDrop, sema, func(guard *clientACKer) func([]beat.Event, int) { - return func(events []beat.Event, acked int) { - b.cb(len(events), acked) + return buildClientEventACK(b.pipeline, canDrop, sema, func(guard *clientACKer) func([]interface{}, int) { + return func(data []interface{}, acked int) { + b.cb(len(data), acked) if guard.Active() { - fn(events) + fn(data) } } }) @@ -81,7 +81,7 @@ func (b *pipelineCountACK) createEventACKer( type pipelineEventsACK struct { pipeline *Pipeline - cb func([]beat.Event, int) + cb func([]interface{}, int) } func (b *pipelineEventsACK) createPipelineACKer(canDrop bool, sema *sema) acker { @@ -89,22 +89,22 @@ func (b *pipelineEventsACK) createPipelineACKer(canDrop bool, sema *sema) acker } func (b *pipelineEventsACK) createCountACKer(canDrop bool, sema *sema, fn func(int)) acker { - return buildClientEventACK(b.pipeline, canDrop, sema, func(guard *clientACKer) func([]beat.Event, int) { - return func(events []beat.Event, acked int) { - b.cb(events, acked) + return buildClientEventACK(b.pipeline, canDrop, sema, func(guard *clientACKer) func([]interface{}, int) { + return func(data []interface{}, acked int) { + b.cb(data, acked) if guard.Active() { - fn(len(events)) + fn(len(data)) } } }) } -func (b *pipelineEventsACK) createEventACKer(canDrop bool, sema *sema, fn func([]beat.Event)) acker { - return buildClientEventACK(b.pipeline, canDrop, sema, func(guard *clientACKer) func([]beat.Event, int) { - return func(events []beat.Event, acked int) { - b.cb(events, acked) +func (b *pipelineEventsACK) createEventACKer(canDrop bool, sema *sema, fn func([]interface{})) acker { + return buildClientEventACK(b.pipeline, canDrop, sema, func(guard *clientACKer) func([]interface{}, int) { + return func(data []interface{}, acked int) { + b.cb(data, acked) if guard.Active() { - fn(events) + fn(data) } } }) @@ -124,15 +124,15 @@ type pipelineEventCB struct { acks chan int - events chan eventsMsg - droppedEvents chan eventsMsg + events chan eventsDataMsg + droppedEvents chan eventsDataMsg mode pipelineACKMode handler beat.PipelineACKHandler } -type eventsMsg struct { - events []beat.Event +type eventsDataMsg struct { + data []interface{} total, acked int sig chan struct{} } @@ -173,8 +173,8 @@ func newPipelineEventCB(handler beat.PipelineACKHandler) (*pipelineEventCB, erro acks: make(chan int), mode: mode, handler: handler, - events: make(chan eventsMsg), - droppedEvents: make(chan eventsMsg), + events: make(chan eventsDataMsg), + droppedEvents: make(chan eventsDataMsg), } go cb.worker() return cb, nil @@ -196,15 +196,15 @@ func (p *pipelineEventCB) close() { // by the pipeline, before receiving/processing another ACK event. // In the meantime the queue has the chance of batching-up more ACK events, // such that only one ACK event is being reported to the pipeline handler -func (p *pipelineEventCB) onEvents(events []beat.Event, acked int) { - p.pushMsg(eventsMsg{events: events, total: len(events), acked: acked}) +func (p *pipelineEventCB) onEvents(data []interface{}, acked int) { + p.pushMsg(eventsDataMsg{data: data, total: len(data), acked: acked}) } func (p *pipelineEventCB) onCounts(total, acked int) { - p.pushMsg(eventsMsg{total: total, acked: acked}) + p.pushMsg(eventsDataMsg{total: total, acked: acked}) } -func (p *pipelineEventCB) pushMsg(msg eventsMsg) { +func (p *pipelineEventCB) pushMsg(msg eventsDataMsg) { if msg.acked == 0 { p.droppedEvents <- msg } else { @@ -235,7 +235,7 @@ func (p *pipelineEventCB) worker() { // short circuite dropped events, but have client block until all events // have been processed by pipeline ack handler case msg := <-p.droppedEvents: - p.reportEvents(msg.events, msg.total) + p.reportEventsData(msg.data, msg.total) if msg.sig != nil { close(msg.sig) } @@ -249,13 +249,13 @@ func (p *pipelineEventCB) worker() { func (p *pipelineEventCB) collect(count int) (exit bool) { var ( signalers []chan struct{} - events []beat.Event + data []interface{} acked int total int ) for acked < count { - var msg eventsMsg + var msg eventsDataMsg select { case msg = <-p.events: case msg = <-p.droppedEvents: @@ -276,11 +276,11 @@ func (p *pipelineEventCB) collect(count int) (exit bool) { switch p.mode { case eventsACKMode: - events = append(events, msg.events...) + data = append(data, msg.data...) case lastEventsACKMode: - if L := len(msg.events); L > 0 { - events = append(events, msg.events[L-1]) + if L := len(msg.data); L > 0 { + data = append(data, msg.data[L-1]) } } } @@ -289,18 +289,18 @@ func (p *pipelineEventCB) collect(count int) (exit bool) { for _, sig := range signalers { close(sig) } - p.reportEvents(events, total) + p.reportEventsData(data, total) return } -func (p *pipelineEventCB) reportEvents(events []beat.Event, total int) { +func (p *pipelineEventCB) reportEventsData(data []interface{}, total int) { // report ACK back to the beat switch p.mode { case countACKMode: p.handler.ACKCount(total) case eventsACKMode: - p.handler.ACKEvents(events) + p.handler.ACKEvents(data) case lastEventsACKMode: - p.handler.ACKLastEvents(events) + p.handler.ACKLastEvents(data) } } diff --git a/winlogbeat/beater/winlogbeat.go b/winlogbeat/beater/winlogbeat.go index e6cd037f4a1..b7413586f8b 100644 --- a/winlogbeat/beater/winlogbeat.go +++ b/winlogbeat/beater/winlogbeat.go @@ -121,19 +121,11 @@ func (eb *Winlogbeat) Run(b *beat.Beat) error { // setup global event ACK handler err := eb.pipeline.SetACKHandler(beat.PipelineACKHandler{ - ACKLastEvents: func(events []beat.Event) { - for _, event := range events { - priv := event.Private - if priv == nil { - continue + ACKLastEvents: func(data []interface{}) { + for _, datum := range data { + if st, ok := datum.(checkpoint.EventLogState); ok { + eb.checkpoint.PersistState(st) } - - st, ok := priv.(checkpoint.EventLogState) - if !ok { - continue - } - - eb.checkpoint.PersistState(st) } }, }) From be011f333d269f03a0213d858b0e95a78a8e3603 Mon Sep 17 00:00:00 2001 From: Steffen Siering Date: Thu, 24 Aug 2017 12:24:51 +0200 Subject: [PATCH 113/139] Delay device opening (#4939) * Delay device opening Reimplement the sniffer to delay: - opening the sniffing device until sniffer.Run is executed. - do some preliminary config validation on New only - split file handling into separate sniffer handle type, to clean up the run loop a little * fix pcap file close handling * always sleep for a few ms on pcap file close * Reduce chance for races on publisher being closed on shutdown * Fix flows setup being too late * reduce flow timeout in system tests * replace sleep in file pcap reader with default setting in test config file --- packetbeat/beater/packetbeat.go | 122 ++--- packetbeat/publish/publish.go | 24 +- packetbeat/sniffer/afpacket.go | 27 + packetbeat/sniffer/afpacket_linux.go | 5 + packetbeat/sniffer/afpacket_nonlinux.go | 5 + packetbeat/sniffer/device.go | 88 ++++ packetbeat/sniffer/file.go | 100 ++++ packetbeat/sniffer/sniffer.go | 493 ++++++++---------- .../tests/system/config/packetbeat.yml.j2 | 4 +- 9 files changed, 503 insertions(+), 365 deletions(-) create mode 100644 packetbeat/sniffer/afpacket.go create mode 100644 packetbeat/sniffer/device.go create mode 100644 packetbeat/sniffer/file.go diff --git a/packetbeat/beater/packetbeat.go b/packetbeat/beater/packetbeat.go index e244a4a12c0..5dfee9c017c 100644 --- a/packetbeat/beater/packetbeat.go +++ b/packetbeat/beater/packetbeat.go @@ -32,16 +32,12 @@ import ( type packetbeat struct { config config.Config cmdLineArgs flags - sniff *sniffer.SnifferSetup + sniff *sniffer.Sniffer // publisher/pipeline pipeline beat.Pipeline transPub *publish.TransactionPublisher - - services []interface { - Start() - Stop() - } + flows *flows.Flows } type flags struct { @@ -118,10 +114,55 @@ func (pb *packetbeat) init(b *beat.Beat) error { return fmt.Errorf("Initializing protocol analyzers failed: %v", err) } - logp.Debug("main", "Initializing sniffer") - err = pb.setupSniffer() + if err := pb.setupFlows(); err != nil { + return err + } + + return pb.setupSniffer() +} + +func (pb *packetbeat) setupSniffer() error { + config := &pb.config + + icmp, err := pb.icmpConfig() if err != nil { - return fmt.Errorf("Initializing sniffer failed: %v", err) + return err + } + + withVlans := config.Interfaces.WithVlans + withICMP := icmp.Enabled() + + filter := config.Interfaces.BpfFilter + if filter == "" && !config.Flows.IsEnabled() { + filter = protos.Protos.BpfFilter(withVlans, withICMP) + } + + pb.sniff, err = sniffer.New(false, filter, pb.createWorker, config.Interfaces) + return err +} + +func (pb *packetbeat) setupFlows() error { + config := &pb.config + if !config.Flows.IsEnabled() { + return nil + } + + processors, err := processors.New(config.Flows.Processors) + if err != nil { + return err + } + + client, err := pb.pipeline.ConnectWith(beat.ClientConfig{ + EventMetadata: config.Flows.EventMetadata, + Processor: processors, + }) + if err != nil { + return err + } + + pb.flows, err = flows.NewFlows(client.PublishAll, config.Flows) + if err != nil { + return err } return nil @@ -141,9 +182,10 @@ func (pb *packetbeat) Run(b *beat.Beat) error { return err } - // start services - for _, service := range pb.services { - service.Start() + defer pb.transPub.Stop() + if pb.flows != nil { + pb.flows.Start() + defer pb.flows.Stop() } var wg sync.WaitGroup @@ -154,8 +196,6 @@ func (pb *packetbeat) Run(b *beat.Beat) error { go func() { defer wg.Done() - defer pb.transPub.Stop() - err := pb.sniff.Run() if err != nil { errC <- fmt.Errorf("Sniffer main loop failed: %v", err) @@ -170,11 +210,6 @@ func (pb *packetbeat) Run(b *beat.Beat) error { return err } - // kill services - for _, service := range pb.services { - service.Stop() - } - timeout := pb.config.ShutdownTimeout if timeout > 0 { time.Sleep(timeout) @@ -189,51 +224,7 @@ func (pb *packetbeat) Stop() { pb.sniff.Stop() } -func (pb *packetbeat) setupSniffer() error { - config := &pb.config - - icmp, err := pb.icmpConfig() - if err != nil { - return err - } - - withVlans := config.Interfaces.WithVlans - withICMP := icmp.Enabled() - - filter := config.Interfaces.BpfFilter - if filter == "" && !config.Flows.IsEnabled() { - filter = protos.Protos.BpfFilter(withVlans, withICMP) - } - - pb.sniff = &sniffer.SnifferSetup{} - return pb.sniff.Init(false, filter, pb.createWorker, &config.Interfaces) -} - func (pb *packetbeat) createWorker(dl layers.LinkType) (sniffer.Worker, error) { - var f *flows.Flows - var err error - config := &pb.config - - if config.Flows.IsEnabled() { - processors, err := processors.New(config.Flows.Processors) - if err != nil { - return nil, err - } - - client, err := pb.pipeline.ConnectWith(beat.ClientConfig{ - EventMetadata: config.Flows.EventMetadata, - Processor: processors, - }) - if err != nil { - return nil, err - } - - f, err = flows.NewFlows(client.PublishAll, config.Flows) - if err != nil { - return nil, err - } - } - var icmp4 icmp.ICMPv4Processor var icmp6 icmp.ICMPv6Processor cfg, err := pb.icmpConfig() @@ -265,14 +256,11 @@ func (pb *packetbeat) createWorker(dl layers.LinkType) (sniffer.Worker, error) { return nil, err } - worker, err := decoder.New(f, dl, icmp4, icmp6, tcp, udp) + worker, err := decoder.New(pb.flows, dl, icmp4, icmp6, tcp, udp) if err != nil { return nil, err } - if f != nil { - pb.services = append(pb.services, f) - } return worker, nil } diff --git a/packetbeat/publish/publish.go b/packetbeat/publish/publish.go index 4699c0397ca..c7b8fd233c1 100644 --- a/packetbeat/publish/publish.go +++ b/packetbeat/publish/publish.go @@ -88,20 +88,24 @@ func (p *TransactionPublisher) CreateReporter( ch := make(chan beat.Event, 3) go p.worker(ch, client) return func(event beat.Event) { - ch <- event + select { + case ch <- event: + case <-p.done: + ch = nil // stop serving more send requests + } }, nil } func (p *TransactionPublisher) worker(ch chan beat.Event, client beat.Client) { - go func() { - <-p.done - close(ch) - }() - - for event := range ch { - pub, _ := p.processor.Run(&event) - if pub != nil { - client.Publish(*pub) + for { + select { + case <-p.done: + return + case event := <-ch: + pub, _ := p.processor.Run(&event) + if pub != nil { + client.Publish(*pub) + } } } } diff --git a/packetbeat/sniffer/afpacket.go b/packetbeat/sniffer/afpacket.go new file mode 100644 index 00000000000..1a9475ca00e --- /dev/null +++ b/packetbeat/sniffer/afpacket.go @@ -0,0 +1,27 @@ +package sniffer + +import "fmt" + +// Computes the block_size and the num_blocks in such a way that the +// allocated mmap buffer is close to but smaller than target_size_mb. +// The restriction is that the block_size must be divisible by both the +// frame size and page size. +func afpacketComputeSize(targetSizeMb int, snaplen int, pageSize int) ( + frameSize int, blockSize int, numBlocks int, err error) { + + if snaplen < pageSize { + frameSize = pageSize / (pageSize / snaplen) + } else { + frameSize = (snaplen/pageSize + 1) * pageSize + } + + // 128 is the default from the gopacket library so just use that + blockSize = frameSize * 128 + numBlocks = (targetSizeMb * 1024 * 1024) / blockSize + + if numBlocks == 0 { + return 0, 0, 0, fmt.Errorf("Buffer size too small") + } + + return frameSize, blockSize, numBlocks, nil +} diff --git a/packetbeat/sniffer/afpacket_linux.go b/packetbeat/sniffer/afpacket_linux.go index a8eaf48621f..c9ff6da8390 100644 --- a/packetbeat/sniffer/afpacket_linux.go +++ b/packetbeat/sniffer/afpacket_linux.go @@ -7,6 +7,7 @@ import ( "github.com/tsg/gopacket" "github.com/tsg/gopacket/afpacket" + "github.com/tsg/gopacket/layers" ) type afpacketHandle struct { @@ -45,6 +46,10 @@ func (h *afpacketHandle) SetBPFFilter(expr string) (_ error) { return h.TPacket.SetBPFFilter(expr) } +func (h *afpacketHandle) LinkType() layers.LinkType { + return layers.LinkTypeEthernet +} + func (h *afpacketHandle) Close() { h.TPacket.Close() } diff --git a/packetbeat/sniffer/afpacket_nonlinux.go b/packetbeat/sniffer/afpacket_nonlinux.go index c0d268f84a4..46c8cbcd0d3 100644 --- a/packetbeat/sniffer/afpacket_nonlinux.go +++ b/packetbeat/sniffer/afpacket_nonlinux.go @@ -7,6 +7,7 @@ import ( "time" "github.com/tsg/gopacket" + "github.com/tsg/gopacket/layers" ) type afpacketHandle struct { @@ -26,5 +27,9 @@ func (h *afpacketHandle) SetBPFFilter(expr string) (_ error) { return fmt.Errorf("Afpacket MMAP sniffing is only available on Linux") } +func (h *afpacketHandle) LinkType() layers.LinkType { + return layers.LinkTypeEthernet +} + func (h *afpacketHandle) Close() { } diff --git a/packetbeat/sniffer/device.go b/packetbeat/sniffer/device.go new file mode 100644 index 00000000000..b1fe749e71e --- /dev/null +++ b/packetbeat/sniffer/device.go @@ -0,0 +1,88 @@ +package sniffer + +import ( + "fmt" + "runtime" + "strconv" + + "github.com/tsg/gopacket/pcap" + + "github.com/elastic/beats/libbeat/logp" +) + +var deviceAnySupported = runtime.GOOS == "linux" + +// ListDevicesNames returns the list of adapters available for sniffing on +// this computer. If the withDescription parameter is set to true, a human +// readable version of the adapter name is added. If the withIP parameter +// is set to true, IP address of the adapter is added. +func ListDeviceNames(withDescription bool, withIP bool) ([]string, error) { + devices, err := pcap.FindAllDevs() + if err != nil { + return []string{}, err + } + + ret := []string{} + for _, dev := range devices { + r := dev.Name + + if withDescription { + desc := "No description available" + if len(dev.Description) > 0 { + desc = dev.Description + } + r += fmt.Sprintf(" (%s)", desc) + } + + if withIP { + ips := "Not assigned ip address" + if len(dev.Addresses) > 0 { + ips = "" + + for i, address := range []pcap.InterfaceAddress(dev.Addresses) { + // Add a space between the IP address. + if i > 0 { + ips += " " + } + + ips += fmt.Sprintf("%s", address.IP.String()) + } + } + r += fmt.Sprintf(" (%s)", ips) + + } + ret = append(ret, r) + } + return ret, nil +} + +func resolveDeviceName(name string) (string, error) { + if name == "" { + return "any", nil + } + + if index, err := strconv.Atoi(name); err == nil { // Device is numeric id + devices, err := ListDeviceNames(false, false) + if err != nil { + return "", fmt.Errorf("Error getting devices list: %v", err) + } + + name, err = deviceNameFromIndex(index, devices) + if err != nil { + return "", fmt.Errorf("Couldn't understand device index %d: %v", index, err) + } + + logp.Info("Resolved device index %d to device: %s", index, name) + } + + return name, nil +} + +func deviceNameFromIndex(index int, devices []string) (string, error) { + if index >= len(devices) { + return "", fmt.Errorf("Looking for device index %d, but there are only %d devices", + index, len(devices)) + } + + return devices[index], nil +} diff --git a/packetbeat/sniffer/file.go b/packetbeat/sniffer/file.go new file mode 100644 index 00000000000..c8dd9174606 --- /dev/null +++ b/packetbeat/sniffer/file.go @@ -0,0 +1,100 @@ +package sniffer + +import ( + "fmt" + "io" + "time" + + "github.com/tsg/gopacket" + "github.com/tsg/gopacket/layers" + "github.com/tsg/gopacket/pcap" + + "github.com/elastic/beats/libbeat/logp" +) + +type fileHandler struct { + pcapHandle *pcap.Handle + file string + + loopCount, maxLoopCount int + + topSpeed bool + lastTS time.Time +} + +func newFileHandler(file string, topSpeed bool, maxLoopCount int) (*fileHandler, error) { + h := &fileHandler{ + file: file, + topSpeed: topSpeed, + maxLoopCount: maxLoopCount, + } + if err := h.open(); err != nil { + return nil, err + } + + return h, nil +} + +func (h *fileHandler) open() error { + tmp, err := pcap.OpenOffline(h.file) + if err != nil { + return err + } + + h.pcapHandle = tmp + return nil +} + +func (h *fileHandler) ReadPacketData() ([]byte, gopacket.CaptureInfo, error) { + data, ci, err := h.pcapHandle.ReadPacketData() + if err != nil { + if err != io.EOF { + return data, ci, err + } + + h.pcapHandle.Close() + h.pcapHandle = nil + + h.loopCount++ + if h.loopCount >= h.maxLoopCount { + return data, ci, err + } + + logp.Debug("sniffer", "Reopening the file") + if err = h.open(); err != nil { + return nil, ci, fmt.Errorf("Error reopening file: %s", err) + } + + data, ci, err = h.pcapHandle.ReadPacketData() + h.lastTS = ci.Timestamp + return data, ci, err + } + + if h.topSpeed { + return data, ci, nil + } + + if !h.lastTS.IsZero() { + sleep := ci.Timestamp.Sub(h.lastTS) + if sleep > 0 { + time.Sleep(sleep) + } else { + logp.Warn("Time in pcap went backwards: %d", sleep) + } + } + + h.lastTS = ci.Timestamp + ci.Timestamp = time.Now() + return data, ci, nil +} + +func (h *fileHandler) LinkType() layers.LinkType { + return h.pcapHandle.LinkType() +} + +func (h *fileHandler) Close() { + if h.pcapHandle != nil { + h.pcapHandle.Close() + h.pcapHandle = nil + } +} diff --git a/packetbeat/sniffer/sniffer.go b/packetbeat/sniffer/sniffer.go index 8dfd5698a13..d19df7be9c8 100644 --- a/packetbeat/sniffer/sniffer.go +++ b/packetbeat/sniffer/sniffer.go @@ -5,384 +5,305 @@ import ( "io" "os" "runtime" - "strconv" "syscall" "time" - "github.com/elastic/beats/libbeat/logp" - - "github.com/elastic/beats/packetbeat/config" - "github.com/tsg/gopacket" "github.com/tsg/gopacket/layers" "github.com/tsg/gopacket/pcap" + + "github.com/elastic/beats/libbeat/common/atomic" + "github.com/elastic/beats/libbeat/logp" + + "github.com/elastic/beats/packetbeat/config" ) -type SnifferSetup struct { - pcapHandle *pcap.Handle - afpacketHandle *afpacketHandle - config *config.InterfacesConfig - isAlive bool - dumper *pcap.Dumper +// Sniffer provides packet sniffing capabilities, forwarding packets read +// to a Worker. +type Sniffer struct { + config config.InterfacesConfig + dumper *pcap.Dumper + + state atomic.Int32 // store snifferState // bpf filter filter string - // Decoder *decoder.DecoderStruct - worker Worker - DataSource gopacket.PacketDataSource + factory WorkerFactory } +// WorkerFactory constructs a new worker instance for use with a Sniffer. +type WorkerFactory func(layers.LinkType) (Worker, error) + +// Worker defines the callback interfaces a Sniffer instance will use +// to forward packets. type Worker interface { OnPacket(data []byte, ci *gopacket.CaptureInfo) } -type WorkerFactory func(layers.LinkType) (Worker, error) - -// Computes the block_size and the num_blocks in such a way that the -// allocated mmap buffer is close to but smaller than target_size_mb. -// The restriction is that the block_size must be divisible by both the -// frame size and page size. -func afpacketComputeSize(targetSizeMb int, snaplen int, pageSize int) ( - frameSize int, blockSize int, numBlocks int, err error) { - - if snaplen < pageSize { - frameSize = pageSize / (pageSize / snaplen) - } else { - frameSize = (snaplen/pageSize + 1) * pageSize - } - - // 128 is the default from the gopacket library so just use that - blockSize = frameSize * 128 - numBlocks = (targetSizeMb * 1024 * 1024) / blockSize +type snifferHandle interface { + gopacket.PacketDataSource - if numBlocks == 0 { - return 0, 0, 0, fmt.Errorf("Buffer size too small") - } - - return frameSize, blockSize, numBlocks, nil + LinkType() layers.LinkType + Close() } -func deviceNameFromIndex(index int, devices []string) (string, error) { - if index >= len(devices) { - return "", fmt.Errorf("Looking for device index %d, but there are only %d devices", - index, len(devices)) - } - - return devices[index], nil -} +// sniffer state values +const ( + snifferInactive = 0 + snifferClosing = 1 + snifferActive = 2 +) -// ListDevicesNames returns the list of adapters available for sniffing on -// this computer. If the withDescription parameter is set to true, a human -// readable version of the adapter name is added. If the withIP parameter -// is set to true, IP address of the adapter is added. -func ListDeviceNames(withDescription bool, withIP bool) ([]string, error) { - devices, err := pcap.FindAllDevs() - if err != nil { - return []string{}, err +// New create a new Sniffer instance. Settings are validated in a best effort +// only, but no device is opened yet. Accessing and configuring the actual device +// is done by the Run method. +func New( + testMode bool, + filter string, + factory WorkerFactory, + interfaces config.InterfacesConfig, +) (*Sniffer, error) { + s := &Sniffer{ + filter: filter, + config: interfaces, + factory: factory, + state: atomic.MakeInt32(snifferInactive), } - ret := []string{} - for _, dev := range devices { - r := dev.Name + logp.Debug("sniffer", "BPF filter: '%s'", filter) - if withDescription { - desc := "No description available" - if len(dev.Description) > 0 { - desc = dev.Description - } - r += fmt.Sprintf(" (%s)", desc) - } + // pre-check and normalize configuration: + // - resolve potential device name + // - check for file output + // - set some defaults + if s.config.File != "" { + logp.Debug("sniffer", "Reading from file: %s", s.config.File) - if withIP { - ips := "Not assigned ip address" - if len(dev.Addresses) > 0 { - ips = "" + if s.config.BpfFilter != "" { + logp.Warn("Packet filters are not applied to pcap files.") + } - for i, address := range []pcap.InterfaceAddress(dev.Addresses) { - // Add a space between the IP address. - if i > 0 { - ips += " " - } + // we read file with the pcap provider + s.config.Type = "pcap" + s.config.Device = "" + } else { + // try to resolve device name (ignore error if testMode is enabled) + if name, err := resolveDeviceName(s.config.Device); err != nil { + if !testMode { + return nil, err + } + } else { + s.config.Device = name + if name == "any" && !deviceAnySupported { + return nil, fmt.Errorf("any interface is not supported on %s", runtime.GOOS) + } - ips += fmt.Sprintf("%s", address.IP.String()) - } + if s.config.Snaplen == 0 { + s.config.Snaplen = 65535 + } + if s.config.BufferSizeMb <= 0 { + s.config.BufferSizeMb = 24 } - r += fmt.Sprintf(" (%s)", ips) + if t := s.config.Type; t == "autodetect" || t == "" { + s.config.Type = "pcap" + } + logp.Debug("sniffer", "Sniffer type: %s device: %s", s.config.Type, s.config.Device) } - ret = append(ret, r) } - return ret, nil -} -func (sniffer *SnifferSetup) setFromConfig(config *config.InterfacesConfig) error { - var err error + err := validateConfig(filter, &s.config) + if err != nil { + return nil, err + } - sniffer.config = config + return s, nil +} - if len(sniffer.config.File) > 0 { - logp.Debug("sniffer", "Reading from file: %s", sniffer.config.File) - // we read file with the pcap provider - sniffer.config.Type = "pcap" - } +// Run opens the sniffing device and processes packets being read from that device. +// Worker instances are instantiated as needed. +func (s *Sniffer) Run() error { + var ( + counter = 0 + dumper *pcap.Dumper + ) - // set defaults - if len(sniffer.config.Device) == 0 { - sniffer.config.Device = "any" + handle, err := s.open() + if err != nil { + return fmt.Errorf("Error starting sniffer: %s", err) } + defer handle.Close() - if index, err := strconv.Atoi(sniffer.config.Device); err == nil { // Device is numeric - devices, err := ListDeviceNames(false, false) + if s.config.Dumpfile != "" { + dumper, err = openDumper(s.config.Dumpfile, handle.LinkType()) if err != nil { - return fmt.Errorf("Error getting devices list: %v", err) - } - sniffer.config.Device, err = deviceNameFromIndex(index, devices) - if err != nil { - return fmt.Errorf("Couldn't understand device index %d: %v", index, err) + return err } - logp.Info("Resolved device index %d to device: %s", index, sniffer.config.Device) - } - if sniffer.config.Snaplen == 0 { - sniffer.config.Snaplen = 65535 + defer dumper.Close() } - if sniffer.config.Type == "autodetect" || sniffer.config.Type == "" { - sniffer.config.Type = "pcap" + worker, err := s.factory(handle.LinkType()) + if err != nil { + return err } - logp.Debug("sniffer", "Sniffer type: %s device: %s", sniffer.config.Type, sniffer.config.Device) + // Mark inactive sniffer as active. In case of the sniffer/packetbeat closing + // before/while Run is executed, the state will be snifferClosing. + // => return if state is already snifferClosing. + if !s.state.CAS(snifferInactive, snifferActive) { + return nil + } + defer s.state.Store(snifferInactive) - switch sniffer.config.Type { - case "pcap": - if len(sniffer.config.File) > 0 { - sniffer.pcapHandle, err = pcap.OpenOffline(sniffer.config.File) - if err != nil { - return err - } - } else { - sniffer.pcapHandle, err = pcap.OpenLive( - sniffer.config.Device, - int32(sniffer.config.Snaplen), - true, - 500*time.Millisecond) - if err != nil { - return err - } - err = sniffer.pcapHandle.SetBPFFilter(sniffer.filter) - if err != nil { - return err - } + for s.state.Load() == snifferActive { + if s.config.OneAtATime { + fmt.Println("Press enter to read packet") + fmt.Scanln() } - sniffer.DataSource = gopacket.PacketDataSource(sniffer.pcapHandle) - - case "af_packet": - if sniffer.config.BufferSizeMb == 0 { - sniffer.config.BufferSizeMb = 24 + data, ci, err := handle.ReadPacketData() + if err == pcap.NextErrorTimeoutExpired || err == syscall.EINTR { + logp.Debug("sniffer", "Interrupted") + continue } - frameSize, blockSize, numBlocks, err := afpacketComputeSize( - sniffer.config.BufferSizeMb, - sniffer.config.Snaplen, - os.Getpagesize()) if err != nil { - return err - } + // ignore EOF, if sniffer was driven from file + if err == io.EOF && s.config.File != "" { + return nil + } - sniffer.afpacketHandle, err = newAfpacketHandle( - sniffer.config.Device, - frameSize, - blockSize, - numBlocks, - 500*time.Millisecond) - if err != nil { - return err + s.state.Store(snifferInactive) + return fmt.Errorf("Sniffing error: %s", err) } - err = sniffer.afpacketHandle.SetBPFFilter(sniffer.filter) - if err != nil { - return fmt.Errorf("SetBPFFilter failed: %s", err) + if len(data) == 0 { + // Empty packet, probably timeout from afpacket + continue } - sniffer.DataSource = gopacket.PacketDataSource(sniffer.afpacketHandle) + if dumper != nil { + dumper.WritePacketData(data, ci) + } - default: - return fmt.Errorf("Unknown sniffer type: %s", sniffer.config.Type) + counter++ + logp.Debug("sniffer", "Packet number: %d", counter) + worker.OnPacket(data, &ci) } return nil } -func (sniffer *SnifferSetup) Reopen() error { - var err error - - if sniffer.config.Type != "pcap" || sniffer.config.File == "" { - return fmt.Errorf("Reopen is only possible for files") +func (s *Sniffer) open() (snifferHandle, error) { + if s.config.File != "" { + return newFileHandler(s.config.File, s.config.TopSpeed, s.config.Loop) } - sniffer.pcapHandle.Close() - sniffer.pcapHandle, err = pcap.OpenOffline(sniffer.config.File) - if err != nil { - return err + switch s.config.Type { + case "pcap": + return openPcap(s.filter, &s.config) + case "af_packet": + return openAFPacket(s.filter, &s.config) + default: + return nil, fmt.Errorf("Unknown sniffer type: %s", s.config.Type) } - - sniffer.DataSource = gopacket.PacketDataSource(sniffer.pcapHandle) - - return nil } -func (sniffer *SnifferSetup) Datalink() layers.LinkType { - if sniffer.config.Type == "pcap" { - return sniffer.pcapHandle.LinkType() - } - return layers.LinkTypeEthernet +// Stop marks a sniffer as stopped. The Run method will return once the stop +// signal has been given. +func (s *Sniffer) Stop() error { + s.state.Store(snifferClosing) + return nil } -func (sniffer *SnifferSetup) Init(testMode bool, filter string, factory WorkerFactory, interfaces *config.InterfacesConfig) error { - var err error - - if !testMode { - sniffer.filter = filter - logp.Debug("sniffer", "BPF filter: '%s'", sniffer.filter) - err = sniffer.setFromConfig(interfaces) - if err != nil { - return fmt.Errorf("Error creating sniffer: %v", err) - } - } - - if len(interfaces.File) == 0 { - if interfaces.Device == "any" { - // OS X or Windows - if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { - return fmt.Errorf("any interface is not supported on %s", runtime.GOOS) - } - } - } - - sniffer.worker, err = factory(sniffer.Datalink()) - if err != nil { - return fmt.Errorf("Error creating decoder: %v", err) - } - - if sniffer.config.Dumpfile != "" { - p, err := pcap.OpenDead(sniffer.Datalink(), 65535) - if err != nil { - return err - } - sniffer.dumper, err = p.NewDumper(sniffer.config.Dumpfile) - if err != nil { +func validateConfig(filter string, cfg *config.InterfacesConfig) error { + if cfg.File == "" { + if err := validatePcapFilter(filter); err != nil { return err } } - sniffer.isAlive = true + switch cfg.Type { + case "pcap": + return validatePcapConfig(cfg) + case "af_packet": + return validateAfPacketConfig(cfg) + default: + return fmt.Errorf("Unknown sniffer type: %s", cfg.Type) + } +} +func validatePcapConfig(cfg *config.InterfacesConfig) error { return nil } -func (sniffer *SnifferSetup) Run() error { - counter := 0 - loopCount := 1 - var lastPktTime *time.Time - var retError error - - for sniffer.isAlive { - if sniffer.config.OneAtATime { - fmt.Println("Press enter to read packet") - fmt.Scanln() - } - - data, ci, err := sniffer.DataSource.ReadPacketData() +func validateAfPacketConfig(cfg *config.InterfacesConfig) error { + _, _, _, err := afpacketComputeSize(cfg.BufferSizeMb, cfg.Snaplen, os.Getpagesize()) + return err +} - if err == pcap.NextErrorTimeoutExpired || err == syscall.EINTR { - logp.Debug("sniffer", "Interrupted") - continue - } +func validatePcapFilter(expr string) error { + if expr == "" { + return nil + } - if err == io.EOF { - logp.Debug("sniffer", "End of file") - loopCount++ - if sniffer.config.Loop > 0 && loopCount > sniffer.config.Loop { - // give a bit of time to the publish goroutine - // to flush - time.Sleep(300 * time.Millisecond) - sniffer.isAlive = false - continue - } + // Open a dummy pcap handle to compile the filter + p, err := pcap.OpenDead(layers.LinkTypeEthernet, 65535) + if err != nil { + return fmt.Errorf("OpenDead: %s", err) + } - logp.Debug("sniffer", "Reopening the file") - err = sniffer.Reopen() - if err != nil { - retError = fmt.Errorf("Error reopening file: %s", err) - sniffer.isAlive = false - continue - } - lastPktTime = nil - continue - } + defer p.Close() - if err != nil { - retError = fmt.Errorf("Sniffing error: %s", err) - sniffer.isAlive = false - continue - } + _, err = p.NewBPF(expr) + return fmt.Errorf("invalid filter: %s", err) +} - if len(data) == 0 { - // Empty packet, probably timeout from afpacket - continue - } +func openPcap(filter string, cfg *config.InterfacesConfig) (snifferHandle, error) { + snaplen := int32(cfg.Snaplen) + timeout := 500 * time.Millisecond + h, err := pcap.OpenLive(cfg.Device, snaplen, true, timeout) + if err != nil { + return nil, err + } - if sniffer.config.File != "" { - if lastPktTime != nil && !sniffer.config.TopSpeed { - sleep := ci.Timestamp.Sub(*lastPktTime) - if sleep > 0 { - time.Sleep(sleep) - } else { - logp.Warn("Time in pcap went backwards: %d", sleep) - } - } - _lastPktTime := ci.Timestamp - lastPktTime = &_lastPktTime - if !sniffer.config.TopSpeed { - ci.Timestamp = time.Now() // overwrite what we get from the pcap - } - } - counter++ + err = h.SetBPFFilter(filter) + if err != nil { + h.Close() + return nil, err + } - if sniffer.dumper != nil { - sniffer.dumper.WritePacketData(data, ci) - } - logp.Debug("sniffer", "Packet number: %d", counter) + return h, nil +} - sniffer.worker.OnPacket(data, &ci) +func openAFPacket(filter string, cfg *config.InterfacesConfig) (snifferHandle, error) { + szFrame, szBlock, numBlocks, err := afpacketComputeSize(cfg.BufferSizeMb, cfg.Snaplen, os.Getpagesize()) + if err != nil { + return nil, err } - logp.Info("Input finish. Processed %d packets. Have a nice day!", counter) + timeout := 500 * time.Millisecond + h, err := newAfpacketHandle(cfg.Device, szFrame, szBlock, numBlocks, timeout) + if err != nil { + return nil, err + } - if sniffer.dumper != nil { - sniffer.dumper.Close() + err = h.SetBPFFilter(filter) + if err != nil { + h.Close() + return nil, err } - return retError + return h, nil } -func (sniffer *SnifferSetup) Close() error { - switch sniffer.config.Type { - case "pcap": - sniffer.pcapHandle.Close() - case "af_packet": - sniffer.afpacketHandle.Close() +func openDumper(file string, linkType layers.LinkType) (*pcap.Dumper, error) { + p, err := pcap.OpenDead(linkType, 65535) + if err != nil { + return nil, err } - return nil -} - -func (sniffer *SnifferSetup) Stop() error { - sniffer.isAlive = false - return nil -} -func (sniffer *SnifferSetup) IsAlive() bool { - return sniffer.isAlive + return p.NewDumper(file) } diff --git a/packetbeat/tests/system/config/packetbeat.yml.j2 b/packetbeat/tests/system/config/packetbeat.yml.j2 index 928074be778..fe36c259301 100644 --- a/packetbeat/tests/system/config/packetbeat.yml.j2 +++ b/packetbeat/tests/system/config/packetbeat.yml.j2 @@ -8,7 +8,7 @@ packetbeat.interfaces.device: {{ iface_device|default("any") }} #================================== Flows ===================================== # Set network flow timeout. Flow is killed if no packet is received before being # timed out. -packetbeat.flows.timeout: 10s +packetbeat.flows.timeout: 2s # Configure reporting period. If set to -1, only killed flows will be reported packetbeat.flows.period: -1s @@ -168,7 +168,7 @@ tags: [ {%- endif -%} ] -packetbeat.shutdown_timeout: {{ shutdown_timeout|default(0) }} +packetbeat.shutdown_timeout: {{ shutdown_timeout|default('400ms') }} {%- if processors %} From 30badf6e96bc58681793d2c34abce8caeb0d718c Mon Sep 17 00:00:00 2001 From: Monica Sarbu Date: Thu, 24 Aug 2017 12:37:57 +0200 Subject: [PATCH 114/139] Rename all dashboards and viz to follow a similar format (#4979) --- ...e.json => Metricbeat-apache-overview.json} | 58 ++-- metricbeat/module/apache/module.yml | 3 + .../dashboard/Metricbeat-docker-overview.json | 188 ++++++++++++ .../default/dashboard/Metricbeat-docker.json | 135 --------- metricbeat/module/docker/module.yml | 3 + .../dashboard/Metricbeat-golang-overview.json | 113 +++++++ .../default/dashboard/Metricbeat-golang.json | 113 ------- metricbeat/module/golang/module.yml | 3 + .../Metricbeat-kubernetes-overview.json | 283 ++++++++++++++++++ .../dashboard/Metricbeat-kubernetes.json | 200 ------------- metricbeat/module/kubernetes/module.yml | 3 + .../Metricbeat-mongodb-overview.json | 172 +++++++++++ .../default/dashboard/Metricbeat-mongodb.json | 172 ----------- metricbeat/module/mongodb/module.yml | 3 + .../dashboard/Metricbeat-mysql-overview.json | 152 ++++++++++ .../default/dashboard/Metricbeat-mysql.json | 168 ----------- metricbeat/module/mysql/module.yml | 3 + .../Metricbeat-rabbitmq-overview.json | 107 +++++++ metricbeat/module/rabbitmq/module.yml | 3 + .../dashboard/Metricbeat-mysql-overview.json | 173 +++++++++++ .../default/dashboard/Metricbeat-redis.json | 138 --------- metricbeat/module/redis/module.yml | 3 + .../Metricbeat-containers-overview.json | 83 +++++ .../dashboard/Metricbeat-docker-overview.json | 83 ----- .../dashboard/Metricbeat-host-overview.json | 197 ++++++------ .../dashboard/Metricbeat-system-overview.json | 105 +++---- metricbeat/module/system/module.yml | 3 +- 27 files changed, 1461 insertions(+), 1206 deletions(-) rename metricbeat/module/apache/_meta/kibana/default/dashboard/{Metricbeat-apache.json => Metricbeat-apache-overview.json} (50%) create mode 100644 metricbeat/module/apache/module.yml create mode 100644 metricbeat/module/docker/_meta/kibana/default/dashboard/Metricbeat-docker-overview.json delete mode 100644 metricbeat/module/docker/_meta/kibana/default/dashboard/Metricbeat-docker.json create mode 100644 metricbeat/module/docker/module.yml create mode 100644 metricbeat/module/golang/_meta/kibana/default/dashboard/Metricbeat-golang-overview.json delete mode 100644 metricbeat/module/golang/_meta/kibana/default/dashboard/Metricbeat-golang.json create mode 100644 metricbeat/module/golang/module.yml create mode 100644 metricbeat/module/kubernetes/_meta/kibana/default/dashboard/Metricbeat-kubernetes-overview.json delete mode 100644 metricbeat/module/kubernetes/_meta/kibana/default/dashboard/Metricbeat-kubernetes.json create mode 100644 metricbeat/module/kubernetes/module.yml create mode 100644 metricbeat/module/mongodb/_meta/kibana/default/dashboard/Metricbeat-mongodb-overview.json delete mode 100644 metricbeat/module/mongodb/_meta/kibana/default/dashboard/Metricbeat-mongodb.json create mode 100644 metricbeat/module/mongodb/module.yml create mode 100644 metricbeat/module/mysql/_meta/kibana/default/dashboard/Metricbeat-mysql-overview.json delete mode 100644 metricbeat/module/mysql/_meta/kibana/default/dashboard/Metricbeat-mysql.json create mode 100644 metricbeat/module/mysql/module.yml create mode 100644 metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-rabbitmq-overview.json create mode 100644 metricbeat/module/rabbitmq/module.yml create mode 100644 metricbeat/module/redis/_meta/kibana/default/dashboard/Metricbeat-mysql-overview.json delete mode 100644 metricbeat/module/redis/_meta/kibana/default/dashboard/Metricbeat-redis.json create mode 100644 metricbeat/module/redis/module.yml create mode 100644 metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-containers-overview.json delete mode 100644 metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-docker-overview.json diff --git a/metricbeat/module/apache/_meta/kibana/default/dashboard/Metricbeat-apache.json b/metricbeat/module/apache/_meta/kibana/default/dashboard/Metricbeat-apache-overview.json similarity index 50% rename from metricbeat/module/apache/_meta/kibana/default/dashboard/Metricbeat-apache.json rename to metricbeat/module/apache/_meta/kibana/default/dashboard/Metricbeat-apache-overview.json index 79cf14d42a4..587e59674fe 100644 --- a/metricbeat/module/apache/_meta/kibana/default/dashboard/Metricbeat-apache.json +++ b/metricbeat/module/apache/_meta/kibana/default/dashboard/Metricbeat-apache-overview.json @@ -7,78 +7,78 @@ "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Apache-HTTPD", - "title": "Apache HTTPD - CPU", + "title": "CPU usage [Metricbeat Apache]", "uiStateJSON": "{}", "version": 1, "visState": "{\n \"title\": \"Apache HTTPD - CPU\",\n \"type\": \"line\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"showCircles\": true,\n \"smoothLines\": false,\n \"interpolate\": \"linear\",\n \"scale\": \"linear\",\n \"drawLinesBetweenPoints\": true,\n \"radiusRatio\": 9,\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.cpu.load\",\n \"customLabel\": \"CPU load\"\n }\n },\n {\n \"id\": \"2\",\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"type\": \"terms\",\n \"schema\": \"split\",\n \"params\": {\n \"field\": \"apache.status.hostname\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"row\": true\n }\n },\n {\n \"id\": \"4\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.cpu.user\",\n \"customLabel\": \"CPU user\"\n }\n },\n {\n \"id\": \"5\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.cpu.system\",\n \"customLabel\": \"CPU system\"\n }\n },\n {\n \"id\": \"6\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.cpu.children_user\",\n \"customLabel\": \"CPU children user\"\n }\n },\n {\n \"id\": \"7\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.cpu.children_system\",\n \"customLabel\": \"CPU children system\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Apache-HTTPD-CPU", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Apache-HTTPD", - "title": "Apache HTTPD - Hostname list", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "title": "Hostname list [Metricbeat Apache]", + "uiStateJSON": "{\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"Apache HTTPD - Hostname list\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Events count\"}},{\"id\":\"2\",\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"apache.status.hostname\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Apache HTTD Hostname\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Apache HTTPD - Hostname list\",\n \"type\": \"table\",\n \"params\": {\n \"perPage\": 10,\n \"showPartialRows\": false,\n \"showMeticsAtAllLevels\": false,\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {\n \"customLabel\": \"Events count\"\n }\n },\n {\n \"id\": \"2\",\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"apache.status.hostname\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Apache HTTD Hostname\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Apache-HTTPD-Hostname-list", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Apache-HTTPD", - "title": "Apache HTTPD - Load1/5/15", + "title": "Load1/5/15 [Metricbeat Apache]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Apache HTTPD - Load1/5/15\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"showCircles\":true,\"smoothLines\":false,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.load.5\",\"customLabel\":\"Load 5\"}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.load.1\",\"customLabel\":\"Load 1\"}},{\"id\":\"4\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.load.15\",\"customLabel\":\"Load 15\"}},{\"id\":\"5\",\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"apache.status.hostname\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Hostname\",\"row\":true}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Apache HTTPD - Load1/5/15\",\n \"type\": \"line\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"showCircles\": true,\n \"smoothLines\": false,\n \"interpolate\": \"linear\",\n \"scale\": \"linear\",\n \"drawLinesBetweenPoints\": true,\n \"radiusRatio\": 9,\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.load.5\",\n \"customLabel\": \"Load 5\"\n }\n },\n {\n \"id\": \"2\",\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.load.1\",\n \"customLabel\": \"Load 1\"\n }\n },\n {\n \"id\": \"4\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.load.15\",\n \"customLabel\": \"Load 15\"\n }\n },\n {\n \"id\": \"5\",\n \"type\": \"terms\",\n \"schema\": \"split\",\n \"params\": {\n \"field\": \"apache.status.hostname\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Hostname\",\n \"row\": true\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Apache-HTTPD-Load1-slash-5-slash-15", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Apache-HTTPD", - "title": "Apache HTTPD - Scoreboard", + "title": "Scoreboard [Metricbeat Apache]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Apache HTTPD - Scoreboard\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"showCircles\":true,\"smoothLines\":false,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.scoreboard.closing_connection\",\"customLabel\":\"Closing connection\"}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"apache.status.hostname\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Hostname\",\"row\":true}},{\"id\":\"4\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.scoreboard.dns_lookup\",\"customLabel\":\"DNS lookup\"}},{\"id\":\"5\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.scoreboard.gracefully_finishing\",\"customLabel\":\"Gracefully finishing\"}},{\"id\":\"6\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.scoreboard.idle_cleanup\",\"customLabel\":\"Idle cleanup\"}},{\"id\":\"7\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.scoreboard.keepalive\",\"customLabel\":\"Keepalive\"}},{\"id\":\"8\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.scoreboard.logging\",\"customLabel\":\"Logging\"}},{\"id\":\"9\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.scoreboard.open_slot\",\"customLabel\":\"Open slot\"}},{\"id\":\"10\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.scoreboard.reading_request\",\"customLabel\":\"Reading request\"}},{\"id\":\"11\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.scoreboard.sending_reply\",\"customLabel\":\"Sending reply\"}},{\"id\":\"12\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.scoreboard.starting_up\",\"customLabel\":\"Starting up\"}},{\"id\":\"13\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.scoreboard.total\",\"customLabel\":\"Total\"}},{\"id\":\"14\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.scoreboard.waiting_for_connection\",\"customLabel\":\"Waiting for connection\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Apache HTTPD - Scoreboard\",\n \"type\": \"line\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"showCircles\": true,\n \"smoothLines\": false,\n \"interpolate\": \"linear\",\n \"scale\": \"linear\",\n \"drawLinesBetweenPoints\": true,\n \"radiusRatio\": 9,\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.scoreboard.closing_connection\",\n \"customLabel\": \"Closing connection\"\n }\n },\n {\n \"id\": \"2\",\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"type\": \"terms\",\n \"schema\": \"split\",\n \"params\": {\n \"field\": \"apache.status.hostname\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Hostname\",\n \"row\": true\n }\n },\n {\n \"id\": \"4\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.scoreboard.dns_lookup\",\n \"customLabel\": \"DNS lookup\"\n }\n },\n {\n \"id\": \"5\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.scoreboard.gracefully_finishing\",\n \"customLabel\": \"Gracefully finishing\"\n }\n },\n {\n \"id\": \"6\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.scoreboard.idle_cleanup\",\n \"customLabel\": \"Idle cleanup\"\n }\n },\n {\n \"id\": \"7\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.scoreboard.keepalive\",\n \"customLabel\": \"Keepalive\"\n }\n },\n {\n \"id\": \"8\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.scoreboard.logging\",\n \"customLabel\": \"Logging\"\n }\n },\n {\n \"id\": \"9\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.scoreboard.open_slot\",\n \"customLabel\": \"Open slot\"\n }\n },\n {\n \"id\": \"10\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.scoreboard.reading_request\",\n \"customLabel\": \"Reading request\"\n }\n },\n {\n \"id\": \"11\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.scoreboard.sending_reply\",\n \"customLabel\": \"Sending reply\"\n }\n },\n {\n \"id\": \"12\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.scoreboard.starting_up\",\n \"customLabel\": \"Starting up\"\n }\n },\n {\n \"id\": \"13\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.scoreboard.total\",\n \"customLabel\": \"Total\"\n }\n },\n {\n \"id\": \"14\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.scoreboard.waiting_for_connection\",\n \"customLabel\": \"Waiting for connection\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Apache-HTTPD-Scoreboard", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Apache-HTTPD", - "title": "Apache HTTPD - Total accesses and kbytes", + "title": "Total accesses and kbytes [Metricbeat Apache]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Apache HTTPD - Total accesses and kbytes\",\"type\":\"metric\",\"params\":{\"handleNoResults\":true,\"fontSize\":60},\"aggs\":[{\"id\":\"1\",\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.total_kbytes\",\"customLabel\":\"Total kbytes\"}},{\"id\":\"2\",\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"apache.status.total_accesses\",\"customLabel\":\"Total accesses\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Apache HTTPD - Total accesses and kbytes\",\n \"type\": \"metric\",\n \"params\": {\n \"handleNoResults\": true,\n \"fontSize\": 60\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.total_kbytes\",\n \"customLabel\": \"Total kbytes\"\n }\n },\n {\n \"id\": \"2\",\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.total_accesses\",\n \"customLabel\": \"Total accesses\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Apache-HTTPD-Total-accesses-and-kbytes", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { @@ -87,14 +87,14 @@ "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Apache-HTTPD", - "title": "Apache HTTPD - Uptime", + "title": "Uptime [Metricbeat Apache]", "uiStateJSON": "{}", "version": 1, "visState": "{\n \"title\": \"Apache HTTPD - Uptime\",\n \"type\": \"metric\",\n \"params\": {\n \"handleNoResults\": true,\n \"fontSize\": 60\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.uptime.uptime\",\n \"customLabel\": \"Uptime\"\n }\n },\n {\n \"id\": \"2\",\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.uptime.server_uptime\",\n \"customLabel\": \"Server uptime\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Apache-HTTPD-Uptime", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { @@ -103,14 +103,14 @@ "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Apache-HTTPD", - "title": "Apache HTTPD - Workers", + "title": "Workers [Metricbeat Apache]", "uiStateJSON": "{}", "version": 1, "visState": "{\n \"title\": \"Apache HTTPD - Workers\",\n \"type\": \"line\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"showCircles\": true,\n \"smoothLines\": false,\n \"interpolate\": \"linear\",\n \"scale\": \"linear\",\n \"drawLinesBetweenPoints\": true,\n \"radiusRatio\": 9,\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.workers.busy\",\n \"customLabel\": \"Busy workers\"\n }\n },\n {\n \"id\": \"2\",\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"type\": \"terms\",\n \"schema\": \"split\",\n \"params\": {\n \"field\": \"apache.status.hostname\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Hostname\",\n \"row\": true\n }\n },\n {\n \"id\": \"4\",\n \"type\": \"avg\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"apache.status.workers.idle\",\n \"customLabel\": \"Idle workers\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Apache-HTTPD-Workers", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { @@ -131,26 +131,26 @@ }, "id": "Apache-HTTPD", "type": "search", - "version": 7 + "version": 1 }, { "attributes": { "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true,\"default_field\":\"*\"}},\"language\":\"lucene\"},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", "panelsJSON": "[{\"id\":\"Apache-HTTPD-CPU\",\"type\":\"visualization\",\"panelIndex\":1,\"size_x\":6,\"size_y\":3,\"col\":7,\"row\":10},{\"id\":\"Apache-HTTPD-Hostname-list\",\"type\":\"visualization\",\"panelIndex\":2,\"size_x\":3,\"size_y\":3,\"col\":1,\"row\":1},{\"id\":\"Apache-HTTPD-Load1-slash-5-slash-15\",\"type\":\"visualization\",\"panelIndex\":3,\"size_x\":6,\"size_y\":3,\"col\":1,\"row\":10},{\"id\":\"Apache-HTTPD-Scoreboard\",\"type\":\"visualization\",\"panelIndex\":4,\"size_x\":12,\"size_y\":3,\"col\":1,\"row\":7},{\"id\":\"Apache-HTTPD-Total-accesses-and-kbytes\",\"type\":\"visualization\",\"panelIndex\":5,\"size_x\":6,\"size_y\":3,\"col\":7,\"row\":1},{\"id\":\"Apache-HTTPD-Uptime\",\"type\":\"visualization\",\"panelIndex\":6,\"size_x\":3,\"size_y\":3,\"col\":4,\"row\":1},{\"id\":\"Apache-HTTPD-Workers\",\"type\":\"visualization\",\"panelIndex\":7,\"size_x\":12,\"size_y\":3,\"col\":1,\"row\":4}]", "timeRestore": false, - "title": "Metricbeat - Apache HTTPD server status", - "uiStateJSON": "{\"P-2\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", + "title": "[Metricbeat Apache] Overview", + "uiStateJSON": "{\"P-2\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-6\":{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}},\"P-5\":{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}}", "version": 1 }, "id": "Metricbeat-Apache-HTTPD-server-status", "type": "dashboard", - "version": 1 + "version": 3 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/metricbeat/module/apache/module.yml b/metricbeat/module/apache/module.yml new file mode 100644 index 00000000000..6d77cafd6ce --- /dev/null +++ b/metricbeat/module/apache/module.yml @@ -0,0 +1,3 @@ +dashboards: + - id: Metricbeat-Apache-HTTPD-server-status + file: Metricbeat-apache-overview.json diff --git a/metricbeat/module/docker/_meta/kibana/default/dashboard/Metricbeat-docker-overview.json b/metricbeat/module/docker/_meta/kibana/default/dashboard/Metricbeat-docker-overview.json new file mode 100644 index 00000000000..591f6cd0e7c --- /dev/null +++ b/metricbeat/module/docker/_meta/kibana/default/dashboard/Metricbeat-docker-overview.json @@ -0,0 +1,188 @@ +{ + "objects": [ + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "Metricbeat-Docker", + "title": "Docker containers [Metricbeat Docker]", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":1,\"direction\":\"asc\"}}}}", + "version": 1, + "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"2\",\"params\":{\"customLabel\":\"Name\",\"field\":\"docker.container.name\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":5},\"schema\":\"bucket\",\"type\":\"terms\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"customLabel\":\"CPU usage (%)\",\"field\":\"docker.cpu.total.pct\"},\"schema\":\"metric\",\"type\":\"max\"},{\"enabled\":true,\"id\":\"4\",\"params\":{\"customLabel\":\"DiskIO\",\"field\":\"docker.diskio.total\"},\"schema\":\"metric\",\"type\":\"max\"},{\"enabled\":true,\"id\":\"5\",\"params\":{\"customLabel\":\"Mem (%)\",\"field\":\"docker.memory.usage.pct\"},\"schema\":\"metric\",\"type\":\"max\"},{\"enabled\":true,\"id\":\"6\",\"params\":{\"customLabel\":\"Mem RSS\",\"field\":\"docker.memory.rss.total\"},\"schema\":\"metric\",\"type\":\"max\"},{\"enabled\":true,\"id\":\"1\",\"params\":{\"customLabel\":\"Number of Containers\",\"field\":\"docker.container.id\"},\"schema\":\"metric\",\"type\":\"cardinality\"}],\"listeners\":{},\"params\":{\"perPage\":8,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":true,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"title\":\"Docker containers [Metricbeat Docker]\",\"type\":\"table\"}" + }, + "col": 1, + "id": "Docker-containers", + "panelIndex": 1, + "row": 1, + "size_x": 7, + "size_y": 5, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "Metricbeat-Docker", + "title": "Number of Containers [Metricbeat Docker]", + "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}", + "version": 1, + "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"2\",\"params\":{\"customLabel\":\"Running\",\"field\":\"docker.info.containers.running\"},\"schema\":\"metric\",\"type\":\"max\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"customLabel\":\"Paused\",\"field\":\"docker.info.containers.paused\"},\"schema\":\"metric\",\"type\":\"max\"},{\"enabled\":true,\"id\":\"4\",\"params\":{\"customLabel\":\"Stopped\",\"field\":\"docker.info.containers.stopped\"},\"schema\":\"metric\",\"type\":\"max\"}],\"listeners\":{},\"params\":{\"addLegend\":false,\"addTooltip\":true,\"fontSize\":\"36\",\"gauge\":{\"autoExtend\":false,\"backStyle\":\"Full\",\"colorSchema\":\"Green to Red\",\"colorsRange\":[{\"from\":0,\"to\":100}],\"gaugeColorMode\":\"None\",\"gaugeStyle\":\"Full\",\"gaugeType\":\"Metric\",\"invertColors\":false,\"labels\":{\"color\":\"black\",\"show\":true},\"orientation\":\"vertical\",\"percentageMode\":false,\"scale\":{\"color\":\"#333\",\"labels\":false,\"show\":false,\"width\":2},\"style\":{\"bgColor\":false,\"fontSize\":60,\"labelColor\":false,\"subText\":\"\"},\"type\":\"simple\",\"useRange\":false,\"verticalSplit\":false},\"handleNoResults\":true,\"type\":\"gauge\"},\"title\":\"Number of Containers [Metricbeat Docker]\",\"type\":\"metric\"}" + }, + "col": 8, + "id": "Docker-Number-of-Containers", + "panelIndex": 2, + "row": 1, + "size_x": 5, + "size_y": 2, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "Metricbeat-Docker", + "title": "Docker containers per host [Metricbeat Docker]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Docker containers per host [Metricbeat Docker]\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"isDonut\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"docker.container.id\",\"customLabel\":\"Number of containers\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"beat.hostname\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Hosts\"}}],\"listeners\":{}}" + }, + "col": 8, + "id": "Docker-containers-per-host", + "panelIndex": 3, + "row": 3, + "size_x": 2, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "Metricbeat-Docker", + "title": "Docker images and names [Metricbeat Docker]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Docker images and names [Metricbeat Docker]\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"isDonut\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"docker.container.image\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"docker.container.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + }, + "col": 10, + "id": "Docker-images-and-names", + "panelIndex": 7, + "row": 3, + "size_x": 3, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"index\":\"metricbeat-*\",\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:docker AND metricset.name:cpu\",\"analyze_wildcard\":true}}}" + }, + "title": "CPU usage [Metricbeat Docker]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{\"customLabel\":\"Total CPU time\",\"field\":\"docker.cpu.total.pct\",\"percents\":[75]},\"schema\":\"metric\",\"type\":\"percentiles\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"customInterval\":\"2h\",\"extended_bounds\":{},\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1},\"schema\":\"segment\",\"type\":\"date_histogram\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"customLabel\":\"Container name\",\"field\":\"docker.container.name\",\"order\":\"desc\",\"orderBy\":\"1.75\",\"size\":5},\"schema\":\"group\",\"type\":\"terms\"}],\"listeners\":{},\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{},\"type\":\"category\"}],\"defaultYExtents\":false,\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"interpolate\":\"linear\",\"legendPosition\":\"top\",\"mode\":\"stacked\",\"scale\":\"linear\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"mode\":\"stacked\",\"show\":\"true\",\"showCircles\":true,\"type\":\"area\",\"valueAxis\":\"ValueAxis-1\"}],\"setYExtents\":false,\"shareYAxis\":true,\"smoothLines\":true,\"times\":[],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Count\"},\"type\":\"value\"}],\"yAxis\":{}},\"title\":\"CPU usage [Metricbeat Docker]\",\"type\":\"area\"}" + }, + "col": 1, + "id": "Docker-CPU-usage", + "panelIndex": 4, + "row": 6, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"index\":\"metricbeat-*\",\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:docker AND metricset.name:memory\",\"analyze_wildcard\":true}}}" + }, + "title": "Memory usage [Metricbeat Docker]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{\"customLabel\":\"Memory\",\"field\":\"docker.memory.usage.total\"},\"schema\":\"metric\",\"type\":\"max\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"customInterval\":\"2h\",\"extended_bounds\":{},\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1},\"schema\":\"segment\",\"type\":\"date_histogram\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"customLabel\":\"Container name\",\"field\":\"docker.container.name\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":5},\"schema\":\"group\",\"type\":\"terms\"}],\"listeners\":{},\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{},\"type\":\"category\"}],\"defaultYExtents\":false,\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"interpolate\":\"linear\",\"legendPosition\":\"top\",\"mode\":\"stacked\",\"scale\":\"linear\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"mode\":\"stacked\",\"show\":\"true\",\"showCircles\":true,\"type\":\"area\",\"valueAxis\":\"ValueAxis-1\"}],\"setYExtents\":false,\"shareYAxis\":true,\"smoothLines\":false,\"times\":[],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Count\"},\"type\":\"value\"}],\"yAxis\":{}},\"title\":\"Memory usage [Metricbeat Docker]\",\"type\":\"area\"}" + }, + "col": 7, + "id": "Docker-memory-usage", + "panelIndex": 5, + "row": 6, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"index\":\"metricbeat-*\",\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:docker AND metricset.name:network\",\"analyze_wildcard\":true}}}" + }, + "title": "Network IO [Metricbeat Docker]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{\"customLabel\":\"IN bytes\",\"field\":\"docker.network.in.bytes\"},\"schema\":\"metric\",\"type\":\"max\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"customInterval\":\"2h\",\"extended_bounds\":{},\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1},\"schema\":\"segment\",\"type\":\"date_histogram\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"customLabel\":\"Container name\",\"field\":\"docker.container.name\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":5},\"schema\":\"group\",\"type\":\"terms\"},{\"enabled\":true,\"id\":\"4\",\"params\":{\"customLabel\":\"OUT bytes\",\"field\":\"docker.network.out.bytes\"},\"schema\":\"metric\",\"type\":\"max\"}],\"listeners\":{},\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{},\"type\":\"category\"}],\"defaultYExtents\":false,\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"interpolate\":\"linear\",\"legendPosition\":\"top\",\"mode\":\"stacked\",\"scale\":\"linear\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"mode\":\"stacked\",\"show\":\"true\",\"showCircles\":true,\"type\":\"area\",\"valueAxis\":\"ValueAxis-1\"}],\"setYExtents\":false,\"shareYAxis\":true,\"smoothLines\":true,\"times\":[],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Count\"},\"type\":\"value\"}],\"yAxis\":{}},\"title\":\"Network IO [Metricbeat Docker]\",\"type\":\"area\"}" + }, + "col": 1, + "id": "Docker-Network-IO", + "panelIndex": 6, + "row": 9, + "size_x": 12, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "columns": [ + "_source" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:docker\",\"analyze_wildcard\":true}}}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "Metricbeat Docker", + "version": 1 + }, + "id": "Metricbeat-Docker", + "type": "search", + "version": 4 + }, + { + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}],\"highlightAll\":true,\"version\":true}" + }, + "optionsJSON": "{\"darkTheme\":false}", + "panelsJSON": "[{\"col\":1,\"id\":\"Docker-containers\",\"panelIndex\":1,\"row\":1,\"size_x\":7,\"size_y\":5,\"type\":\"visualization\"},{\"col\":8,\"id\":\"Docker-Number-of-Containers\",\"panelIndex\":2,\"row\":1,\"size_x\":5,\"size_y\":2,\"type\":\"visualization\"},{\"col\":8,\"id\":\"Docker-containers-per-host\",\"panelIndex\":3,\"row\":3,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":10,\"id\":\"Docker-images-and-names\",\"panelIndex\":7,\"row\":3,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Docker-CPU-usage\",\"panelIndex\":4,\"row\":6,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"Docker-memory-usage\",\"panelIndex\":5,\"row\":6,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Docker-Network-IO\",\"panelIndex\":6,\"row\":9,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"}]", + "timeRestore": false, + "title": "[Metricbeat Docker] Overview", + "uiStateJSON": "{\"P-1\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":1,\"direction\":\"asc\"}}}},\"P-2\":{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}},\"P-3\":{\"vis\":{\"legendOpen\":true}},\"P-5\":{\"vis\":{\"legendOpen\":true}},\"P-7\":{\"vis\":{\"legendOpen\":true}}}", + "version": 1 + }, + "id": "AV4REOpp5NkDleZmzKkE", + "type": "dashboard", + "version": 3 + } + ], + "version": "5.6.0-SNAPSHOT" +} \ No newline at end of file diff --git a/metricbeat/module/docker/_meta/kibana/default/dashboard/Metricbeat-docker.json b/metricbeat/module/docker/_meta/kibana/default/dashboard/Metricbeat-docker.json deleted file mode 100644 index ea9b108fe66..00000000000 --- a/metricbeat/module/docker/_meta/kibana/default/dashboard/Metricbeat-docker.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "objects": [ - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\n \"filter\": []\n}" - }, - "savedSearchId": "Metricbeat-Docker", - "title": "Docker containers", - "uiStateJSON": "{\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": 1,\n \"direction\": \"asc\"\n }\n }\n }\n}", - "version": 1, - "visState": "{\n \"title\": \"Docker containers\",\n \"type\": \"table\",\n \"params\": {\n \"perPage\": 8,\n \"showMeticsAtAllLevels\": false,\n \"showPartialRows\": false,\n \"showTotal\": true,\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n },\n \"totalFunc\": \"sum\"\n },\n \"aggs\": [\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"docker.container.name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Name\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"docker.cpu.total.pct\",\n \"customLabel\": \"CPU usage (%)\"\n }\n },\n {\n \"id\": \"4\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"docker.diskio.total\",\n \"customLabel\": \"DiskIO\"\n }\n },\n {\n \"id\": \"5\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"docker.memory.usage.pct\",\n \"customLabel\": \"Mem (%)\"\n }\n },\n {\n \"id\": \"6\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"docker.memory.rss.total\",\n \"customLabel\": \"Mem RSS\"\n }\n },\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"docker.container.id\",\n \"customLabel\": \"Number of Containers\"\n }\n }\n ],\n \"listeners\": {}\n}" - }, - "id": "Docker-containers", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "Metricbeat-Docker", - "title": "Docker Number of Containers", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Docker Number of Containers\",\"type\":\"metric\",\"params\":{\"handleNoResults\":true,\"fontSize\":\"36\"},\"aggs\":[{\"id\":\"2\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"docker.info.containers.running\",\"customLabel\":\"Running\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"docker.info.containers.paused\",\"customLabel\":\"Paused\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"docker.info.containers.stopped\",\"customLabel\":\"Stopped\"}}],\"listeners\":{}}" - }, - "id": "Docker-Number-of-Containers", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "Metricbeat-Docker", - "title": "Docker containers per host", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Docker containers per host\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"isDonut\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"docker.container.id\",\"customLabel\":\"Number of containers\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"beat.hostname\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Hosts\"}}],\"listeners\":{}}" - }, - "id": "Docker-containers-per-host", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "Metricbeat-Docker", - "title": "Docker images and names", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Docker images and names\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"isDonut\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"docker.container.image\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"docker.container.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" - }, - "id": "Docker-images-and-names", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\n \"filter\": [],\n \"index\": \"metricbeat-*\",\n \"highlight\": {\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n },\n \"query\": {\n \"query_string\": {\n \"query\": \"metricset.module:docker AND metricset.name:cpu\",\n \"analyze_wildcard\": true\n }\n }\n}" - }, - "title": "Docker CPU usage", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\n \"title\": \"Docker CPU usage\",\n \"type\": \"area\",\n \"params\": {\n \"addLegend\": true,\n \"addTimeMarker\": false,\n \"addTooltip\": true,\n \"defaultYExtents\": false,\n \"interpolate\": \"linear\",\n \"legendPosition\": \"top\",\n \"mode\": \"stacked\",\n \"scale\": \"linear\",\n \"setYExtents\": false,\n \"shareYAxis\": true,\n \"smoothLines\": true,\n \"times\": [],\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"percentiles\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"docker.cpu.total.pct\",\n \"percents\": [\n 75\n ],\n \"customLabel\": \"Total CPU time\"\n }\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"docker.container.name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1.75\",\n \"customLabel\": \"Container name\"\n }\n }\n ],\n \"listeners\": {}\n}" - }, - "id": "Docker-CPU-usage", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[],\"index\":\"metricbeat-*\",\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:docker AND metricset.name:memory\",\"analyze_wildcard\":true}}}" - }, - "title": "Docker memory usage", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Docker memory usage\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"docker.memory.usage.total\",\"customLabel\":\"Memory\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"docker.container.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Container name\"}}],\"listeners\":{}}" - }, - "id": "Docker-memory-usage", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[],\"index\":\"metricbeat-*\",\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:docker AND metricset.name:network\",\"analyze_wildcard\":true}}}" - }, - "title": "Docker Network IO", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Docker Network IO\",\"type\":\"area\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"interpolate\":\"linear\",\"legendPosition\":\"top\",\"mode\":\"stacked\",\"scale\":\"linear\",\"setYExtents\":false,\"shareYAxis\":true,\"smoothLines\":true,\"times\":[],\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"docker.network.in.bytes\",\"customLabel\":\"IN bytes\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"docker.container.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Container name\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"docker.network.out.bytes\",\"customLabel\":\"OUT bytes\"}}],\"listeners\":{}}" - }, - "id": "Docker-Network-IO", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "columns": [ - "_source" - ], - "description": "", - "hits": 0, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:docker\",\"analyze_wildcard\":true}}}" - }, - "sort": [ - "@timestamp", - "desc" - ], - "title": "Metricbeat Docker", - "version": 1 - }, - "id": "Metricbeat-Docker", - "type": "search", - "version": 4 - } - ], - "version": "6.0.0-alpha3-SNAPSHOT" -} \ No newline at end of file diff --git a/metricbeat/module/docker/module.yml b/metricbeat/module/docker/module.yml new file mode 100644 index 00000000000..74288253750 --- /dev/null +++ b/metricbeat/module/docker/module.yml @@ -0,0 +1,3 @@ +dashboards: + - id: AV4REOpp5NkDleZmzKkE + file: Metricbeat-docker-overview.json diff --git a/metricbeat/module/golang/_meta/kibana/default/dashboard/Metricbeat-golang-overview.json b/metricbeat/module/golang/_meta/kibana/default/dashboard/Metricbeat-golang-overview.json new file mode 100644 index 00000000000..dee177cea52 --- /dev/null +++ b/metricbeat/module/golang/_meta/kibana/default/dashboard/Metricbeat-golang-overview.json @@ -0,0 +1,113 @@ +{ + "objects": [ + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"language\":\"lucene\"},\"filter\":[]}" + }, + "title": "Heap Summary [Metricbeat Golang]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Heap Summary [Metricbeat Golang]\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.system.total\\\").label(\\\"System Total Memory\\\").yaxis(label=\\\"Bytes\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"min:golang.heap.allocations.allocated\\\").label(\\\"Bytes Allocated(min)\\\").movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.allocations.allocated\\\").label(\\\"Bytes Allocated(max)\\\").movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.gc.next_gc_limit\\\").label(\\\"GC Limit\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.gc.pause.count\\\").condition(lt,1, null).points().label(\\\"GC Cycles(count)\\\").yaxis(2,label=\\\"Count\\\")\",\"interval\":\"10s\"},\"aggs\":[]}" + }, + "id": "58000780-f529-11e6-844d-b170e2f0a07e", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"language\":\"lucene\"},\"filter\":[]}" + }, + "title": "Heap [Metricbeat Golang]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Heap [Metricbeat Golang]\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.allocations.total\\\").label(\\\"Heap Total\\\").derivative().movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.allocations.active\\\").label(\\\"Heap Inuse\\\").movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.allocations.allocated\\\").label(\\\"Heap Allocated\\\").movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.allocations.idle\\\").label(\\\"Heap Idle\\\").movingaverage(30)\",\"interval\":\"10s\"},\"aggs\":[]}" + }, + "id": "95388680-f52a-11e6-969c-518c48c913e4", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"language\":\"lucene\"},\"filter\":[]}" + }, + "title": "Objects [Metricbeat Golang]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Objects [Metricbeat Golang]\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.allocations.objects\\\").label(\\\"Object Count(avg)\\\").yaxis(1,label=\\\"Count\\\").movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.allocations.total\\\").derivative().label(\\\"Allocation Rate\\\").yaxis(2,label=\\\"Rate\\\").movingaverage(30)\",\"interval\":\"10s\"},\"aggs\":[]}" + }, + "id": "b59a5200-f52a-11e6-969c-518c48c913e4", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"language\":\"lucene\"},\"filter\":[]}" + }, + "title": "System [Metricbeat Golang]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"System [Metricbeat Golang]\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.system.total\\\").label(\\\"System Total\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.system.optained\\\").label(\\\"System Obtained\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.system.stack\\\").label(\\\"System Stack\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.system.released\\\").label(\\\"System Released\\\")\",\"interval\":\"10s\"},\"aggs\":[]}" + }, + "id": "9a9a8bf0-f52a-11e6-969c-518c48c913e4", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"language\":\"lucene\"},\"filter\":[]}" + }, + "title": "GC count [Metricbeat Golang]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"GC count [Metricbeat Golang]\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.gc.pause.count\\\").label(\\\"GC Count\\\").bars().yaxis(label=\\\"Count\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.gc.total_count\\\").label(\\\"GC Rate\\\").derivative().movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.gc.cpu_fraction\\\").label(\\\"CPU Fraction\\\").yaxis(2,label=\\\"Fraction\\\")\",\"interval\":\"10s\"},\"aggs\":[]}" + }, + "id": "b046cb80-f52a-11e6-969c-518c48c913e4", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"language\":\"lucene\"},\"filter\":[]}" + }, + "title": "GC durations [Metricbeat Golang]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"GC durations [Metricbeat Golang]\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.gc.pause.sum.ns\\\").bars().label(\\\"sum of GC Pause durations(ns)\\\").yaxis(label=\\\"Durations(ns)\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.gc.total_pause.ns\\\").derivative().movingaverage(30).label(\\\"Total GC Pause(ns) Rate\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.gc.pause.max.ns\\\").label(\\\"Max GC Pause(ns)\\\").movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.gc.pause.avg.ns\\\").label(\\\"Avg GC Pause(ns)\\\").movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.gc.pause.count\\\").condition(lt,1, null).label(\\\"GC Pause count\\\").points().yaxis(2,label=\\\"Count\\\")\",\"interval\":\"10s\"},\"aggs\":[]}" + }, + "id": "ab226b50-f52a-11e6-969c-518c48c913e4", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"highlightAll\":true,\"version\":true}" + }, + "optionsJSON": "{\"darkTheme\":false}", + "panelsJSON": "[{\"col\":1,\"id\":\"58000780-f529-11e6-844d-b170e2f0a07e\",\"panelIndex\":8,\"row\":1,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"95388680-f52a-11e6-969c-518c48c913e4\",\"panelIndex\":9,\"row\":4,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":9,\"id\":\"b59a5200-f52a-11e6-969c-518c48c913e4\",\"panelIndex\":10,\"row\":4,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":5,\"id\":\"9a9a8bf0-f52a-11e6-969c-518c48c913e4\",\"panelIndex\":11,\"row\":4,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":7,\"id\":\"b046cb80-f52a-11e6-969c-518c48c913e4\",\"panelIndex\":12,\"row\":8,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"ab226b50-f52a-11e6-969c-518c48c913e4\",\"panelIndex\":13,\"row\":8,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"}]", + "timeRestore": false, + "title": "[Metricbeat Golang] Overview", + "uiStateJSON": "{}", + "version": 1 + }, + "id": "f2dc7320-f519-11e6-a3c9-9d1f7c42b045", + "type": "dashboard", + "version": 3 + } + ], + "version": "6.0.0-beta1-SNAPSHOT" +} \ No newline at end of file diff --git a/metricbeat/module/golang/_meta/kibana/default/dashboard/Metricbeat-golang.json b/metricbeat/module/golang/_meta/kibana/default/dashboard/Metricbeat-golang.json deleted file mode 100644 index e96bbad89e9..00000000000 --- a/metricbeat/module/golang/_meta/kibana/default/dashboard/Metricbeat-golang.json +++ /dev/null @@ -1,113 +0,0 @@ -{ - "objects": [ - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - }, - "title": "Golang: Heap Summary", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Golang: Heap Summary\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.system.total\\\").label(\\\"System Total Memory\\\").yaxis(label=\\\"Bytes\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"min:golang.heap.allocations.allocated\\\").label(\\\"Bytes Allocated(min)\\\").movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.allocations.allocated\\\").label(\\\"Bytes Allocated(max)\\\").movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.gc.next_gc_limit\\\").label(\\\"GC Limit\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.gc.pause.count\\\").condition(lt,1, null).points().label(\\\"GC Cycles(count)\\\").yaxis(2,label=\\\"Count\\\")\",\"interval\":\"10s\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "58000780-f529-11e6-844d-b170e2f0a07e", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - }, - "title": "Golang: Heap", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Golang: Heap\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.allocations.total\\\").label(\\\"Heap Total\\\").derivative().movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.allocations.active\\\").label(\\\"Heap Inuse\\\").movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.allocations.allocated\\\").label(\\\"Heap Allocated\\\").movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.allocations.idle\\\").label(\\\"Heap Idle\\\").movingaverage(30)\",\"interval\":\"10s\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "95388680-f52a-11e6-969c-518c48c913e4", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - }, - "title": "Golang: Objects", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Golang: Objects\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.allocations.objects\\\").label(\\\"Object Count(avg)\\\").yaxis(1,label=\\\"Count\\\").movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.allocations.total\\\").derivative().label(\\\"Allocation Rate\\\").yaxis(2,label=\\\"Rate\\\").movingaverage(30)\",\"interval\":\"10s\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "b59a5200-f52a-11e6-969c-518c48c913e4", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - }, - "title": "Golang: System", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Golang: System\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.system.total\\\").label(\\\"System Total\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.system.optained\\\").label(\\\"System Obtained\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.system.stack\\\").label(\\\"System Stack\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.system.released\\\").label(\\\"System Released\\\")\",\"interval\":\"10s\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "9a9a8bf0-f52a-11e6-969c-518c48c913e4", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - }, - "title": "Golang: GC count", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Golang: GC count\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.gc.pause.count\\\").label(\\\"GC Count\\\").bars().yaxis(label=\\\"Count\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.gc.total_count\\\").label(\\\"GC Rate\\\").derivative().movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.gc.cpu_fraction\\\").label(\\\"CPU Fraction\\\").yaxis(2,label=\\\"Fraction\\\")\",\"interval\":\"10s\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "b046cb80-f52a-11e6-969c-518c48c913e4", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - }, - "title": "Golang: GC durations", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Golang: GC durations\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.gc.pause.sum.ns\\\").bars().label(\\\"sum of GC Pause durations(ns)\\\").yaxis(label=\\\"Durations(ns)\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.gc.total_pause.ns\\\").derivative().movingaverage(30).label(\\\"Total GC Pause(ns) Rate\\\"),.es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.gc.pause.max.ns\\\").label(\\\"Max GC Pause(ns)\\\").movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"avg:golang.heap.gc.pause.avg.ns\\\").label(\\\"Avg GC Pause(ns)\\\").movingaverage(30),.es(index=\\\"metricbeat*\\\",metric=\\\"max:golang.heap.gc.pause.count\\\").condition(lt,1, null).label(\\\"GC Pause count\\\").points().yaxis(2,label=\\\"Count\\\")\",\"interval\":\"10s\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "ab226b50-f52a-11e6-969c-518c48c913e4", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "hits": 0, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" - }, - "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"58000780-f529-11e6-844d-b170e2f0a07e\",\"panelIndex\":8,\"row\":1,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"95388680-f52a-11e6-969c-518c48c913e4\",\"panelIndex\":9,\"row\":4,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":9,\"id\":\"b59a5200-f52a-11e6-969c-518c48c913e4\",\"panelIndex\":10,\"row\":4,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":5,\"id\":\"9a9a8bf0-f52a-11e6-969c-518c48c913e4\",\"panelIndex\":11,\"row\":4,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":7,\"id\":\"b046cb80-f52a-11e6-969c-518c48c913e4\",\"panelIndex\":12,\"row\":8,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"ab226b50-f52a-11e6-969c-518c48c913e4\",\"panelIndex\":13,\"row\":8,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"}]", - "timeRestore": false, - "title": "Golang: Heap", - "uiStateJSON": "{}", - "version": 1 - }, - "id": "f2dc7320-f519-11e6-a3c9-9d1f7c42b045", - "type": "dashboard", - "version": 1 - } - ], - "version": "6.0.0-alpha3-SNAPSHOT" -} \ No newline at end of file diff --git a/metricbeat/module/golang/module.yml b/metricbeat/module/golang/module.yml new file mode 100644 index 00000000000..11beeafaeb9 --- /dev/null +++ b/metricbeat/module/golang/module.yml @@ -0,0 +1,3 @@ +dashboards: + - id: f2dc7320-f519-11e6-a3c9-9d1f7c42b045 + file: Metricbeat-golang-overview.json diff --git a/metricbeat/module/kubernetes/_meta/kibana/default/dashboard/Metricbeat-kubernetes-overview.json b/metricbeat/module/kubernetes/_meta/kibana/default/dashboard/Metricbeat-kubernetes-overview.json new file mode 100644 index 00000000000..ffc704eb57f --- /dev/null +++ b/metricbeat/module/kubernetes/_meta/kibana/default/dashboard/Metricbeat-kubernetes-overview.json @@ -0,0 +1,283 @@ +{ + "objects": [ + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + }, + "title": "Available pods per deployment [Metricbeat Kubernetes]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Available pods per deployment [Metricbeat Kubernetes]\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"filter\":\"metricset.module:kubernetes AND metricset.name:state_deployment\",\"id\":\"117fadf0-30df-11e7-8df8-6d3604a72912\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"rgba(104,188,0,1)\",\"fill\":0.5,\"formatter\":\"number\",\"id\":\"64456840-30df-11e7-8df8-6d3604a72912\",\"label\":\"Available pods\",\"line_width\":1,\"metrics\":[{\"field\":\"kubernetes.deployment.replicas.available\",\"id\":\"64456841-30df-11e7-8df8-6d3604a72912\",\"type\":\"sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_filters\":[{\"color\":\"#68BC00\",\"id\":\"53d35ad0-30df-11e7-8df8-6d3604a72912\"}],\"split_mode\":\"terms\",\"stacked\":\"stacked\",\"terms_field\":\"kubernetes.deployment.name\",\"terms_size\":\"10000\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"timeseries\"},\"aggs\":[],\"listeners\":{}}" + }, + "col": 7, + "id": "022a54c0-2bf5-11e7-859b-f78b612cde28", + "panelIndex": 1, + "row": 1, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + }, + "title": "CPU usage by node [Metricbeat Kubernetes]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"CPU usage by node [Metricbeat Kubernetes]\",\"type\":\"metrics\",\"params\":{\"id\":\"0d5c6b10-2bf2-11e7-859b-f78b612cde28\",\"type\":\"timeseries\",\"series\":[{\"id\":\"0d5c9220-2bf2-11e7-859b-f78b612cde28\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\",\"type\":\"sum\",\"field\":\"kubernetes.container.cpu.usage.nanocores\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"0.0a\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":\"0.5\",\"stacked\":\"none\",\"terms_field\":\"kubernetes.node.name\",\"terms_size\":\"10000\",\"terms_order_by\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\",\"value_template\":\"{{value}} nanocores\",\"override_index_pattern\":0,\"series_interval\":\"10s\",\"series_time_field\":\"@timestamp\"},{\"id\":\"22f65d40-31a7-11e7-84cc-096d2b38e6e5\",\"color\":\"rgba(211,49,21,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"22f65d41-31a7-11e7-84cc-096d2b38e6e5\",\"type\":\"avg\",\"field\":\"kubernetes.node.cpu.capacity.cores\"},{\"script\":\"params.cores * 1000000000\",\"id\":\"4af4c390-34d6-11e7-be88-cb6a123dc1bb\",\"type\":\"calculation\",\"variables\":[{\"id\":\"4cd32080-34d6-11e7-be88-cb6a123dc1bb\",\"name\":\"cores\",\"field\":\"22f65d41-31a7-11e7-84cc-096d2b38e6e5\"}]}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"0.0a\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"0\",\"stacked\":\"none\",\"terms_field\":\"kubernetes.node.name\",\"terms_size\":\"10000\",\"terms_order_by\":\"22f65d41-31a7-11e7-84cc-096d2b38e6e5\",\"value_template\":\"{{value}} nanocores\",\"hide_in_legend\":1,\"label\":\"\",\"override_index_pattern\":0,\"series_interval\":\"10s\",\"series_time_field\":\"@timestamp\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"12c1f2f0-2bf2-11e7-859b-f78b612cde28\"}],\"bar_color_rules\":[{\"id\":\"1373ddd0-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_color_rules\":[{\"id\":\"140e4910-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"filter\":\"metricset.module:kubernetes AND (metricset.name:container OR metricset.name:state_node)\"},\"aggs\":[],\"listeners\":{}}" + }, + "col": 1, + "id": "44f12b40-2bf4-11e7-859b-f78b612cde28", + "panelIndex": 2, + "row": 7, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + }, + "title": "Kubernetes - Deployments", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Kubernetes - Deployments\",\"type\":\"metrics\",\"params\":{\"id\":\"4c4690b0-30e0-11e7-8df8-6d3604a72912\",\"type\":\"metric\",\"series\":[{\"id\":\"4c4690b1-30e0-11e7-8df8-6d3604a72912\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"4c4690b2-30e0-11e7-8df8-6d3604a72912\",\"type\":\"cardinality\",\"field\":\"kubernetes.deployment.name\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"kubernetes.deployment.name\",\"label\":\"Deployments\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"filter\":\"metricset.module:kubernetes AND metricset.name:state_deployment\",\"background_color_rules\":[{\"id\":\"67ee7da0-30e0-11e7-8df8-6d3604a72912\"}],\"bar_color_rules\":[{\"id\":\"68cdba10-30e0-11e7-8df8-6d3604a72912\"}],\"gauge_color_rules\":[{\"id\":\"69765620-30e0-11e7-8df8-6d3604a72912\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\"},\"aggs\":[],\"listeners\":{}}" + }, + "col": 4, + "id": "cd059410-2bfb-11e7-859b-f78b612cde28", + "panelIndex": 5, + "row": 1, + "size_x": 3, + "size_y": 3, + "type": "visualization", + "version": 1 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + }, + "title": "Kubernetes - Desired pods", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Kubernetes - Desired pods\",\"type\":\"metrics\",\"params\":{\"id\":\"2fe9d3b0-30d5-11e7-8df8-6d3604a72912\",\"type\":\"metric\",\"series\":[{\"id\":\"2fe9d3b1-30d5-11e7-8df8-6d3604a72912\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"54cf79a0-30d5-11e7-8df8-6d3604a72912\",\"type\":\"sum\",\"field\":\"kubernetes.deployment.replicas.desired\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Desired Pods\",\"override_index_pattern\":1,\"series_time_field\":\"@timestamp\",\"series_interval\":\"10s\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"508ffb30-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_color_rules\":[{\"id\":\"50f9b980-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_width\":\"10\",\"gauge_inner_width\":\"10\",\"gauge_style\":\"half\",\"bar_color_rules\":[{\"id\":\"674d83b0-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_max\":\"5\",\"filter\":\"metricset.module:kubernetes AND metricset.name:state_deployment\"},\"aggs\":[],\"listeners\":{}}" + }, + "col": 1, + "id": "e1018b90-2bfb-11e7-859b-f78b612cde28", + "panelIndex": 6, + "row": 4, + "size_x": 2, + "size_y": 3, + "type": "visualization", + "version": 1 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + }, + "title": "Memory usage by node [Metricbeat Kubernetes]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Memory usage by node [Metricbeat Kubernetes]\",\"type\":\"metrics\",\"params\":{\"id\":\"0d5c6b10-2bf2-11e7-859b-f78b612cde28\",\"type\":\"timeseries\",\"series\":[{\"id\":\"0d5c9220-2bf2-11e7-859b-f78b612cde28\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\",\"type\":\"sum\",\"field\":\"kubernetes.container.memory.usage.bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"kubernetes.node.name\",\"terms_size\":\"10000\",\"terms_order_by\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\"},{\"id\":\"8ba3b270-31a7-11e7-84cc-096d2b38e6e5\",\"color\":\"rgba(211,49,21,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"8ba3b271-31a7-11e7-84cc-096d2b38e6e5\",\"type\":\"sum\",\"field\":\"kubernetes.node.memory.capacity.bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"0\",\"stacked\":\"none\",\"terms_field\":\"kubernetes.node.name\",\"terms_size\":\"10000\",\"terms_order_by\":\"8ba3b271-31a7-11e7-84cc-096d2b38e6e5\",\"hide_in_legend\":1,\"label\":\"Node capacity\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"12c1f2f0-2bf2-11e7-859b-f78b612cde28\"}],\"bar_color_rules\":[{\"id\":\"1373ddd0-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_color_rules\":[{\"id\":\"140e4910-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"filter\":\"metricset.module:kubernetes AND (metricset.name:container OR metricset.name:state_node)\"},\"aggs\":[],\"listeners\":{}}" + }, + "col": 7, + "id": "d6564360-2bfc-11e7-859b-f78b612cde28", + "panelIndex": 7, + "row": 7, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + }, + "title": "Network in by node [Metricbeat Kubernetes]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Network in by node [Metricbeat Kubernetes]\",\"type\":\"metrics\",\"params\":{\"id\":\"0d5c6b10-2bf2-11e7-859b-f78b612cde28\",\"type\":\"timeseries\",\"series\":[{\"id\":\"0d5c9220-2bf2-11e7-859b-f78b612cde28\",\"color\":\"rgba(104,188,0,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\",\"type\":\"sum\",\"field\":\"kubernetes.pod.network.rx.bytes\"},{\"unit\":\"\",\"id\":\"494fc310-2bf7-11e7-859b-f78b612cde28\",\"type\":\"derivative\",\"field\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\"},{\"unit\":\"\",\"id\":\"37c72a70-3598-11e7-aa4a-8313a0c92a88\",\"type\":\"positive_only\",\"field\":\"494fc310-2bf7-11e7-859b-f78b612cde28\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"stacked\",\"terms_field\":\"kubernetes.node.name\",\"terms_size\":\"100000\",\"terms_order_by\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\",\"label\":\"\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"12c1f2f0-2bf2-11e7-859b-f78b612cde28\"}],\"bar_color_rules\":[{\"id\":\"1373ddd0-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_color_rules\":[{\"id\":\"140e4910-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"filter\":\"metricset.module:kubernetes AND metricset.name:pod\"},\"aggs\":[],\"listeners\":{}}" + }, + "col": 7, + "id": "16fa4470-2bfd-11e7-859b-f78b612cde28", + "panelIndex": 8, + "row": 10, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + }, + "title": "Network out by node [Metricbeat Kubernetes]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Network out by node [Metricbeat Kubernetes]\",\"type\":\"metrics\",\"params\":{\"id\":\"0d5c6b10-2bf2-11e7-859b-f78b612cde28\",\"type\":\"timeseries\",\"series\":[{\"id\":\"0d5c9220-2bf2-11e7-859b-f78b612cde28\",\"color\":\"rgba(104,188,0,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\",\"type\":\"sum\",\"field\":\"kubernetes.pod.network.tx.bytes\"},{\"unit\":\"\",\"id\":\"494fc310-2bf7-11e7-859b-f78b612cde28\",\"type\":\"derivative\",\"field\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\"},{\"unit\":\"\",\"id\":\"244c70e0-3598-11e7-aa4a-8313a0c92a88\",\"type\":\"positive_only\",\"field\":\"494fc310-2bf7-11e7-859b-f78b612cde28\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"stacked\",\"terms_field\":\"kubernetes.node.name\",\"terms_size\":\"10000\",\"terms_order_by\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\",\"label\":\"\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"12c1f2f0-2bf2-11e7-859b-f78b612cde28\"}],\"bar_color_rules\":[{\"id\":\"1373ddd0-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_color_rules\":[{\"id\":\"140e4910-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"filter\":\"metricset.module:kubernetes AND metricset.name:pod\"},\"aggs\":[],\"listeners\":{}}" + }, + "col": 1, + "id": "294546b0-30d6-11e7-8df8-6d3604a72912", + "panelIndex": 9, + "row": 10, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + }, + "title": "Kubernetes - Nodes", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Kubernetes - Nodes\",\"type\":\"metrics\",\"params\":{\"id\":\"4c4690b0-30e0-11e7-8df8-6d3604a72912\",\"type\":\"metric\",\"series\":[{\"id\":\"4c4690b1-30e0-11e7-8df8-6d3604a72912\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"4c4690b2-30e0-11e7-8df8-6d3604a72912\",\"type\":\"cardinality\",\"field\":\"kubernetes.node.name\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"kubernetes.deployment.name\",\"label\":\"Nodes\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"filter\":\"metricset.module:kubernetes AND metricset.name:state_node\",\"background_color_rules\":[{\"id\":\"67ee7da0-30e0-11e7-8df8-6d3604a72912\"}],\"bar_color_rules\":[{\"id\":\"68cdba10-30e0-11e7-8df8-6d3604a72912\"}],\"gauge_color_rules\":[{\"id\":\"69765620-30e0-11e7-8df8-6d3604a72912\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\"},\"aggs\":[],\"listeners\":{}}" + }, + "col": 1, + "id": "408fccf0-30d6-11e7-8df8-6d3604a72912", + "panelIndex": 10, + "row": 1, + "size_x": 3, + "size_y": 3, + "type": "visualization", + "version": 1 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + }, + "title": "Top CPU intensive pods [Metricbeat Kubernetes]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Top CPU intensive pods [Metricbeat Kubernetes]\",\"type\":\"metrics\",\"params\":{\"id\":\"5d3692a0-2bfc-11e7-859b-f78b612cde28\",\"type\":\"top_n\",\"series\":[{\"id\":\"5d3692a1-2bfc-11e7-859b-f78b612cde28\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"5d3692a2-2bfc-11e7-859b-f78b612cde28\",\"type\":\"sum\",\"field\":\"kubernetes.container.cpu.usage.core.ns\"},{\"unit\":\"1s\",\"id\":\"6c905240-2bfc-11e7-859b-f78b612cde28\",\"type\":\"derivative\",\"field\":\"5d3692a2-2bfc-11e7-859b-f78b612cde28\"},{\"unit\":\"\",\"id\":\"9a51f710-359d-11e7-aa4a-8313a0c92a88\",\"type\":\"positive_only\",\"field\":\"6c905240-2bfc-11e7-859b-f78b612cde28\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"0.0 a\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"kubernetes.pod.name\",\"terms_order_by\":\"5d3692a2-2bfc-11e7-859b-f78b612cde28\",\"value_template\":\"{{value}} ns\",\"offset_time\":\"\",\"override_index_pattern\":0}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"id\":\"802104d0-2bfc-11e7-859b-f78b612cde28\"}],\"filter\":\"metricset.module:kubernetes AND metricset.name:container\"},\"aggs\":[],\"listeners\":{}}" + }, + "col": 1, + "id": "58e644f0-30d6-11e7-8df8-6d3604a72912", + "panelIndex": 11, + "row": 13, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + }, + "title": "Top memory intensive pods [Metricbeat Kubernetes]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Top memory intensive pods [Metricbeat Kubernetes]\",\"type\":\"metrics\",\"params\":{\"id\":\"5d3692a0-2bfc-11e7-859b-f78b612cde28\",\"type\":\"top_n\",\"series\":[{\"id\":\"5d3692a1-2bfc-11e7-859b-f78b612cde28\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"5d3692a2-2bfc-11e7-859b-f78b612cde28\",\"type\":\"sum\",\"field\":\"kubernetes.container.memory.usage.bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"kubernetes.pod.name\",\"terms_order_by\":\"5d3692a2-2bfc-11e7-859b-f78b612cde28\",\"value_template\":\"\",\"offset_time\":\"\",\"override_index_pattern\":0,\"terms_size\":\"10\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"id\":\"802104d0-2bfc-11e7-859b-f78b612cde28\"}],\"filter\":\"metricset.module:kubernetes AND metricset.name:container\"},\"aggs\":[],\"listeners\":{}}" + }, + "col": 7, + "id": "a4c9d360-30df-11e7-8df8-6d3604a72912", + "panelIndex": 12, + "row": 13, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + }, + "title": "Kubernetes - Unavailable pods", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Kubernetes - Unavailable pods\",\"type\":\"metrics\",\"params\":{\"id\":\"2fe9d3b0-30d5-11e7-8df8-6d3604a72912\",\"type\":\"metric\",\"series\":[{\"id\":\"2fe9d3b1-30d5-11e7-8df8-6d3604a72912\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"54cf79a0-30d5-11e7-8df8-6d3604a72912\",\"type\":\"sum\",\"field\":\"kubernetes.deployment.replicas.unavailable\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Unavailable Pods\",\"override_index_pattern\":1,\"series_interval\":\"10s\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"508ffb30-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_color_rules\":[{\"id\":\"50f9b980-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_width\":\"10\",\"gauge_inner_width\":\"10\",\"gauge_style\":\"half\",\"bar_color_rules\":[{\"id\":\"674d83b0-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_max\":\"\",\"filter\":\"metricset.module:kubernetes AND metricset.name:state_deployment\"},\"aggs\":[],\"listeners\":{}}" + }, + "col": 5, + "id": "174a6ad0-30e0-11e7-8df8-6d3604a72912", + "panelIndex": 13, + "row": 4, + "size_x": 2, + "size_y": 3, + "type": "visualization", + "version": 1 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + }, + "title": "Unavailable pods per deployment [Metricbeat Kubernetes]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Unavailable pods per deployment [Metricbeat Kubernetes]\",\"type\":\"metrics\",\"params\":{\"id\":\"117fadf0-30df-11e7-8df8-6d3604a72912\",\"type\":\"timeseries\",\"series\":[{\"id\":\"64456840-30df-11e7-8df8-6d3604a72912\",\"color\":\"rgba(254,146,0,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"64456841-30df-11e7-8df8-6d3604a72912\",\"type\":\"sum\",\"field\":\"kubernetes.deployment.replicas.unavailable\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"stacked\",\"split_filters\":[{\"color\":\"#68BC00\",\"id\":\"53d35ad0-30df-11e7-8df8-6d3604a72912\"}],\"terms_field\":\"kubernetes.deployment.name\",\"label\":\"Unavailable pods\",\"terms_size\":\"10000\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"filter\":\"metricset.module:kubernetes AND metricset.name:state_deployment\"},\"aggs\":[],\"listeners\":{}}" + }, + "col": 7, + "id": "7aac4fd0-30e0-11e7-8df8-6d3604a72912", + "panelIndex": 14, + "row": 4, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + }, + "title": "Kubernetes - Available pods", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Kubernetes - Available pods\",\"type\":\"metrics\",\"params\":{\"id\":\"2fe9d3b0-30d5-11e7-8df8-6d3604a72912\",\"type\":\"metric\",\"series\":[{\"id\":\"2fe9d3b1-30d5-11e7-8df8-6d3604a72912\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"54cf79a0-30d5-11e7-8df8-6d3604a72912\",\"type\":\"sum\",\"field\":\"kubernetes.deployment.replicas.available\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Available Pods\",\"override_index_pattern\":1,\"series_time_field\":\"@timestamp\",\"series_index_pattern\":\"*\",\"series_interval\":\"10s\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"508ffb30-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_color_rules\":[{\"id\":\"50f9b980-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_width\":\"10\",\"gauge_inner_width\":\"10\",\"gauge_style\":\"half\",\"bar_color_rules\":[{\"id\":\"674d83b0-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_max\":\"5\",\"filter\":\"metricset.module:kubernetes AND metricset.name:state_deployment\"},\"aggs\":[],\"listeners\":{}}" + }, + "col": 3, + "id": "da1ff7c0-30ed-11e7-b9e5-2b5b07213ab3", + "panelIndex": 15, + "row": 4, + "size_x": 2, + "size_y": 3, + "type": "visualization", + "version": 1 + }, + { + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}],\"highlightAll\":true,\"version\":true}" + }, + "optionsJSON": "{\"darkTheme\":false}", + "panelsJSON": "[{\"col\":7,\"id\":\"022a54c0-2bf5-11e7-859b-f78b612cde28\",\"panelIndex\":1,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"44f12b40-2bf4-11e7-859b-f78b612cde28\",\"panelIndex\":2,\"row\":7,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":4,\"id\":\"cd059410-2bfb-11e7-859b-f78b612cde28\",\"panelIndex\":5,\"row\":1,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"e1018b90-2bfb-11e7-859b-f78b612cde28\",\"panelIndex\":6,\"row\":4,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"d6564360-2bfc-11e7-859b-f78b612cde28\",\"panelIndex\":7,\"row\":7,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"16fa4470-2bfd-11e7-859b-f78b612cde28\",\"panelIndex\":8,\"row\":10,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"294546b0-30d6-11e7-8df8-6d3604a72912\",\"panelIndex\":9,\"row\":10,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"408fccf0-30d6-11e7-8df8-6d3604a72912\",\"panelIndex\":10,\"row\":1,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"58e644f0-30d6-11e7-8df8-6d3604a72912\",\"panelIndex\":11,\"row\":13,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"a4c9d360-30df-11e7-8df8-6d3604a72912\",\"panelIndex\":12,\"row\":13,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"174a6ad0-30e0-11e7-8df8-6d3604a72912\",\"panelIndex\":13,\"row\":4,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"7aac4fd0-30e0-11e7-8df8-6d3604a72912\",\"panelIndex\":14,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":3,\"id\":\"da1ff7c0-30ed-11e7-b9e5-2b5b07213ab3\",\"panelIndex\":15,\"row\":4,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"}]", + "timeRestore": false, + "title": "[Metricbeat Kubernetes] Overview", + "uiStateJSON": "{}", + "version": 1 + }, + "id": "AV4RGUqo5NkDleZmzKuZ", + "type": "dashboard", + "version": 3 + } + ], + "version": "5.6.0-SNAPSHOT" +} \ No newline at end of file diff --git a/metricbeat/module/kubernetes/_meta/kibana/default/dashboard/Metricbeat-kubernetes.json b/metricbeat/module/kubernetes/_meta/kibana/default/dashboard/Metricbeat-kubernetes.json deleted file mode 100644 index a4075dc2f57..00000000000 --- a/metricbeat/module/kubernetes/_meta/kibana/default/dashboard/Metricbeat-kubernetes.json +++ /dev/null @@ -1,200 +0,0 @@ -{ - "objects": [ - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Kubernetes - Available pods per deployment", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Kubernetes - Available pods per deployment\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"filter\":\"metricset.module:kubernetes AND metricset.name:state_deployment\",\"id\":\"117fadf0-30df-11e7-8df8-6d3604a72912\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"rgba(104,188,0,1)\",\"fill\":0.5,\"formatter\":\"number\",\"id\":\"64456840-30df-11e7-8df8-6d3604a72912\",\"label\":\"Available pods\",\"line_width\":1,\"metrics\":[{\"field\":\"kubernetes.deployment.replicas.available\",\"id\":\"64456841-30df-11e7-8df8-6d3604a72912\",\"type\":\"sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_filters\":[{\"color\":\"#68BC00\",\"id\":\"53d35ad0-30df-11e7-8df8-6d3604a72912\"}],\"split_mode\":\"terms\",\"stacked\":\"stacked\",\"terms_field\":\"kubernetes.deployment.name\",\"terms_size\":\"10000\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"timeseries\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "022a54c0-2bf5-11e7-859b-f78b612cde28", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Kubernetes - CPU usage by node", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Kubernetes - CPU usage by node\",\"type\":\"metrics\",\"params\":{\"id\":\"0d5c6b10-2bf2-11e7-859b-f78b612cde28\",\"type\":\"timeseries\",\"series\":[{\"id\":\"0d5c9220-2bf2-11e7-859b-f78b612cde28\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\",\"type\":\"sum\",\"field\":\"kubernetes.container.cpu.usage.nanocores\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"0.0a\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":\"0.5\",\"stacked\":\"none\",\"terms_field\":\"kubernetes.node.name\",\"terms_size\":\"10000\",\"terms_order_by\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\",\"value_template\":\"{{value}} nanocores\",\"override_index_pattern\":0,\"series_interval\":\"10s\",\"series_time_field\":\"@timestamp\"},{\"id\":\"22f65d40-31a7-11e7-84cc-096d2b38e6e5\",\"color\":\"rgba(211,49,21,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"22f65d41-31a7-11e7-84cc-096d2b38e6e5\",\"type\":\"avg\",\"field\":\"kubernetes.node.cpu.capacity.cores\"},{\"script\":\"params.cores * 1000000000\",\"id\":\"4af4c390-34d6-11e7-be88-cb6a123dc1bb\",\"type\":\"calculation\",\"variables\":[{\"id\":\"4cd32080-34d6-11e7-be88-cb6a123dc1bb\",\"name\":\"cores\",\"field\":\"22f65d41-31a7-11e7-84cc-096d2b38e6e5\"}]}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"0.0a\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"0\",\"stacked\":\"none\",\"terms_field\":\"kubernetes.node.name\",\"terms_size\":\"10000\",\"terms_order_by\":\"22f65d41-31a7-11e7-84cc-096d2b38e6e5\",\"value_template\":\"{{value}} nanocores\",\"hide_in_legend\":1,\"label\":\"\",\"override_index_pattern\":0,\"series_interval\":\"10s\",\"series_time_field\":\"@timestamp\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"12c1f2f0-2bf2-11e7-859b-f78b612cde28\"}],\"bar_color_rules\":[{\"id\":\"1373ddd0-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_color_rules\":[{\"id\":\"140e4910-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"filter\":\"metricset.module:kubernetes AND (metricset.name:container OR metricset.name:state_node)\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "44f12b40-2bf4-11e7-859b-f78b612cde28", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Kubernetes - Deployments", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Kubernetes - Deployments\",\"type\":\"metrics\",\"params\":{\"id\":\"4c4690b0-30e0-11e7-8df8-6d3604a72912\",\"type\":\"metric\",\"series\":[{\"id\":\"4c4690b1-30e0-11e7-8df8-6d3604a72912\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"4c4690b2-30e0-11e7-8df8-6d3604a72912\",\"type\":\"cardinality\",\"field\":\"kubernetes.deployment.name\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"kubernetes.deployment.name\",\"label\":\"Deployments\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"filter\":\"metricset.module:kubernetes AND metricset.name:state_deployment\",\"background_color_rules\":[{\"id\":\"67ee7da0-30e0-11e7-8df8-6d3604a72912\"}],\"bar_color_rules\":[{\"id\":\"68cdba10-30e0-11e7-8df8-6d3604a72912\"}],\"gauge_color_rules\":[{\"id\":\"69765620-30e0-11e7-8df8-6d3604a72912\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "cd059410-2bfb-11e7-859b-f78b612cde28", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Kubernetes - Desired pods", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Kubernetes - Desired pods\",\"type\":\"metrics\",\"params\":{\"id\":\"2fe9d3b0-30d5-11e7-8df8-6d3604a72912\",\"type\":\"metric\",\"series\":[{\"id\":\"2fe9d3b1-30d5-11e7-8df8-6d3604a72912\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"54cf79a0-30d5-11e7-8df8-6d3604a72912\",\"type\":\"sum\",\"field\":\"kubernetes.deployment.replicas.desired\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Desired Pods\",\"override_index_pattern\":1,\"series_time_field\":\"@timestamp\",\"series_interval\":\"10s\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"508ffb30-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_color_rules\":[{\"id\":\"50f9b980-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_width\":\"10\",\"gauge_inner_width\":\"10\",\"gauge_style\":\"half\",\"bar_color_rules\":[{\"id\":\"674d83b0-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_max\":\"5\",\"filter\":\"metricset.module:kubernetes AND metricset.name:state_deployment\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "e1018b90-2bfb-11e7-859b-f78b612cde28", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Kubernetes - Memory usage by node", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Kubernetes - Memory usage by node\",\"type\":\"metrics\",\"params\":{\"id\":\"0d5c6b10-2bf2-11e7-859b-f78b612cde28\",\"type\":\"timeseries\",\"series\":[{\"id\":\"0d5c9220-2bf2-11e7-859b-f78b612cde28\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\",\"type\":\"sum\",\"field\":\"kubernetes.container.memory.usage.bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"kubernetes.node.name\",\"terms_size\":\"10000\",\"terms_order_by\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\"},{\"id\":\"8ba3b270-31a7-11e7-84cc-096d2b38e6e5\",\"color\":\"rgba(211,49,21,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"8ba3b271-31a7-11e7-84cc-096d2b38e6e5\",\"type\":\"sum\",\"field\":\"kubernetes.node.memory.capacity.bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"0\",\"stacked\":\"none\",\"terms_field\":\"kubernetes.node.name\",\"terms_size\":\"10000\",\"terms_order_by\":\"8ba3b271-31a7-11e7-84cc-096d2b38e6e5\",\"hide_in_legend\":1,\"label\":\"Node capacity\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"12c1f2f0-2bf2-11e7-859b-f78b612cde28\"}],\"bar_color_rules\":[{\"id\":\"1373ddd0-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_color_rules\":[{\"id\":\"140e4910-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"filter\":\"metricset.module:kubernetes AND (metricset.name:container OR metricset.name:state_node)\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "d6564360-2bfc-11e7-859b-f78b612cde28", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Kubernetes - Network in by node", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Kubernetes - Network in by node\",\"type\":\"metrics\",\"params\":{\"id\":\"0d5c6b10-2bf2-11e7-859b-f78b612cde28\",\"type\":\"timeseries\",\"series\":[{\"id\":\"0d5c9220-2bf2-11e7-859b-f78b612cde28\",\"color\":\"rgba(104,188,0,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\",\"type\":\"sum\",\"field\":\"kubernetes.pod.network.rx.bytes\"},{\"unit\":\"\",\"id\":\"494fc310-2bf7-11e7-859b-f78b612cde28\",\"type\":\"derivative\",\"field\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\"},{\"unit\":\"\",\"id\":\"37c72a70-3598-11e7-aa4a-8313a0c92a88\",\"type\":\"positive_only\",\"field\":\"494fc310-2bf7-11e7-859b-f78b612cde28\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"stacked\",\"terms_field\":\"kubernetes.node.name\",\"terms_size\":\"100000\",\"terms_order_by\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\",\"label\":\"\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"12c1f2f0-2bf2-11e7-859b-f78b612cde28\"}],\"bar_color_rules\":[{\"id\":\"1373ddd0-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_color_rules\":[{\"id\":\"140e4910-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"filter\":\"metricset.module:kubernetes AND metricset.name:pod\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "16fa4470-2bfd-11e7-859b-f78b612cde28", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Kubernetes - Network out by node", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Kubernetes - Network out by node\",\"type\":\"metrics\",\"params\":{\"id\":\"0d5c6b10-2bf2-11e7-859b-f78b612cde28\",\"type\":\"timeseries\",\"series\":[{\"id\":\"0d5c9220-2bf2-11e7-859b-f78b612cde28\",\"color\":\"rgba(104,188,0,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\",\"type\":\"sum\",\"field\":\"kubernetes.pod.network.tx.bytes\"},{\"unit\":\"\",\"id\":\"494fc310-2bf7-11e7-859b-f78b612cde28\",\"type\":\"derivative\",\"field\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\"},{\"unit\":\"\",\"id\":\"244c70e0-3598-11e7-aa4a-8313a0c92a88\",\"type\":\"positive_only\",\"field\":\"494fc310-2bf7-11e7-859b-f78b612cde28\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"stacked\",\"terms_field\":\"kubernetes.node.name\",\"terms_size\":\"10000\",\"terms_order_by\":\"0d5c9221-2bf2-11e7-859b-f78b612cde28\",\"label\":\"\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"12c1f2f0-2bf2-11e7-859b-f78b612cde28\"}],\"bar_color_rules\":[{\"id\":\"1373ddd0-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_color_rules\":[{\"id\":\"140e4910-2bf2-11e7-859b-f78b612cde28\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"filter\":\"metricset.module:kubernetes AND metricset.name:pod\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "294546b0-30d6-11e7-8df8-6d3604a72912", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Kubernetes - Nodes", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Kubernetes - Nodes\",\"type\":\"metrics\",\"params\":{\"id\":\"4c4690b0-30e0-11e7-8df8-6d3604a72912\",\"type\":\"metric\",\"series\":[{\"id\":\"4c4690b1-30e0-11e7-8df8-6d3604a72912\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"4c4690b2-30e0-11e7-8df8-6d3604a72912\",\"type\":\"cardinality\",\"field\":\"kubernetes.node.name\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"kubernetes.deployment.name\",\"label\":\"Nodes\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"filter\":\"metricset.module:kubernetes AND metricset.name:state_node\",\"background_color_rules\":[{\"id\":\"67ee7da0-30e0-11e7-8df8-6d3604a72912\"}],\"bar_color_rules\":[{\"id\":\"68cdba10-30e0-11e7-8df8-6d3604a72912\"}],\"gauge_color_rules\":[{\"id\":\"69765620-30e0-11e7-8df8-6d3604a72912\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "408fccf0-30d6-11e7-8df8-6d3604a72912", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Kubernetes - Top CPU intensive pods", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Kubernetes - Top CPU intensive pods\",\"type\":\"metrics\",\"params\":{\"id\":\"5d3692a0-2bfc-11e7-859b-f78b612cde28\",\"type\":\"top_n\",\"series\":[{\"id\":\"5d3692a1-2bfc-11e7-859b-f78b612cde28\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"5d3692a2-2bfc-11e7-859b-f78b612cde28\",\"type\":\"sum\",\"field\":\"kubernetes.container.cpu.usage.core.ns\"},{\"unit\":\"1s\",\"id\":\"6c905240-2bfc-11e7-859b-f78b612cde28\",\"type\":\"derivative\",\"field\":\"5d3692a2-2bfc-11e7-859b-f78b612cde28\"},{\"unit\":\"\",\"id\":\"9a51f710-359d-11e7-aa4a-8313a0c92a88\",\"type\":\"positive_only\",\"field\":\"6c905240-2bfc-11e7-859b-f78b612cde28\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"0.0 a\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"kubernetes.pod.name\",\"terms_order_by\":\"5d3692a2-2bfc-11e7-859b-f78b612cde28\",\"value_template\":\"{{value}} ns\",\"offset_time\":\"\",\"override_index_pattern\":0}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"id\":\"802104d0-2bfc-11e7-859b-f78b612cde28\"}],\"filter\":\"metricset.module:kubernetes AND metricset.name:container\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "58e644f0-30d6-11e7-8df8-6d3604a72912", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Kubernetes - Top memory intensive pods", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Kubernetes - Top memory intensive pods\",\"type\":\"metrics\",\"params\":{\"id\":\"5d3692a0-2bfc-11e7-859b-f78b612cde28\",\"type\":\"top_n\",\"series\":[{\"id\":\"5d3692a1-2bfc-11e7-859b-f78b612cde28\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"5d3692a2-2bfc-11e7-859b-f78b612cde28\",\"type\":\"sum\",\"field\":\"kubernetes.container.memory.usage.bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"kubernetes.pod.name\",\"terms_order_by\":\"5d3692a2-2bfc-11e7-859b-f78b612cde28\",\"value_template\":\"\",\"offset_time\":\"\",\"override_index_pattern\":0,\"terms_size\":\"10\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"id\":\"802104d0-2bfc-11e7-859b-f78b612cde28\"}],\"filter\":\"metricset.module:kubernetes AND metricset.name:container\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "a4c9d360-30df-11e7-8df8-6d3604a72912", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Kubernetes - Unavailable pods", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Kubernetes - Unavailable pods\",\"type\":\"metrics\",\"params\":{\"id\":\"2fe9d3b0-30d5-11e7-8df8-6d3604a72912\",\"type\":\"metric\",\"series\":[{\"id\":\"2fe9d3b1-30d5-11e7-8df8-6d3604a72912\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"54cf79a0-30d5-11e7-8df8-6d3604a72912\",\"type\":\"sum\",\"field\":\"kubernetes.deployment.replicas.unavailable\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Unavailable Pods\",\"override_index_pattern\":1,\"series_interval\":\"10s\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"508ffb30-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_color_rules\":[{\"id\":\"50f9b980-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_width\":\"10\",\"gauge_inner_width\":\"10\",\"gauge_style\":\"half\",\"bar_color_rules\":[{\"id\":\"674d83b0-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_max\":\"\",\"filter\":\"metricset.module:kubernetes AND metricset.name:state_deployment\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "174a6ad0-30e0-11e7-8df8-6d3604a72912", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Kubernetes - Unavailable pods per deployment", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Kubernetes - Unavailable pods per deployment\",\"type\":\"metrics\",\"params\":{\"id\":\"117fadf0-30df-11e7-8df8-6d3604a72912\",\"type\":\"timeseries\",\"series\":[{\"id\":\"64456840-30df-11e7-8df8-6d3604a72912\",\"color\":\"rgba(254,146,0,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"64456841-30df-11e7-8df8-6d3604a72912\",\"type\":\"sum\",\"field\":\"kubernetes.deployment.replicas.unavailable\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"stacked\",\"split_filters\":[{\"color\":\"#68BC00\",\"id\":\"53d35ad0-30df-11e7-8df8-6d3604a72912\"}],\"terms_field\":\"kubernetes.deployment.name\",\"label\":\"Unavailable pods\",\"terms_size\":\"10000\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"filter\":\"metricset.module:kubernetes AND metricset.name:state_deployment\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "7aac4fd0-30e0-11e7-8df8-6d3604a72912", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Kubernetes - Available pods", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Kubernetes - Available pods\",\"type\":\"metrics\",\"params\":{\"id\":\"2fe9d3b0-30d5-11e7-8df8-6d3604a72912\",\"type\":\"metric\",\"series\":[{\"id\":\"2fe9d3b1-30d5-11e7-8df8-6d3604a72912\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"54cf79a0-30d5-11e7-8df8-6d3604a72912\",\"type\":\"sum\",\"field\":\"kubernetes.deployment.replicas.available\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Available Pods\",\"override_index_pattern\":1,\"series_time_field\":\"@timestamp\",\"series_index_pattern\":\"*\",\"series_interval\":\"10s\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"508ffb30-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_color_rules\":[{\"id\":\"50f9b980-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_width\":\"10\",\"gauge_inner_width\":\"10\",\"gauge_style\":\"half\",\"bar_color_rules\":[{\"id\":\"674d83b0-30d5-11e7-8df8-6d3604a72912\"}],\"gauge_max\":\"5\",\"filter\":\"metricset.module:kubernetes AND metricset.name:state_deployment\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "da1ff7c0-30ed-11e7-b9e5-2b5b07213ab3", - "type": "visualization", - "version": 1 - } - ], - "version": "6.0.0-alpha3-SNAPSHOT" -} \ No newline at end of file diff --git a/metricbeat/module/kubernetes/module.yml b/metricbeat/module/kubernetes/module.yml new file mode 100644 index 00000000000..5c79a2dc241 --- /dev/null +++ b/metricbeat/module/kubernetes/module.yml @@ -0,0 +1,3 @@ +dashboards: + - id: AV4RGUqo5NkDleZmzKuZ + file: Metricbeat-kubernetes-overview.json diff --git a/metricbeat/module/mongodb/_meta/kibana/default/dashboard/Metricbeat-mongodb-overview.json b/metricbeat/module/mongodb/_meta/kibana/default/dashboard/Metricbeat-mongodb-overview.json new file mode 100644 index 00000000000..4ab00466b52 --- /dev/null +++ b/metricbeat/module/mongodb/_meta/kibana/default/dashboard/Metricbeat-mongodb-overview.json @@ -0,0 +1,172 @@ +{ + "objects": [ + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "MongoDB-search", + "title": "Hosts [Metricbeat MongoDB]", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "version": 1, + "visState": "{\"title\":\"Hosts [Metricbeat MongoDB]\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.connections.current\",\"customLabel\":\"Number of connections\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"metricset.host\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.memory.bits\",\"customLabel\":\"Arch\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.memory.resident.mb\",\"customLabel\":\"Resident memory\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.memory.virtual.mb\",\"customLabel\":\"Virtual memory\"}}]}" + }, + "id": "MongoDB-hosts", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "MongoDB-search", + "title": "Engine \u0026 Version [Metricbeat MongoDB]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Engine \u0026 Version [Metricbeat MongoDB]\",\"type\":\"pie\",\"params\":{\"addLegend\":true,\"addTooltip\":true,\"isDonut\":true,\"legendPosition\":\"bottom\",\"shareYAxis\":true,\"type\":\"pie\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"metricset.host\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"mongodb.status.storage_engine.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Engine\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"mongodb.status.version\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Version\"}}]}" + }, + "id": "MongoDB-Engine-ampersand-Version", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "MongoDB-search", + "title": "Operation counters [Metricbeat MongoDB]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Operation counters [Metricbeat MongoDB]\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{},\"type\":\"area\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.opcounters.command\",\"customLabel\":\"command\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.opcounters.delete\",\"customLabel\":\"delete\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.opcounters.getmore\",\"customLabel\":\"getmore\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.opcounters.insert\",\"customLabel\":\"insert\"}},{\"id\":\"6\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.opcounters.query\",\"customLabel\":\"query\"}},{\"id\":\"7\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.opcounters_replicated.update\",\"customLabel\":\"update\"}}]}" + }, + "id": "MongoDB-operation-counters", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "MongoDB-search", + "title": "Concurrent transactions Read [Metricbeat MongoDB]", + "uiStateJSON": "{\"vis\":{\"colors\":{\"Read Available\":\"#508642\",\"Read Used\":\"#BF1B00\"}}}", + "version": 1, + "visState": "{\"title\":\"Concurrent transactions Read [Metricbeat MongoDB]\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{},\"type\":\"area\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.wired_tiger.concurrent_transactions.read.available\",\"customLabel\":\"Read Available\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.wired_tiger.concurrent_transactions.read.out\",\"customLabel\":\"Read Used\"}}]}" + }, + "id": "MongoDB-Concurrent-transactions-Read", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "MongoDB-search", + "title": "Concurrent transactions Write [Metricbeat MongoDB]", + "uiStateJSON": "{\"vis\":{\"colors\":{\"Write Available\":\"#629E51\",\"Write Used\":\"#BF1B00\"}}}", + "version": 1, + "visState": "{\"title\":\"Concurrent transactions Write [Metricbeat MongoDB]\",\"type\":\"area\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"interpolate\":\"linear\",\"legendPosition\":\"bottom\",\"mode\":\"stacked\",\"scale\":\"linear\",\"setYExtents\":false,\"shareYAxis\":true,\"smoothLines\":false,\"times\":[],\"yAxis\":{},\"type\":\"area\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.wired_tiger.concurrent_transactions.write.available\",\"customLabel\":\"Write Available\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.wired_tiger.concurrent_transactions.write.out\",\"customLabel\":\"Write Used\"}}]}" + }, + "id": "MongoDB-Concurrent-transactions-Write", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "MongoDB-search", + "title": "Memory stats [Metricbeat MongoDB]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Memory stats [Metricbeat MongoDB]\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"showCircles\":true,\"smoothLines\":false,\"interpolate\":\"linear\",\"scale\":\"log\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{},\"type\":\"line\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"line\",\"mode\":\"normal\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.memory.mapped.mb\",\"customLabel\":\"Mapped\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.memory.mapped_with_journal.mb\",\"customLabel\":\"Mapped with journal\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.memory.resident.mb\",\"customLabel\":\"Rezident\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.memory.virtual.mb\",\"customLabel\":\"Virtual\"}}]}" + }, + "id": "MongoDB-memory-stats", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "MongoDB-search", + "title": "Asserts [Metricbeat MongoDB]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Asserts [Metricbeat MongoDB]\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{},\"type\":\"area\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.asserts.msg\",\"customLabel\":\"message\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.asserts.regular\",\"customLabel\":\"regular\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.asserts.rollovers\",\"customLabel\":\"rollover\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.asserts.user\",\"customLabel\":\"user\"}},{\"id\":\"6\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.asserts.warning\",\"customLabel\":\"warning\"}}]}" + }, + "id": "MongoDB-asserts", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "MongoDB-search", + "title": "WiredTiger Cache [Metricbeat MongoDB]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"WiredTiger Cache [Metricbeat MongoDB]\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"overlap\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{},\"type\":\"area\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.wired_tiger.cache.maximum.bytes\",\"customLabel\":\"max\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.wired_tiger.cache.used.bytes\",\"customLabel\":\"used\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.wired_tiger.cache.dirty.bytes\",\"customLabel\":\"dirty\"}}]}" + }, + "id": "MongoDB-WiredTiger-Cache", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "columns": [ + "_source" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"metricset.module:mongodb\"}},\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647}}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "MongoDB search", + "version": 1 + }, + "id": "MongoDB-search", + "type": "search", + "version": 1 + }, + { + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"default_field\":\"*\",\"query\":\"*\"}}},\"highlightAll\":true,\"version\":true}" + }, + "optionsJSON": "{\"darkTheme\":false}", + "panelsJSON": "[{\"col\":1,\"id\":\"MongoDB-hosts\",\"panelIndex\":1,\"row\":1,\"size_x\":8,\"size_y\":3,\"type\":\"visualization\"},{\"col\":9,\"id\":\"MongoDB-Engine-ampersand-Version\",\"panelIndex\":4,\"row\":1,\"size_x\":4,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"MongoDB-operation-counters\",\"panelIndex\":2,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"MongoDB-Concurrent-transactions-Read\",\"panelIndex\":6,\"row\":4,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":10,\"id\":\"MongoDB-Concurrent-transactions-Write\",\"panelIndex\":7,\"row\":4,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"MongoDB-memory-stats\",\"panelIndex\":5,\"row\":10,\"size_x\":12,\"size_y\":4,\"type\":\"visualization\"},{\"col\":7,\"id\":\"MongoDB-asserts\",\"panelIndex\":3,\"row\":7,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"MongoDB-WiredTiger-Cache\",\"panelIndex\":8,\"row\":7,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"}]", + "timeRestore": false, + "title": "[Metricbeat MongoDB] Overview", + "uiStateJSON": "{\"P-1\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", + "version": 1 + }, + "id": "Metricbeat-MongoDB", + "type": "dashboard", + "version": 3 + } + ], + "version": "6.0.0-beta1-SNAPSHOT" +} \ No newline at end of file diff --git a/metricbeat/module/mongodb/_meta/kibana/default/dashboard/Metricbeat-mongodb.json b/metricbeat/module/mongodb/_meta/kibana/default/dashboard/Metricbeat-mongodb.json deleted file mode 100644 index 689e2068091..00000000000 --- a/metricbeat/module/mongodb/_meta/kibana/default/dashboard/Metricbeat-mongodb.json +++ /dev/null @@ -1,172 +0,0 @@ -{ - "objects": [ - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "MongoDB-search", - "title": "MongoDB hosts", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "version": 1, - "visState": "{\"title\":\"MongoDB hosts\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.connections.current\",\"customLabel\":\"Number of connections\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"metricset.host\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.memory.bits\",\"customLabel\":\"Arch\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.memory.resident.mb\",\"customLabel\":\"Resident memory\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.memory.virtual.mb\",\"customLabel\":\"Virtual memory\"}}],\"listeners\":{}}" - }, - "id": "MongoDB-hosts", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "MongoDB-search", - "title": "MongoDB Engine \u0026 Version", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"MongoDB Engine \u0026 Version\",\"type\":\"pie\",\"params\":{\"addLegend\":true,\"addTooltip\":true,\"isDonut\":true,\"legendPosition\":\"bottom\",\"shareYAxis\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"metricset.host\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"mongodb.status.storage_engine.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Engine\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"mongodb.status.version\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Version\"}}],\"listeners\":{}}" - }, - "id": "MongoDB-Engine-ampersand-Version", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "MongoDB-search", - "title": "MongoDB operation counters", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"MongoDB operation counters\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.opcounters.command\",\"customLabel\":\"command\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.opcounters.delete\",\"customLabel\":\"delete\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.opcounters.getmore\",\"customLabel\":\"getmore\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.opcounters.insert\",\"customLabel\":\"insert\"}},{\"id\":\"6\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.opcounters.query\",\"customLabel\":\"query\"}},{\"id\":\"7\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.opcounters_replicated.update\",\"customLabel\":\"update\"}}],\"listeners\":{}}" - }, - "id": "MongoDB-operation-counters", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "MongoDB-search", - "title": "MongoDB Concurrent transactions Read", - "uiStateJSON": "{\"vis\":{\"colors\":{\"Read Available\":\"#508642\",\"Read Used\":\"#BF1B00\"}}}", - "version": 1, - "visState": "{\"title\":\"MongoDB Concurrent transactions Read\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.wired_tiger.concurrent_transactions.read.available\",\"customLabel\":\"Read Available\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.wired_tiger.concurrent_transactions.read.out\",\"customLabel\":\"Read Used\"}}],\"listeners\":{}}" - }, - "id": "MongoDB-Concurrent-transactions-Read", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "MongoDB-search", - "title": "MongoDB Concurrent transactions Write", - "uiStateJSON": "{\"vis\":{\"colors\":{\"Write Available\":\"#629E51\",\"Write Used\":\"#BF1B00\"}}}", - "version": 1, - "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{\"customLabel\":\"Write Available\",\"field\":\"mongodb.status.wired_tiger.concurrent_transactions.write.available\"},\"schema\":\"metric\",\"type\":\"avg\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"customInterval\":\"2h\",\"extended_bounds\":{},\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1},\"schema\":\"segment\",\"type\":\"date_histogram\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"customLabel\":\"Write Used\",\"field\":\"mongodb.status.wired_tiger.concurrent_transactions.write.out\"},\"schema\":\"metric\",\"type\":\"avg\"}],\"listeners\":{},\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"interpolate\":\"linear\",\"legendPosition\":\"bottom\",\"mode\":\"stacked\",\"scale\":\"linear\",\"setYExtents\":false,\"shareYAxis\":true,\"smoothLines\":false,\"times\":[],\"yAxis\":{}},\"title\":\"MongoDB Concurrent transactions Write\",\"type\":\"area\"}" - }, - "id": "MongoDB-Concurrent-transactions-Write", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "MongoDB-search", - "title": "MongoDB memory stats", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"MongoDB memory stats\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"showCircles\":true,\"smoothLines\":false,\"interpolate\":\"linear\",\"scale\":\"log\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.memory.mapped.mb\",\"customLabel\":\"Mapped\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.memory.mapped_with_journal.mb\",\"customLabel\":\"Mapped with journal\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.memory.resident.mb\",\"customLabel\":\"Rezident\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.memory.virtual.mb\",\"customLabel\":\"Virtual\"}}],\"listeners\":{}}" - }, - "id": "MongoDB-memory-stats", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "MongoDB-search", - "title": "MongoDB asserts", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"MongoDB asserts\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.asserts.msg\",\"customLabel\":\"message\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.asserts.regular\",\"customLabel\":\"regular\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.asserts.rollovers\",\"customLabel\":\"rollover\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.asserts.user\",\"customLabel\":\"user\"}},{\"id\":\"6\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.asserts.warning\",\"customLabel\":\"warning\"}}],\"listeners\":{}}" - }, - "id": "MongoDB-asserts", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "MongoDB-search", - "title": "MongoDB WiredTiger Cache", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"MongoDB WiredTiger Cache\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"overlap\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.wired_tiger.cache.maximum.bytes\",\"customLabel\":\"max\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.wired_tiger.cache.used.bytes\",\"customLabel\":\"used\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mongodb.status.wired_tiger.cache.dirty.bytes\",\"customLabel\":\"dirty\"}}],\"listeners\":{}}" - }, - "id": "MongoDB-WiredTiger-Cache", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "columns": [ - "_source" - ], - "description": "", - "hits": 0, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"metricset.module:mongodb\"}},\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647}}" - }, - "sort": [ - "@timestamp", - "desc" - ], - "title": "MongoDB search", - "version": 1 - }, - "id": "MongoDB-search", - "type": "search", - "version": 8 - }, - { - "attributes": { - "description": "", - "hits": 0, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" - }, - "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"MongoDB-hosts\",\"panelIndex\":1,\"row\":1,\"size_x\":8,\"size_y\":3,\"type\":\"visualization\"},{\"col\":9,\"id\":\"MongoDB-Engine-ampersand-Version\",\"panelIndex\":4,\"row\":1,\"size_x\":4,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"MongoDB-operation-counters\",\"panelIndex\":2,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"MongoDB-Concurrent-transactions-Read\",\"panelIndex\":6,\"row\":4,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":10,\"id\":\"MongoDB-Concurrent-transactions-Write\",\"panelIndex\":7,\"row\":4,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"MongoDB-memory-stats\",\"panelIndex\":5,\"row\":10,\"size_x\":12,\"size_y\":4,\"type\":\"visualization\"},{\"col\":7,\"id\":\"MongoDB-asserts\",\"panelIndex\":3,\"row\":7,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"id\":\"MongoDB-WiredTiger-Cache\",\"type\":\"visualization\",\"panelIndex\":8,\"size_x\":6,\"size_y\":3,\"col\":1,\"row\":7}]", - "timeRestore": false, - "title": "Metricbeat MongoDB", - "uiStateJSON": "{\"P-1\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", - "version": 1 - }, - "id": "Metricbeat-MongoDB", - "type": "dashboard", - "version": 1 - } - ], - "version": "6.0.0-alpha3-SNAPSHOT" -} \ No newline at end of file diff --git a/metricbeat/module/mongodb/module.yml b/metricbeat/module/mongodb/module.yml new file mode 100644 index 00000000000..3a523a410e2 --- /dev/null +++ b/metricbeat/module/mongodb/module.yml @@ -0,0 +1,3 @@ +dashboards: + - id: Metricbeat-MongoDB + file: Metricbeat-mongodb-overview.json diff --git a/metricbeat/module/mysql/_meta/kibana/default/dashboard/Metricbeat-mysql-overview.json b/metricbeat/module/mysql/_meta/kibana/default/dashboard/Metricbeat-mysql-overview.json new file mode 100644 index 00000000000..f522a673cac --- /dev/null +++ b/metricbeat/module/mysql/_meta/kibana/default/dashboard/Metricbeat-mysql-overview.json @@ -0,0 +1,152 @@ +{ + "objects": [ + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "67e88e60-0005-11e7-aaf1-b342e4b94bb0", + "title": "Active connections [Metricbeat MySQL]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Active connections [Metricbeat MySQL]\",\"type\":\"line\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"showCircles\":true,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"type\":\"line\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"line\",\"mode\":\"normal\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mysql.status.connections\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}]}" + }, + "id": "e784dc50-0005-11e7-bf7f-c9acc3d3e306", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "67e88e60-0005-11e7-aaf1-b342e4b94bb0", + "title": "Files opened [Metricbeat MySQL]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Files opened [Metricbeat MySQL]\",\"type\":\"line\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"showCircles\":true,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"type\":\"line\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"line\",\"mode\":\"normal\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mysql.status.open.files\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}]}" + }, + "id": "0f506420-0006-11e7-bf7f-c9acc3d3e306", + "type": "visualization", + "version": 4 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "67e88e60-0005-11e7-aaf1-b342e4b94bb0", + "title": "Running threads [Metricbeat MySQL]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Running threads [Metricbeat MySQL]\",\"type\":\"line\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"showCircles\":true,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"type\":\"line\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"line\",\"mode\":\"normal\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mysql.status.threads.running\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}]}" + }, + "id": "45a00c10-0006-11e7-bf7f-c9acc3d3e306", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" + }, + "title": "MySQL commands [Metricbeat MySQL]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"MySQL commands [Metricbeat MySQL]\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(*, metric='avg:mysql.status.command.select').derivative().label(\\\"SELECT\\\"),.es(*, metric='avg:mysql.status.command.insert').derivative().label(\\\"INSERT\\\"),.es(*, metric='avg:mysql.status.command.update').derivative().label(\\\"UPDATE\\\"),.es(*, metric='avg:mysql.status.command.delete').derivative().label(\\\"DELETE\\\")\",\"interval\":\"1m\"},\"aggs\":[]}" + }, + "id": "1eda2280-0008-11e7-82f3-2f380154876c", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" + }, + "title": "Threads created [Metricbeat MySQL]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Threads created [Metricbeat MySQL]\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(*, metric='avg:mysql.status.threads.created').derivative().label(\\\"Threads created\\\")\",\"interval\":\"1m\"},\"aggs\":[]}" + }, + "id": "1ede99e0-0009-11e7-8cd4-73b67e9e3f3c", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" + }, + "title": "Tables opened [Metricbeat MySQL]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Tables opened [Metricbeat MySQL]\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(*, metric='avg:mysql.status.opened_tables').derivative().label(\\\"Opened tables\\\")\",\"interval\":\"1m\"},\"aggs\":[]}" + }, + "id": "4c36c420-000a-11e7-8cd4-73b67e9e3f3c", + "type": "visualization", + "version": 4 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" + }, + "title": "Sent and received bytes [Metricbeat MySQL]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"Sent and received bytes [Metricbeat MySQL]\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(*,metric=\\\"avg:mysql.status.bytes.sent\\\").derivative().divide(1000).label(\\\"Sent bytes (KB)\\\"),.es(*,metric=\\\"avg:mysql.status.bytes.received\\\").derivative().multiply(-1).divide(1000).label(\\\"Received bytes (KB)\\\")\",\"interval\":\"1m\"},\"aggs\":[]}" + }, + "id": "a2175300-000a-11e7-b001-85aac4878445", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "columns": [ + "_source" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"highlightAll\":true,\"query\":{\"query_string\":{\"query\":\"_exists_:mysql.status\",\"analyze_wildcard\":true}},\"filter\":[]}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "Metricbeat MySQL status", + "version": 1 + }, + "id": "67e88e60-0005-11e7-aaf1-b342e4b94bb0", + "type": "search", + "version": 1 + }, + { + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"default_field\":\"*\",\"query\":\"*\"}}},\"highlightAll\":true,\"version\":true}" + }, + "optionsJSON": "{\"darkTheme\":false}", + "panelsJSON": "[{\"col\":1,\"id\":\"e784dc50-0005-11e7-bf7f-c9acc3d3e306\",\"panelIndex\":1,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"0f506420-0006-11e7-bf7f-c9acc3d3e306\",\"panelIndex\":2,\"row\":7,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"45a00c10-0006-11e7-bf7f-c9acc3d3e306\",\"panelIndex\":4,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"1eda2280-0008-11e7-82f3-2f380154876c\",\"panelIndex\":5,\"row\":1,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"1ede99e0-0009-11e7-8cd4-73b67e9e3f3c\",\"panelIndex\":7,\"row\":10,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"4c36c420-000a-11e7-8cd4-73b67e9e3f3c\",\"panelIndex\":8,\"row\":7,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"a2175300-000a-11e7-b001-85aac4878445\",\"panelIndex\":9,\"row\":10,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"}]", + "timeRestore": false, + "title": "[Metricbeat MySQL] Overview", + "uiStateJSON": "{}", + "version": 1 + }, + "id": "66881e90-0006-11e7-bf7f-c9acc3d3e306", + "type": "dashboard", + "version": 3 + } + ], + "version": "6.0.0-beta1-SNAPSHOT" +} \ No newline at end of file diff --git a/metricbeat/module/mysql/_meta/kibana/default/dashboard/Metricbeat-mysql.json b/metricbeat/module/mysql/_meta/kibana/default/dashboard/Metricbeat-mysql.json deleted file mode 100644 index 8337da99a26..00000000000 --- a/metricbeat/module/mysql/_meta/kibana/default/dashboard/Metricbeat-mysql.json +++ /dev/null @@ -1,168 +0,0 @@ -{ - "objects": [ - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "67e88e60-0005-11e7-aaf1-b342e4b94bb0", - "title": "MySQL active connections", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"MySQL active connections\",\"type\":\"line\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"showCircles\":true,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mysql.status.connections\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" - }, - "id": "e784dc50-0005-11e7-bf7f-c9acc3d3e306", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "67e88e60-0005-11e7-aaf1-b342e4b94bb0", - "title": "MySQL open files", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"MySQL open files\",\"type\":\"line\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"showCircles\":true,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mysql.status.open.files\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" - }, - "id": "0f506420-0006-11e7-bf7f-c9acc3d3e306", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "67e88e60-0005-11e7-aaf1-b342e4b94bb0", - "title": "MySQL open tables", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"MySQL open tables\",\"type\":\"line\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"showCircles\":true,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mysql.status.open.files\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" - }, - "id": "1a99f2b0-0006-11e7-bf7f-c9acc3d3e306", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "67e88e60-0005-11e7-aaf1-b342e4b94bb0", - "title": "MySQL running threads", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"MySQL running threads\",\"type\":\"line\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"bottom\",\"showCircles\":true,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"mysql.status.threads.running\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" - }, - "id": "45a00c10-0006-11e7-bf7f-c9acc3d3e306", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "MySQL commands", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"MySQL commands\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(*, metric='avg:mysql.status.command.select').derivative().label(\\\"SELECT\\\"),.es(*, metric='avg:mysql.status.command.insert').derivative().label(\\\"INSERT\\\"),.es(*, metric='avg:mysql.status.command.update').derivative().label(\\\"UPDATE\\\"),.es(*, metric='avg:mysql.status.command.delete').derivative().label(\\\"DELETE\\\")\",\"interval\":\"1m\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "1eda2280-0008-11e7-82f3-2f380154876c", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "MySQL threads created", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"MySQL threads created\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(*, metric='avg:mysql.status.threads.created').derivative().label(\\\"Threads created\\\")\",\"interval\":\"1m\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "1ede99e0-0009-11e7-8cd4-73b67e9e3f3c", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "MySQL table opens", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"aggs\":[],\"listeners\":{},\"params\":{\"expression\":\".es(*, metric='avg:mysql.status.opened_tables').derivative().label(\\\"Opened tables\\\")\",\"interval\":\"1m\"},\"title\":\"MySQL table opens\",\"type\":\"timelion\"}" - }, - "id": "4c36c420-000a-11e7-8cd4-73b67e9e3f3c", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Mysql sent and received bytes", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Mysql sent and received bytes\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(*,metric=\\\"avg:mysql.status.bytes.sent\\\").derivative().divide(1000).label(\\\"Sent bytes (KB)\\\"),.es(*,metric=\\\"avg:mysql.status.bytes.received\\\").derivative().multiply(-1).divide(1000).label(\\\"Received bytes (KB)\\\")\",\"interval\":\"1m\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "a2175300-000a-11e7-b001-85aac4878445", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "columns": [ - "_source" - ], - "description": "", - "hits": 0, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"highlightAll\":true,\"query\":{\"query_string\":{\"query\":\"_exists_:mysql.status\",\"analyze_wildcard\":true}},\"filter\":[]}" - }, - "sort": [ - "@timestamp", - "desc" - ], - "title": "Metricbeat MySQL status", - "version": 1 - }, - "id": "67e88e60-0005-11e7-aaf1-b342e4b94bb0", - "type": "search", - "version": 4 - }, - { - "attributes": { - "description": "", - "hits": 0, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" - }, - "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"e784dc50-0005-11e7-bf7f-c9acc3d3e306\",\"panelIndex\":1,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"0f506420-0006-11e7-bf7f-c9acc3d3e306\",\"panelIndex\":2,\"row\":7,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"1a99f2b0-0006-11e7-bf7f-c9acc3d3e306\",\"panelIndex\":3,\"row\":10,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"45a00c10-0006-11e7-bf7f-c9acc3d3e306\",\"panelIndex\":4,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"1eda2280-0008-11e7-82f3-2f380154876c\",\"panelIndex\":5,\"row\":1,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"1ede99e0-0009-11e7-8cd4-73b67e9e3f3c\",\"panelIndex\":7,\"row\":10,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"4c36c420-000a-11e7-8cd4-73b67e9e3f3c\",\"panelIndex\":8,\"row\":7,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"size_x\":12,\"size_y\":3,\"panelIndex\":9,\"type\":\"visualization\",\"id\":\"a2175300-000a-11e7-b001-85aac4878445\",\"col\":1,\"row\":13}]", - "timeRestore": false, - "title": "Metricbeat MySQL", - "uiStateJSON": "{}", - "version": 1 - }, - "id": "66881e90-0006-11e7-bf7f-c9acc3d3e306", - "type": "dashboard", - "version": 1 - } - ], - "version": "6.0.0-alpha3-SNAPSHOT" -} diff --git a/metricbeat/module/mysql/module.yml b/metricbeat/module/mysql/module.yml new file mode 100644 index 00000000000..ea9854af761 --- /dev/null +++ b/metricbeat/module/mysql/module.yml @@ -0,0 +1,3 @@ +dashboards: + - id: 66881e90-0006-11e7-bf7f-c9acc3d3e306 + file: Metricbeat-mysql-overview.json diff --git a/metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-rabbitmq-overview.json b/metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-rabbitmq-overview.json new file mode 100644 index 00000000000..54942d2768b --- /dev/null +++ b/metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-rabbitmq-overview.json @@ -0,0 +1,107 @@ +{ + "objects": [ + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "Metricbeat-Rabbitmq", + "title": "RabbitMQ Memory Usage", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"RabbitMQ Memory Usage\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"showCircles\":false,\"smoothLines\":true,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":true,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.mem.used.bytes\",\"json\":\"\",\"customLabel\":\"Used memory\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"rabbitmq.node.name.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Node name\"}}],\"listeners\":{}}" + }, + "col": 1, + "id": "RabbitMQ-Memory-Usage", + "panelIndex": 8, + "row": 1, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 3 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\n \"filter\": []\n}" + }, + "savedSearchId": "Metricbeat-Rabbitmq", + "title": "RabbitMQ Number of Nodes", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\n \"title\": \"Rabbitmq-Number-of-Nodes\",\n \"type\": \"metric\",\n \"params\": {\n \"handleNoResults\": true,\n \"fontSize\": 60\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"rabbitmq.node.name.keyword\",\n \"customLabel\": \"RabbitMQ Nodes\"\n }\n }\n ],\n \"listeners\": {}\n}" + }, + "col": 8, + "id": "Rabbitmq-Number-of-Nodes", + "panelIndex": 2, + "row": 1, + "size_x": 3, + "size_y": 3, + "type": "visualization", + "version": 4 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "Metricbeat-Rabbitmq", + "title": "RabbitMQ Erlang Process Usage", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"RabbitMQ Erlang Process Usage\",\"type\":\"line\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"legendPosition\":\"top\",\"radiusRatio\":9,\"scale\":\"linear\",\"setYExtents\":false,\"shareYAxis\":true,\"showCircles\":false,\"smoothLines\":true,\"times\":[],\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.proc.used\",\"customLabel\":\"Used Process\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"rabbitmq.node.name.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Node name\"}}],\"listeners\":{}}" + }, + "col": 1, + "id": "RabbitMQ-Erlang-Process-Usage", + "panelIndex": 10, + "row": 4, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 3 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "Metricbeat-Rabbitmq", + "title": "RabbitMQ Queue Index Operations", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"RabbitMQ Queue Index Operations\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"showCircles\":false,\"smoothLines\":false,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.read.count\",\"customLabel\":\"Queue Index Read\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.journal_write.count\",\"customLabel\":\"Queue Index Jornal Write\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.write.count\",\"customLabel\":\"Queue Index Write\"}}],\"listeners\":{}}" + }, + "col": 7, + "id": "RabbitMQ-Queue-Index-Operations", + "panelIndex": 9, + "row": 4, + "size_x": 6, + "size_y": 3, + "type": "visualization", + "version": 3 + }, + { + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:rabbitmq\",\"analyze_wildcard\":true}}}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "Metricbeat-Rabbitmq", + "version": 1 + }, + "id": "Metricbeat-Rabbitmq", + "type": "search", + "version": 8 + } + ], + "version": "5.6.0-SNAPSHOT" +} \ No newline at end of file diff --git a/metricbeat/module/rabbitmq/module.yml b/metricbeat/module/rabbitmq/module.yml new file mode 100644 index 00000000000..583b99796bf --- /dev/null +++ b/metricbeat/module/rabbitmq/module.yml @@ -0,0 +1,3 @@ +dashboards: + - id: Metricbeat-Rabbitmq + file: Metricbeat-rabbitmq-overview.json diff --git a/metricbeat/module/redis/_meta/kibana/default/dashboard/Metricbeat-mysql-overview.json b/metricbeat/module/redis/_meta/kibana/default/dashboard/Metricbeat-mysql-overview.json new file mode 100644 index 00000000000..371cde2c5ce --- /dev/null +++ b/metricbeat/module/redis/_meta/kibana/default/dashboard/Metricbeat-mysql-overview.json @@ -0,0 +1,173 @@ +{ + "objects": [ + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "Metricbeat-Redis", + "title": "Clients Metrics [Metricbeat Redis]", + "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}", + "version": 1, + "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{\"customLabel\":\"Connected clients\",\"field\":\"redis.info.clients.connected\"},\"schema\":\"metric\",\"type\":\"max\"}],\"listeners\":{},\"params\":{\"addLegend\":false,\"addTooltip\":true,\"fontSize\":60,\"gauge\":{\"autoExtend\":false,\"backStyle\":\"Full\",\"colorSchema\":\"Green to Red\",\"colorsRange\":[{\"from\":0,\"to\":100}],\"gaugeColorMode\":\"None\",\"gaugeStyle\":\"Full\",\"gaugeType\":\"Metric\",\"invertColors\":false,\"labels\":{\"color\":\"black\",\"show\":true},\"orientation\":\"vertical\",\"percentageMode\":false,\"scale\":{\"color\":\"#333\",\"labels\":false,\"show\":false,\"width\":2},\"style\":{\"bgColor\":false,\"fontSize\":60,\"labelColor\":false,\"subText\":\"\"},\"type\":\"simple\",\"useRange\":false,\"verticalSplit\":false},\"handleNoResults\":true,\"type\":\"gauge\"},\"title\":\"Clients Metrics [Metricbeat Redis]\",\"type\":\"metric\"}" + }, + "col": 1, + "id": "Redis-Clients-Metrics", + "panelIndex": 2, + "row": 1, + "size_x": 3, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "Metricbeat-Redis", + "title": "Connected clients [Metricbeat Redis]", + "uiStateJSON": "{\"vis\":{\"colors\":{\"Blocked\":\"#C15C17\"}}}", + "version": 1, + "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{\"customLabel\":\"Connected\",\"field\":\"redis.info.clients.connected\"},\"schema\":\"metric\",\"type\":\"max\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"customInterval\":\"2h\",\"extended_bounds\":{},\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1},\"schema\":\"segment\",\"type\":\"date_histogram\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"customLabel\":\"Blocked\",\"field\":\"redis.info.clients.blocked\"},\"schema\":\"metric\",\"type\":\"max\"}],\"listeners\":{},\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{},\"type\":\"category\"}],\"defaultYExtents\":false,\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"legendPosition\":\"right\",\"mode\":\"grouped\",\"scale\":\"linear\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"mode\":\"stacked\",\"show\":\"true\",\"showCircles\":true,\"type\":\"histogram\",\"valueAxis\":\"ValueAxis-1\"}],\"setYExtents\":false,\"shareYAxis\":true,\"times\":[],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Count\"},\"type\":\"value\"}],\"yAxis\":{}},\"title\":\"Connected clients [Metricbeat Redis]\",\"type\":\"histogram\"}" + }, + "col": 4, + "id": "Redis-Connected-clients", + "panelIndex": 1, + "row": 1, + "size_x": 5, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\n \"filter\": []\n}" + }, + "savedSearchId": "Metricbeat-Redis", + "title": "Hosts [Metricbeat Redis]", + "uiStateJSON": "{\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n}", + "version": 1, + "visState": "{\n \"title\": \"Redis hosts\",\n \"type\": \"table\",\n \"params\": {\n \"perPage\": 10,\n \"showPartialRows\": false,\n \"showMeticsAtAllLevels\": false,\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n },\n \"showTotal\": false,\n \"totalFunc\": \"sum\"\n },\n \"aggs\": [\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"metricset.host\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"redis.info.server.uptime\",\n \"customLabel\": \"Uptime (s)\"\n }\n },\n {\n \"id\": \"6\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"redis.info.server.process_id\",\n \"customLabel\": \"PID\"\n }\n },\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"redis.info.memory.used.peak\",\n \"customLabel\": \"Memory\"\n }\n },\n {\n \"id\": \"4\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"redis.info.cpu.used.user\",\n \"customLabel\": \"CPU used (user)\"\n }\n },\n {\n \"id\": \"5\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"redis.info.cpu.used.sys\",\n \"customLabel\": \"CPU used (system)\"\n }\n }\n ],\n \"listeners\": {}\n}" + }, + "col": 1, + "id": "Redis-hosts", + "panelIndex": 3, + "row": 4, + "size_x": 12, + "size_y": 2, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\n \"filter\": []\n}" + }, + "savedSearchId": "Metricbeat-Redis", + "title": "Server Versions [Metricbeat Redis]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\n \"title\": \"Redis Server Versions\",\n \"type\": \"pie\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"isDonut\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"metricset.host\",\n \"customLabel\": \"Hosts\"\n }\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"redis.info.server.version\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Multiplexing API\"\n }\n }\n ],\n \"listeners\": {}\n}" + }, + "col": 1, + "id": "Redis-Server-Versions", + "panelIndex": 4, + "row": 6, + "size_x": 4, + "size_y": 2, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\n \"filter\": []\n}" + }, + "savedSearchId": "Metricbeat-Redis", + "title": "Server mode [Metricbeat Redis]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\n \"title\": \"Redis server mode\",\n \"type\": \"pie\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"isDonut\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"metricset.host\",\n \"customLabel\": \"Hosts\"\n }\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"redis.info.server.mode\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Server mode\"\n }\n }\n ],\n \"listeners\": {}\n}" + }, + "col": 5, + "id": "Redis-server-mode", + "panelIndex": 5, + "row": 6, + "size_x": 4, + "size_y": 2, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\n \"filter\": []\n}" + }, + "savedSearchId": "Metricbeat-Redis", + "title": "Multiplexing API [Metricbeat Redis]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\n \"title\": \"Redis multiplexing API\",\n \"type\": \"pie\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"isDonut\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"metricset.host\",\n \"customLabel\": \"Hosts\"\n }\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"redis.info.server.multiplexing_api\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Multiplexing API\"\n }\n }\n ],\n \"listeners\": {}\n}" + }, + "col": 9, + "id": "Redis-multiplexing-API", + "panelIndex": 6, + "row": 6, + "size_x": 3, + "size_y": 2, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + }, + "savedSearchId": "Metricbeat-Redis", + "title": "Keyspaces [Metricbeat Redis]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{\"customLabel\":\"Number of keys\",\"field\":\"redis.keyspace.keys\"},\"schema\":\"metric\",\"type\":\"avg\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"customInterval\":\"2h\",\"extended_bounds\":{},\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1},\"schema\":\"segment\",\"type\":\"date_histogram\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"customLabel\":\"Keyspaces\",\"field\":\"redis.keyspace.id\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":5},\"schema\":\"group\",\"type\":\"terms\"}],\"listeners\":{},\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{},\"type\":\"category\"}],\"defaultYExtents\":false,\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"interpolate\":\"linear\",\"legendPosition\":\"right\",\"mode\":\"stacked\",\"scale\":\"linear\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"mode\":\"stacked\",\"show\":\"true\",\"showCircles\":true,\"type\":\"area\",\"valueAxis\":\"ValueAxis-1\"}],\"setYExtents\":false,\"shareYAxis\":true,\"smoothLines\":false,\"times\":[],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Count\"},\"type\":\"value\"}],\"yAxis\":{}},\"title\":\"Keyspaces [Metricbeat Redis]\",\"type\":\"area\"}" + }, + "col": 9, + "id": "Redis-Keyspaces", + "panelIndex": 7, + "row": 1, + "size_x": 4, + "size_y": 3, + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "columns": [ + "_source" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:redis\",\"analyze_wildcard\":true}}}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "Metricbeat Redis", + "version": 1 + }, + "id": "Metricbeat-Redis", + "type": "search", + "version": 7 + } + ], + "version": "5.6.0-SNAPSHOT" +} \ No newline at end of file diff --git a/metricbeat/module/redis/_meta/kibana/default/dashboard/Metricbeat-redis.json b/metricbeat/module/redis/_meta/kibana/default/dashboard/Metricbeat-redis.json deleted file mode 100644 index 5511a3ecac3..00000000000 --- a/metricbeat/module/redis/_meta/kibana/default/dashboard/Metricbeat-redis.json +++ /dev/null @@ -1,138 +0,0 @@ -{ - "objects": [ - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "Metricbeat-Redis", - "title": "Redis Clients Metrics", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Redis Clients Metrics\",\"type\":\"metric\",\"params\":{\"handleNoResults\":true,\"fontSize\":60},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.info.clients.connected\",\"customLabel\":\"Connected clients\"}}],\"listeners\":{}}" - }, - "id": "Redis-Clients-Metrics", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "Metricbeat-Redis", - "title": "Redis Connected clients", - "uiStateJSON": "{\"vis\":{\"colors\":{\"Blocked\":\"#C15C17\"}}}", - "version": 1, - "visState": "{\"title\":\"Redis Connected clients\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"grouped\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.info.clients.connected\",\"customLabel\":\"Connected\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.info.clients.blocked\",\"customLabel\":\"Blocked\"}}],\"listeners\":{}}" - }, - "id": "Redis-Connected-clients", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "Metricbeat-Redis", - "title": "Redis hosts", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "version": 1, - "visState": "{\"title\":\"Redis hosts\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"metricset.host\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.info.server.uptime\",\"customLabel\":\"Uptime (s)\"}},{\"id\":\"6\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.info.server.process_id\",\"customLabel\":\"PID\"}},{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.info.memory.used.peak\",\"customLabel\":\"Memory\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.info.cpu.used.user\",\"customLabel\":\"CPU used (user)\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.info.cpu.used.sys\",\"customLabel\":\"CPU used (system)\"}}],\"listeners\":{}}" - }, - "id": "Redis-hosts", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "Metricbeat-Redis", - "title": "Redis Server Versions", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Redis Server Versions\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"metricset.host\",\"customLabel\":\"Hosts\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"redis.info.server.version\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Multiplexing API\"}}],\"listeners\":{}}" - }, - "id": "Redis-Server-Versions", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "Metricbeat-Redis", - "title": "Redis server mode", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Redis server mode\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"metricset.host\",\"customLabel\":\"Hosts\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"redis.info.server.mode\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Server mode\"}}],\"listeners\":{}}" - }, - "id": "Redis-server-mode", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "Metricbeat-Redis", - "title": "Redis multiplexing API", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Redis multiplexing API\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"metricset.host\",\"customLabel\":\"Hosts\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"redis.info.server.multiplexing_api\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Multiplexing API\"}}],\"listeners\":{}}" - }, - "id": "Redis-multiplexing-API", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "Metricbeat-Redis", - "title": "Redis Keyspaces", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Redis Keyspaces\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.keyspace.keys\",\"customLabel\":\"Number of keys\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"redis.keyspace.id\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Keyspaces\"}}],\"listeners\":{}}" - }, - "id": "Redis-Keyspaces", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "columns": [ - "_source" - ], - "description": "", - "hits": 0, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:redis\",\"analyze_wildcard\":true}}}" - }, - "sort": [ - "@timestamp", - "desc" - ], - "title": "Metricbeat Redis", - "version": 1 - }, - "id": "Metricbeat-Redis", - "type": "search", - "version": 7 - } - ], - "version": "6.0.0-alpha3-SNAPSHOT" -} \ No newline at end of file diff --git a/metricbeat/module/redis/module.yml b/metricbeat/module/redis/module.yml new file mode 100644 index 00000000000..24c7b0ba045 --- /dev/null +++ b/metricbeat/module/redis/module.yml @@ -0,0 +1,3 @@ +dashboards: + - id: Metricbeat-Redis + file: Metricbeat-redis-overview.json diff --git a/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-containers-overview.json b/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-containers-overview.json new file mode 100644 index 00000000000..4366bb67ef2 --- /dev/null +++ b/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-containers-overview.json @@ -0,0 +1,83 @@ +{ + "objects": [ + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true,\"default_field\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" + }, + "title": "Container CPU usage [Metricbeat System]", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "version": 1, + "visState": "{\"title\":\"Container CPU usage [Metricbeat System]\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.cpuacct.stats.user.ns\",\"customLabel\":\"CPU user\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.cpu.cfs.quota.us\",\"customLabel\":\"CPU quota\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.process.cgroup.id\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Container ID\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.cpu.stats.throttled.ns\",\"customLabel\":\"CPU throttling\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.cpuacct.stats.system.ns\",\"customLabel\":\"CPU kernel\"}},{\"id\":\"6\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.process.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Process name\"}}]}" + }, + "id": "Container-CPU-usage", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" + }, + "title": "System Navigation [Metricbeat System]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"System Navigation [Metricbeat System]\",\"type\":\"markdown\",\"params\":{\"markdown\":\"[System Overview](#/dashboard/Metricbeat-system-overview) | [Host Overview](#/dashboard/79ffd6e0-faa0-11e6-947f-177f697178b8) |\\n[Containers overview](#/dashboard/CPU-slash-Memory-per-container)\",\"fontSize\":12},\"aggs\":[]}" + }, + "id": "System-Navigation", + "type": "visualization", + "version": 6 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true,\"default_field\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" + }, + "title": "Container Memory stats [Metricbeat System]", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "version": 1, + "visState": "{\"title\":\"Container Memory stats [Metricbeat System]\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"13\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.mem.usage.bytes\",\"customLabel\":\"Usage\"}},{\"id\":\"14\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.mem.usage.max.bytes\",\"customLabel\":\"Max usage\"}},{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.page_faults\",\"customLabel\":\"Page faults\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.pages_in\",\"customLabel\":\"Pages in memory\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.pages_out\",\"customLabel\":\"Pages out of memory\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.process.cgroup.id\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Container ID\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.inactive_file.bytes\",\"customLabel\":\"Inactive files\"}},{\"id\":\"6\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.major_page_faults\",\"customLabel\":\"# Major page faults\"}},{\"id\":\"8\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.process.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Process name\"}},{\"id\":\"12\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.mem.failures\",\"customLabel\":\"Failures\"}},{\"id\":\"10\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.kmem_tcp.usage.bytes\",\"customLabel\":\"TCP buffers\"}},{\"id\":\"11\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.rss_huge.bytes\",\"customLabel\":\"Huge pages\"}},{\"id\":\"7\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.rss.bytes\",\"customLabel\":\"Swap caches\"}},{\"id\":\"15\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.swap.bytes\",\"customLabel\":\"Swap usage\"}},{\"id\":\"16\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.blkio.total.ios\",\"customLabel\":\"Block I/O\"}}]}" + }, + "id": "Container-Memory-stats", + "type": "visualization", + "version": 2 + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\",\"default_field\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" + }, + "title": "Container Block IO [Metricbeat System]", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "version": 1, + "visState": "{\"title\":\"Container Block IO [Metricbeat System]\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.blkio.total.bytes\",\"customLabel\":\"Total\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.blkio.total.ios\",\"customLabel\":\"I/O\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.process.cgroup.id\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Container ID\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.process.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Process name\"}}]}" + }, + "id": "Container-Block-IO", + "type": "visualization", + "version": 3 + }, + { + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"default_field\":\"*\",\"query\":\"*\"}}}}" + }, + "optionsJSON": "{\"darkTheme\":false}", + "panelsJSON": "[{\"col\":1,\"id\":\"Container-CPU-usage\",\"panelIndex\":2,\"row\":2,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"System-Navigation\",\"panelIndex\":3,\"row\":1,\"size_x\":12,\"size_y\":1,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Container-Memory-stats\",\"panelIndex\":4,\"row\":5,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Container-Block-IO\",\"panelIndex\":5,\"row\":8,\"size_x\":12,\"size_y\":4,\"type\":\"visualization\"}]", + "timeRestore": false, + "title": "[Metricbeat System] Containers overview", + "uiStateJSON": "{\"P-2\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-4\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-5\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", + "version": 1 + }, + "id": "CPU-slash-Memory-per-container", + "type": "dashboard", + "version": 4 + } + ], + "version": "6.0.0-beta1-SNAPSHOT" +} \ No newline at end of file diff --git a/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-docker-overview.json b/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-docker-overview.json deleted file mode 100644 index 5dcfb8809c0..00000000000 --- a/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-docker-overview.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "objects": [ - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - }, - "title": "Container CPU usage", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "version": 1, - "visState": "{\"title\":\"Container CPU usage\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.cpuacct.stats.user.ns\",\"customLabel\":\"CPU user\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.cpu.cfs.quota.us\",\"customLabel\":\"CPU quota\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.process.cgroup.id\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Container ID\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.cpu.stats.throttled.ns\",\"customLabel\":\"CPU throttling\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.cpuacct.stats.system.ns\",\"customLabel\":\"CPU kernel\"}},{\"id\":\"6\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.process.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Process name\"}}],\"listeners\":{}}" - }, - "id": "Container-CPU-usage", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "System Navigation", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"System Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"[System Overview](#/dashboard/Metricbeat-system-overview) | [Host Overview (requires Kibana =\u003e 5.4)](#/dashboard/79ffd6e0-faa0-11e6-947f-177f697178b8) |\\n[Docker containers overview](#/dashboard/CPU-slash-Memory-per-container)\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "System-Navigation", - "type": "visualization", - "version": 2 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - }, - "title": "Container Memory stats", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "version": 1, - "visState": "{\"title\":\"Container Memory stats\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"13\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.mem.usage.bytes\",\"customLabel\":\"Usage\"}},{\"id\":\"14\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.mem.usage.max.bytes\",\"customLabel\":\"Max usage\"}},{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.page_faults\",\"customLabel\":\"Page faults\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.pages_in\",\"customLabel\":\"Pages in memory\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.pages_out\",\"customLabel\":\"Pages out of memory\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.process.cgroup.id\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Container ID\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.inactive_file.bytes\",\"customLabel\":\"Inactive files\"}},{\"id\":\"6\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.major_page_faults\",\"customLabel\":\"# Major page faults\"}},{\"id\":\"8\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"system.process.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Process name\"}},{\"id\":\"12\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.mem.failures\",\"customLabel\":\"Failures\"}},{\"id\":\"10\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.kmem_tcp.usage.bytes\",\"customLabel\":\"TCP buffers\"}},{\"id\":\"11\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.rss_huge.bytes\",\"customLabel\":\"Huge pages\"}},{\"id\":\"7\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.rss.bytes\",\"customLabel\":\"Swap caches\"}},{\"id\":\"15\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.memory.stats.swap.bytes\",\"customLabel\":\"Swap usage\"}},{\"id\":\"16\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.cgroup.blkio.total.ios\",\"customLabel\":\"Block I/O\"}}],\"listeners\":{}}" - }, - "id": "Container-Memory-stats", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Container Block IO", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "version": 1, - "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{\"customLabel\":\"Total\",\"field\":\"system.process.cgroup.blkio.total.bytes\"},\"schema\":\"metric\",\"type\":\"avg\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"customLabel\":\"I/O\",\"field\":\"system.process.cgroup.blkio.total.ios\"},\"schema\":\"metric\",\"type\":\"avg\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"customLabel\":\"Container ID\",\"field\":\"system.process.cgroup.id\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":5},\"schema\":\"bucket\",\"type\":\"terms\"},{\"enabled\":true,\"id\":\"4\",\"params\":{\"customLabel\":\"Process name\",\"field\":\"system.process.name\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":5},\"schema\":\"bucket\",\"type\":\"terms\"}],\"listeners\":{},\"params\":{\"perPage\":10,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"title\":\"Container Block IO\",\"type\":\"table\"}" - }, - "id": "Container-Block-IO", - "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "hits": 0, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}],\"highlightAll\":true,\"version\":true}" - }, - "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"Container-CPU-usage\",\"panelIndex\":2,\"row\":2,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"System-Navigation\",\"panelIndex\":3,\"row\":1,\"size_x\":12,\"size_y\":1,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Container-Memory-stats\",\"panelIndex\":4,\"row\":5,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Container-Block-IO\",\"panelIndex\":5,\"row\":8,\"size_x\":12,\"size_y\":4,\"type\":\"visualization\"}]", - "timeRestore": false, - "title": "Metricbeat CPU/Memory per container", - "uiStateJSON": "{\"P-2\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-4\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-5\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", - "version": 1 - }, - "id": "CPU-slash-Memory-per-container", - "type": "dashboard", - "version": 1 - } - ], - "version": "6.0.0-alpha3-SNAPSHOT" -} \ No newline at end of file diff --git a/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-host-overview.json b/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-host-overview.json index a5b115a8d79..a94b6014269 100644 --- a/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-host-overview.json +++ b/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-host-overview.json @@ -4,256 +4,241 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\n \"query\": {\n \"query_string\": {\n \"query\": \"*\"\n }\n },\n \"filter\": []\n}" }, - "title": "Mericbeat: Network Traffic (Packets)", + "title": "Network Traffic (Packets) [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Mericbeat: Network Traffic (Packets)\",\"type\":\"metrics\",\"params\":{\"id\":\"da1046f0-faa0-11e6-86b1-cd7735ff7e23\",\"type\":\"timeseries\",\"series\":[{\"id\":\"da1046f1-faa0-11e6-86b1-cd7735ff7e23\",\"color\":\"rgba(0,156,224,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"da1046f2-faa0-11e6-86b1-cd7735ff7e23\",\"type\":\"max\",\"field\":\"system.network.in.packets\"},{\"unit\":\"1s\",\"id\":\"f41f9280-faa0-11e6-86b1-cd7735ff7e23\",\"type\":\"derivative\",\"field\":\"da1046f2-faa0-11e6-86b1-cd7735ff7e23\"},{\"unit\":\"\",\"id\":\"c0da3d80-1b93-11e7-8ada-3df93aab833e\",\"type\":\"positive_only\",\"field\":\"f41f9280-faa0-11e6-86b1-cd7735ff7e23\"},{\"id\":\"ecaad010-2c2c-11e7-be71-3162da85303f\",\"type\":\"series_agg\",\"function\":\"sum\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"0.[00]a\",\"chart_type\":\"line\",\"line_width\":\"0\",\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"none\",\"label\":\"Inbound\",\"value_template\":\"{{value}}/s\",\"terms_field\":\"system.network.name\"},{\"id\":\"fbbd5720-faa0-11e6-86b1-cd7735ff7e23\",\"color\":\"rgba(250,40,255,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"fbbd7e30-faa0-11e6-86b1-cd7735ff7e23\",\"type\":\"max\",\"field\":\"system.network.out.packets\"},{\"unit\":\"1s\",\"id\":\"fbbd7e31-faa0-11e6-86b1-cd7735ff7e23\",\"type\":\"derivative\",\"field\":\"fbbd7e30-faa0-11e6-86b1-cd7735ff7e23\"},{\"script\":\"params.rate != null \u0026\u0026 params.rate \u003e 0 ? params.rate * -1 : null\",\"id\":\"17e597a0-faa1-11e6-86b1-cd7735ff7e23\",\"type\":\"calculation\",\"variables\":[{\"id\":\"1940bad0-faa1-11e6-86b1-cd7735ff7e23\",\"name\":\"rate\",\"field\":\"fbbd7e31-faa0-11e6-86b1-cd7735ff7e23\"}]},{\"id\":\"fe5fbdc0-2c2c-11e7-be71-3162da85303f\",\"type\":\"series_agg\",\"function\":\"sum\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"0.[00]a\",\"chart_type\":\"line\",\"line_width\":\"0\",\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"none\",\"label\":\"Outbound\",\"value_template\":\"{{value}}/s\",\"terms_field\":\"system.network.name\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"filter\":\"-system.network.name:l*\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\n \"title\": \"Mericbeat: Network Traffic (Packets)\",\n \"type\": \"metrics\",\n \"params\": {\n \"id\": \"da1046f0-faa0-11e6-86b1-cd7735ff7e23\",\n \"type\": \"timeseries\",\n \"series\": [\n {\n \"id\": \"da1046f1-faa0-11e6-86b1-cd7735ff7e23\",\n \"color\": \"rgba(0,156,224,1)\",\n \"split_mode\": \"terms\",\n \"metrics\": [\n {\n \"id\": \"da1046f2-faa0-11e6-86b1-cd7735ff7e23\",\n \"type\": \"max\",\n \"field\": \"system.network.in.packets\"\n },\n {\n \"unit\": \"1s\",\n \"id\": \"f41f9280-faa0-11e6-86b1-cd7735ff7e23\",\n \"type\": \"derivative\",\n \"field\": \"da1046f2-faa0-11e6-86b1-cd7735ff7e23\"\n },\n {\n \"unit\": \"\",\n \"id\": \"c0da3d80-1b93-11e7-8ada-3df93aab833e\",\n \"type\": \"positive_only\",\n \"field\": \"f41f9280-faa0-11e6-86b1-cd7735ff7e23\"\n },\n {\n \"id\": \"ecaad010-2c2c-11e7-be71-3162da85303f\",\n \"type\": \"series_agg\",\n \"function\": \"sum\"\n }\n ],\n \"seperate_axis\": 0,\n \"axis_position\": \"right\",\n \"formatter\": \"0.[00]a\",\n \"chart_type\": \"line\",\n \"line_width\": \"0\",\n \"point_size\": \"0\",\n \"fill\": \"1\",\n \"stacked\": \"none\",\n \"label\": \"Inbound\",\n \"value_template\": \"{{value}}/s\",\n \"terms_field\": \"system.network.name\"\n },\n {\n \"id\": \"fbbd5720-faa0-11e6-86b1-cd7735ff7e23\",\n \"color\": \"rgba(250,40,255,1)\",\n \"split_mode\": \"terms\",\n \"metrics\": [\n {\n \"id\": \"fbbd7e30-faa0-11e6-86b1-cd7735ff7e23\",\n \"type\": \"max\",\n \"field\": \"system.network.out.packets\"\n },\n {\n \"unit\": \"1s\",\n \"id\": \"fbbd7e31-faa0-11e6-86b1-cd7735ff7e23\",\n \"type\": \"derivative\",\n \"field\": \"fbbd7e30-faa0-11e6-86b1-cd7735ff7e23\"\n },\n {\n \"script\": \"params.rate != null \u0026\u0026 params.rate \u003e 0 ? params.rate * -1 : null\",\n \"id\": \"17e597a0-faa1-11e6-86b1-cd7735ff7e23\",\n \"type\": \"calculation\",\n \"variables\": [\n {\n \"id\": \"1940bad0-faa1-11e6-86b1-cd7735ff7e23\",\n \"name\": \"rate\",\n \"field\": \"fbbd7e31-faa0-11e6-86b1-cd7735ff7e23\"\n }\n ]\n },\n {\n \"id\": \"fe5fbdc0-2c2c-11e7-be71-3162da85303f\",\n \"type\": \"series_agg\",\n \"function\": \"sum\"\n }\n ],\n \"seperate_axis\": 0,\n \"axis_position\": \"right\",\n \"formatter\": \"0.[00]a\",\n \"chart_type\": \"line\",\n \"line_width\": \"0\",\n \"point_size\": \"0\",\n \"fill\": \"1\",\n \"stacked\": \"none\",\n \"label\": \"Outbound\",\n \"value_template\": \"{{value}}/s\",\n \"terms_field\": \"system.network.name\"\n }\n ],\n \"time_field\": \"@timestamp\",\n \"index_pattern\": \"*\",\n \"interval\": \"auto\",\n \"axis_position\": \"left\",\n \"axis_formatter\": \"number\",\n \"show_legend\": 1,\n \"filter\": \"-system.network.name:l*\"\n },\n \"aggs\": [],\n \"listeners\": {}\n}" }, "id": "6b7b9a40-faa1-11e6-86b1-cd7735ff7e23", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: System Load", + "title": "System Load [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: System Load\",\"type\":\"metrics\",\"params\":{\"id\":\"f6264ad0-1b14-11e7-b09e-037021c4f8df\",\"type\":\"timeseries\",\"series\":[{\"id\":\"f62671e0-1b14-11e7-b09e-037021c4f8df\",\"color\":\"rgba(115,216,255,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"f62671e1-1b14-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.load.1\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":\"3\",\"point_size\":1,\"fill\":\"0\",\"stacked\":\"none\",\"label\":\"1m\"},{\"id\":\"1c324850-1b15-11e7-b09e-037021c4f8df\",\"color\":\"rgba(0,156,224,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"1c324851-1b15-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.load.5\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":\"3\",\"point_size\":\"0\",\"fill\":\"0\",\"stacked\":\"none\",\"label\":\"5m\"},{\"id\":\"3287e740-1b15-11e7-b09e-037021c4f8df\",\"color\":\"rgba(0,98,177,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"32880e50-1b15-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.load.15\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":\"3\",\"point_size\":\"0\",\"fill\":\"0\",\"stacked\":\"none\",\"label\":\"15m\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"System Load [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"f6264ad0-1b14-11e7-b09e-037021c4f8df\",\"type\":\"timeseries\",\"series\":[{\"id\":\"f62671e0-1b14-11e7-b09e-037021c4f8df\",\"color\":\"rgba(115,216,255,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"f62671e1-1b14-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.load.1\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":\"3\",\"point_size\":1,\"fill\":\"0\",\"stacked\":\"none\",\"label\":\"1m\"},{\"id\":\"1c324850-1b15-11e7-b09e-037021c4f8df\",\"color\":\"rgba(0,156,224,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"1c324851-1b15-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.load.5\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":\"3\",\"point_size\":\"0\",\"fill\":\"0\",\"stacked\":\"none\",\"label\":\"5m\"},{\"id\":\"3287e740-1b15-11e7-b09e-037021c4f8df\",\"color\":\"rgba(0,98,177,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"32880e50-1b15-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.load.15\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":\"3\",\"point_size\":\"0\",\"fill\":\"0\",\"stacked\":\"none\",\"label\":\"15m\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1},\"aggs\":[]}" }, "id": "4d546850-1b15-11e7-b09e-037021c4f8df", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\n \"query\": {\n \"query_string\": {\n \"query\": \"*\"\n }\n },\n \"filter\": []\n}" }, - "title": "Mericbeat: Network Traffic (Bytes)", + "title": "Network Traffic (Bytes) [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Mericbeat: Network Traffic (Bytes)\",\"type\":\"metrics\",\"params\":{\"id\":\"da1046f0-faa0-11e6-86b1-cd7735ff7e23\",\"type\":\"timeseries\",\"series\":[{\"id\":\"da1046f1-faa0-11e6-86b1-cd7735ff7e23\",\"color\":\"rgba(0,156,224,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"da1046f2-faa0-11e6-86b1-cd7735ff7e23\",\"type\":\"max\",\"field\":\"system.network.in.bytes\"},{\"unit\":\"1s\",\"id\":\"f41f9280-faa0-11e6-86b1-cd7735ff7e23\",\"type\":\"derivative\",\"field\":\"da1046f2-faa0-11e6-86b1-cd7735ff7e23\"},{\"unit\":\"\",\"id\":\"a87398e0-1b93-11e7-8ada-3df93aab833e\",\"type\":\"positive_only\",\"field\":\"f41f9280-faa0-11e6-86b1-cd7735ff7e23\"},{\"id\":\"2d533df0-2c2d-11e7-be71-3162da85303f\",\"type\":\"series_agg\",\"function\":\"sum\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":\"0\",\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"none\",\"label\":\"Inbound \",\"value_template\":\"{{value}}/s\",\"terms_field\":\"system.network.name\"},{\"id\":\"fbbd5720-faa0-11e6-86b1-cd7735ff7e23\",\"color\":\"rgba(250,40,255,1)\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"fbbd7e30-faa0-11e6-86b1-cd7735ff7e23\",\"type\":\"max\",\"field\":\"system.network.out.bytes\"},{\"unit\":\"1s\",\"id\":\"fbbd7e31-faa0-11e6-86b1-cd7735ff7e23\",\"type\":\"derivative\",\"field\":\"fbbd7e30-faa0-11e6-86b1-cd7735ff7e23\"},{\"script\":\"params.rate != null \u0026\u0026 params.rate \u003e 0 ? params.rate * -1 : null\",\"id\":\"17e597a0-faa1-11e6-86b1-cd7735ff7e23\",\"type\":\"calculation\",\"variables\":[{\"id\":\"1940bad0-faa1-11e6-86b1-cd7735ff7e23\",\"name\":\"rate\",\"field\":\"fbbd7e31-faa0-11e6-86b1-cd7735ff7e23\"}]},{\"id\":\"533da9b0-2c2d-11e7-be71-3162da85303f\",\"type\":\"series_agg\",\"function\":\"sum\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":\"0\",\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"none\",\"label\":\"Outbound \",\"value_template\":\"{{value}}/s\",\"terms_field\":\"system.network.name\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"filter\":\"-system.network.name:l*\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\n \"title\": \"Mericbeat: Network Traffic (Bytes)\",\n \"type\": \"metrics\",\n \"params\": {\n \"id\": \"da1046f0-faa0-11e6-86b1-cd7735ff7e23\",\n \"type\": \"timeseries\",\n \"series\": [\n {\n \"id\": \"da1046f1-faa0-11e6-86b1-cd7735ff7e23\",\n \"color\": \"rgba(0,156,224,1)\",\n \"split_mode\": \"terms\",\n \"metrics\": [\n {\n \"id\": \"da1046f2-faa0-11e6-86b1-cd7735ff7e23\",\n \"type\": \"max\",\n \"field\": \"system.network.in.bytes\"\n },\n {\n \"unit\": \"1s\",\n \"id\": \"f41f9280-faa0-11e6-86b1-cd7735ff7e23\",\n \"type\": \"derivative\",\n \"field\": \"da1046f2-faa0-11e6-86b1-cd7735ff7e23\"\n },\n {\n \"unit\": \"\",\n \"id\": \"a87398e0-1b93-11e7-8ada-3df93aab833e\",\n \"type\": \"positive_only\",\n \"field\": \"f41f9280-faa0-11e6-86b1-cd7735ff7e23\"\n },\n {\n \"id\": \"2d533df0-2c2d-11e7-be71-3162da85303f\",\n \"type\": \"series_agg\",\n \"function\": \"sum\"\n }\n ],\n \"seperate_axis\": 0,\n \"axis_position\": \"right\",\n \"formatter\": \"bytes\",\n \"chart_type\": \"line\",\n \"line_width\": \"0\",\n \"point_size\": \"0\",\n \"fill\": \"1\",\n \"stacked\": \"none\",\n \"label\": \"Inbound \",\n \"value_template\": \"{{value}}/s\",\n \"terms_field\": \"system.network.name\"\n },\n {\n \"id\": \"fbbd5720-faa0-11e6-86b1-cd7735ff7e23\",\n \"color\": \"rgba(250,40,255,1)\",\n \"split_mode\": \"terms\",\n \"metrics\": [\n {\n \"id\": \"fbbd7e30-faa0-11e6-86b1-cd7735ff7e23\",\n \"type\": \"max\",\n \"field\": \"system.network.out.bytes\"\n },\n {\n \"unit\": \"1s\",\n \"id\": \"fbbd7e31-faa0-11e6-86b1-cd7735ff7e23\",\n \"type\": \"derivative\",\n \"field\": \"fbbd7e30-faa0-11e6-86b1-cd7735ff7e23\"\n },\n {\n \"script\": \"params.rate != null \u0026\u0026 params.rate \u003e 0 ? params.rate * -1 : null\",\n \"id\": \"17e597a0-faa1-11e6-86b1-cd7735ff7e23\",\n \"type\": \"calculation\",\n \"variables\": [\n {\n \"id\": \"1940bad0-faa1-11e6-86b1-cd7735ff7e23\",\n \"name\": \"rate\",\n \"field\": \"fbbd7e31-faa0-11e6-86b1-cd7735ff7e23\"\n }\n ]\n },\n {\n \"id\": \"533da9b0-2c2d-11e7-be71-3162da85303f\",\n \"type\": \"series_agg\",\n \"function\": \"sum\"\n }\n ],\n \"seperate_axis\": 0,\n \"axis_position\": \"right\",\n \"formatter\": \"bytes\",\n \"chart_type\": \"line\",\n \"line_width\": \"0\",\n \"point_size\": \"0\",\n \"fill\": \"1\",\n \"stacked\": \"none\",\n \"label\": \"Outbound \",\n \"value_template\": \"{{value}}/s\",\n \"terms_field\": \"system.network.name\"\n }\n ],\n \"time_field\": \"@timestamp\",\n \"index_pattern\": \"*\",\n \"interval\": \"auto\",\n \"axis_position\": \"left\",\n \"axis_formatter\": \"number\",\n \"show_legend\": 1,\n \"filter\": \"-system.network.name:l*\"\n },\n \"aggs\": [],\n \"listeners\": {}\n}" }, "id": "089b85d0-1b16-11e7-b09e-037021c4f8df", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: Memory Usage", + "title": "Memory Usage [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: Memory Usage\",\"type\":\"metrics\",\"params\":{\"id\":\"32f46f40-1b16-11e7-b09e-037021c4f8df\",\"type\":\"timeseries\",\"series\":[{\"id\":\"4ff61fd0-1b16-11e7-b09e-037021c4f8df\",\"color\":\"rgba(211,49,21,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"4ff61fd1-1b16-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.memory.actual.used.bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"Used\"},{\"id\":\"753a6080-1b16-11e7-b09e-037021c4f8df\",\"color\":\"rgba(0,156,224,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"753a6081-1b16-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.memory.actual.used.bytes\"},{\"id\":\"7c9d3f00-1b16-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.memory.used.bytes\"},{\"script\":\"params.actual != null \u0026\u0026 params.used != null ? params.used - params.actual : null\",\"id\":\"869cc160-1b16-11e7-b09e-037021c4f8df\",\"type\":\"calculation\",\"variables\":[{\"id\":\"890f9620-1b16-11e7-b09e-037021c4f8df\",\"name\":\"actual\",\"field\":\"753a6081-1b16-11e7-b09e-037021c4f8df\"},{\"id\":\"8f3ab7f0-1b16-11e7-b09e-037021c4f8df\",\"name\":\"used\",\"field\":\"7c9d3f00-1b16-11e7-b09e-037021c4f8df\"}]}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"Cache\"},{\"id\":\"32f46f41-1b16-11e7-b09e-037021c4f8df\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"32f46f42-1b16-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.memory.free\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"Free\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Memory Usage [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"32f46f40-1b16-11e7-b09e-037021c4f8df\",\"type\":\"timeseries\",\"series\":[{\"id\":\"4ff61fd0-1b16-11e7-b09e-037021c4f8df\",\"color\":\"rgba(211,49,21,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"4ff61fd1-1b16-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.memory.actual.used.bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"Used\"},{\"id\":\"753a6080-1b16-11e7-b09e-037021c4f8df\",\"color\":\"rgba(0,156,224,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"753a6081-1b16-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.memory.actual.used.bytes\"},{\"id\":\"7c9d3f00-1b16-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.memory.used.bytes\"},{\"script\":\"params.actual != null \u0026\u0026 params.used != null ? params.used - params.actual : null\",\"id\":\"869cc160-1b16-11e7-b09e-037021c4f8df\",\"type\":\"calculation\",\"variables\":[{\"id\":\"890f9620-1b16-11e7-b09e-037021c4f8df\",\"name\":\"actual\",\"field\":\"753a6081-1b16-11e7-b09e-037021c4f8df\"},{\"id\":\"8f3ab7f0-1b16-11e7-b09e-037021c4f8df\",\"name\":\"used\",\"field\":\"7c9d3f00-1b16-11e7-b09e-037021c4f8df\"}]}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"Cache\"},{\"id\":\"32f46f41-1b16-11e7-b09e-037021c4f8df\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"32f46f42-1b16-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.memory.free\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"Free\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1},\"aggs\":[]}" }, "id": "bfa5e400-1b16-11e7-b09e-037021c4f8df", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: Top Processes By CPU", + "title": "Top Processes By CPU [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: Top Processes By CPU\",\"type\":\"metrics\",\"params\":{\"id\":\"5f5b8d50-1b18-11e7-b09e-037021c4f8df\",\"type\":\"top_n\",\"series\":[{\"id\":\"5f5b8d51-1b18-11e7-b09e-037021c4f8df\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"5f5b8d52-1b18-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.process.cpu.total.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"system.process.name\",\"terms_order_by\":\"5f5b8d52-1b18-11e7-b09e-037021c4f8df\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"value\":0,\"id\":\"60e11be0-1b18-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"}],\"drilldown_url\":\"\",\"filter\":\"\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Top Processes By CPU [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"5f5b8d50-1b18-11e7-b09e-037021c4f8df\",\"type\":\"top_n\",\"series\":[{\"id\":\"5f5b8d51-1b18-11e7-b09e-037021c4f8df\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"5f5b8d52-1b18-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.process.cpu.total.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"system.process.name\",\"terms_order_by\":\"5f5b8d52-1b18-11e7-b09e-037021c4f8df\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"value\":0,\"id\":\"60e11be0-1b18-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"}],\"drilldown_url\":\"\",\"filter\":\"\",\"show_grid\":1},\"aggs\":[]}" }, "id": "e0f001c0-1b18-11e7-b09e-037021c4f8df", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: Processes By Memory", + "title": "Processes By Memory [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: Processes By Memory\",\"type\":\"metrics\",\"params\":{\"id\":\"edfceb30-1b18-11e7-b09e-037021c4f8df\",\"type\":\"top_n\",\"series\":[{\"id\":\"edfceb31-1b18-11e7-b09e-037021c4f8df\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"edfceb32-1b18-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.process.memory.rss.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"system.process.name\",\"terms_order_by\":\"edfceb32-1b18-11e7-b09e-037021c4f8df\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"value\":0,\"id\":\"efb9b660-1b18-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.7,\"id\":\"17fcb820-1b19-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(254,146,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"1dd61070-1b19-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"drilldown_url\":\"\",\"filter\":\"\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Processes By Memory [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"edfceb30-1b18-11e7-b09e-037021c4f8df\",\"type\":\"top_n\",\"series\":[{\"id\":\"edfceb31-1b18-11e7-b09e-037021c4f8df\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"edfceb32-1b18-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.process.memory.rss.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"system.process.name\",\"terms_order_by\":\"edfceb32-1b18-11e7-b09e-037021c4f8df\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"value\":0,\"id\":\"efb9b660-1b18-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.7,\"id\":\"17fcb820-1b19-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(254,146,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"1dd61070-1b19-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"drilldown_url\":\"\",\"filter\":\"\",\"show_grid\":1},\"aggs\":[]}" }, "id": "2e224660-1b19-11e7-b09e-037021c4f8df", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: CPU Usage", + "title": "CPU Usage [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: CPU Usage\",\"type\":\"metrics\",\"params\":{\"id\":\"80a04950-1b19-11e7-b09e-037021c4f8df\",\"type\":\"timeseries\",\"series\":[{\"id\":\"80a04951-1b19-11e7-b09e-037021c4f8df\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"80a04952-1b19-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.cpu.user.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"user\"},{\"id\":\"993acf30-1b19-11e7-b09e-037021c4f8df\",\"color\":\"rgba(211,49,21,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"993acf31-1b19-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.cpu.system.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"system\"},{\"id\":\"65ca35e0-1b1a-11e7-b09e-037021c4f8df\",\"color\":\"rgba(123,100,255,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"65ca5cf0-1b1a-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.cpu.nice.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"nice\"},{\"id\":\"741b5f20-1b1a-11e7-b09e-037021c4f8df\",\"color\":\"rgba(226,115,0,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"741b5f21-1b1a-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.cpu.irq.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"irq\"},{\"id\":\"2efc5d40-1b1a-11e7-b09e-037021c4f8df\",\"color\":\"rgba(176,188,0,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"2efc5d41-1b1a-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.cpu.softirq.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"softirq\"},{\"id\":\"ae644a30-1b19-11e7-b09e-037021c4f8df\",\"color\":\"rgba(15,20,25,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"ae644a31-1b19-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.cpu.iowait.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"iowait\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"CPU Usage [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"80a04950-1b19-11e7-b09e-037021c4f8df\",\"type\":\"timeseries\",\"series\":[{\"id\":\"80a04951-1b19-11e7-b09e-037021c4f8df\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"80a04952-1b19-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.cpu.user.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"user\"},{\"id\":\"993acf30-1b19-11e7-b09e-037021c4f8df\",\"color\":\"rgba(211,49,21,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"993acf31-1b19-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.cpu.system.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"system\"},{\"id\":\"65ca35e0-1b1a-11e7-b09e-037021c4f8df\",\"color\":\"rgba(123,100,255,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"65ca5cf0-1b1a-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.cpu.nice.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"nice\"},{\"id\":\"741b5f20-1b1a-11e7-b09e-037021c4f8df\",\"color\":\"rgba(226,115,0,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"741b5f21-1b1a-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.cpu.irq.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"irq\"},{\"id\":\"2efc5d40-1b1a-11e7-b09e-037021c4f8df\",\"color\":\"rgba(176,188,0,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"2efc5d41-1b1a-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.cpu.softirq.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"softirq\"},{\"id\":\"ae644a30-1b19-11e7-b09e-037021c4f8df\",\"color\":\"rgba(15,20,25,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"ae644a31-1b19-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.cpu.iowait.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"stacked\",\"label\":\"iowait\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1},\"aggs\":[]}" }, "id": "ab2d1e90-1b1a-11e7-b09e-037021c4f8df", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: Disk IO (Bytes)", + "title": "Disk IO (Bytes) [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: Disk IO (Bytes)\",\"type\":\"metrics\",\"params\":{\"id\":\"d3c67db0-1b1a-11e7-b09e-037021c4f8df\",\"type\":\"timeseries\",\"series\":[{\"id\":\"d3c67db1-1b1a-11e7-b09e-037021c4f8df\",\"color\":\"rgba(22,165,165,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"d3c67db2-1b1a-11e7-b09e-037021c4f8df\",\"type\":\"max\",\"field\":\"system.diskio.read.bytes\"},{\"unit\":\"1s\",\"id\":\"f55b9910-1b1a-11e7-b09e-037021c4f8df\",\"type\":\"derivative\",\"field\":\"d3c67db2-1b1a-11e7-b09e-037021c4f8df\"},{\"unit\":\"\",\"id\":\"dcbbb100-1b93-11e7-8ada-3df93aab833e\",\"type\":\"positive_only\",\"field\":\"f55b9910-1b1a-11e7-b09e-037021c4f8df\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"none\",\"label\":\"reads\",\"value_template\":\"{{value}}/s\"},{\"id\":\"144124d0-1b1b-11e7-b09e-037021c4f8df\",\"color\":\"rgba(251,158,0,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"144124d1-1b1b-11e7-b09e-037021c4f8df\",\"type\":\"max\",\"field\":\"system.diskio.write.bytes\"},{\"unit\":\"1s\",\"id\":\"144124d2-1b1b-11e7-b09e-037021c4f8df\",\"type\":\"derivative\",\"field\":\"144124d1-1b1b-11e7-b09e-037021c4f8df\"},{\"script\":\"params.rate \u003e 0 ? params.rate * -1 : 0\",\"id\":\"144124d4-1b1b-11e7-b09e-037021c4f8df\",\"type\":\"calculation\",\"variables\":[{\"id\":\"144124d3-1b1b-11e7-b09e-037021c4f8df\",\"name\":\"rate\",\"field\":\"144124d2-1b1b-11e7-b09e-037021c4f8df\"}]}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"none\",\"label\":\"writes\",\"value_template\":\"{{value}}/s\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"filter\":\"\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Disk IO (Bytes) [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"d3c67db0-1b1a-11e7-b09e-037021c4f8df\",\"type\":\"timeseries\",\"series\":[{\"id\":\"d3c67db1-1b1a-11e7-b09e-037021c4f8df\",\"color\":\"rgba(22,165,165,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"d3c67db2-1b1a-11e7-b09e-037021c4f8df\",\"type\":\"max\",\"field\":\"system.diskio.read.bytes\"},{\"unit\":\"1s\",\"id\":\"f55b9910-1b1a-11e7-b09e-037021c4f8df\",\"type\":\"derivative\",\"field\":\"d3c67db2-1b1a-11e7-b09e-037021c4f8df\"},{\"unit\":\"\",\"id\":\"dcbbb100-1b93-11e7-8ada-3df93aab833e\",\"type\":\"positive_only\",\"field\":\"f55b9910-1b1a-11e7-b09e-037021c4f8df\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"none\",\"label\":\"reads\",\"value_template\":\"{{value}}/s\"},{\"id\":\"144124d0-1b1b-11e7-b09e-037021c4f8df\",\"color\":\"rgba(251,158,0,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"144124d1-1b1b-11e7-b09e-037021c4f8df\",\"type\":\"max\",\"field\":\"system.diskio.write.bytes\"},{\"unit\":\"1s\",\"id\":\"144124d2-1b1b-11e7-b09e-037021c4f8df\",\"type\":\"derivative\",\"field\":\"144124d1-1b1b-11e7-b09e-037021c4f8df\"},{\"script\":\"params.rate \u003e 0 ? params.rate * -1 : 0\",\"id\":\"144124d4-1b1b-11e7-b09e-037021c4f8df\",\"type\":\"calculation\",\"variables\":[{\"id\":\"144124d3-1b1b-11e7-b09e-037021c4f8df\",\"name\":\"rate\",\"field\":\"144124d2-1b1b-11e7-b09e-037021c4f8df\"}]}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":\"0\",\"fill\":\"1\",\"stacked\":\"none\",\"label\":\"writes\",\"value_template\":\"{{value}}/s\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"filter\":\"\",\"show_grid\":1},\"aggs\":[]}" }, "id": "4e4bb1e0-1b1b-11e7-b09e-037021c4f8df", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: 5m Load Gauge", + "title": "Load Gauge [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: 5m Load Gauge\",\"type\":\"metrics\",\"params\":{\"id\":\"fdcc6180-1b90-11e7-bec4-a5e9ec5cab8b\",\"type\":\"gauge\",\"series\":[{\"id\":\"fdcc6181-1b90-11e7-bec4-a5e9ec5cab8b\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"fdcc6182-1b90-11e7-bec4-a5e9ec5cab8b\",\"type\":\"avg\",\"field\":\"system.load.5\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"5m Load\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"feefabd0-1b90-11e7-bec4-a5e9ec5cab8b\"}],\"gauge_color_rules\":[{\"id\":\"ffd94880-1b90-11e7-bec4-a5e9ec5cab8b\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Load Gauge [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"fdcc6180-1b90-11e7-bec4-a5e9ec5cab8b\",\"type\":\"gauge\",\"series\":[{\"id\":\"fdcc6181-1b90-11e7-bec4-a5e9ec5cab8b\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"fdcc6182-1b90-11e7-bec4-a5e9ec5cab8b\",\"type\":\"avg\",\"field\":\"system.load.5\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"5m Load\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"feefabd0-1b90-11e7-bec4-a5e9ec5cab8b\"}],\"gauge_color_rules\":[{\"id\":\"ffd94880-1b90-11e7-bec4-a5e9ec5cab8b\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"show_grid\":1},\"aggs\":[]}" }, "id": "26732e20-1b91-11e7-bec4-a5e9ec5cab8b", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: CPU Usage Gauge", + "title": "CPU Usage Gauge [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: CPU Usage Gauge\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"filter\":\"\",\"gauge_color_rules\":[{\"gauge\":\"rgba(104,188,0,1)\",\"id\":\"4ef2c3b0-1b91-11e7-bec4-a5e9ec5cab8b\",\"opperator\":\"gte\",\"value\":0},{\"gauge\":\"rgba(254,146,0,1)\",\"id\":\"e6561ae0-1b91-11e7-bec4-a5e9ec5cab8b\",\"opperator\":\"gte\",\"value\":0.7},{\"gauge\":\"rgba(211,49,21,1)\",\"id\":\"ec655040-1b91-11e7-bec4-a5e9ec5cab8b\",\"opperator\":\"gte\",\"value\":0.85}],\"gauge_inner_width\":10,\"gauge_max\":\"1\",\"gauge_style\":\"half\",\"gauge_width\":10,\"id\":\"4c9e2550-1b91-11e7-bec4-a5e9ec5cab8b\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"percent\",\"id\":\"4c9e2551-1b91-11e7-bec4-a5e9ec5cab8b\",\"label\":\"CPU Usage\",\"line_width\":1,\"metrics\":[{\"field\":\"system.cpu.user.pct\",\"id\":\"4c9e2552-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"avg\"},{\"field\":\"system.cpu.system.pct\",\"id\":\"225c2140-5fd7-11e7-a63a-a937b7c1a7e1\",\"type\":\"avg\"},{\"field\":\"system.cpu.cores\",\"id\":\"837a30c0-5fd7-11e7-a63a-a937b7c1a7e1\",\"type\":\"avg\"},{\"script\":\"params.n \u003e 0 ? (params.user+params.system)/params.n : null\",\"id\":\"587aa510-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"calculation\",\"variables\":[{\"field\":\"4c9e2552-1b91-11e7-bec4-a5e9ec5cab8b\",\"id\":\"5a19af10-1b91-11e7-bec4-a5e9ec5cab8b\",\"name\":\"user\"},{\"field\":\"225c2140-5fd7-11e7-a63a-a937b7c1a7e1\",\"id\":\"32b54f80-5fd7-11e7-a63a-a937b7c1a7e1\",\"name\":\"system\"},{\"field\":\"837a30c0-5fd7-11e7-a63a-a937b7c1a7e1\",\"id\":\"8ba6eef0-5fd7-11e7-a63a-a937b7c1a7e1\",\"name\":\"n\"}]}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"everything\",\"stacked\":\"none\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"gauge\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"CPU Usage Gauge [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"filter\":\"\",\"gauge_color_rules\":[{\"gauge\":\"rgba(104,188,0,1)\",\"id\":\"4ef2c3b0-1b91-11e7-bec4-a5e9ec5cab8b\",\"opperator\":\"gte\",\"value\":0},{\"gauge\":\"rgba(254,146,0,1)\",\"id\":\"e6561ae0-1b91-11e7-bec4-a5e9ec5cab8b\",\"opperator\":\"gte\",\"value\":0.7},{\"gauge\":\"rgba(211,49,21,1)\",\"id\":\"ec655040-1b91-11e7-bec4-a5e9ec5cab8b\",\"opperator\":\"gte\",\"value\":0.85}],\"gauge_inner_width\":10,\"gauge_max\":\"1\",\"gauge_style\":\"half\",\"gauge_width\":10,\"id\":\"4c9e2550-1b91-11e7-bec4-a5e9ec5cab8b\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"percent\",\"id\":\"4c9e2551-1b91-11e7-bec4-a5e9ec5cab8b\",\"label\":\"CPU Usage\",\"line_width\":1,\"metrics\":[{\"field\":\"system.cpu.user.pct\",\"id\":\"4c9e2552-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"avg\"},{\"field\":\"system.cpu.system.pct\",\"id\":\"225c2140-5fd7-11e7-a63a-a937b7c1a7e1\",\"type\":\"avg\"},{\"field\":\"system.cpu.cores\",\"id\":\"837a30c0-5fd7-11e7-a63a-a937b7c1a7e1\",\"type\":\"avg\"},{\"script\":\"params.n \u003e 0 ? (params.user+params.system)/params.n : null\",\"id\":\"587aa510-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"calculation\",\"variables\":[{\"field\":\"4c9e2552-1b91-11e7-bec4-a5e9ec5cab8b\",\"id\":\"5a19af10-1b91-11e7-bec4-a5e9ec5cab8b\",\"name\":\"user\"},{\"field\":\"225c2140-5fd7-11e7-a63a-a937b7c1a7e1\",\"id\":\"32b54f80-5fd7-11e7-a63a-a937b7c1a7e1\",\"name\":\"system\"},{\"field\":\"837a30c0-5fd7-11e7-a63a-a937b7c1a7e1\",\"id\":\"8ba6eef0-5fd7-11e7-a63a-a937b7c1a7e1\",\"name\":\"n\"}]}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"everything\",\"stacked\":\"none\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"gauge\",\"show_grid\":1},\"aggs\":[]}" }, "id": "83e12df0-1b91-11e7-bec4-a5e9ec5cab8b", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: Memory Usage Gauge", + "title": "Memory Usage Gauge [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: Memory Usage Gauge\",\"type\":\"metrics\",\"params\":{\"id\":\"9f51b730-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"gauge\",\"series\":[{\"id\":\"9f51b731-1b91-11e7-bec4-a5e9ec5cab8b\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"9f51b732-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"avg\",\"field\":\"system.memory.actual.used.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Memory Usage\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"gauge_color_rules\":[{\"value\":0,\"id\":\"a0d522e0-1b91-11e7-bec4-a5e9ec5cab8b\",\"gauge\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.7,\"id\":\"b45ad8f0-1b91-11e7-bec4-a5e9ec5cab8b\",\"gauge\":\"rgba(254,146,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"c06e9550-1b91-11e7-bec4-a5e9ec5cab8b\",\"gauge\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"gauge_max\":\"1\",\"filter\":\"\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Memory Usage Gauge [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"9f51b730-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"gauge\",\"series\":[{\"id\":\"9f51b731-1b91-11e7-bec4-a5e9ec5cab8b\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"9f51b732-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"avg\",\"field\":\"system.memory.actual.used.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Memory Usage\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"gauge_color_rules\":[{\"value\":0,\"id\":\"a0d522e0-1b91-11e7-bec4-a5e9ec5cab8b\",\"gauge\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.7,\"id\":\"b45ad8f0-1b91-11e7-bec4-a5e9ec5cab8b\",\"gauge\":\"rgba(254,146,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"c06e9550-1b91-11e7-bec4-a5e9ec5cab8b\",\"gauge\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"gauge_max\":\"1\",\"filter\":\"\",\"show_grid\":1},\"aggs\":[]}" }, "id": "d3166e80-1b91-11e7-bec4-a5e9ec5cab8b", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: Inbound Traffic Metric", + "title": "Inbound Traffic [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: Inbound Traffic Metric\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"background_color_rules\":[{\"id\":\"0e346760-1b92-11e7-bec4-a5e9ec5cab8b\"}],\"filter\":\"-system.network.name:l*\",\"id\":\"0c761590-1b92-11e7-bec4-a5e9ec5cab8b\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"0c761591-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Inbound Traffic\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.in.bytes\",\"id\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"1s\"},{\"field\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"f2074f70-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"unit\":\"\"},{\"id\":\"c40e18f0-2c55-11e7-a0ad-277ce466684d\",\"type\":\"series_agg\",\"function\":\"sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}/s\",\"terms_field\":\"system.network.name\"},{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"37f70440-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Total Transfered\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.in.bytes\",\"id\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"\"},{\"unit\":\"\",\"id\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"field\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\"},{\"sigma\":\"\",\"field\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"id\":\"3e63c2f0-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"series_agg\",\"function\":\"overall_sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}\",\"terms_field\":\"system.network.name\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"metric\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Inbound Traffic [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"background_color_rules\":[{\"id\":\"0e346760-1b92-11e7-bec4-a5e9ec5cab8b\"}],\"filter\":\"-system.network.name:l*\",\"id\":\"0c761590-1b92-11e7-bec4-a5e9ec5cab8b\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"0c761591-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Inbound Traffic\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.in.bytes\",\"id\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"1s\"},{\"field\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"f2074f70-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"unit\":\"\"},{\"id\":\"c40e18f0-2c55-11e7-a0ad-277ce466684d\",\"type\":\"series_agg\",\"function\":\"sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}/s\",\"terms_field\":\"system.network.name\"},{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"37f70440-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Total Transfered\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.in.bytes\",\"id\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"\"},{\"unit\":\"\",\"id\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"field\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\"},{\"sigma\":\"\",\"field\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"id\":\"3e63c2f0-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"series_agg\",\"function\":\"overall_sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}\",\"terms_field\":\"system.network.name\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"metric\",\"show_grid\":1},\"aggs\":[]}" }, "id": "522ee670-1b92-11e7-bec4-a5e9ec5cab8b", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: Outbound Traffic Metric", + "title": "Outbound Traffic [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: Outbound Traffic Metric\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"background_color_rules\":[{\"id\":\"0e346760-1b92-11e7-bec4-a5e9ec5cab8b\"}],\"filter\":\"-system.network.name:l*\",\"id\":\"0c761590-1b92-11e7-bec4-a5e9ec5cab8b\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"0c761591-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Outbound Traffic\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.out.bytes\",\"id\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"1s\"},{\"field\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"f2074f70-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"unit\":\"\"},{\"id\":\"a1737470-2c55-11e7-a0ad-277ce466684d\",\"type\":\"series_agg\",\"function\":\"sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}/s\",\"terms_field\":\"system.network.name\"},{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"37f70440-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Total Transfered\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.out.bytes\",\"id\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"\"},{\"unit\":\"\",\"id\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"field\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\"},{\"sigma\":\"\",\"field\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"id\":\"3e63c2f0-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"series_agg\",\"function\":\"overall_sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}\",\"terms_field\":\"system.network.name\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"metric\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Outbound Traffic [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"background_color_rules\":[{\"id\":\"0e346760-1b92-11e7-bec4-a5e9ec5cab8b\"}],\"filter\":\"-system.network.name:l*\",\"id\":\"0c761590-1b92-11e7-bec4-a5e9ec5cab8b\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"0c761591-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Outbound Traffic\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.out.bytes\",\"id\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"1s\"},{\"field\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"f2074f70-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"unit\":\"\"},{\"id\":\"a1737470-2c55-11e7-a0ad-277ce466684d\",\"type\":\"series_agg\",\"function\":\"sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}/s\",\"terms_field\":\"system.network.name\"},{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"37f70440-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Total Transfered\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.out.bytes\",\"id\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"\"},{\"unit\":\"\",\"id\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"field\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\"},{\"sigma\":\"\",\"field\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"id\":\"3e63c2f0-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"series_agg\",\"function\":\"overall_sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}\",\"terms_field\":\"system.network.name\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"metric\",\"show_grid\":1},\"aggs\":[]}" }, "id": "1aae9140-1b93-11e7-8ada-3df93aab833e", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: Disk Usage", + "title": "Disk Usage [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: Disk Usage\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"bar_color_rules\":[{\"bar_color\":\"rgba(104,188,0,1)\",\"id\":\"bf525310-1b95-11e7-8ada-3df93aab833e\",\"opperator\":\"gte\",\"value\":0},{\"bar_color\":\"rgba(254,146,0,1)\",\"id\":\"125fc4c0-1b96-11e7-8ada-3df93aab833e\",\"opperator\":\"gte\",\"value\":0.7},{\"bar_color\":\"rgba(211,49,21,1)\",\"id\":\"1a5c7240-1b96-11e7-8ada-3df93aab833e\",\"opperator\":\"gte\",\"value\":0.85}],\"drilldown_url\":\"\",\"filter\":\"-system.filesystem.mount_point:\\\\/run* AND -system.filesystem.mount_point:\\\\/sys* AND -system.filesystem.mount_point:\\\\/dev* AND -system.filesystem.mount_point:\\\\/proc* AND -system.filesystem.mount_point:\\\\/var* AND -system.filesystem.mount_point:\\\\/boot\",\"id\":\"9f7e48a0-1b95-11e7-8ada-3df93aab833e\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"percent\",\"id\":\"9f7e48a1-1b95-11e7-8ada-3df93aab833e\",\"line_width\":1,\"metrics\":[{\"field\":\"system.filesystem.used.pct\",\"id\":\"9f7e48a2-1b95-11e7-8ada-3df93aab833e\",\"type\":\"avg\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"terms_field\":\"system.filesystem.mount_point\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"top_n\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Disk Usage [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"bar_color_rules\":[{\"bar_color\":\"rgba(104,188,0,1)\",\"id\":\"bf525310-1b95-11e7-8ada-3df93aab833e\",\"opperator\":\"gte\",\"value\":0},{\"bar_color\":\"rgba(254,146,0,1)\",\"id\":\"125fc4c0-1b96-11e7-8ada-3df93aab833e\",\"opperator\":\"gte\",\"value\":0.7},{\"bar_color\":\"rgba(211,49,21,1)\",\"id\":\"1a5c7240-1b96-11e7-8ada-3df93aab833e\",\"opperator\":\"gte\",\"value\":0.85}],\"drilldown_url\":\"\",\"filter\":\"-system.filesystem.mount_point:\\\\/run* AND -system.filesystem.mount_point:\\\\/sys* AND -system.filesystem.mount_point:\\\\/dev* AND -system.filesystem.mount_point:\\\\/proc* AND -system.filesystem.mount_point:\\\\/var* AND -system.filesystem.mount_point:\\\\/boot\",\"id\":\"9f7e48a0-1b95-11e7-8ada-3df93aab833e\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"percent\",\"id\":\"9f7e48a1-1b95-11e7-8ada-3df93aab833e\",\"line_width\":1,\"metrics\":[{\"field\":\"system.filesystem.used.pct\",\"id\":\"9f7e48a2-1b95-11e7-8ada-3df93aab833e\",\"type\":\"avg\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"terms_field\":\"system.filesystem.mount_point\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"top_n\",\"show_grid\":1},\"aggs\":[]}" }, "id": "34f97ee0-1b96-11e7-8ada-3df93aab833e", "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Warning", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Warning\",\"type\":\"markdown\",\"params\":{\"markdown\":\"**This dashboard is only compatible with Kibana 5.4 and above. **\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "aa984970-1e0b-11e7-852e-cdcfcfdffddd", - "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "System Navigation", + "title": "System Navigation [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"System Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"[System Overview](#/dashboard/Metricbeat-system-overview) | [Host Overview (requires Kibana =\u003e 5.4)](#/dashboard/79ffd6e0-faa0-11e6-947f-177f697178b8) |\\n[Docker containers overview](#/dashboard/CPU-slash-Memory-per-container)\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"System Navigation [Metricbeat System]\",\"type\":\"markdown\",\"params\":{\"markdown\":\"[System Overview](#/dashboard/Metricbeat-system-overview) | [Host Overview](#/dashboard/79ffd6e0-faa0-11e6-947f-177f697178b8) |\\n[Containers overview](#/dashboard/CPU-slash-Memory-per-container)\",\"fontSize\":12},\"aggs\":[]}" }, "id": "System-Navigation", "type": "visualization", - "version": 2 + "version": 6 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Swap usage", + "title": "Swap usage [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Swap usage\",\"type\":\"metrics\",\"params\":{\"id\":\"cee2fd20-4d59-11e7-aee5-fdc812cc3bec\",\"type\":\"gauge\",\"series\":[{\"id\":\"cee2fd21-4d59-11e7-aee5-fdc812cc3bec\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"cee2fd22-4d59-11e7-aee5-fdc812cc3bec\",\"type\":\"avg\",\"field\":\"system.memory.swap.used.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Swap usage\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"gauge_color_rules\":[{\"value\":0,\"id\":\"d17c1e90-4d59-11e7-aee5-fdc812cc3bec\",\"gauge\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.7,\"id\":\"fc1d3490-4d59-11e7-aee5-fdc812cc3bec\",\"gauge\":\"rgba(251,158,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"0e204240-4d5a-11e7-aee5-fdc812cc3bec\",\"gauge\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"gauge_max\":\"\",\"filter\":\"\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Swap usage [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"cee2fd20-4d59-11e7-aee5-fdc812cc3bec\",\"type\":\"gauge\",\"series\":[{\"id\":\"cee2fd21-4d59-11e7-aee5-fdc812cc3bec\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"cee2fd22-4d59-11e7-aee5-fdc812cc3bec\",\"type\":\"avg\",\"field\":\"system.memory.swap.used.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Swap usage\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"gauge_color_rules\":[{\"value\":0,\"id\":\"d17c1e90-4d59-11e7-aee5-fdc812cc3bec\",\"gauge\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.7,\"id\":\"fc1d3490-4d59-11e7-aee5-fdc812cc3bec\",\"gauge\":\"rgba(251,158,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"0e204240-4d5a-11e7-aee5-fdc812cc3bec\",\"gauge\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"gauge_max\":\"\",\"filter\":\"\",\"show_grid\":1},\"aggs\":[]}" }, "id": "19e123b0-4d5a-11e7-aee5-fdc812cc3bec", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { @@ -274,86 +259,86 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Disk used", + "title": "Disk used [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Disk used\",\"type\":\"metrics\",\"params\":{\"id\":\"4e4dc780-4d1d-11e7-b5f2-2b7c1895bf32\",\"type\":\"gauge\",\"series\":[{\"id\":\"4e4dee90-4d1d-11e7-b5f2-2b7c1895bf32\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"4e4dee91-4d1d-11e7-b5f2-2b7c1895bf32\",\"type\":\"avg\",\"field\":\"system.fsstat.total_size.used\"},{\"id\":\"57c96ee0-4d54-11e7-b5f2-2b7c1895bf32\",\"type\":\"avg\",\"field\":\"system.fsstat.total_size.total\"},{\"script\":\"params.total != null \u0026\u0026 params.total \u003e 0 ? params.used/params.total : null\",\"id\":\"6304cca0-4d54-11e7-b5f2-2b7c1895bf32\",\"type\":\"calculation\",\"variables\":[{\"id\":\"6da10430-4d54-11e7-b5f2-2b7c1895bf32\",\"field\":\"4e4dee91-4d1d-11e7-b5f2-2b7c1895bf32\",\"name\":\"used\"},{\"id\":\"73b8c510-4d54-11e7-b5f2-2b7c1895bf32\",\"name\":\"total\",\"field\":\"57c96ee0-4d54-11e7-b5f2-2b7c1895bf32\"}]}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Disk used\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"gauge_color_rules\":[{\"value\":0,\"id\":\"51921d10-4d1d-11e7-b5f2-2b7c1895bf32\",\"gauge\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.7,\"id\":\"f26de750-4d54-11e7-b5f2-2b7c1895bf32\",\"gauge\":\"rgba(251,158,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"fa31d190-4d54-11e7-b5f2-2b7c1895bf32\",\"gauge\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"gauge_max\":\"1\",\"filter\":\"\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Disk used [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"4e4dc780-4d1d-11e7-b5f2-2b7c1895bf32\",\"type\":\"gauge\",\"series\":[{\"id\":\"4e4dee90-4d1d-11e7-b5f2-2b7c1895bf32\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"4e4dee91-4d1d-11e7-b5f2-2b7c1895bf32\",\"type\":\"avg\",\"field\":\"system.fsstat.total_size.used\"},{\"id\":\"57c96ee0-4d54-11e7-b5f2-2b7c1895bf32\",\"type\":\"avg\",\"field\":\"system.fsstat.total_size.total\"},{\"script\":\"params.total != null \u0026\u0026 params.total \u003e 0 ? params.used/params.total : null\",\"id\":\"6304cca0-4d54-11e7-b5f2-2b7c1895bf32\",\"type\":\"calculation\",\"variables\":[{\"id\":\"6da10430-4d54-11e7-b5f2-2b7c1895bf32\",\"field\":\"4e4dee91-4d1d-11e7-b5f2-2b7c1895bf32\",\"name\":\"used\"},{\"id\":\"73b8c510-4d54-11e7-b5f2-2b7c1895bf32\",\"name\":\"total\",\"field\":\"57c96ee0-4d54-11e7-b5f2-2b7c1895bf32\"}]}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Disk used\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"gauge_color_rules\":[{\"value\":0,\"id\":\"51921d10-4d1d-11e7-b5f2-2b7c1895bf32\",\"gauge\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.7,\"id\":\"f26de750-4d54-11e7-b5f2-2b7c1895bf32\",\"gauge\":\"rgba(251,158,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"fa31d190-4d54-11e7-b5f2-2b7c1895bf32\",\"gauge\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"gauge_max\":\"1\",\"filter\":\"\",\"show_grid\":1},\"aggs\":[]}" }, "id": "825fdb80-4d1d-11e7-b5f2-2b7c1895bf32", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Packetloss", + "title": "Packetloss [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Packetloss\",\"type\":\"metrics\",\"params\":{\"id\":\"6984af10-4d5d-11e7-aa29-87a97a796de6\",\"type\":\"metric\",\"series\":[{\"id\":\"6984af11-4d5d-11e7-aa29-87a97a796de6\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"6984af12-4d5d-11e7-aa29-87a97a796de6\",\"type\":\"max\",\"field\":\"system.network.in.dropped\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"In Packetloss\"},{\"id\":\"ac2e6b30-4d5d-11e7-aa29-87a97a796de6\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"ac2e6b31-4d5d-11e7-aa29-87a97a796de6\",\"type\":\"max\",\"field\":\"system.network.out.dropped\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Out Packetloss\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"6ba9b1f0-4d5d-11e7-aa29-87a97a796de6\"}]},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Packetloss [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"6984af10-4d5d-11e7-aa29-87a97a796de6\",\"type\":\"metric\",\"series\":[{\"id\":\"6984af11-4d5d-11e7-aa29-87a97a796de6\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"6984af12-4d5d-11e7-aa29-87a97a796de6\",\"type\":\"max\",\"field\":\"system.network.in.dropped\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"In Packetloss\"},{\"id\":\"ac2e6b30-4d5d-11e7-aa29-87a97a796de6\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"ac2e6b31-4d5d-11e7-aa29-87a97a796de6\",\"type\":\"max\",\"field\":\"system.network.out.dropped\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Out Packetloss\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"background_color_rules\":[{\"id\":\"6ba9b1f0-4d5d-11e7-aa29-87a97a796de6\"}],\"show_grid\":1},\"aggs\":[]}" }, "id": "96976150-4d5d-11e7-aa29-87a97a796de6", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: Interfaces by Incoming traffic", + "title": "Interfaces by Incoming traffic [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: Interfaces by Incoming traffic\",\"type\":\"metrics\",\"params\":{\"id\":\"42ceae90-4d60-11e7-9a4c-ed99bbcaa42b\",\"type\":\"top_n\",\"series\":[{\"id\":\"42ced5a0-4d60-11e7-9a4c-ed99bbcaa42b\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"42ced5a1-4d60-11e7-9a4c-ed99bbcaa42b\",\"type\":\"avg\",\"field\":\"system.network.in.bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Interfaces by Incoming traffic\",\"terms_field\":\"system.network.name\",\"terms_order_by\":\"42ced5a1-4d60-11e7-9a4c-ed99bbcaa42b\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"id\":\"44596d40-4d60-11e7-9a4c-ed99bbcaa42b\"}]},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Interfaces by Incoming traffic [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"42ceae90-4d60-11e7-9a4c-ed99bbcaa42b\",\"type\":\"top_n\",\"series\":[{\"id\":\"42ced5a0-4d60-11e7-9a4c-ed99bbcaa42b\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"42ced5a1-4d60-11e7-9a4c-ed99bbcaa42b\",\"type\":\"avg\",\"field\":\"system.network.in.bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Interfaces by Incoming traffic\",\"terms_field\":\"system.network.name\",\"terms_order_by\":\"42ced5a1-4d60-11e7-9a4c-ed99bbcaa42b\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"id\":\"44596d40-4d60-11e7-9a4c-ed99bbcaa42b\"}],\"show_grid\":1},\"aggs\":[]}" }, "id": "99381c80-4d60-11e7-9a4c-ed99bbcaa42b", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: Interfaces by Outgoing traffic", + "title": "Interfaces by Outgoing traffic [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: Interfaces by Outgoing traffic\",\"type\":\"metrics\",\"params\":{\"id\":\"9cdba910-4d60-11e7-9a4c-ed99bbcaa42b\",\"type\":\"top_n\",\"series\":[{\"id\":\"9cdba911-4d60-11e7-9a4c-ed99bbcaa42b\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"9cdba912-4d60-11e7-9a4c-ed99bbcaa42b\",\"type\":\"avg\",\"field\":\"system.network.out.bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"system.network.name\",\"terms_order_by\":\"9cdba912-4d60-11e7-9a4c-ed99bbcaa42b\",\"label\":\"Interfaces by Outgoing traffic\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"id\":\"9db20be0-4d60-11e7-9a4c-ed99bbcaa42b\"}]},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Interfaces by Outgoing traffic [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"9cdba910-4d60-11e7-9a4c-ed99bbcaa42b\",\"type\":\"top_n\",\"series\":[{\"id\":\"9cdba911-4d60-11e7-9a4c-ed99bbcaa42b\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"9cdba912-4d60-11e7-9a4c-ed99bbcaa42b\",\"type\":\"avg\",\"field\":\"system.network.out.bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"bytes\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"system.network.name\",\"terms_order_by\":\"9cdba912-4d60-11e7-9a4c-ed99bbcaa42b\",\"label\":\"Interfaces by Outgoing traffic\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"id\":\"9db20be0-4d60-11e7-9a4c-ed99bbcaa42b\"}],\"show_grid\":1},\"aggs\":[]}" }, "id": "c5e3cf90-4d60-11e7-9a4c-ed99bbcaa42b", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\n \"index\": \"metricbeat-*\",\n \"query\": {\n \"query_string\": {\n \"query\": \"*\",\n \"analyze_wildcard\": true\n }\n },\n \"filter\": []\n}" }, - "title": "Number of processes", - "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}", + "title": "Number of processes [Metricbeat System]", + "uiStateJSON": "{\n \"vis\": {\n \"defaultColors\": {\n \"0 - 100\": \"rgb(0,104,55)\"\n }\n }\n}", "version": 1, - "visState": "{\"title\":\"Number of processes\",\"type\":\"metric\",\"params\":{\"addLegend\":false,\"addTooltip\":true,\"gauge\":{\"autoExtend\":false,\"backStyle\":\"Full\",\"colorSchema\":\"Green to Red\",\"colorsRange\":[{\"from\":0,\"to\":100}],\"gaugeColorMode\":\"None\",\"gaugeStyle\":\"Full\",\"gaugeType\":\"Metric\",\"invertColors\":false,\"labels\":{\"color\":\"black\",\"show\":true},\"orientation\":\"vertical\",\"percentageMode\":false,\"scale\":{\"color\":\"#333\",\"labels\":false,\"show\":false,\"width\":2},\"style\":{\"bgColor\":false,\"bgFill\":\"#000\",\"fontSize\":60,\"labelColor\":false,\"subText\":\"\"},\"type\":\"simple\",\"useRange\":false,\"verticalSplit\":false},\"type\":\"gauge\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"system.process.pid\",\"customLabel\":\"Processes\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Number of processes\",\n \"type\": \"metric\",\n \"params\": {\n \"addLegend\": false,\n \"addTooltip\": true,\n \"gauge\": {\n \"autoExtend\": false,\n \"backStyle\": \"Full\",\n \"colorSchema\": \"Green to Red\",\n \"colorsRange\": [\n {\n \"from\": 0,\n \"to\": 100\n }\n ],\n \"gaugeColorMode\": \"None\",\n \"gaugeStyle\": \"Full\",\n \"gaugeType\": \"Metric\",\n \"invertColors\": false,\n \"labels\": {\n \"color\": \"black\",\n \"show\": true\n },\n \"orientation\": \"vertical\",\n \"percentageMode\": false,\n \"scale\": {\n \"color\": \"#333\",\n \"labels\": false,\n \"show\": false,\n \"width\": 2\n },\n \"style\": {\n \"bgColor\": false,\n \"bgFill\": \"#000\",\n \"fontSize\": 60,\n \"labelColor\": false,\n \"subText\": \"\"\n },\n \"type\": \"simple\",\n \"useRange\": false,\n \"verticalSplit\": false\n },\n \"type\": \"gauge\"\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"system.process.pid\",\n \"customLabel\": \"Processes\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "590a60f0-5d87-11e7-8884-1bb4c3b890e4", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"\"}}}],\"highlightAll\":true,\"version\":true}" + "searchSourceJSON": "{\"filter\":[],\"highlightAll\":true,\"version\":true,\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"\",\"default_field\":\"*\"}},\"language\":\"lucene\"}}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"6b7b9a40-faa1-11e6-86b1-cd7735ff7e23\",\"panelIndex\":1,\"row\":12,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"4d546850-1b15-11e7-b09e-037021c4f8df\",\"panelIndex\":2,\"row\":6,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"089b85d0-1b16-11e7-b09e-037021c4f8df\",\"panelIndex\":3,\"row\":12,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"bfa5e400-1b16-11e7-b09e-037021c4f8df\",\"panelIndex\":4,\"row\":9,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"e0f001c0-1b18-11e7-b09e-037021c4f8df\",\"panelIndex\":5,\"row\":15,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"2e224660-1b19-11e7-b09e-037021c4f8df\",\"panelIndex\":6,\"row\":15,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"ab2d1e90-1b1a-11e7-b09e-037021c4f8df\",\"panelIndex\":7,\"row\":6,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"4e4bb1e0-1b1b-11e7-b09e-037021c4f8df\",\"panelIndex\":8,\"row\":9,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"26732e20-1b91-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":9,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"83e12df0-1b91-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":10,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":3,\"id\":\"d3166e80-1b91-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":11,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":7,\"id\":\"522ee670-1b92-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":12,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":9,\"id\":\"1aae9140-1b93-11e7-8ada-3df93aab833e\",\"panelIndex\":13,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":9,\"id\":\"34f97ee0-1b96-11e7-8ada-3df93aab833e\",\"panelIndex\":14,\"row\":4,\"size_x\":4,\"size_y\":2,\"type\":\"visualization\"},{\"col\":10,\"id\":\"aa984970-1e0b-11e7-852e-cdcfcfdffddd\",\"panelIndex\":15,\"row\":1,\"size_x\":3,\"size_y\":1,\"type\":\"visualization\"},{\"col\":1,\"id\":\"System-Navigation\",\"panelIndex\":16,\"row\":1,\"size_x\":9,\"size_y\":1,\"type\":\"visualization\"},{\"col\":1,\"id\":\"19e123b0-4d5a-11e7-aee5-fdc812cc3bec\",\"panelIndex\":21,\"row\":4,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":3,\"id\":\"d2e80340-4d5c-11e7-aa29-87a97a796de6\",\"panelIndex\":22,\"row\":4,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":7,\"id\":\"825fdb80-4d1d-11e7-b5f2-2b7c1895bf32\",\"panelIndex\":23,\"row\":4,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":11,\"id\":\"96976150-4d5d-11e7-aa29-87a97a796de6\",\"panelIndex\":25,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"99381c80-4d60-11e7-9a4c-ed99bbcaa42b\",\"panelIndex\":27,\"row\":18,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"c5e3cf90-4d60-11e7-9a4c-ed99bbcaa42b\",\"panelIndex\":28,\"row\":18,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"590a60f0-5d87-11e7-8884-1bb4c3b890e4\",\"panelIndex\":29,\"row\":4,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"}]", + "panelsJSON": "[{\"col\":1,\"id\":\"6b7b9a40-faa1-11e6-86b1-cd7735ff7e23\",\"panelIndex\":1,\"row\":12,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"4d546850-1b15-11e7-b09e-037021c4f8df\",\"panelIndex\":2,\"row\":6,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"089b85d0-1b16-11e7-b09e-037021c4f8df\",\"panelIndex\":3,\"row\":12,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"bfa5e400-1b16-11e7-b09e-037021c4f8df\",\"panelIndex\":4,\"row\":9,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"e0f001c0-1b18-11e7-b09e-037021c4f8df\",\"panelIndex\":5,\"row\":15,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"2e224660-1b19-11e7-b09e-037021c4f8df\",\"panelIndex\":6,\"row\":15,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"ab2d1e90-1b1a-11e7-b09e-037021c4f8df\",\"panelIndex\":7,\"row\":6,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"4e4bb1e0-1b1b-11e7-b09e-037021c4f8df\",\"panelIndex\":8,\"row\":9,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"26732e20-1b91-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":9,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"83e12df0-1b91-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":10,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":3,\"id\":\"d3166e80-1b91-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":11,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":7,\"id\":\"522ee670-1b92-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":12,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":9,\"id\":\"1aae9140-1b93-11e7-8ada-3df93aab833e\",\"panelIndex\":13,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":9,\"id\":\"34f97ee0-1b96-11e7-8ada-3df93aab833e\",\"panelIndex\":14,\"row\":4,\"size_x\":4,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"System-Navigation\",\"panelIndex\":16,\"row\":1,\"size_x\":12,\"size_y\":1,\"type\":\"visualization\"},{\"col\":1,\"id\":\"19e123b0-4d5a-11e7-aee5-fdc812cc3bec\",\"panelIndex\":21,\"row\":4,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":3,\"id\":\"d2e80340-4d5c-11e7-aa29-87a97a796de6\",\"panelIndex\":22,\"row\":4,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":7,\"id\":\"825fdb80-4d1d-11e7-b5f2-2b7c1895bf32\",\"panelIndex\":23,\"row\":4,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":11,\"id\":\"96976150-4d5d-11e7-aa29-87a97a796de6\",\"panelIndex\":25,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"99381c80-4d60-11e7-9a4c-ed99bbcaa42b\",\"panelIndex\":27,\"row\":18,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"c5e3cf90-4d60-11e7-9a4c-ed99bbcaa42b\",\"panelIndex\":28,\"row\":18,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"590a60f0-5d87-11e7-8884-1bb4c3b890e4\",\"panelIndex\":29,\"row\":4,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"}]", "refreshInterval": { "display": "Off", "pause": false, @@ -362,14 +347,14 @@ "timeFrom": "now-15m", "timeRestore": true, "timeTo": "now", - "title": "Metricbeat host overview", + "title": "[Metricbeat System] Host overview", "uiStateJSON": "{\"P-29\":{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}}", "version": 1 }, "id": "79ffd6e0-faa0-11e6-947f-177f697178b8", "type": "dashboard", - "version": 1 + "version": 3 } ], - "version": "6.0.0-alpha3-SNAPSHOT" -} + "version": "6.0.0-beta1-SNAPSHOT" +} \ No newline at end of file diff --git a/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-system-overview.json b/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-system-overview.json index a0516f18ec0..828c0a9447e 100644 --- a/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-system-overview.json +++ b/metricbeat/module/system/_meta/kibana/default/dashboard/Metricbeat-system-overview.json @@ -4,185 +4,170 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "System Navigation", + "title": "System Navigation [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"System Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"[System Overview](#/dashboard/Metricbeat-system-overview) | [Host Overview (requires Kibana =\u003e 5.4)](#/dashboard/79ffd6e0-faa0-11e6-947f-177f697178b8) |\\n[Docker containers overview](#/dashboard/CPU-slash-Memory-per-container)\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"System Navigation [Metricbeat System]\",\"type\":\"markdown\",\"params\":{\"markdown\":\"[System Overview](#/dashboard/Metricbeat-system-overview) | [Host Overview](#/dashboard/79ffd6e0-faa0-11e6-947f-177f697178b8) |\\n[Containers overview](#/dashboard/CPU-slash-Memory-per-container)\",\"fontSize\":12},\"aggs\":[]}" }, "id": "System-Navigation", "type": "visualization", - "version": 2 + "version": 6 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true,\"default_field\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Number of hosts", + "title": "Number of hosts [Metricbeat System]", "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}", "version": 1, - "visState": "{\"title\":\"Number of hosts\",\"type\":\"metric\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":false,\"gaugeType\":\"Metric\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"None\",\"useRange\":false,\"colorsRange\":[{\"from\":0,\"to\":100}],\"invertColors\":false,\"labels\":{\"show\":false,\"color\":\"black\"},\"scale\":{\"show\":false,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"simple\",\"style\":{\"fontSize\":\"63\",\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\"}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"beat.hostname\",\"customLabel\":\"Number of hosts\"}}],\"listeners\":{}}" + "visState": "{\"title\":\"Number of hosts [Metricbeat System]\",\"type\":\"metric\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":false,\"gaugeType\":\"Metric\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"None\",\"useRange\":false,\"colorsRange\":[{\"from\":0,\"to\":100}],\"invertColors\":false,\"labels\":{\"show\":false,\"color\":\"black\"},\"scale\":{\"show\":false,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"simple\",\"style\":{\"fontSize\":\"63\",\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\"}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"beat.hostname\",\"customLabel\":\"Number of hosts\"}}]}" }, "id": "c6f2ffd0-4d17-11e7-a196-69b9a7a020a9", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Top Hosts By Memory (Realtime)", + "title": "Top Hosts By Memory (Realtime) [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Top Hosts By Memory (Realtime)\",\"type\":\"metrics\",\"params\":{\"id\":\"31e5afa0-1b1c-11e7-b09e-037021c4f8df\",\"type\":\"top_n\",\"series\":[{\"id\":\"31e5afa1-1b1c-11e7-b09e-037021c4f8df\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"31e5afa2-1b1c-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.memory.actual.used.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"beat.hostname\",\"terms_order_by\":\"31e5afa2-1b1c-11e7-b09e-037021c4f8df\",\"terms_size\":\"10\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"value\":0,\"id\":\"33349dd0-1b1c-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.6,\"id\":\"997dc440-1b1c-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(254,146,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"a10d7f20-1b1c-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"drilldown_url\":\"../app/kibana#/dashboard/79ffd6e0-faa0-11e6-947f-177f697178b8?_a=(query:(query_string:(analyze_wildcard:!t,query:'beat.hostname:\\\"{{key}}\\\"')))\",\"filter\":\"\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Top Hosts By Memory (Realtime) [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"31e5afa0-1b1c-11e7-b09e-037021c4f8df\",\"type\":\"top_n\",\"series\":[{\"id\":\"31e5afa1-1b1c-11e7-b09e-037021c4f8df\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"31e5afa2-1b1c-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.memory.actual.used.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"beat.hostname\",\"terms_order_by\":\"31e5afa2-1b1c-11e7-b09e-037021c4f8df\",\"terms_size\":\"10\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"value\":0,\"id\":\"33349dd0-1b1c-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.6,\"id\":\"997dc440-1b1c-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(254,146,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"a10d7f20-1b1c-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"drilldown_url\":\"../app/kibana#/dashboard/79ffd6e0-faa0-11e6-947f-177f697178b8?_a=(query:(query_string:(analyze_wildcard:!t,query:'beat.hostname:\\\"{{key}}\\\"')))\",\"filter\":\"\",\"show_grid\":1},\"aggs\":[]}" }, "id": "fe064790-1b1f-11e7-bec4-a5e9ec5cab8b", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\n \"query\": {\n \"query_string\": {\n \"query\": \"*\"\n }\n },\n \"filter\": []\n}" }, - "title": "Top Hosts By CPU (Realtime)", + "title": "Top Hosts By CPU (Realtime) [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Top Hosts By CPU (Realtime)\",\"type\":\"metrics\",\"params\":{\"id\":\"31e5afa0-1b1c-11e7-b09e-037021c4f8df\",\"type\":\"top_n\",\"series\":[{\"id\":\"31e5afa1-1b1c-11e7-b09e-037021c4f8df\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"31e5afa2-1b1c-11e7-b09e-037021c4f8df\",\"type\":\"avg\",\"field\":\"system.cpu.user.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"beat.hostname\",\"terms_order_by\":\"31e5afa2-1b1c-11e7-b09e-037021c4f8df\",\"terms_size\":\"10\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"bar_color_rules\":[{\"value\":0,\"id\":\"33349dd0-1b1c-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.6,\"id\":\"997dc440-1b1c-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(254,146,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"a10d7f20-1b1c-11e7-b09e-037021c4f8df\",\"bar_color\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"drilldown_url\":\"../app/kibana#/dashboard/79ffd6e0-faa0-11e6-947f-177f697178b8?_a=(query:(query_string:(analyze_wildcard:!t,query:'beat.hostname:\\\"{{key}}\\\"')))\",\"filter\":\"\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\n \"title\": \"Top Hosts By CPU (Realtime)\",\n \"type\": \"metrics\",\n \"params\": {\n \"id\": \"31e5afa0-1b1c-11e7-b09e-037021c4f8df\",\n \"type\": \"top_n\",\n \"series\": [\n {\n \"id\": \"31e5afa1-1b1c-11e7-b09e-037021c4f8df\",\n \"color\": \"#68BC00\",\n \"split_mode\": \"terms\",\n \"metrics\": [\n {\n \"id\": \"31e5afa2-1b1c-11e7-b09e-037021c4f8df\",\n \"type\": \"avg\",\n \"field\": \"system.cpu.user.pct\"\n }\n ],\n \"seperate_axis\": 0,\n \"axis_position\": \"right\",\n \"formatter\": \"percent\",\n \"chart_type\": \"line\",\n \"line_width\": 1,\n \"point_size\": 1,\n \"fill\": 0.5,\n \"stacked\": \"none\",\n \"terms_field\": \"beat.hostname\",\n \"terms_order_by\": \"31e5afa2-1b1c-11e7-b09e-037021c4f8df\",\n \"terms_size\": \"10\"\n }\n ],\n \"time_field\": \"@timestamp\",\n \"index_pattern\": \"*\",\n \"interval\": \"auto\",\n \"axis_position\": \"left\",\n \"axis_formatter\": \"number\",\n \"show_legend\": 1,\n \"bar_color_rules\": [\n {\n \"value\": 0,\n \"id\": \"33349dd0-1b1c-11e7-b09e-037021c4f8df\",\n \"bar_color\": \"rgba(104,188,0,1)\",\n \"opperator\": \"gte\"\n },\n {\n \"value\": 0.6,\n \"id\": \"997dc440-1b1c-11e7-b09e-037021c4f8df\",\n \"bar_color\": \"rgba(254,146,0,1)\",\n \"opperator\": \"gte\"\n },\n {\n \"value\": 0.85,\n \"id\": \"a10d7f20-1b1c-11e7-b09e-037021c4f8df\",\n \"bar_color\": \"rgba(211,49,21,1)\",\n \"opperator\": \"gte\"\n }\n ],\n \"drilldown_url\": \"../app/kibana#/dashboard/79ffd6e0-faa0-11e6-947f-177f697178b8?_a=(query:(query_string:(analyze_wildcard:!t,query:'beat.hostname:\\\"{{key}}\\\"')))\",\n \"filter\": \"\"\n },\n \"aggs\": [],\n \"listeners\": {}\n}" }, "id": "855899e0-1b1c-11e7-b09e-037021c4f8df", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true,\"default_field\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Hosts histogram by CPU usage", + "title": "Hosts histogram by CPU usage [Metricbeat System]", "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0% - 5%\":\"rgb(247,252,245)\",\"5% - 10%\":\"rgb(199,233,192)\",\"10% - 15%\":\"rgb(116,196,118)\",\"15% - 20%\":\"rgb(35,139,69)\"}}}", "version": 1, - "visState": "{\"title\":\"Hosts histogram by CPU usage\",\"type\":\"heatmap\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"enableHover\":false,\"legendPosition\":\"right\",\"times\":[],\"colorsNumber\":4,\"colorSchema\":\"Greens\",\"setColorRange\":false,\"colorsRange\":[],\"invertColors\":false,\"percentageMode\":false,\"valueAxes\":[{\"show\":false,\"id\":\"ValueAxis-1\",\"type\":\"value\",\"scale\":{\"type\":\"linear\",\"defaultYExtents\":false},\"labels\":{\"show\":false,\"rotate\":0,\"color\":\"#555\"}}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.cpu.user.pct\",\"customLabel\":\"CPU usage\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"beat.hostname\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Hosts\"}}],\"listeners\":{}}" + "visState": "{\"title\":\"Hosts histogram by CPU usage [Metricbeat System]\",\"type\":\"heatmap\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"enableHover\":false,\"legendPosition\":\"right\",\"times\":[],\"colorsNumber\":4,\"colorSchema\":\"Greens\",\"setColorRange\":false,\"colorsRange\":[],\"invertColors\":false,\"percentageMode\":false,\"valueAxes\":[{\"show\":false,\"id\":\"ValueAxis-1\",\"type\":\"value\",\"scale\":{\"type\":\"linear\",\"defaultYExtents\":false},\"labels\":{\"show\":false,\"rotate\":0,\"color\":\"#555\"}}],\"type\":\"heatmap\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"system.cpu.user.pct\",\"customLabel\":\"CPU usage\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"beat.hostname\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Hosts\"}}]}" }, "id": "7cdb1330-4d1a-11e7-a196-69b9a7a020a9", "type": "visualization", - "version": 1 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: Inbound Traffic Metric", + "title": "Inbound Traffic [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: Inbound Traffic Metric\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"background_color_rules\":[{\"id\":\"0e346760-1b92-11e7-bec4-a5e9ec5cab8b\"}],\"filter\":\"-system.network.name:l*\",\"id\":\"0c761590-1b92-11e7-bec4-a5e9ec5cab8b\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"0c761591-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Inbound Traffic\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.in.bytes\",\"id\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"1s\"},{\"field\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"f2074f70-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"unit\":\"\"},{\"id\":\"c40e18f0-2c55-11e7-a0ad-277ce466684d\",\"type\":\"series_agg\",\"function\":\"sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}/s\",\"terms_field\":\"system.network.name\"},{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"37f70440-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Total Transfered\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.in.bytes\",\"id\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"\"},{\"unit\":\"\",\"id\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"field\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\"},{\"sigma\":\"\",\"field\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"id\":\"3e63c2f0-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"series_agg\",\"function\":\"overall_sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}\",\"terms_field\":\"system.network.name\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"metric\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Inbound Traffic [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"background_color_rules\":[{\"id\":\"0e346760-1b92-11e7-bec4-a5e9ec5cab8b\"}],\"filter\":\"-system.network.name:l*\",\"id\":\"0c761590-1b92-11e7-bec4-a5e9ec5cab8b\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"0c761591-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Inbound Traffic\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.in.bytes\",\"id\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"1s\"},{\"field\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"f2074f70-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"unit\":\"\"},{\"id\":\"c40e18f0-2c55-11e7-a0ad-277ce466684d\",\"type\":\"series_agg\",\"function\":\"sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}/s\",\"terms_field\":\"system.network.name\"},{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"37f70440-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Total Transfered\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.in.bytes\",\"id\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"\"},{\"unit\":\"\",\"id\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"field\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\"},{\"sigma\":\"\",\"field\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"id\":\"3e63c2f0-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"series_agg\",\"function\":\"overall_sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}\",\"terms_field\":\"system.network.name\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"metric\",\"show_grid\":1},\"aggs\":[]}" }, "id": "522ee670-1b92-11e7-bec4-a5e9ec5cab8b", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: Outbound Traffic Metric", + "title": "Outbound Traffic [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: Outbound Traffic Metric\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"background_color_rules\":[{\"id\":\"0e346760-1b92-11e7-bec4-a5e9ec5cab8b\"}],\"filter\":\"-system.network.name:l*\",\"id\":\"0c761590-1b92-11e7-bec4-a5e9ec5cab8b\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"0c761591-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Outbound Traffic\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.out.bytes\",\"id\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"1s\"},{\"field\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"f2074f70-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"unit\":\"\"},{\"id\":\"a1737470-2c55-11e7-a0ad-277ce466684d\",\"type\":\"series_agg\",\"function\":\"sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}/s\",\"terms_field\":\"system.network.name\"},{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"37f70440-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Total Transfered\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.out.bytes\",\"id\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"\"},{\"unit\":\"\",\"id\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"field\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\"},{\"sigma\":\"\",\"field\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"id\":\"3e63c2f0-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"series_agg\",\"function\":\"overall_sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}\",\"terms_field\":\"system.network.name\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"metric\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Outbound Traffic [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"background_color_rules\":[{\"id\":\"0e346760-1b92-11e7-bec4-a5e9ec5cab8b\"}],\"filter\":\"-system.network.name:l*\",\"id\":\"0c761590-1b92-11e7-bec4-a5e9ec5cab8b\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"0c761591-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Outbound Traffic\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.out.bytes\",\"id\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"0c761592-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"1s\"},{\"field\":\"1d659060-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"f2074f70-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"unit\":\"\"},{\"id\":\"a1737470-2c55-11e7-a0ad-277ce466684d\",\"type\":\"series_agg\",\"function\":\"sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}/s\",\"terms_field\":\"system.network.name\"},{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"bytes\",\"id\":\"37f70440-1b92-11e7-bec4-a5e9ec5cab8b\",\"label\":\"Total Transfered\",\"line_width\":1,\"metrics\":[{\"field\":\"system.network.out.bytes\",\"id\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"max\"},{\"field\":\"37f72b50-1b92-11e7-bec4-a5e9ec5cab8b\",\"id\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"derivative\",\"unit\":\"\"},{\"unit\":\"\",\"id\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"type\":\"positive_only\",\"field\":\"37f72b51-1b92-11e7-bec4-a5e9ec5cab8b\"},{\"sigma\":\"\",\"field\":\"f9da2dd0-1b92-11e7-a416-41f5ccdba2e6\",\"id\":\"3e63c2f0-1b92-11e7-bec4-a5e9ec5cab8b\",\"type\":\"series_agg\",\"function\":\"overall_sum\"}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"value_template\":\"{{value}}\",\"terms_field\":\"system.network.name\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"metric\",\"show_grid\":1},\"aggs\":[]}" }, "id": "1aae9140-1b93-11e7-8ada-3df93aab833e", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Disk used", + "title": "Disk used [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Disk used\",\"type\":\"metrics\",\"params\":{\"id\":\"4e4dc780-4d1d-11e7-b5f2-2b7c1895bf32\",\"type\":\"gauge\",\"series\":[{\"id\":\"4e4dee90-4d1d-11e7-b5f2-2b7c1895bf32\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"4e4dee91-4d1d-11e7-b5f2-2b7c1895bf32\",\"type\":\"avg\",\"field\":\"system.fsstat.total_size.used\"},{\"id\":\"57c96ee0-4d54-11e7-b5f2-2b7c1895bf32\",\"type\":\"avg\",\"field\":\"system.fsstat.total_size.total\"},{\"script\":\"params.total != null \u0026\u0026 params.total \u003e 0 ? params.used/params.total : null\",\"id\":\"6304cca0-4d54-11e7-b5f2-2b7c1895bf32\",\"type\":\"calculation\",\"variables\":[{\"id\":\"6da10430-4d54-11e7-b5f2-2b7c1895bf32\",\"field\":\"4e4dee91-4d1d-11e7-b5f2-2b7c1895bf32\",\"name\":\"used\"},{\"id\":\"73b8c510-4d54-11e7-b5f2-2b7c1895bf32\",\"name\":\"total\",\"field\":\"57c96ee0-4d54-11e7-b5f2-2b7c1895bf32\"}]}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Disk used\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"gauge_color_rules\":[{\"value\":0,\"id\":\"51921d10-4d1d-11e7-b5f2-2b7c1895bf32\",\"gauge\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.7,\"id\":\"f26de750-4d54-11e7-b5f2-2b7c1895bf32\",\"gauge\":\"rgba(251,158,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"fa31d190-4d54-11e7-b5f2-2b7c1895bf32\",\"gauge\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"gauge_max\":\"1\",\"filter\":\"\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Disk used [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"4e4dc780-4d1d-11e7-b5f2-2b7c1895bf32\",\"type\":\"gauge\",\"series\":[{\"id\":\"4e4dee90-4d1d-11e7-b5f2-2b7c1895bf32\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"4e4dee91-4d1d-11e7-b5f2-2b7c1895bf32\",\"type\":\"avg\",\"field\":\"system.fsstat.total_size.used\"},{\"id\":\"57c96ee0-4d54-11e7-b5f2-2b7c1895bf32\",\"type\":\"avg\",\"field\":\"system.fsstat.total_size.total\"},{\"script\":\"params.total != null \u0026\u0026 params.total \u003e 0 ? params.used/params.total : null\",\"id\":\"6304cca0-4d54-11e7-b5f2-2b7c1895bf32\",\"type\":\"calculation\",\"variables\":[{\"id\":\"6da10430-4d54-11e7-b5f2-2b7c1895bf32\",\"field\":\"4e4dee91-4d1d-11e7-b5f2-2b7c1895bf32\",\"name\":\"used\"},{\"id\":\"73b8c510-4d54-11e7-b5f2-2b7c1895bf32\",\"name\":\"total\",\"field\":\"57c96ee0-4d54-11e7-b5f2-2b7c1895bf32\"}]}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Disk used\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"gauge_color_rules\":[{\"value\":0,\"id\":\"51921d10-4d1d-11e7-b5f2-2b7c1895bf32\",\"gauge\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.7,\"id\":\"f26de750-4d54-11e7-b5f2-2b7c1895bf32\",\"gauge\":\"rgba(251,158,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"fa31d190-4d54-11e7-b5f2-2b7c1895bf32\",\"gauge\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"gauge_max\":\"1\",\"filter\":\"\",\"show_grid\":1},\"aggs\":[]}" }, "id": "825fdb80-4d1d-11e7-b5f2-2b7c1895bf32", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: Memory Usage Gauge", + "title": "Memory Usage Gauge [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: Memory Usage Gauge\",\"type\":\"metrics\",\"params\":{\"id\":\"9f51b730-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"gauge\",\"series\":[{\"id\":\"9f51b731-1b91-11e7-bec4-a5e9ec5cab8b\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"9f51b732-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"avg\",\"field\":\"system.memory.actual.used.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Memory Usage\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"gauge_color_rules\":[{\"value\":0,\"id\":\"a0d522e0-1b91-11e7-bec4-a5e9ec5cab8b\",\"gauge\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.7,\"id\":\"b45ad8f0-1b91-11e7-bec4-a5e9ec5cab8b\",\"gauge\":\"rgba(254,146,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"c06e9550-1b91-11e7-bec4-a5e9ec5cab8b\",\"gauge\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"gauge_max\":\"1\",\"filter\":\"\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Memory Usage Gauge [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"id\":\"9f51b730-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"gauge\",\"series\":[{\"id\":\"9f51b731-1b91-11e7-bec4-a5e9ec5cab8b\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"9f51b732-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"avg\",\"field\":\"system.memory.actual.used.pct\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Memory Usage\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"gauge_color_rules\":[{\"value\":0,\"id\":\"a0d522e0-1b91-11e7-bec4-a5e9ec5cab8b\",\"gauge\":\"rgba(104,188,0,1)\",\"opperator\":\"gte\"},{\"value\":0.7,\"id\":\"b45ad8f0-1b91-11e7-bec4-a5e9ec5cab8b\",\"gauge\":\"rgba(254,146,0,1)\",\"opperator\":\"gte\"},{\"value\":0.85,\"id\":\"c06e9550-1b91-11e7-bec4-a5e9ec5cab8b\",\"gauge\":\"rgba(211,49,21,1)\",\"opperator\":\"gte\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"gauge_max\":\"1\",\"filter\":\"\",\"show_grid\":1},\"aggs\":[]}" }, "id": "d3166e80-1b91-11e7-bec4-a5e9ec5cab8b", "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, - "title": "Metricbeat: CPU Usage Gauge", + "title": "CPU Usage Gauge [Metricbeat System]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Metricbeat: CPU Usage Gauge\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"filter\":\"\",\"gauge_color_rules\":[{\"gauge\":\"rgba(104,188,0,1)\",\"id\":\"4ef2c3b0-1b91-11e7-bec4-a5e9ec5cab8b\",\"opperator\":\"gte\",\"value\":0},{\"gauge\":\"rgba(254,146,0,1)\",\"id\":\"e6561ae0-1b91-11e7-bec4-a5e9ec5cab8b\",\"opperator\":\"gte\",\"value\":0.7},{\"gauge\":\"rgba(211,49,21,1)\",\"id\":\"ec655040-1b91-11e7-bec4-a5e9ec5cab8b\",\"opperator\":\"gte\",\"value\":0.85}],\"gauge_inner_width\":10,\"gauge_max\":\"1\",\"gauge_style\":\"half\",\"gauge_width\":10,\"id\":\"4c9e2550-1b91-11e7-bec4-a5e9ec5cab8b\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"percent\",\"id\":\"4c9e2551-1b91-11e7-bec4-a5e9ec5cab8b\",\"label\":\"CPU Usage\",\"line_width\":1,\"metrics\":[{\"field\":\"system.cpu.user.pct\",\"id\":\"4c9e2552-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"avg\"},{\"field\":\"system.cpu.system.pct\",\"id\":\"225c2140-5fd7-11e7-a63a-a937b7c1a7e1\",\"type\":\"avg\"},{\"field\":\"system.cpu.cores\",\"id\":\"837a30c0-5fd7-11e7-a63a-a937b7c1a7e1\",\"type\":\"avg\"},{\"script\":\"params.n \u003e 0 ? (params.user+params.system)/params.n : null\",\"id\":\"587aa510-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"calculation\",\"variables\":[{\"field\":\"4c9e2552-1b91-11e7-bec4-a5e9ec5cab8b\",\"id\":\"5a19af10-1b91-11e7-bec4-a5e9ec5cab8b\",\"name\":\"user\"},{\"field\":\"225c2140-5fd7-11e7-a63a-a937b7c1a7e1\",\"id\":\"32b54f80-5fd7-11e7-a63a-a937b7c1a7e1\",\"name\":\"system\"},{\"field\":\"837a30c0-5fd7-11e7-a63a-a937b7c1a7e1\",\"id\":\"8ba6eef0-5fd7-11e7-a63a-a937b7c1a7e1\",\"name\":\"n\"}]}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"everything\",\"stacked\":\"none\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"gauge\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"CPU Usage Gauge [Metricbeat System]\",\"type\":\"metrics\",\"params\":{\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"filter\":\"\",\"gauge_color_rules\":[{\"gauge\":\"rgba(104,188,0,1)\",\"id\":\"4ef2c3b0-1b91-11e7-bec4-a5e9ec5cab8b\",\"opperator\":\"gte\",\"value\":0},{\"gauge\":\"rgba(254,146,0,1)\",\"id\":\"e6561ae0-1b91-11e7-bec4-a5e9ec5cab8b\",\"opperator\":\"gte\",\"value\":0.7},{\"gauge\":\"rgba(211,49,21,1)\",\"id\":\"ec655040-1b91-11e7-bec4-a5e9ec5cab8b\",\"opperator\":\"gte\",\"value\":0.85}],\"gauge_inner_width\":10,\"gauge_max\":\"1\",\"gauge_style\":\"half\",\"gauge_width\":10,\"id\":\"4c9e2550-1b91-11e7-bec4-a5e9ec5cab8b\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"percent\",\"id\":\"4c9e2551-1b91-11e7-bec4-a5e9ec5cab8b\",\"label\":\"CPU Usage\",\"line_width\":1,\"metrics\":[{\"field\":\"system.cpu.user.pct\",\"id\":\"4c9e2552-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"avg\"},{\"field\":\"system.cpu.system.pct\",\"id\":\"225c2140-5fd7-11e7-a63a-a937b7c1a7e1\",\"type\":\"avg\"},{\"field\":\"system.cpu.cores\",\"id\":\"837a30c0-5fd7-11e7-a63a-a937b7c1a7e1\",\"type\":\"avg\"},{\"script\":\"params.n \u003e 0 ? (params.user+params.system)/params.n : null\",\"id\":\"587aa510-1b91-11e7-bec4-a5e9ec5cab8b\",\"type\":\"calculation\",\"variables\":[{\"field\":\"4c9e2552-1b91-11e7-bec4-a5e9ec5cab8b\",\"id\":\"5a19af10-1b91-11e7-bec4-a5e9ec5cab8b\",\"name\":\"user\"},{\"field\":\"225c2140-5fd7-11e7-a63a-a937b7c1a7e1\",\"id\":\"32b54f80-5fd7-11e7-a63a-a937b7c1a7e1\",\"name\":\"system\"},{\"field\":\"837a30c0-5fd7-11e7-a63a-a937b7c1a7e1\",\"id\":\"8ba6eef0-5fd7-11e7-a63a-a937b7c1a7e1\",\"name\":\"n\"}]}],\"point_size\":1,\"seperate_axis\":0,\"split_mode\":\"everything\",\"stacked\":\"none\"}],\"show_legend\":1,\"time_field\":\"@timestamp\",\"type\":\"gauge\",\"show_grid\":1},\"aggs\":[]}" }, "id": "83e12df0-1b91-11e7-bec4-a5e9ec5cab8b", "type": "visualization", - "version": 1 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\"}},\"filter\":[]}" - }, - "title": "Tip System overview", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"Tip System overview\",\"type\":\"metrics\",\"params\":{\"id\":\"0a46a600-4d64-11e7-aa29-87a97a796de6\",\"type\":\"markdown\",\"series\":[{\"id\":\"0a46cd10-4d64-11e7-aa29-87a97a796de6\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"0a46cd11-4d64-11e7-aa29-87a97a796de6\",\"type\":\"count\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"markdown\":\"**Tip:** Click on any of the hosts from the Top Hosts By CPU or Top Hosts by Memory to view more details about the host.\",\"background_color\":\"rgba(252,220,0,0)\"},\"aggs\":[],\"listeners\":{}}" - }, - "id": "e9d22060-4d64-11e7-aa29-87a97a796de6", - "type": "visualization", - "version": 1 + "version": 3 }, { "attributes": { "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}],\"highlightAll\":true,\"version\":true}" + "searchSourceJSON": "{\"filter\":[],\"highlightAll\":true,\"version\":true,\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\",\"default_field\":\"*\"}},\"language\":\"lucene\"}}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"System-Navigation\",\"panelIndex\":9,\"row\":1,\"size_x\":8,\"size_y\":1,\"type\":\"visualization\"},{\"col\":1,\"id\":\"c6f2ffd0-4d17-11e7-a196-69b9a7a020a9\",\"panelIndex\":11,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":7,\"id\":\"fe064790-1b1f-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":12,\"row\":4,\"size_x\":6,\"size_y\":5,\"type\":\"visualization\"},{\"col\":1,\"id\":\"855899e0-1b1c-11e7-b09e-037021c4f8df\",\"panelIndex\":13,\"row\":4,\"size_x\":6,\"size_y\":5,\"type\":\"visualization\"},{\"col\":1,\"id\":\"7cdb1330-4d1a-11e7-a196-69b9a7a020a9\",\"panelIndex\":14,\"row\":9,\"size_x\":12,\"size_y\":6,\"type\":\"visualization\"},{\"col\":9,\"id\":\"522ee670-1b92-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":16,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":11,\"id\":\"1aae9140-1b93-11e7-8ada-3df93aab833e\",\"panelIndex\":17,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":7,\"id\":\"825fdb80-4d1d-11e7-b5f2-2b7c1895bf32\",\"panelIndex\":18,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":5,\"id\":\"d3166e80-1b91-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":19,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":3,\"id\":\"83e12df0-1b91-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":20,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":9,\"id\":\"e9d22060-4d64-11e7-aa29-87a97a796de6\",\"panelIndex\":21,\"row\":1,\"size_x\":4,\"size_y\":1,\"type\":\"visualization\"}]", + "panelsJSON": "[{\"col\":1,\"id\":\"System-Navigation\",\"panelIndex\":9,\"row\":1,\"size_x\":12,\"size_y\":1,\"type\":\"visualization\"},{\"col\":1,\"id\":\"c6f2ffd0-4d17-11e7-a196-69b9a7a020a9\",\"panelIndex\":11,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":7,\"id\":\"fe064790-1b1f-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":12,\"row\":4,\"size_x\":6,\"size_y\":5,\"type\":\"visualization\"},{\"col\":1,\"id\":\"855899e0-1b1c-11e7-b09e-037021c4f8df\",\"panelIndex\":13,\"row\":4,\"size_x\":6,\"size_y\":5,\"type\":\"visualization\"},{\"col\":1,\"id\":\"7cdb1330-4d1a-11e7-a196-69b9a7a020a9\",\"panelIndex\":14,\"row\":9,\"size_x\":12,\"size_y\":6,\"type\":\"visualization\"},{\"col\":9,\"id\":\"522ee670-1b92-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":16,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":11,\"id\":\"1aae9140-1b93-11e7-8ada-3df93aab833e\",\"panelIndex\":17,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":7,\"id\":\"825fdb80-4d1d-11e7-b5f2-2b7c1895bf32\",\"panelIndex\":18,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":5,\"id\":\"d3166e80-1b91-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":19,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"},{\"col\":3,\"id\":\"83e12df0-1b91-11e7-bec4-a5e9ec5cab8b\",\"panelIndex\":20,\"row\":2,\"size_x\":2,\"size_y\":2,\"type\":\"visualization\"}]", "timeRestore": false, - "title": "Metricbeat system overview", + "title": "[Metricbeat System] Overview", "uiStateJSON": "{\"P-11\":{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}},\"P-12\":{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}},\"P-14\":{\"vis\":{\"defaultColors\":{\"0% - 8.75%\":\"rgb(247,252,245)\",\"17.5% - 26.25%\":\"rgb(116,196,118)\",\"26.25% - 35%\":\"rgb(35,139,69)\",\"8.75% - 17.5%\":\"rgb(199,233,192)\"}}},\"P-16\":{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}},\"P-2\":{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}},\"P-3\":{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}}", "version": 1 }, "id": "Metricbeat-system-overview", "type": "dashboard", - "version": 1 + "version": 3 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/metricbeat/module/system/module.yml b/metricbeat/module/system/module.yml index f047e9ee2a1..1cb7bc8f4b2 100644 --- a/metricbeat/module/system/module.yml +++ b/metricbeat/module/system/module.yml @@ -6,5 +6,4 @@ dashboards: file: Metricbeat-host-overview.json - id: CPU-slash-Memory-per-container - file: Metricbeat-docker-overview.json - + file: Metricbeat-containers-overview.json From 54293d38a934cd50b66b471c9463a1b66c4e5b25 Mon Sep 17 00:00:00 2001 From: Max Jonas Werner Date: Thu, 24 Aug 2017 14:27:47 +0200 Subject: [PATCH 115/139] closes #4837 Travis errors on chmod command (#4936) The command seems to do nothing helpful so I just removed it. --- generator/beat/{beat}/.travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/generator/beat/{beat}/.travis.yml b/generator/beat/{beat}/.travis.yml index 2e9d3058def..94d70a60049 100644 --- a/generator/beat/{beat}/.travis.yml +++ b/generator/beat/{beat}/.travis.yml @@ -28,7 +28,6 @@ addons: before_install: - umask 022 - - chmod -R go-w $GOPATH/src/github.com/elastic/beats # Redo the travis setup but with the elastic/libbeat path. This is needed so the package path is correct - mkdir -p $HOME/gopath/src/github.com/{github_name}/{beat}/ - rsync -az ${TRAVIS_BUILD_DIR}/ $HOME/gopath/src/github.com/{github_name}/{beat}/ From 211f9175fcc23d0f66e528ed1b19e4609bfb7c19 Mon Sep 17 00:00:00 2001 From: Steffen Siering Date: Thu, 24 Aug 2017 22:16:55 +0200 Subject: [PATCH 116/139] Update saram dependency to v1.12 (#4977) * Update saram dependency to v1.12 * Update kafka versions and add lz4 compression * Update kafka output docs * Update Changelog * Fix build --- CHANGELOG.asciidoc | 2 + NOTICE | 28 +++++++ libbeat/docs/outputconfig.asciidoc | 5 +- libbeat/outputs/kafka/kafka.go | 18 +++- vendor/github.com/Shopify/sarama/CHANGELOG.md | 39 +++++++++ .../Shopify/sarama/{MIT-LICENSE => LICENSE} | 0 vendor/github.com/Shopify/sarama/README.md | 6 +- .../Shopify/sarama/api_versions_response.go | 7 +- .../Shopify/sarama/async_producer.go | 21 +++-- vendor/github.com/Shopify/sarama/broker.go | 13 ++- vendor/github.com/Shopify/sarama/client.go | 51 +++++++++++- vendor/github.com/Shopify/sarama/config.go | 7 +- vendor/github.com/Shopify/sarama/consumer.go | 18 ++-- .../github.com/Shopify/sarama/crc32_field.go | 3 +- .../sarama/describe_groups_response.go | 7 +- vendor/github.com/Shopify/sarama/errors.go | 26 +++++- .../Shopify/sarama/fetch_request.go | 2 +- .../Shopify/sarama/heartbeat_response.go | 6 +- .../Shopify/sarama/join_group_request.go | 83 +++++++++++++------ .../Shopify/sarama/join_group_response.go | 7 +- .../Shopify/sarama/leave_group_response.go | 6 +- .../Shopify/sarama/list_groups_response.go | 7 +- .../github.com/Shopify/sarama/partitioner.go | 12 +++ .../Shopify/sarama/produce_response.go | 7 +- .../github.com/Shopify/sarama/real_decoder.go | 7 +- .../Shopify/sarama/sasl_handshake_response.go | 8 +- .../Shopify/sarama/sync_group_response.go | 7 +- .../Shopify/sarama/sync_producer.go | 8 +- vendor/github.com/Shopify/sarama/utils.go | 1 + vendor/vendor.json | 9 +- 30 files changed, 322 insertions(+), 99 deletions(-) rename vendor/github.com/Shopify/sarama/{MIT-LICENSE => LICENSE} (100%) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 1409a2b4adf..59b1e929751 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -76,6 +76,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Get by default the credentials for connecting to Kibana from the Elasticsearch output configuration. {pull}4867[4867] - Move TCP UDP start up into `server.Start()` {pull}4903[4903] - Added `cloud.id` and `cloud.auth` settings, for simplifying using Beats with the Elastic Cloud. {issue}4959[4959] +- Add lz4 compression support to kafka output. {pull}4977[4977] +- Add newer kafka versions to kafka output. {pull}4977[4977] *Auditbeat* diff --git a/NOTICE b/NOTICE index fe0ffa0ebd2..28087a70ecb 100644 --- a/NOTICE +++ b/NOTICE @@ -3034,6 +3034,34 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------- +Dependency: github.com/Shopify/sarama +Version: v1.12/enh/offset-replica-id +Revision: c292021939f5aba53b3ffc2cb09c7aadb32a42df +License type (autodetected): MIT license +./vendor/github.com/Shopify/sarama/LICENSE: +-------------------------------------------------------------------- +Copyright (c) 2013 Evan Huus + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + -------------------------------------------------------------------- Dependency: github.com/Sirupsen/logrus Revision: 5e5dc898656f695e2a086b8e12559febbfc01562 diff --git a/libbeat/docs/outputconfig.asciidoc b/libbeat/docs/outputconfig.asciidoc index c07e0037a2b..a2443fc8abe 100644 --- a/libbeat/docs/outputconfig.asciidoc +++ b/libbeat/docs/outputconfig.asciidoc @@ -596,8 +596,7 @@ supported stable version (currently version 0.8.2.0). Event timestamps will be added, if version 0.10.0.0+ is enabled. -Valid values are `0.8.2.0`, `0.8.2.1`, `0.8.2.2`, `0.8.2`, `0.8`, `0.9.0.0`, -`0.9.0.1`, `0.9.0`, `0.9`, `0.10.0.0`, `0.10.0`, and `0.10`. +Valid values are all kafka releases in between `0.8.2.0` and `0.11.0.0`. ===== `username` @@ -720,7 +719,7 @@ The keep-alive period for an active network connection. If 0s, keep-alives are d ===== `compression` -Sets the output compression codec. Must be one of `none`, `snappy` and `gzip`. The default is `gzip`. +Sets the output compression codec. Must be one of `none`, `snappy`, `lz4` and `gzip`. The default is `gzip`. [[kafka-max_message_bytes]] ===== `max_message_bytes` diff --git a/libbeat/outputs/kafka/kafka.go b/libbeat/outputs/kafka/kafka.go index 3abed124473..c7d2cc21bef 100644 --- a/libbeat/outputs/kafka/kafka.go +++ b/libbeat/outputs/kafka/kafka.go @@ -45,12 +45,21 @@ var ( errNoHosts = errors.New("No hosts configured") ) +// TODO: remove me. +// Compat version overwrite for missing versions in sarama +// Public API is compatible between these versions. +var ( + v0_10_2_1 = sarama.V0_10_2_0 + v0_11_0_0 = sarama.V0_10_2_0 +) + var ( compressionModes = map[string]sarama.CompressionCodec{ "none": sarama.CompressionNone, "no": sarama.CompressionNone, "off": sarama.CompressionNone, "gzip": sarama.CompressionGZIP, + "lz4": sarama.CompressionLZ4, "snappy": sarama.CompressionSnappy, } @@ -73,7 +82,14 @@ var ( "0.10.0": sarama.V0_10_0_1, "0.10.1.0": sarama.V0_10_1_0, "0.10.1": sarama.V0_10_1_0, - "0.10": sarama.V0_10_1_0, + "0.10.2.0": sarama.V0_10_2_0, + "0.10.2.1": v0_10_2_1, + "0.10.2": v0_10_2_1, + "0.10": v0_10_2_1, + + "0.11.0.0": v0_11_0_0, + "0.11.0": v0_11_0_0, + "0.11": v0_11_0_0, } ) diff --git a/vendor/github.com/Shopify/sarama/CHANGELOG.md b/vendor/github.com/Shopify/sarama/CHANGELOG.md index aad986fef9a..0a0082df752 100644 --- a/vendor/github.com/Shopify/sarama/CHANGELOG.md +++ b/vendor/github.com/Shopify/sarama/CHANGELOG.md @@ -1,7 +1,46 @@ # Changelog +#### Version 1.12.0 (2017-05-08) + +New Features: + - Added support for the `ApiVersions` request and response pair, and Kafka + version 0.10.2 ([#867](https://github.com/Shopify/sarama/pull/867)). Note + that you still need to specify the Kafka version in the Sarama configuration + for the time being. + - Added a `Brokers` method to the Client which returns the complete set of + active brokers ([#813](https://github.com/Shopify/sarama/pull/813)). + - Added an `InSyncReplicas` method to the Client which returns the set of all + in-sync broker IDs for the given partition, now that the Kafka versions for + which this was misleading are no longer in our supported set + ([#872](https://github.com/Shopify/sarama/pull/872)). + - Added a `NewCustomHashPartitioner` method which allows constructing a hash + partitioner with a custom hash method in case the default (FNV-1a) is not + suitable + ([#837](https://github.com/Shopify/sarama/pull/837), + [#841](https://github.com/Shopify/sarama/pull/841)). + +Improvements: + - Recognize more Kafka error codes + ([#859](https://github.com/Shopify/sarama/pull/859)). + +Bug Fixes: + - Fix an issue where decoding a malformed FetchRequest would not return the + correct error ([#818](https://github.com/Shopify/sarama/pull/818)). + - Respect ordering of group protocols in JoinGroupRequests. This fix is + transparent if you're using the `AddGroupProtocol` or + `AddGroupProtocolMetadata` helpers; otherwise you will need to switch from + the `GroupProtocols` field (now deprecated) to use `OrderedGroupProtocols` + ([#812](https://github.com/Shopify/sarama/issues/812)). + - Fix an alignment-related issue with atomics on 32-bit architectures + ([#859](https://github.com/Shopify/sarama/pull/859)). + #### Version 1.11.0 (2016-12-20) +_Important:_ As of Sarama 1.11 it is necessary to set the config value of +`Producer.Return.Successes` to true in order to use the SyncProducer. Previous +versions would silently override this value when instantiating a SyncProducer +which led to unexpected values and data races. + New Features: - Metrics! Thanks to Sébastien Launay for all his work on this feature ([#701](https://github.com/Shopify/sarama/pull/701), diff --git a/vendor/github.com/Shopify/sarama/MIT-LICENSE b/vendor/github.com/Shopify/sarama/LICENSE similarity index 100% rename from vendor/github.com/Shopify/sarama/MIT-LICENSE rename to vendor/github.com/Shopify/sarama/LICENSE diff --git a/vendor/github.com/Shopify/sarama/README.md b/vendor/github.com/Shopify/sarama/README.md index c2968b92c35..6e12a07ae08 100644 --- a/vendor/github.com/Shopify/sarama/README.md +++ b/vendor/github.com/Shopify/sarama/README.md @@ -13,12 +13,14 @@ Sarama is an MIT-licensed Go client library for [Apache Kafka](https://kafka.apa - The [examples](./examples) directory contains more elaborate example applications. - The [tools](./tools) directory contains command line tools that can be useful for testing, diagnostics, and instrumentation. +You might also want to look at the [Frequently Asked Questions](https://github.com/Shopify/sarama/wiki/Frequently-Asked-Questions). + ### Compatibility and API stability Sarama provides a "2 releases + 2 months" compatibility guarantee: we support the two latest stable releases of Kafka and Go, and we provide a two month grace period for older releases. This means we currently officially support -Go 1.7 and 1.6, and Kafka 0.10.0 and 0.9.0, although older releases are +Go 1.8 and 1.7, and Kafka 0.10 and 0.9, although older releases are still likely to work. Sarama follows semantic versioning and provides API stability via the gopkg.in service. @@ -27,7 +29,7 @@ A changelog is available [here](CHANGELOG.md). ### Contributing -* Get started by checking our [contribution guidelines](https://github.com/Shopify/sarama/blob/master/CONTRIBUTING.md). +* Get started by checking our [contribution guidelines](https://github.com/Shopify/sarama/blob/master/.github/CONTRIBUTING.md). * Read the [Sarama wiki](https://github.com/Shopify/sarama/wiki) for more technical and design details. * The [Kafka Protocol Specification](https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol) diff --git a/vendor/github.com/Shopify/sarama/api_versions_response.go b/vendor/github.com/Shopify/sarama/api_versions_response.go index 16d62db2d30..23bc326e15f 100644 --- a/vendor/github.com/Shopify/sarama/api_versions_response.go +++ b/vendor/github.com/Shopify/sarama/api_versions_response.go @@ -50,12 +50,13 @@ func (r *ApiVersionsResponse) encode(pe packetEncoder) error { } func (r *ApiVersionsResponse) decode(pd packetDecoder, version int16) error { - if kerr, err := pd.getInt16(); err != nil { + kerr, err := pd.getInt16() + if err != nil { return err - } else { - r.Err = KError(kerr) } + r.Err = KError(kerr) + numBlocks, err := pd.getArrayLength() if err != nil { return err diff --git a/vendor/github.com/Shopify/sarama/async_producer.go b/vendor/github.com/Shopify/sarama/async_producer.go index 3af47fddd8e..6d71a6d8feb 100644 --- a/vendor/github.com/Shopify/sarama/async_producer.go +++ b/vendor/github.com/Shopify/sarama/async_producer.go @@ -17,24 +17,23 @@ import ( // scope. type AsyncProducer interface { - // AsyncClose triggers a shutdown of the producer, flushing any messages it may - // have buffered. The shutdown has completed when both the Errors and Successes - // channels have been closed. When calling AsyncClose, you *must* continue to - // read from those channels in order to drain the results of any messages in - // flight. + // AsyncClose triggers a shutdown of the producer. The shutdown has completed + // when both the Errors and Successes channels have been closed. When calling + // AsyncClose, you *must* continue to read from those channels in order to + // drain the results of any messages in flight. AsyncClose() - // Close shuts down the producer and flushes any messages it may have buffered. - // You must call this function before a producer object passes out of scope, as - // it may otherwise leak memory. You must call this before calling Close on the - // underlying client. + // Close shuts down the producer and waits for any buffered messages to be + // flushed. You must call this function before a producer object passes out of + // scope, as it may otherwise leak memory. You must call this before calling + // Close on the underlying client. Close() error // Input is the input channel for the user to write messages to that they // wish to send. Input() chan<- *ProducerMessage - // Successes is the success output channel back to the user when AckSuccesses is + // Successes is the success output channel back to the user when Return.Successes is // enabled. If Return.Successes is true, you MUST read from this channel or the // Producer will deadlock. It is suggested that you send and read messages // together in a single select statement. @@ -200,7 +199,7 @@ func (p *asyncProducer) Close() error { if p.conf.Producer.Return.Successes { go withRecover(func() { - for _ = range p.successes { + for range p.successes { } }) } diff --git a/vendor/github.com/Shopify/sarama/broker.go b/vendor/github.com/Shopify/sarama/broker.go index 89beecc8648..f57a6909429 100644 --- a/vendor/github.com/Shopify/sarama/broker.go +++ b/vendor/github.com/Shopify/sarama/broker.go @@ -52,7 +52,7 @@ type responsePromise struct { errors chan error } -// NewBroker creates and returns a Broker targetting the given host:port address. +// NewBroker creates and returns a Broker targeting the given host:port address. // This does not attempt to actually connect, you have to call Open() for that. func NewBroker(addr string) *Broker { return &Broker{id: -1, addr: addr} @@ -355,6 +355,17 @@ func (b *Broker) DescribeGroups(request *DescribeGroupsRequest) (*DescribeGroups return response, nil } +func (b *Broker) ApiVersions(request *ApiVersionsRequest) (*ApiVersionsResponse, error) { + response := new(ApiVersionsResponse) + + err := b.sendAndReceive(request, response) + if err != nil { + return nil, err + } + + return response, nil +} + func (b *Broker) send(rb protocolBody, promiseResponse bool) (*responsePromise, error) { b.lock.Lock() defer b.lock.Unlock() diff --git a/vendor/github.com/Shopify/sarama/client.go b/vendor/github.com/Shopify/sarama/client.go index f869a1434f7..45de3973d55 100644 --- a/vendor/github.com/Shopify/sarama/client.go +++ b/vendor/github.com/Shopify/sarama/client.go @@ -17,6 +17,9 @@ type Client interface { // altered after it has been created. Config() *Config + // Brokers returns the current set of active brokers as retrieved from cluster metadata. + Brokers() []*Broker + // Topics returns the set of available topics as retrieved from cluster metadata. Topics() ([]string, error) @@ -35,6 +38,11 @@ type Client interface { // Replicas returns the set of all replica IDs for the given partition. Replicas(topic string, partitionID int32) ([]int32, error) + // InSyncReplicas returns the set of all in-sync replica IDs for the given + // partition. In-sync replicas are replicas which are fully caught up with + // the partition leader. + InSyncReplicas(topic string, partitionID int32) ([]int32, error) + // RefreshMetadata takes a list of topics and queries the cluster to refresh the // available metadata for those topics. If no topics are provided, it will refresh // metadata for all topics. @@ -133,7 +141,7 @@ func NewClient(addrs []string, conf *Config) (Client, error) { client.seedBrokers = append(client.seedBrokers, NewBroker(addrs[index])) } - // do an initial fetch of all cluster metadata by specifing an empty list of topics + // do an initial fetch of all cluster metadata by specifying an empty list of topics err := client.RefreshMetadata() switch err { case nil: @@ -157,6 +165,16 @@ func (client *client) Config() *Config { return client.conf } +func (client *client) Brokers() []*Broker { + client.lock.RLock() + defer client.lock.RUnlock() + brokers := make([]*Broker, 0) + for _, broker := range client.brokers { + brokers = append(brokers, broker) + } + return brokers +} + func (client *client) Close() error { if client.Closed() { // Chances are this is being called from a defer() and the error will go unobserved @@ -282,6 +300,31 @@ func (client *client) Replicas(topic string, partitionID int32) ([]int32, error) return dupeAndSort(metadata.Replicas), nil } +func (client *client) InSyncReplicas(topic string, partitionID int32) ([]int32, error) { + if client.Closed() { + return nil, ErrClosedClient + } + + metadata := client.cachedMetadata(topic, partitionID) + + if metadata == nil { + err := client.RefreshMetadata(topic) + if err != nil { + return nil, err + } + metadata = client.cachedMetadata(topic, partitionID) + } + + if metadata == nil { + return nil, ErrUnknownTopicOrPartition + } + + if metadata.Err == ErrReplicaNotAvailable { + return nil, metadata.Err + } + return dupeAndSort(metadata.Isr), nil +} + func (client *client) Leader(topic string, partitionID int32) (*Broker, error) { if client.Closed() { return nil, ErrClosedClient @@ -592,12 +635,12 @@ func (client *client) tryRefreshMetadata(topics []string, attemptsRemaining int) switch err.(type) { case nil: // valid response, use it - if shouldRetry, err := client.updateMetadata(response); shouldRetry { + shouldRetry, err := client.updateMetadata(response) + if shouldRetry { Logger.Println("client/metadata found some partitions to be leaderless") return retry(err) // note: err can be nil - } else { - return err } + return err case PacketEncodingError: // didn't even send, return the error diff --git a/vendor/github.com/Shopify/sarama/config.go b/vendor/github.com/Shopify/sarama/config.go index a417a38b2e6..5021c57e908 100644 --- a/vendor/github.com/Shopify/sarama/config.go +++ b/vendor/github.com/Shopify/sarama/config.go @@ -305,10 +305,13 @@ func (c *Config) Validate() error { Logger.Println("Producer.RequiredAcks > 1 is deprecated and will raise an exception with kafka >= 0.8.2.0.") } if c.Producer.MaxMessageBytes >= int(MaxRequestSize) { - Logger.Println("Producer.MaxMessageBytes is larger than MaxRequestSize; it will be ignored.") + Logger.Println("Producer.MaxMessageBytes must be smaller than MaxRequestSize; it will be ignored.") } if c.Producer.Flush.Bytes >= int(MaxRequestSize) { - Logger.Println("Producer.Flush.Bytes is larger than MaxRequestSize; it will be ignored.") + Logger.Println("Producer.Flush.Bytes must be smaller than MaxRequestSize; it will be ignored.") + } + if (c.Producer.Flush.Bytes > 0 || c.Producer.Flush.Messages > 0) && c.Producer.Flush.Frequency == 0 { + Logger.Println("Producer.Flush: Bytes or Messages are set, but Frequency is not; messages may not get flushed.") } if c.Producer.Timeout%time.Millisecond != 0 { Logger.Println("Producer.Timeout only supports millisecond resolution; nanoseconds will be truncated.") diff --git a/vendor/github.com/Shopify/sarama/consumer.go b/vendor/github.com/Shopify/sarama/consumer.go index ddac564ff5a..78d7fa2caa6 100644 --- a/vendor/github.com/Shopify/sarama/consumer.go +++ b/vendor/github.com/Shopify/sarama/consumer.go @@ -289,10 +289,11 @@ type PartitionConsumer interface { } type partitionConsumer struct { - consumer *consumer - conf *Config - topic string - partition int32 + highWaterMarkOffset int64 // must be at the top of the struct because https://golang.org/pkg/sync/atomic/#pkg-note-BUG + consumer *consumer + conf *Config + topic string + partition int32 broker *brokerConsumer messages chan *ConsumerMessage @@ -302,9 +303,8 @@ type partitionConsumer struct { trigger, dying chan none responseResult error - fetchSize int32 - offset int64 - highWaterMarkOffset int64 + fetchSize int32 + offset int64 } var errTimedOut = errors.New("timed out feeding messages to the user") // not user-facing @@ -324,7 +324,7 @@ func (child *partitionConsumer) sendError(err error) { } func (child *partitionConsumer) dispatcher() { - for _ = range child.trigger { + for range child.trigger { select { case <-child.dying: close(child.trigger) @@ -411,7 +411,7 @@ func (child *partitionConsumer) Close() error { child.AsyncClose() go withRecover(func() { - for _ = range child.messages { + for range child.messages { // drain } }) diff --git a/vendor/github.com/Shopify/sarama/crc32_field.go b/vendor/github.com/Shopify/sarama/crc32_field.go index 5c286079056..f4fde18ad25 100644 --- a/vendor/github.com/Shopify/sarama/crc32_field.go +++ b/vendor/github.com/Shopify/sarama/crc32_field.go @@ -2,8 +2,7 @@ package sarama import ( "encoding/binary" - - "github.com/klauspost/crc32" + "hash/crc32" ) // crc32Field implements the pushEncoder and pushDecoder interfaces for calculating CRC32s. diff --git a/vendor/github.com/Shopify/sarama/describe_groups_response.go b/vendor/github.com/Shopify/sarama/describe_groups_response.go index d2c2071e1e6..542b3a97170 100644 --- a/vendor/github.com/Shopify/sarama/describe_groups_response.go +++ b/vendor/github.com/Shopify/sarama/describe_groups_response.go @@ -89,12 +89,13 @@ func (gd *GroupDescription) encode(pe packetEncoder) error { } func (gd *GroupDescription) decode(pd packetDecoder) (err error) { - if kerr, err := pd.getInt16(); err != nil { + kerr, err := pd.getInt16() + if err != nil { return err - } else { - gd.Err = KError(kerr) } + gd.Err = KError(kerr) + if gd.GroupId, err = pd.getString(); err != nil { return } diff --git a/vendor/github.com/Shopify/sarama/errors.go b/vendor/github.com/Shopify/sarama/errors.go index cc3f623d0d7..e6800ed4929 100644 --- a/vendor/github.com/Shopify/sarama/errors.go +++ b/vendor/github.com/Shopify/sarama/errors.go @@ -108,12 +108,20 @@ const ( ErrUnsupportedSASLMechanism KError = 33 ErrIllegalSASLState KError = 34 ErrUnsupportedVersion KError = 35 + ErrTopicAlreadyExists KError = 36 + ErrInvalidPartitions KError = 37 + ErrInvalidReplicationFactor KError = 38 + ErrInvalidReplicaAssignment KError = 39 + ErrInvalidConfig KError = 40 + ErrNotController KError = 41 + ErrInvalidRequest KError = 42 ErrUnsupportedForMessageFormat KError = 43 + ErrPolicyViolation KError = 44 ) func (err KError) Error() string { // Error messages stolen/adapted from - // https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol + // https://kafka.apache.org/protocol#protocol_error_codes switch err { case ErrNoError: return "kafka server: Not an error, why are you printing me?" @@ -189,8 +197,24 @@ func (err KError) Error() string { return "kafka server: Request is not valid given the current SASL state." case ErrUnsupportedVersion: return "kafka server: The version of API is not supported." + case ErrTopicAlreadyExists: + return "kafka server: Topic with this name already exists." + case ErrInvalidPartitions: + return "kafka server: Number of partitions is invalid." + case ErrInvalidReplicationFactor: + return "kafka server: Replication-factor is invalid." + case ErrInvalidReplicaAssignment: + return "kafka server: Replica assignment is invalid." + case ErrInvalidConfig: + return "kafka server: Configuration is invalid." + case ErrNotController: + return "kafka server: This is not the correct controller for this cluster." + case ErrInvalidRequest: + return "kafka server: This most likely occurs because of a request being malformed by the client library or the message was sent to an incompatible broker. See the broker logs for more details." case ErrUnsupportedForMessageFormat: return "kafka server: The requested operation is not supported by the message format version." + case ErrPolicyViolation: + return "kafka server: Request parameters do not satisfy the configured policy." } return fmt.Sprintf("Unknown error, how did this happen? Error code = %d", err) diff --git a/vendor/github.com/Shopify/sarama/fetch_request.go b/vendor/github.com/Shopify/sarama/fetch_request.go index ae701a3f29a..ab817a06eee 100644 --- a/vendor/github.com/Shopify/sarama/fetch_request.go +++ b/vendor/github.com/Shopify/sarama/fetch_request.go @@ -92,7 +92,7 @@ func (r *FetchRequest) decode(pd packetDecoder, version int16) (err error) { } fetchBlock := &fetchRequestBlock{} if err = fetchBlock.decode(pd); err != nil { - return nil + return err } r.blocks[topic][partition] = fetchBlock } diff --git a/vendor/github.com/Shopify/sarama/heartbeat_response.go b/vendor/github.com/Shopify/sarama/heartbeat_response.go index 3c51163ad1f..766f5fdec6f 100644 --- a/vendor/github.com/Shopify/sarama/heartbeat_response.go +++ b/vendor/github.com/Shopify/sarama/heartbeat_response.go @@ -10,11 +10,11 @@ func (r *HeartbeatResponse) encode(pe packetEncoder) error { } func (r *HeartbeatResponse) decode(pd packetDecoder, version int16) error { - if kerr, err := pd.getInt16(); err != nil { + kerr, err := pd.getInt16() + if err != nil { return err - } else { - r.Err = KError(kerr) } + r.Err = KError(kerr) return nil } diff --git a/vendor/github.com/Shopify/sarama/join_group_request.go b/vendor/github.com/Shopify/sarama/join_group_request.go index 656db4562d3..3a7ba17122d 100644 --- a/vendor/github.com/Shopify/sarama/join_group_request.go +++ b/vendor/github.com/Shopify/sarama/join_group_request.go @@ -1,11 +1,36 @@ package sarama +type GroupProtocol struct { + Name string + Metadata []byte +} + +func (p *GroupProtocol) decode(pd packetDecoder) (err error) { + p.Name, err = pd.getString() + if err != nil { + return err + } + p.Metadata, err = pd.getBytes() + return err +} + +func (p *GroupProtocol) encode(pe packetEncoder) (err error) { + if err := pe.putString(p.Name); err != nil { + return err + } + if err := pe.putBytes(p.Metadata); err != nil { + return err + } + return nil +} + type JoinGroupRequest struct { - GroupId string - SessionTimeout int32 - MemberId string - ProtocolType string - GroupProtocols map[string][]byte + GroupId string + SessionTimeout int32 + MemberId string + ProtocolType string + GroupProtocols map[string][]byte // deprecated; use OrderedGroupProtocols + OrderedGroupProtocols []*GroupProtocol } func (r *JoinGroupRequest) encode(pe packetEncoder) error { @@ -20,16 +45,31 @@ func (r *JoinGroupRequest) encode(pe packetEncoder) error { return err } - if err := pe.putArrayLength(len(r.GroupProtocols)); err != nil { - return err - } - for name, metadata := range r.GroupProtocols { - if err := pe.putString(name); err != nil { + if len(r.GroupProtocols) > 0 { + if len(r.OrderedGroupProtocols) > 0 { + return PacketDecodingError{"cannot specify both GroupProtocols and OrderedGroupProtocols on JoinGroupRequest"} + } + + if err := pe.putArrayLength(len(r.GroupProtocols)); err != nil { return err } - if err := pe.putBytes(metadata); err != nil { + for name, metadata := range r.GroupProtocols { + if err := pe.putString(name); err != nil { + return err + } + if err := pe.putBytes(metadata); err != nil { + return err + } + } + } else { + if err := pe.putArrayLength(len(r.OrderedGroupProtocols)); err != nil { return err } + for _, protocol := range r.OrderedGroupProtocols { + if err := protocol.encode(pe); err != nil { + return err + } + } } return nil @@ -62,16 +102,12 @@ func (r *JoinGroupRequest) decode(pd packetDecoder, version int16) (err error) { r.GroupProtocols = make(map[string][]byte) for i := 0; i < n; i++ { - name, err := pd.getString() - if err != nil { - return err - } - metadata, err := pd.getBytes() - if err != nil { + protocol := &GroupProtocol{} + if err := protocol.decode(pd); err != nil { return err } - - r.GroupProtocols[name] = metadata + r.GroupProtocols[protocol.Name] = protocol.Metadata + r.OrderedGroupProtocols = append(r.OrderedGroupProtocols, protocol) } return nil @@ -90,11 +126,10 @@ func (r *JoinGroupRequest) requiredVersion() KafkaVersion { } func (r *JoinGroupRequest) AddGroupProtocol(name string, metadata []byte) { - if r.GroupProtocols == nil { - r.GroupProtocols = make(map[string][]byte) - } - - r.GroupProtocols[name] = metadata + r.OrderedGroupProtocols = append(r.OrderedGroupProtocols, &GroupProtocol{ + Name: name, + Metadata: metadata, + }) } func (r *JoinGroupRequest) AddGroupProtocolMetadata(name string, metadata *ConsumerGroupMemberMetadata) error { diff --git a/vendor/github.com/Shopify/sarama/join_group_response.go b/vendor/github.com/Shopify/sarama/join_group_response.go index 94c7a7fde07..6d35fe36494 100644 --- a/vendor/github.com/Shopify/sarama/join_group_response.go +++ b/vendor/github.com/Shopify/sarama/join_group_response.go @@ -53,12 +53,13 @@ func (r *JoinGroupResponse) encode(pe packetEncoder) error { } func (r *JoinGroupResponse) decode(pd packetDecoder, version int16) (err error) { - if kerr, err := pd.getInt16(); err != nil { + kerr, err := pd.getInt16() + if err != nil { return err - } else { - r.Err = KError(kerr) } + r.Err = KError(kerr) + if r.GenerationId, err = pd.getInt32(); err != nil { return } diff --git a/vendor/github.com/Shopify/sarama/leave_group_response.go b/vendor/github.com/Shopify/sarama/leave_group_response.go index bd4a34f46ce..d60c626da01 100644 --- a/vendor/github.com/Shopify/sarama/leave_group_response.go +++ b/vendor/github.com/Shopify/sarama/leave_group_response.go @@ -10,11 +10,11 @@ func (r *LeaveGroupResponse) encode(pe packetEncoder) error { } func (r *LeaveGroupResponse) decode(pd packetDecoder, version int16) (err error) { - if kerr, err := pd.getInt16(); err != nil { + kerr, err := pd.getInt16() + if err != nil { return err - } else { - r.Err = KError(kerr) } + r.Err = KError(kerr) return nil } diff --git a/vendor/github.com/Shopify/sarama/list_groups_response.go b/vendor/github.com/Shopify/sarama/list_groups_response.go index 3a84f9b6c18..56115d4c75a 100644 --- a/vendor/github.com/Shopify/sarama/list_groups_response.go +++ b/vendor/github.com/Shopify/sarama/list_groups_response.go @@ -24,12 +24,13 @@ func (r *ListGroupsResponse) encode(pe packetEncoder) error { } func (r *ListGroupsResponse) decode(pd packetDecoder, version int16) error { - if kerr, err := pd.getInt16(); err != nil { + kerr, err := pd.getInt16() + if err != nil { return err - } else { - r.Err = KError(kerr) } + r.Err = KError(kerr) + n, err := pd.getArrayLength() if err != nil { return err diff --git a/vendor/github.com/Shopify/sarama/partitioner.go b/vendor/github.com/Shopify/sarama/partitioner.go index d24199da9c2..972932728a5 100644 --- a/vendor/github.com/Shopify/sarama/partitioner.go +++ b/vendor/github.com/Shopify/sarama/partitioner.go @@ -87,6 +87,18 @@ type hashPartitioner struct { hasher hash.Hash32 } +// NewCustomHashPartitioner is a wrapper around NewHashPartitioner, allowing the use of custom hasher. +// The argument is a function providing the instance, implementing the hash.Hash32 interface. This is to ensure that +// each partition dispatcher gets its own hasher, to avoid concurrency issues by sharing an instance. +func NewCustomHashPartitioner(hasher func() hash.Hash32) PartitionerConstructor { + return func(topic string) Partitioner { + p := new(hashPartitioner) + p.random = NewRandomPartitioner(topic) + p.hasher = hasher() + return p + } +} + // NewHashPartitioner returns a Partitioner which behaves as follows. If the message's key is nil then a // random partition is chosen. Otherwise the FNV-1a hash of the encoded bytes of the message key is used, // modulus the number of partitions. This ensures that messages with the same key always end up on the diff --git a/vendor/github.com/Shopify/sarama/produce_response.go b/vendor/github.com/Shopify/sarama/produce_response.go index 195abcb812e..3f05dd9fbdb 100644 --- a/vendor/github.com/Shopify/sarama/produce_response.go +++ b/vendor/github.com/Shopify/sarama/produce_response.go @@ -76,11 +76,12 @@ func (r *ProduceResponse) decode(pd packetDecoder, version int16) (err error) { } if r.Version >= 1 { - if millis, err := pd.getInt32(); err != nil { + millis, err := pd.getInt32() + if err != nil { return err - } else { - r.ThrottleTime = time.Duration(millis) * time.Millisecond } + + r.ThrottleTime = time.Duration(millis) * time.Millisecond } return nil diff --git a/vendor/github.com/Shopify/sarama/real_decoder.go b/vendor/github.com/Shopify/sarama/real_decoder.go index a0141af079c..3cf93533a6a 100644 --- a/vendor/github.com/Shopify/sarama/real_decoder.go +++ b/vendor/github.com/Shopify/sarama/real_decoder.go @@ -204,11 +204,12 @@ func (rd *realDecoder) getStringArray() ([]string, error) { ret := make([]string, n) for i := range ret { - if str, err := rd.getString(); err != nil { + str, err := rd.getString() + if err != nil { return nil, err - } else { - ret[i] = str } + + ret[i] = str } return ret, nil } diff --git a/vendor/github.com/Shopify/sarama/sasl_handshake_response.go b/vendor/github.com/Shopify/sarama/sasl_handshake_response.go index 8379bbb269b..ef290d4bc6d 100644 --- a/vendor/github.com/Shopify/sarama/sasl_handshake_response.go +++ b/vendor/github.com/Shopify/sarama/sasl_handshake_response.go @@ -11,13 +11,13 @@ func (r *SaslHandshakeResponse) encode(pe packetEncoder) error { } func (r *SaslHandshakeResponse) decode(pd packetDecoder, version int16) error { - if kerr, err := pd.getInt16(); err != nil { + kerr, err := pd.getInt16() + if err != nil { return err - } else { - r.Err = KError(kerr) } - var err error + r.Err = KError(kerr) + if r.EnabledMechanisms, err = pd.getStringArray(); err != nil { return err } diff --git a/vendor/github.com/Shopify/sarama/sync_group_response.go b/vendor/github.com/Shopify/sarama/sync_group_response.go index 12aef673034..194b382b4ab 100644 --- a/vendor/github.com/Shopify/sarama/sync_group_response.go +++ b/vendor/github.com/Shopify/sarama/sync_group_response.go @@ -17,12 +17,13 @@ func (r *SyncGroupResponse) encode(pe packetEncoder) error { } func (r *SyncGroupResponse) decode(pd packetDecoder, version int16) (err error) { - if kerr, err := pd.getInt16(); err != nil { + kerr, err := pd.getInt16() + if err != nil { return err - } else { - r.Err = KError(kerr) } + r.Err = KError(kerr) + r.MemberAssignment, err = pd.getBytes() return } diff --git a/vendor/github.com/Shopify/sarama/sync_producer.go b/vendor/github.com/Shopify/sarama/sync_producer.go index c77ae314077..dd096b6db67 100644 --- a/vendor/github.com/Shopify/sarama/sync_producer.go +++ b/vendor/github.com/Shopify/sarama/sync_producer.go @@ -25,10 +25,10 @@ type SyncProducer interface { // SendMessages will return an error. SendMessages(msgs []*ProducerMessage) error - // Close shuts down the producer and flushes any messages it may have buffered. - // You must call this function before a producer object passes out of scope, as - // it may otherwise leak memory. You must call this before calling Close on the - // underlying client. + // Close shuts down the producer and waits for any buffered messages to be + // flushed. You must call this function before a producer object passes out of + // scope, as it may otherwise leak memory. You must call this before calling + // Close on the underlying client. Close() error } diff --git a/vendor/github.com/Shopify/sarama/utils.go b/vendor/github.com/Shopify/sarama/utils.go index 3cbab2d92b1..d36db921089 100644 --- a/vendor/github.com/Shopify/sarama/utils.go +++ b/vendor/github.com/Shopify/sarama/utils.go @@ -148,5 +148,6 @@ var ( V0_10_0_0 = newKafkaVersion(0, 10, 0, 0) V0_10_0_1 = newKafkaVersion(0, 10, 0, 1) V0_10_1_0 = newKafkaVersion(0, 10, 1, 0) + V0_10_2_0 = newKafkaVersion(0, 10, 2, 0) minVersion = V0_8_2_0 ) diff --git a/vendor/vendor.json b/vendor/vendor.json index 34c9c2e3d2a..69708a13963 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -9,11 +9,14 @@ "revisionTime": "2017-05-24T00:36:31Z" }, { - "checksumSHA1": "WfQhuFTJ3zYmzVjeghW+9e76Yq0=", + "checksumSHA1": "GCpYz281OE/XkAQK23BLr+nK6O0=", "origin": "github.com/urso/sarama", "path": "github.com/Shopify/sarama", - "revision": "f0996189c86dc27338468f2a9b10077c6d572b34", - "revisionTime": "2016-11-23T00:27:23Z" + "revision": "c292021939f5aba53b3ffc2cb09c7aadb32a42df", + "revisionTime": "2016-11-23T00:27:23Z", + "tree": true, + "version": "v1.12/enh/offset-replica-id", + "versionExact": "v1.12/enh/offset-replica-id" }, { "checksumSHA1": "DYv6Q1+VfnUVxMwvk5IshAClLvw=", From 535439bdbcbf4b852ad2f5ed5a476dcaddfcc728 Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Fri, 25 Aug 2017 10:06:32 +0200 Subject: [PATCH 117/139] Fixes and renamings for Packetbeat dashboards (#5008) * Fixes #4937 by recreating the missing searches. * Adds a `dashboards.yml` file, to simplify importing / exporting * Does the renaming of the dashboards, requested by #4984, but not the visualizations or searches * A few more minor visual improvements --- .../dashboard/Packetbeat-cassandra.json | 32 ++-- .../dashboard/Packetbeat-dns-tunneling.json | 16 +- .../default/dashboard/Packetbeat-flows.json | 22 +-- .../default/dashboard/Packetbeat-http.json | 61 +++++--- .../default/dashboard/Packetbeat-mongodb.json | 63 +++++--- .../default/dashboard/Packetbeat-mysql.json | 38 ++--- .../default/dashboard/Packetbeat-nfs.json | 34 ++--- .../dashboard/Packetbeat-overview.json | 144 ++++++++++++++---- .../default/dashboard/Packetbeat-pgsql.json | 34 ++--- .../default/dashboard/Packetbeat-thrift.json | 30 ++-- packetbeat/dashboards.yml | 21 +++ 11 files changed, 322 insertions(+), 173 deletions(-) create mode 100644 packetbeat/dashboards.yml diff --git a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-cassandra.json b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-cassandra.json index af337c981f6..16eb1f1cb39 100644 --- a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-cassandra.json +++ b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-cassandra.json @@ -13,7 +13,7 @@ }, "id": "Cassandra-ResponseKeyspace", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -28,7 +28,7 @@ }, "id": "Cassandra-ResponseType", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -43,7 +43,7 @@ }, "id": "Cassandra-ResponseTime", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -58,7 +58,7 @@ }, "id": "Cassandra-RequestCount", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -73,7 +73,7 @@ }, "id": "Cassandra-Ops", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -88,7 +88,7 @@ }, "id": "Cassandra-RequestCountStackByType", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -103,7 +103,7 @@ }, "id": "Cassandra-ResponseCountStackByType", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -118,7 +118,7 @@ }, "id": "Cassandra-RequestCountByType", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -133,22 +133,22 @@ }, "id": "Cassandra-ResponseCountByType", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, "title": "Navigation", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\",\"fontSize\":\"10\"},\"aggs\":[]}" }, "id": "Navigation", "type": "visualization", - "version": 18 + "version": 10 }, { "attributes": { @@ -172,19 +172,19 @@ }, "id": "Cassandra-QueryView", "type": "search", - "version": 2 + "version": 1 }, { "attributes": { "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\",\"default_field\":\"*\"}},\"language\":\"lucene\"},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", "panelsJSON": "[{\"col\":10,\"id\":\"Cassandra-ResponseKeyspace\",\"panelIndex\":3,\"row\":3,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\"},{\"col\":7,\"id\":\"Cassandra-ResponseType\",\"panelIndex\":4,\"row\":3,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Cassandra-ResponseTime\",\"panelIndex\":9,\"row\":5,\"size_x\":12,\"size_y\":2,\"type\":\"visualization\"},{\"col\":4,\"id\":\"Cassandra-RequestCount\",\"panelIndex\":10,\"row\":1,\"size_x\":9,\"size_y\":2,\"type\":\"visualization\"},{\"col\":4,\"id\":\"Cassandra-Ops\",\"panelIndex\":11,\"row\":3,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Cassandra-RequestCountStackByType\",\"panelIndex\":15,\"row\":7,\"size_x\":12,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Cassandra-ResponseCountStackByType\",\"panelIndex\":16,\"row\":9,\"size_x\":12,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Cassandra-RequestCountByType\",\"panelIndex\":17,\"row\":11,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"Cassandra-ResponseCountByType\",\"panelIndex\":18,\"row\":11,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Navigation\",\"panelIndex\":19,\"row\":1,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\"},{\"id\":\"Cassandra-QueryView\",\"type\":\"search\",\"panelIndex\":20,\"size_x\":12,\"size_y\":3,\"col\":1,\"row\":14,\"columns\":[\"cassandra.request.query\",\"cassandra.response.result.rows.meta.keyspace\",\"cassandra.response.result.rows.meta.table\",\"cassandra.response.result.rows.num_rows\"],\"sort\":[\"@timestamp\",\"desc\"]}]", "timeRestore": false, - "title": "Packetbeat Cassandra", + "title": "[Packetbeat] Cassandra", "uiStateJSON": "{\"P-10\":{\"vis\":{\"legendOpen\":false}},\"P-17\":{\"vis\":{\"legendOpen\":false}},\"P-18\":{\"vis\":{\"legendOpen\":false}}}", "version": 1 }, @@ -193,5 +193,5 @@ "version": 2 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-dns-tunneling.json b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-dns-tunneling.json index 1231e3ef22a..1563c4dbe4e 100644 --- a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-dns-tunneling.json +++ b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-dns-tunneling.json @@ -14,7 +14,7 @@ }, "id": "Unique-FQDNs-per-eTLD 1", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -30,7 +30,7 @@ }, "id": "Unique-FQDNs-per-eTLD 1-Table", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -46,7 +46,7 @@ }, "id": "Bytes-Transferred-per-Domain", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -61,7 +61,7 @@ }, "id": "dc743240-1665-11e7-a6de-cbac1a3d0a7d", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -82,19 +82,19 @@ }, "id": "DNS", "type": "search", - "version": 10 + "version": 2 }, { "attributes": { "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"query\":\"NOT dns.question.type:PTR\",\"analyze_wildcard\":true}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":{\"query_string\":{\"query\":\"NOT dns.question.type:PTR\",\"analyze_wildcard\":true,\"default_field\":\"*\"}},\"language\":\"lucene\"},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", "panelsJSON": "[{\"col\":1,\"id\":\"Unique-FQDNs-per-eTLD 1\",\"panelIndex\":1,\"row\":1,\"size_x\":12,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Unique-FQDNs-per-eTLD 1-Table\",\"panelIndex\":2,\"row\":8,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Bytes-Transferred-per-Domain\",\"panelIndex\":4,\"row\":5,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"dc743240-1665-11e7-a6de-cbac1a3d0a7d\",\"panelIndex\":5,\"row\":8,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"}]", "timeRestore": false, - "title": "DNS Tunneling", + "title": "[Packetbeat] DNS Tunneling", "uiStateJSON": "{\"P-1\":{\"spy\":{\"mode\":{\"fill\":false,\"name\":null}},\"vis\":{\"legendOpen\":false,\"colors\":{\"Unique count of dns.question.name\":\"#E0752D\",\"Count\":\"#1F78C1\",\"Unique Subdomain Count\":\"#EF843C\"}}},\"P-2\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-4\":{\"vis\":{\"legendOpen\":false}},\"P-5\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", "version": 1 }, @@ -103,5 +103,5 @@ "version": 2 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-flows.json b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-flows.json index 58397f51238..c09eebed92e 100644 --- a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-flows.json +++ b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-flows.json @@ -4,16 +4,16 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, "title": "Navigation", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\",\"fontSize\":\"10\"},\"aggs\":[]}" }, "id": "Navigation", "type": "visualization", - "version": 18 + "version": 10 }, { "attributes": { @@ -29,7 +29,7 @@ }, "id": "Connections-over-time", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -45,7 +45,7 @@ }, "id": "Top-hosts-creating-traffic", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -61,7 +61,7 @@ }, "id": "Top-hosts-receiving-traffic", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -77,7 +77,7 @@ }, "id": "Network-traffic-between-your-hosts", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -106,19 +106,19 @@ }, "id": "Packetbeat-Flows-Search", "type": "search", - "version": 8 + "version": 1 }, { "attributes": { "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\",\"default_field\":\"*\"}},\"language\":\"lucene\"},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", "panelsJSON": "[{\"col\":1,\"id\":\"Navigation\",\"panelIndex\":2,\"row\":1,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\"},{\"col\":4,\"id\":\"Connections-over-time\",\"panelIndex\":3,\"row\":1,\"size_x\":9,\"size_y\":5,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Top-hosts-creating-traffic\",\"panelIndex\":1,\"row\":6,\"size_x\":6,\"size_y\":7,\"type\":\"visualization\"},{\"col\":7,\"id\":\"Top-hosts-receiving-traffic\",\"panelIndex\":4,\"row\":6,\"size_x\":6,\"size_y\":7,\"type\":\"visualization\"},{\"id\":\"Network-traffic-between-your-hosts\",\"type\":\"visualization\",\"panelIndex\":5,\"size_x\":12,\"size_y\":7,\"col\":1,\"row\":13}]", "timeRestore": false, - "title": "Packetbeat Flows", + "title": "[Packetbeat] Flows", "uiStateJSON": "{\"P-5\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", "version": 1 }, @@ -127,5 +127,5 @@ "version": 2 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-http.json b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-http.json index 01869a5aab7..62df971fc84 100644 --- a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-http.json +++ b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-http.json @@ -4,17 +4,17 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, - "savedSearchId": "Web-transactions", + "savedSearchId": "71908f00-88ca-11e7-ad9c-db80de0bf8d3", "title": "Web transactions", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Web transactions\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":false,\"mode\":\"stacked\",\"defaultYExtents\":false,\"scale\":\"linear\",\"times\":[],\"addTimeMarker\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Web transactions\",\n \"type\": \"histogram\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": false,\n \"mode\": \"stacked\",\n \"defaultYExtents\": false,\n \"scale\": \"linear\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Web-transactions", "type": "visualization", - "version": 4 + "version": 3 }, { "attributes": { @@ -29,7 +29,7 @@ }, "id": "HTTP-error-codes", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -44,34 +44,34 @@ }, "id": "HTTP-error-codes-evolution", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, "title": "Navigation", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\",\"fontSize\":\"10\"},\"aggs\":[]}" }, "id": "Navigation", "type": "visualization", - "version": 18 + "version": 10 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, - "savedSearchId": "Web-transactions", + "savedSearchId": "71908f00-88ca-11e7-ad9c-db80de0bf8d3", "title": "Total number of HTTP transactions", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Total number of HTTP transactions\",\"type\":\"metric\",\"params\":{\"fontSize\":\"37\",\"handleNoResults\":true},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Total number of HTTP transactions\",\n \"type\": \"metric\",\n \"params\": {\n \"fontSize\": \"37\",\n \"handleNoResults\": true\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n }\n ],\n \"listeners\": {}\n}" }, "id": "Total-number-of-HTTP-transactions", "type": "visualization", @@ -83,7 +83,7 @@ "kibanaSavedObjectMeta": { "searchSourceJSON": "{\n \"filter\": []\n}" }, - "savedSearchId": "Web-transactions", + "savedSearchId": "71908f00-88ca-11e7-ad9c-db80de0bf8d3", "title": "HTTP codes for the top queries", "version": 1, "visState": "{\n \"type\": \"pie\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"isDonut\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"type\": \"terms\",\n \"schema\": \"split\",\n \"params\": {\n \"field\": \"query\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"row\": false\n }\n },\n {\n \"id\": \"3\",\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"http.response.code\",\n \"size\": 10,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" @@ -96,30 +96,51 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, - "savedSearchId": "Web-transactions", + "savedSearchId": "71908f00-88ca-11e7-ad9c-db80de0bf8d3", "title": "Top 10 HTTP requests", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Top 10 HTTP requests\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"query\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Top 10 HTTP requests\",\n \"type\": \"table\",\n \"params\": {\n \"perPage\": 10,\n \"showPartialRows\": false,\n \"showMeticsAtAllLevels\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"query\",\n \"size\": 10,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Top-10-HTTP-requests", "type": "visualization", "version": 2 }, + { + "attributes": { + "columns": [ + "_source" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"packetbeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"lucene\",\"query\":\"*\"},\"filter\":[{\"meta\":{\"index\":\"packetbeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"type\",\"value\":\"http\",\"params\":{\"query\":\"http\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"type\":{\"query\":\"http\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}]}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "Web Transactions [Packetbeat]", + "version": 1 + }, + "id": "71908f00-88ca-11e7-ad9c-db80de0bf8d3", + "type": "search", + "version": 2 + }, { "attributes": { "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\",\"default_field\":\"*\"}},\"language\":\"lucene\"},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", "panelsJSON": "[{\"col\":4,\"id\":\"Web-transactions\",\"row\":1,\"size_x\":9,\"size_y\":4,\"type\":\"visualization\",\"panelIndex\":1},{\"col\":1,\"id\":\"HTTP-error-codes\",\"row\":8,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":2},{\"col\":7,\"id\":\"HTTP-error-codes-evolution\",\"row\":8,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":3},{\"col\":1,\"id\":\"Navigation\",\"row\":1,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\",\"panelIndex\":4},{\"col\":1,\"id\":\"Total-number-of-HTTP-transactions\",\"row\":5,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":5},{\"col\":4,\"id\":\"HTTP-codes-for-the-top-queries\",\"row\":5,\"size_x\":9,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":6},{\"id\":\"Top-10-HTTP-requests\",\"type\":\"visualization\",\"size_x\":12,\"size_y\":5,\"col\":1,\"row\":11,\"panelIndex\":7}]", "timeRestore": false, - "title": "Packetbeat HTTP", - "uiStateJSON": "{}", + "title": "[Packetbeat] HTTP", + "uiStateJSON": "{\"P-7\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-5\":{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}}", "version": 1 }, "id": "Packetbeat-HTTP", @@ -127,5 +148,5 @@ "version": 2 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-mongodb.json b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-mongodb.json index 37bd9dc0610..b2f66e74bff 100644 --- a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-mongodb.json +++ b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-mongodb.json @@ -4,28 +4,28 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, "title": "Navigation", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\",\"fontSize\":\"10\"},\"aggs\":[]}" }, "id": "Navigation", "type": "visualization", - "version": 18 + "version": 10 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, - "savedSearchId": "MongoDB-errors", + "savedSearchId": "651fd6d0-88d0-11e7-ad9c-db80de0bf8d3", "title": "MongoDB errors", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"MongoDB errors\",\"type\":\"line\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"radiusRatio\":9,\"scale\":\"linear\",\"setYExtents\":false,\"shareYAxis\":true,\"showCircles\":true,\"smoothLines\":false,\"spyPerPage\":10,\"times\":[],\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"resource\",\"size\":3,\"order\":\"desc\",\"orderBy\":\"1\",\"row\":true}},{\"id\":\"4\",\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"method\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"MongoDB errors\",\n \"type\": \"line\",\n \"params\": {\n \"addLegend\": true,\n \"addTimeMarker\": false,\n \"addTooltip\": true,\n \"defaultYExtents\": false,\n \"drawLinesBetweenPoints\": true,\n \"interpolate\": \"linear\",\n \"radiusRatio\": 9,\n \"scale\": \"linear\",\n \"setYExtents\": false,\n \"shareYAxis\": true,\n \"showCircles\": true,\n \"smoothLines\": false,\n \"spyPerPage\": 10,\n \"times\": [],\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"type\": \"terms\",\n \"schema\": \"split\",\n \"params\": {\n \"field\": \"resource\",\n \"size\": 3,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"row\": true\n }\n },\n {\n \"id\": \"4\",\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"method\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "MongoDB-errors", "type": "visualization", @@ -45,19 +45,19 @@ }, "id": "MongoDB-commands", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, - "savedSearchId": "MongoDB-errors", + "savedSearchId": "651fd6d0-88d0-11e7-ad9c-db80de0bf8d3", "title": "MongoDB errors per collection", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"MongoDB errors per collection\",\"type\":\"line\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"radiusRatio\":9,\"scale\":\"linear\",\"setYExtents\":false,\"shareYAxis\":true,\"showCircles\":true,\"smoothLines\":false,\"spyPerPage\":10,\"times\":[],\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"resource\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"MongoDB errors per collection\",\n \"type\": \"line\",\n \"params\": {\n \"addLegend\": true,\n \"addTimeMarker\": false,\n \"addTooltip\": true,\n \"defaultYExtents\": false,\n \"drawLinesBetweenPoints\": true,\n \"interpolate\": \"linear\",\n \"radiusRatio\": 9,\n \"scale\": \"linear\",\n \"setYExtents\": false,\n \"shareYAxis\": true,\n \"showCircles\": true,\n \"smoothLines\": false,\n \"spyPerPage\": 10,\n \"times\": [],\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"resource\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "MongoDB-errors-per-collection", "type": "visualization", @@ -76,7 +76,7 @@ }, "id": "MongoDB-in-slash-out-throughput", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -92,7 +92,7 @@ }, "id": "MongoDB-response-times-by-collection", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -107,7 +107,7 @@ }, "id": "Top-slowest-MongoDB-queries", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -123,7 +123,28 @@ }, "id": "Number-of-MongoDB-transactions-with-writeConcern-w-equal-0", "type": "visualization", - "version": 2 + "version": 1 + }, + { + "attributes": { + "columns": [ + "_source" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"packetbeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"*\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"index\":\"packetbeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"type\",\"value\":\"mongodb\",\"params\":{\"query\":\"mongodb\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"type\":{\"query\":\"mongodb\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}},{\"meta\":{\"index\":\"packetbeat-*\",\"negate\":true,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"status\",\"value\":\"OK\",\"params\":{\"query\":\"OK\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"status\":{\"query\":\"OK\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}]}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "MongoDB errors [Packetbeat]", + "version": 1 + }, + "id": "651fd6d0-88d0-11e7-ad9c-db80de0bf8d3", + "type": "search", + "version": 1 }, { "attributes": { @@ -149,7 +170,7 @@ }, "id": "MongoDB-transactions", "type": "search", - "version": 8 + "version": 1 }, { "attributes": { @@ -175,20 +196,20 @@ }, "id": "MongoDB-transactions-with-write-concern-0", "type": "search", - "version": 2 + "version": 1 }, { "attributes": { "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"default_field\":\"*\",\"query\":\"*\"}}},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"Navigation\",\"row\":1,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\",\"panelIndex\":1},{\"col\":4,\"id\":\"MongoDB-errors\",\"row\":1,\"size_x\":5,\"size_y\":4,\"type\":\"visualization\",\"panelIndex\":2},{\"col\":9,\"id\":\"MongoDB-commands\",\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\",\"panelIndex\":3},{\"col\":1,\"id\":\"MongoDB-errors-per-collection\",\"row\":5,\"size_x\":4,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":4},{\"col\":5,\"id\":\"MongoDB-in-slash-out-throughput\",\"row\":5,\"size_x\":4,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":5},{\"col\":1,\"id\":\"MongoDB-response-times-by-collection\",\"row\":8,\"size_x\":8,\"size_y\":5,\"type\":\"visualization\",\"panelIndex\":6},{\"col\":9,\"id\":\"Top-slowest-MongoDB-queries\",\"row\":8,\"size_x\":4,\"size_y\":5,\"type\":\"visualization\",\"panelIndex\":7},{\"id\":\"Number-of-MongoDB-transactions-with-writeConcern-w-equal-0\",\"type\":\"visualization\",\"size_x\":4,\"size_y\":3,\"col\":9,\"row\":5,\"panelIndex\":8}]", + "panelsJSON": "[{\"col\":1,\"id\":\"Navigation\",\"panelIndex\":1,\"row\":1,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\"},{\"col\":4,\"id\":\"MongoDB-errors\",\"panelIndex\":2,\"row\":1,\"size_x\":5,\"size_y\":4,\"type\":\"visualization\"},{\"col\":9,\"id\":\"MongoDB-commands\",\"panelIndex\":3,\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"MongoDB-errors-per-collection\",\"panelIndex\":4,\"row\":5,\"size_x\":4,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"MongoDB-in-slash-out-throughput\",\"panelIndex\":5,\"row\":5,\"size_x\":4,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"MongoDB-response-times-by-collection\",\"panelIndex\":6,\"row\":8,\"size_x\":8,\"size_y\":5,\"type\":\"visualization\"},{\"col\":9,\"id\":\"Top-slowest-MongoDB-queries\",\"panelIndex\":7,\"row\":8,\"size_x\":4,\"size_y\":5,\"type\":\"visualization\"},{\"col\":9,\"id\":\"Number-of-MongoDB-transactions-with-writeConcern-w-equal-0\",\"panelIndex\":8,\"row\":5,\"size_x\":4,\"size_y\":3,\"type\":\"visualization\"}]", "timeRestore": false, - "title": "Packetbeat MongoDB performance", - "uiStateJSON": "{}", + "title": "[Packetbeat] MongoDB", + "uiStateJSON": "{\"P-7\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", "version": 1 }, "id": "Packetbeat-MongoDB-performance", @@ -196,5 +217,5 @@ "version": 2 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-mysql.json b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-mysql.json index 52ffd70b3dd..ff5e591f0a1 100644 --- a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-mysql.json +++ b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-mysql.json @@ -14,7 +14,7 @@ }, "id": "MySQL-Errors", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -30,22 +30,22 @@ }, "id": "MySQL-Methods", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, "title": "Navigation", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\",\"fontSize\":\"10\"},\"aggs\":[]}" }, "id": "Navigation", "type": "visualization", - "version": 18 + "version": 10 }, { "attributes": { @@ -60,7 +60,7 @@ }, "id": "MySQL-throughput", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -76,7 +76,7 @@ }, "id": "Most-frequent-MySQL-queries", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -91,7 +91,7 @@ }, "id": "Slowest-MySQL-queries", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -106,7 +106,7 @@ }, "id": "Mysql-response-times-percentiles", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -118,11 +118,11 @@ "title": "MySQL Reads vs Writes", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"MySQL Reads vs Writes\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"mode\":\"stacked\",\"defaultYExtents\":false,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"times\":[],\"addTimeMarker\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"method: SELECT\",\"analyze_wildcard\":true}}}},{\"input\":{\"query\":{\"query_string\":{\"query\":\"method: INSERT or method: UPDATE or method: DELETE\",\"analyze_wildcard\":true}}}}]}}],\"listeners\":{}}" + "visState": "{\"title\":\"MySQL Reads vs Writes\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"mode\":\"stacked\",\"defaultYExtents\":false,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"times\":[],\"addTimeMarker\":false,\"setYExtents\":false,\"yAxis\":{},\"type\":\"area\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{\"text\":\"@timestamp per 30 seconds\"}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"legendPosition\":\"right\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"method: SELECT\",\"analyze_wildcard\":true}}}},{\"input\":{\"query\":\"method: INSERT OR method: UPDATE OR method: DELETE\"}}]}}]}" }, "id": "MySQL-Reads-vs-Writes", "type": "visualization", - "version": 2 + "version": 3 }, { "attributes": { @@ -147,7 +147,7 @@ }, "id": "MySQL-errors", "type": "search", - "version": 2 + "version": 1 }, { "attributes": { @@ -161,37 +161,37 @@ "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"packetbeat-*\",\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}}},\"filter\":[{\"meta\":{\"index\":\"packetbeat-*\",\"negate\":false,\"key\":\"type\",\"value\":\"mysql\",\"disabled\":false},\"query\":{\"match\":{\"type\":{\"query\":\"mysql\",\"type\":\"phrase\"}}}}],\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}" + "searchSourceJSON": "{\"index\":\"packetbeat-*\",\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}}},\"filter\":[{\"meta\":{\"index\":\"packetbeat-*\",\"negate\":false,\"key\":\"type\",\"value\":\"mysql\",\"disabled\":false,\"type\":\"phrase\",\"params\":{\"query\":\"mysql\",\"type\":\"phrase\"},\"alias\":null},\"query\":{\"match\":{\"type\":{\"query\":\"mysql\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\",\"default_field\":\"*\"}},\"language\":\"lucene\"},\"highlightAll\":true,\"version\":true}" }, "sort": [ "@timestamp", "desc" ], - "title": "MySQL Transactions", + "title": "MySQL Transactions [Packetbeat]", "version": 1 }, "id": "MySQL-Transactions", "type": "search", - "version": 12 + "version": 2 }, { "attributes": { "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"default_field\":\"*\",\"query\":\"*\"}}},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", "panelsJSON": "[{\"col\":4,\"id\":\"MySQL-Errors\",\"panelIndex\":1,\"row\":1,\"size_x\":5,\"size_y\":4,\"type\":\"visualization\"},{\"col\":9,\"id\":\"MySQL-Methods\",\"panelIndex\":2,\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Navigation\",\"panelIndex\":3,\"row\":1,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\"},{\"col\":7,\"id\":\"MySQL-throughput\",\"panelIndex\":4,\"row\":8,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Most-frequent-MySQL-queries\",\"panelIndex\":5,\"row\":11,\"size_x\":6,\"size_y\":6,\"type\":\"visualization\"},{\"col\":7,\"id\":\"Slowest-MySQL-queries\",\"panelIndex\":6,\"row\":11,\"size_x\":6,\"size_y\":6,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Mysql-response-times-percentiles\",\"panelIndex\":7,\"row\":5,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"MySQL-Reads-vs-Writes\",\"panelIndex\":8,\"row\":8,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"}]", "timeRestore": false, - "title": "Packetbeat MySQL performance", + "title": "[Packetbeat] MySQL performance", "uiStateJSON": "{\"P-5\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-6\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", "version": 1 }, "id": "Packetbeat-MySQL-performance", "type": "dashboard", - "version": 2 + "version": 3 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-nfs.json b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-nfs.json index e5d5b8ef638..e82d26d51b0 100644 --- a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-nfs.json +++ b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-nfs.json @@ -14,7 +14,7 @@ }, "id": "NFS-clients-pie-chart", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -30,7 +30,7 @@ }, "id": "NFS-operations-area-chart", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -46,7 +46,7 @@ }, "id": "NFS-top-group-pie-chart", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -62,7 +62,7 @@ }, "id": "NFS-top-users-pie-chart", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -78,7 +78,7 @@ }, "id": "NFS-response-times", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -94,7 +94,7 @@ }, "id": "NFS-errors", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -110,7 +110,7 @@ }, "id": "NFS-operation-table", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -126,22 +126,22 @@ }, "id": "NFS-bytes-in-slash-out", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, "title": "Navigation", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\",\"fontSize\":\"10\"},\"aggs\":[]}" }, "id": "Navigation", "type": "visualization", - "version": 18 + "version": 10 }, { "attributes": { @@ -162,7 +162,7 @@ }, "id": "nfs", "type": "search", - "version": 14 + "version": 1 }, { "attributes": { @@ -183,20 +183,20 @@ }, "id": "NFS-errors-search", "type": "search", - "version": 2 + "version": 1 }, { "attributes": { "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\",\"default_field\":\"*\"}},\"language\":\"lucene\"},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", "panelsJSON": "[{\"col\":5,\"id\":\"NFS-clients-pie-chart\",\"panelIndex\":1,\"row\":1,\"size_x\":4,\"size_y\":5,\"type\":\"visualization\"},{\"col\":1,\"id\":\"NFS-operations-area-chart\",\"panelIndex\":3,\"row\":12,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":9,\"id\":\"NFS-top-group-pie-chart\",\"panelIndex\":4,\"row\":1,\"size_x\":4,\"size_y\":2,\"type\":\"visualization\"},{\"col\":9,\"id\":\"NFS-top-users-pie-chart\",\"panelIndex\":5,\"row\":3,\"size_x\":4,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"NFS-response-times\",\"panelIndex\":6,\"row\":6,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"NFS-errors\",\"panelIndex\":7,\"row\":9,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"NFS-operation-table\",\"panelIndex\":8,\"row\":12,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"NFS-bytes-in-slash-out\",\"panelIndex\":9,\"row\":6,\"size_x\":6,\"size_y\":6,\"type\":\"visualization\"},{\"id\":\"Navigation\",\"type\":\"visualization\",\"panelIndex\":10,\"size_x\":4,\"size_y\":5,\"col\":1,\"row\":1}]", "timeRestore": false, - "title": "Packetbeat NFS", - "uiStateJSON": "{\"P-1\":{\"vis\":{\"legendOpen\":true}},\"P-4\":{\"spy\":{\"mode\":{\"fill\":false,\"name\":null}},\"vis\":{\"legendOpen\":true}},\"P-5\":{\"vis\":{\"legendOpen\":true}},\"P-6\":{\"vis\":{\"legendOpen\":false}},\"P-9\":{\"vis\":{\"legendOpen\":true}}}", + "title": "[Packetbeat] NFS", + "uiStateJSON": "{\"P-1\":{\"vis\":{\"legendOpen\":true}},\"P-4\":{\"spy\":{\"mode\":{\"fill\":false,\"name\":null}},\"vis\":{\"legendOpen\":true}},\"P-5\":{\"vis\":{\"legendOpen\":true}},\"P-6\":{\"vis\":{\"legendOpen\":false}},\"P-9\":{\"vis\":{\"legendOpen\":true}},\"P-8\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", "version": 1 }, "id": "Packetbeat-NFS", @@ -204,5 +204,5 @@ "version": 2 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-overview.json b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-overview.json index 51883535f62..6ab10cc74df 100644 --- a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-overview.json +++ b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-overview.json @@ -4,29 +4,29 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, - "savedSearchId": "Web-transactions", + "savedSearchId": "71908f00-88ca-11e7-ad9c-db80de0bf8d3", "title": "Web transactions", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Web transactions\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":false,\"mode\":\"stacked\",\"defaultYExtents\":false,\"scale\":\"linear\",\"times\":[],\"addTimeMarker\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Web transactions\",\n \"type\": \"histogram\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": false,\n \"mode\": \"stacked\",\n \"defaultYExtents\": false,\n \"scale\": \"linear\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Web-transactions", "type": "visualization", - "version": 4 + "version": 3 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, - "savedSearchId": "DB-transactions", + "savedSearchId": "800e2a00-88cb-11e7-ad9c-db80de0bf8d3", "title": "DB transactions", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"DB transactions\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"mode\":\"stacked\",\"defaultYExtents\":false,\"scale\":\"linear\",\"times\":[],\"addTimeMarker\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"type\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"DB transactions\",\n \"type\": \"histogram\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"mode\": \"stacked\",\n \"defaultYExtents\": false,\n \"scale\": \"linear\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"type\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "DB-transactions", "type": "visualization", @@ -36,13 +36,13 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, - "savedSearchId": "Cache-transactions", + "savedSearchId": "3dd366e0-88cc-11e7-ad9c-db80de0bf8d3", "title": "Cache transactions", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Cache transactions\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":false,\"mode\":\"stacked\",\"defaultYExtents\":false,\"scale\":\"linear\",\"times\":[],\"addTimeMarker\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"Cache transactions\",\n \"type\": \"histogram\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": false,\n \"mode\": \"stacked\",\n \"defaultYExtents\": false,\n \"scale\": \"linear\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"count\",\n \"schema\": \"metric\",\n \"params\": {}\n },\n {\n \"id\": \"2\",\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "Cache-transactions", "type": "visualization", @@ -52,13 +52,13 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, - "savedSearchId": "RPC-transactions", + "savedSearchId": "d3089370-88cc-11e7-ad9c-db80de0bf8d3", "title": "RPC transactions", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"RPC transactions\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":false,\"mode\":\"stacked\",\"defaultYExtents\":false,\"scale\":\"linear\",\"times\":[],\"addTimeMarker\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"type\"}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"RPC transactions\",\n \"type\": \"histogram\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": false,\n \"mode\": \"stacked\",\n \"defaultYExtents\": false,\n \"scale\": \"linear\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"type\"\n }\n },\n {\n \"id\": \"2\",\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"auto\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n }\n ],\n \"listeners\": {}\n}" }, "id": "RPC-transactions", "type": "visualization", @@ -78,7 +78,7 @@ }, "id": "Response-times-percentiles", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -94,7 +94,7 @@ }, "id": "Errors-count-over-time", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -110,7 +110,7 @@ }, "id": "Errors-vs-successful-transactions", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -126,7 +126,7 @@ }, "id": "Latency-histogram", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -141,7 +141,7 @@ }, "id": "Client-locations", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -157,22 +157,106 @@ }, "id": "Response-times-repartition", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, "title": "Navigation", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\",\"fontSize\":\"10\"},\"aggs\":[]}" }, "id": "Navigation", "type": "visualization", - "version": 18 + "version": 10 + }, + { + "attributes": { + "columns": [ + "_source" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"packetbeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"lucene\",\"query\":\"*\"},\"filter\":[{\"meta\":{\"index\":\"packetbeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"type\",\"value\":\"http\",\"params\":{\"query\":\"http\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"type\":{\"query\":\"http\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}]}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "Web Transactions [Packetbeat]", + "version": 1 + }, + "id": "71908f00-88ca-11e7-ad9c-db80de0bf8d3", + "type": "search", + "version": 2 + }, + { + "attributes": { + "columns": [ + "_source" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"packetbeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"index\":\"packetbeat-*\",\"type\":\"phrases\",\"key\":\"type\",\"value\":\"mysql, postgresql\",\"negate\":false,\"disabled\":false,\"alias\":null},\"query\":{\"bool\":{\"should\":[{\"match_phrase\":{\"type\":\"mysql\"}},{\"match_phrase\":{\"type\":\"postgresql\"}}],\"minimum_should_match\":1}},\"$state\":{\"store\":\"appState\"}}]}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "DB transactions", + "version": 1 + }, + "id": "800e2a00-88cb-11e7-ad9c-db80de0bf8d3", + "type": "search", + "version": 1 + }, + { + "attributes": { + "columns": [ + "_source" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"packetbeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"index\":\"packetbeat-*\",\"type\":\"phrases\",\"key\":\"type\",\"value\":\"redis, memcache\",\"negate\":false,\"disabled\":false,\"alias\":null},\"query\":{\"bool\":{\"should\":[{\"match_phrase\":{\"type\":\"redis\"}},{\"match_phrase\":{\"type\":\"memcache\"}}],\"minimum_should_match\":1}},\"$state\":{\"store\":\"appState\"}}]}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "Cache Transactions [Packetbeat]", + "version": 1 + }, + "id": "3dd366e0-88cc-11e7-ad9c-db80de0bf8d3", + "type": "search", + "version": 1 + }, + { + "attributes": { + "columns": [ + "_source" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"packetbeat-*\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"index\":\"packetbeat-*\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"type\",\"value\":\"thrift\",\"params\":{\"query\":\"thrift\",\"type\":\"phrase\"}},\"query\":{\"match\":{\"type\":{\"query\":\"thrift\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}]}" + }, + "sort": [ + "@timestamp", + "desc" + ], + "title": "RPC transactions", + "version": 1 + }, + "id": "d3089370-88cc-11e7-ad9c-db80de0bf8d3", + "type": "search", + "version": 1 }, { "attributes": { @@ -201,7 +285,7 @@ }, "id": "Packetbeat-Search", "type": "search", - "version": 8 + "version": 1 }, { "attributes": { @@ -230,18 +314,20 @@ }, "id": "Transactions-errors", "type": "search", - "version": 2 + "version": 1 }, { "attributes": { - "description": "", + "description": "Packetbeat overview dashboard", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\",\"default_field\":\"*\"}}},\"highlightAll\":true,\"version\":true}" }, - "panelsJSON": "[{\"col\":1,\"id\":\"Web-transactions\",\"row\":5,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\"},{\"col\":4,\"id\":\"DB-transactions\",\"row\":5,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\"},{\"col\":7,\"id\":\"Cache-transactions\",\"row\":5,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\"},{\"col\":10,\"id\":\"RPC-transactions\",\"row\":5,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Response-times-percentiles\",\"row\":10,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Errors-count-over-time\",\"row\":13,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"Errors-vs-successful-transactions\",\"row\":10,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"Latency-histogram\",\"row\":13,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":4,\"id\":\"Client-locations\",\"row\":1,\"size_x\":9,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Response-times-repartition\",\"row\":7,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"id\":\"Navigation\",\"type\":\"visualization\",\"size_x\":3,\"size_y\":4,\"col\":1,\"row\":1}]", + "optionsJSON": "{\"darkTheme\":false}", + "panelsJSON": "[{\"col\":1,\"id\":\"Web-transactions\",\"row\":5,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\",\"panelIndex\":1},{\"col\":4,\"id\":\"DB-transactions\",\"row\":5,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\",\"panelIndex\":2},{\"col\":7,\"id\":\"Cache-transactions\",\"row\":5,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\",\"panelIndex\":3},{\"col\":10,\"id\":\"RPC-transactions\",\"row\":5,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\",\"panelIndex\":4},{\"col\":1,\"id\":\"Response-times-percentiles\",\"row\":10,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":5},{\"col\":1,\"id\":\"Errors-count-over-time\",\"row\":13,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":6},{\"col\":7,\"id\":\"Errors-vs-successful-transactions\",\"row\":10,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":7},{\"col\":7,\"id\":\"Latency-histogram\",\"row\":13,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":8},{\"col\":4,\"id\":\"Client-locations\",\"row\":1,\"size_x\":9,\"size_y\":4,\"type\":\"visualization\",\"panelIndex\":9},{\"col\":1,\"id\":\"Response-times-repartition\",\"row\":7,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":10},{\"id\":\"Navigation\",\"type\":\"visualization\",\"size_x\":3,\"size_y\":4,\"col\":1,\"row\":1,\"panelIndex\":11}]", "timeRestore": false, - "title": "Packetbeat Dashboard", + "title": "[Packetbeat] Overview", + "uiStateJSON": "{\"P-9\":{\"mapZoom\":2,\"mapBounds\":{\"bottom_right\":{\"lat\":-54.97761367069625,\"lon\":153.984375},\"top_left\":{\"lat\":54.97761367069628,\"lon\":-153.984375}},\"mapCollar\":{\"top_left\":{\"lat\":90,\"lon\":-180},\"bottom_right\":{\"lat\":-90,\"lon\":180},\"zoom\":2}}}", "version": 1 }, "id": "Packetbeat-Dashboard", @@ -249,5 +335,5 @@ "version": 2 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-pgsql.json b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-pgsql.json index f711d0dcdfb..4409453ffae 100644 --- a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-pgsql.json +++ b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-pgsql.json @@ -4,16 +4,16 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, "title": "Navigation", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\",\"fontSize\":\"10\"},\"aggs\":[]}" }, "id": "Navigation", "type": "visualization", - "version": 18 + "version": 10 }, { "attributes": { @@ -29,7 +29,7 @@ }, "id": "PgSQL-Errors", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -45,7 +45,7 @@ }, "id": "PgSQL-Methods", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -60,7 +60,7 @@ }, "id": "PgSQL-response-times-percentiles", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -75,7 +75,7 @@ }, "id": "PgSQL-throughput", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -87,7 +87,7 @@ "title": "PgSQL Reads vs Writes", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"PgSQL Reads vs Writes\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"mode\":\"stacked\",\"defaultYExtents\":false,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"times\":[],\"addTimeMarker\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"method: SELECT\",\"analyze_wildcard\":true}}}},{\"input\":{\"query\":{\"query_string\":{\"query\":\"method: INSERT or method: UPDATE or method: DELETE\",\"analyze_wildcard\":true}}}}]}}],\"listeners\":{}}" + "visState": "{\"title\":\"PgSQL Reads vs Writes\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"mode\":\"stacked\",\"defaultYExtents\":false,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"times\":[],\"addTimeMarker\":false,\"setYExtents\":false,\"yAxis\":{},\"type\":\"area\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{\"text\":\"@timestamp per 30 seconds\"}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"legendPosition\":\"right\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"method: SELECT\",\"analyze_wildcard\":true}}}},{\"input\":{\"query\":\"method: INSERT OR method: UPDATE OR method: DELETE\"}}]}}]}" }, "id": "PgSQL-Reads-vs-Writes", "type": "visualization", @@ -107,7 +107,7 @@ }, "id": "Most-frequent-PgSQL-queries", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -122,7 +122,7 @@ }, "id": "Slowest-PgSQL-queries", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -147,7 +147,7 @@ }, "id": "PgSQL-errors", "type": "search", - "version": 2 + "version": 1 }, { "attributes": { @@ -172,20 +172,20 @@ }, "id": "PgSQL-transactions", "type": "search", - "version": 12 + "version": 1 }, { "attributes": { "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"default_field\":\"*\",\"query\":\"*\"}}},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", - "panelsJSON": "[{\"col\":1,\"id\":\"Navigation\",\"row\":1,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\",\"panelIndex\":1},{\"col\":4,\"id\":\"PgSQL-Errors\",\"row\":1,\"size_x\":5,\"size_y\":4,\"type\":\"visualization\",\"panelIndex\":2},{\"col\":9,\"id\":\"PgSQL-Methods\",\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\",\"panelIndex\":3},{\"col\":1,\"id\":\"PgSQL-response-times-percentiles\",\"row\":5,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":4},{\"col\":7,\"id\":\"PgSQL-throughput\",\"row\":8,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":5},{\"col\":1,\"id\":\"PgSQL-Reads-vs-Writes\",\"row\":8,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":6},{\"id\":\"Most-frequent-PgSQL-queries\",\"type\":\"visualization\",\"size_x\":6,\"size_y\":6,\"col\":1,\"row\":11,\"panelIndex\":7},{\"id\":\"Slowest-PgSQL-queries\",\"type\":\"visualization\",\"size_x\":6,\"size_y\":6,\"col\":7,\"row\":11,\"panelIndex\":8}]", + "panelsJSON": "[{\"col\":1,\"id\":\"Navigation\",\"panelIndex\":1,\"row\":1,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\"},{\"col\":4,\"id\":\"PgSQL-Errors\",\"panelIndex\":2,\"row\":1,\"size_x\":5,\"size_y\":4,\"type\":\"visualization\"},{\"col\":9,\"id\":\"PgSQL-Methods\",\"panelIndex\":3,\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"PgSQL-response-times-percentiles\",\"panelIndex\":4,\"row\":5,\"size_x\":12,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"PgSQL-throughput\",\"panelIndex\":5,\"row\":8,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"PgSQL-Reads-vs-Writes\",\"panelIndex\":6,\"row\":8,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Most-frequent-PgSQL-queries\",\"panelIndex\":7,\"row\":11,\"size_x\":6,\"size_y\":6,\"type\":\"visualization\"},{\"col\":7,\"id\":\"Slowest-PgSQL-queries\",\"panelIndex\":8,\"row\":11,\"size_x\":6,\"size_y\":6,\"type\":\"visualization\"}]", "timeRestore": false, - "title": "Packetbeat PgSQL performance", - "uiStateJSON": "{}", + "title": "[Packetbeat] PgSQL performance", + "uiStateJSON": "{\"P-7\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-8\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", "version": 1 }, "id": "Packetbeat-PgSQL-performance", @@ -193,5 +193,5 @@ "version": 2 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-thrift.json b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-thrift.json index b27201c269f..35c92ca8461 100644 --- a/packetbeat/_meta/kibana/default/dashboard/Packetbeat-thrift.json +++ b/packetbeat/_meta/kibana/default/dashboard/Packetbeat-thrift.json @@ -4,16 +4,16 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + "searchSourceJSON": "{\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"language\":\"lucene\"},\"filter\":[]}" }, "title": "Navigation", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\"},\"aggs\":[],\"listeners\":{}}" + "visState": "{\"title\":\"Navigation\",\"type\":\"markdown\",\"params\":{\"markdown\":\"### Packetbeat:\\n\\n[Overview](#/dashboard/Packetbeat-Dashboard)\\n\\n[Flows](#/dashboard/Packetbeat-Flows)\\n\\n[Web transactions](#/dashboard/Packetbeat-HTTP)\\n\\n[MySQL performance](#/dashboard/Packetbeat-MySQL-performance)\\n\\n[PostgreSQL performance](#/dashboard/Packetbeat-PgSQL-performance)\\n\\n[MongoDB performance](#/dashboard/Packetbeat-MongoDB-performance)\\n\\n[Thrift-RPC performance](#/dashboard/Packetbeat-Thrift-performance)\\n\\n[NFS transactions](#/dashboard/Packetbeat-NFS)\\n\\n[Cassandra performance](#/dashboard/Packetbeat-Cassandra)\",\"fontSize\":\"10\"},\"aggs\":[]}" }, "id": "Navigation", "type": "visualization", - "version": 18 + "version": 10 }, { "attributes": { @@ -29,7 +29,7 @@ }, "id": "Thrift-requests-per-minute", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -45,7 +45,7 @@ }, "id": "Thrift-RPC-Errors", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -60,7 +60,7 @@ }, "id": "Slowest-Thrift-RPC-methods", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -75,7 +75,7 @@ }, "id": "Thrift-response-times-percentiles", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -91,7 +91,7 @@ }, "id": "Top-Thrift-RPC-methods", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -106,7 +106,7 @@ }, "id": "Top-Thrift-RPC-calls-with-errors", "type": "visualization", - "version": 2 + "version": 1 }, { "attributes": { @@ -131,7 +131,7 @@ }, "id": "Thrift-transactions", "type": "search", - "version": 8 + "version": 1 }, { "attributes": { @@ -156,20 +156,20 @@ }, "id": "Thrift-errors", "type": "search", - "version": 4 + "version": 1 }, { "attributes": { "description": "", "hits": 0, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\",\"default_field\":\"*\"}},\"language\":\"lucene\"},\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{\"darkTheme\":false}", "panelsJSON": "[{\"col\":1,\"id\":\"Navigation\",\"row\":1,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\",\"panelIndex\":1},{\"col\":4,\"id\":\"Thrift-requests-per-minute\",\"row\":1,\"size_x\":5,\"size_y\":4,\"type\":\"visualization\",\"panelIndex\":2},{\"col\":9,\"id\":\"Thrift-RPC-Errors\",\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\",\"panelIndex\":3},{\"col\":1,\"id\":\"Slowest-Thrift-RPC-methods\",\"row\":5,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":4},{\"col\":7,\"id\":\"Thrift-response-times-percentiles\",\"row\":5,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\",\"panelIndex\":5},{\"col\":1,\"id\":\"Top-Thrift-RPC-methods\",\"row\":8,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\",\"panelIndex\":6},{\"col\":7,\"id\":\"Top-Thrift-RPC-calls-with-errors\",\"row\":8,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\",\"panelIndex\":7}]", "timeRestore": false, - "title": "Packetbeat Thrift performance", - "uiStateJSON": "{}", + "title": "[Packetbeat] Thrift performance", + "uiStateJSON": "{\"P-4\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", "version": 1 }, "id": "Packetbeat-Thrift-performance", @@ -177,5 +177,5 @@ "version": 2 } ], - "version": "6.0.0-alpha3-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/packetbeat/dashboards.yml b/packetbeat/dashboards.yml new file mode 100644 index 00000000000..909a2199e19 --- /dev/null +++ b/packetbeat/dashboards.yml @@ -0,0 +1,21 @@ +dashboards: +- id: Packetbeat-Dashboard + file: Packetbeat-overview.json +- id: Packetbeat-HTTP + file: Packetbeat-http.json +- id: Packetbeat-Flows + file: Packetbeat-flows.json +- id: Packetbeat-MySQL-performance + file: Packetbeat-mysql.json +- id: Packetbeat-PgSQL-performance + file: Packetbeat-pgsql.json +- id: Packetbeat-MongoDB-performance + file: Packetbeat-mongodb.json +- id: Packetbeat-Thrift-performance + file: Packetbeat-thrift.json +- id: Packetbeat-NFS + file: Packetbeat-nfs.json +- id: Packetbeat-Cassandra + file: Packetbeat-cassandra.json +- id: DNS-Unique-Domains + file: Packetbeat-dns-tunneling.json From c80b5b7f09e5e90b8bb320303054dbf1c2190e01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jarl=20T=C3=B6rnroos?= Date: Fri, 25 Aug 2017 12:31:16 +0300 Subject: [PATCH 118/139] Add Cloudfrontbeat to the community beats (#5007) --- libbeat/docs/communitybeats.asciidoc | 1 + 1 file changed, 1 insertion(+) diff --git a/libbeat/docs/communitybeats.asciidoc b/libbeat/docs/communitybeats.asciidoc index da6a31e8a7e..4bbe2be53ed 100644 --- a/libbeat/docs/communitybeats.asciidoc +++ b/libbeat/docs/communitybeats.asciidoc @@ -25,6 +25,7 @@ https://github.com/verticle-io/apexbeat[apexbeat]:: Extracts configurable contex https://github.com/goomzee/burrowbeat[burrowbeat]:: Monitors Kafka consumer lag using Burrow. https://github.com/goomzee/cassandrabeat[cassandrabeat]:: Uses Cassandra's nodetool cfstats utility to monitor Cassandra database nodes and lag. https://github.com/hartfordfive/cloudflarebeat[cloudflarebeat]:: Indexes log entries from the Cloudflare Enterprise Log Share API. +https://github.com/jarl-tornroos/cloudfrontbeat[cloudfrontbeat]:: Reads log events from Amazon Web Services https://aws.amazon.com/cloudfront/[CloudFront]. https://github.com/aidan-/cloudtrailbeat[cloudtrailbeat]:: Reads events from Amazon Web Services' https://aws.amazon.com/cloudtrail/[CloudTrail]. https://github.com/e-travel/cloudwatchlogsbeat[cloudwatchlogsbeat]:: Reads log events from Amazon Web Services' https://aws.amazon.com/cloudwatch/details/#log-monitoring[CloudWatch Logs]. https://github.com/raboof/connbeat[connbeat]:: Exposes metadata about TCP connections. From c70f5d222a4fc33f7c3956cadaa1f83003c947e6 Mon Sep 17 00:00:00 2001 From: Monica Sarbu Date: Fri, 25 Aug 2017 12:19:25 +0200 Subject: [PATCH 119/139] Fix redis and rabbitmq dashboards (#5015) --- .../5.x/dashboard/Metricbeat-Rabbitmq.json | 20 ++-- .../5.x/search/Metricbeat-Rabbitmq.json | 17 ++- .../Rabbitmq-Erlang-Process-Usage.json | 16 +-- .../visualization/Rabbitmq-Memory-Usage.json | 16 +-- .../Rabbitmq-Number-of-Nodes.json | 14 +-- .../Rabbitmq-Queue-Index-Operations.json | 14 +-- .../dashboard/Metricbeat-Rabbitmq.json | 107 ------------------ .../Metricbeat-rabbitmq-overview.json | 70 ++++++------ metricbeat/module/rabbitmq/module.yml | 2 +- ...ew.json => Metricbeat-redis-overview.json} | 40 +++++-- metricbeat/module/redis/module.yml | 2 +- 11 files changed, 113 insertions(+), 205 deletions(-) delete mode 100644 metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-Rabbitmq.json rename metricbeat/module/redis/_meta/kibana/default/dashboard/{Metricbeat-mysql-overview.json => Metricbeat-redis-overview.json} (62%) diff --git a/metricbeat/module/rabbitmq/_meta/kibana/5.x/dashboard/Metricbeat-Rabbitmq.json b/metricbeat/module/rabbitmq/_meta/kibana/5.x/dashboard/Metricbeat-Rabbitmq.json index 605a68d2cdb..71de4e7bab6 100644 --- a/metricbeat/module/rabbitmq/_meta/kibana/5.x/dashboard/Metricbeat-Rabbitmq.json +++ b/metricbeat/module/rabbitmq/_meta/kibana/5.x/dashboard/Metricbeat-Rabbitmq.json @@ -1,13 +1,13 @@ { - "hits": 0, - "timeRestore": false, - "description": "", - "title": "Metricbeat-Rabbitmq", - "uiStateJSON": "{}", - "panelsJSON": "[{\"col\":1,\"id\":\"RabbitMQ-Memory-Usage\",\"panelIndex\":8,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":8,\"id\":\"Rabbitmq-Number-of-Nodes\",\"panelIndex\":2,\"row\":1,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"RabbitMQ-Erlang-Process-Usage\",\"panelIndex\":10,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"RabbitMQ-Queue-Index-Operations\",\"panelIndex\":9,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"}]", - "optionsJSON": "{\"darkTheme\":false}", - "version": 1, + "hits": 0, + "timeRestore": false, + "version": 1, + "title": "Metricbeat-Rabbitmq", + "uiStateJSON": "{}", + "panelsJSON": "[{\"col\":1,\"id\":\"RabbitMQ-Memory-Usage\",\"panelIndex\":8,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":8,\"id\":\"Rabbitmq-Number-of-Nodes\",\"panelIndex\":2,\"row\":1,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"RabbitMQ-Erlang-Process-Usage\",\"panelIndex\":10,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"RabbitMQ-Queue-Index-Operations\",\"panelIndex\":9,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"}]", + "optionsJSON": "{\"darkTheme\":false}", "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" - } -} + }, + "description": "" +} \ No newline at end of file diff --git a/metricbeat/module/rabbitmq/_meta/kibana/5.x/search/Metricbeat-Rabbitmq.json b/metricbeat/module/rabbitmq/_meta/kibana/5.x/search/Metricbeat-Rabbitmq.json index 860ba3b584c..e8a509d3949 100644 --- a/metricbeat/module/rabbitmq/_meta/kibana/5.x/search/Metricbeat-Rabbitmq.json +++ b/metricbeat/module/rabbitmq/_meta/kibana/5.x/search/Metricbeat-Rabbitmq.json @@ -1,14 +1,13 @@ { - "title": "Metricbeat-Rabbitmq", - "description": "", - "hits": 0, "sort": [ - "@timestamp", + "@timestamp", "desc" - ], - "version": 1, + ], + "hits": 0, + "description": "", + "title": "Metricbeat-Rabbitmq", + "version": 1, "kibanaSavedObjectMeta": { - "searchSourceJSON": - "{\"index\":\"metricbeat-*\",\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:rabbitmq\",\"analyze_wildcard\":true}}}" + "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:rabbitmq\",\"analyze_wildcard\":true}}}" } -} +} \ No newline at end of file diff --git a/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Erlang-Process-Usage.json b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Erlang-Process-Usage.json index 3468f394488..281cf0e4c9f 100644 --- a/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Erlang-Process-Usage.json +++ b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Erlang-Process-Usage.json @@ -1,11 +1,11 @@ { - "title": "RabbitMQ Erlang Process Usage", - "visState": "{\"title\":\"RabbitMQ Erlang Process Usage\",\"type\":\"line\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"legendPosition\":\"top\",\"radiusRatio\":9,\"scale\":\"linear\",\"setYExtents\":false,\"shareYAxis\":true,\"showCircles\":false,\"smoothLines\":true,\"times\":[],\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.proc.used\",\"customLabel\":\"Used Process\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"rabbitmq.node.name.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Node name\"}}],\"listeners\":{}}", - "uiStateJSON": "{}", - "description": "", - "savedSearchId": "Metricbeat-Rabbitmq", - "version": 1, + "visState": "{\n \"title\": \"RabbitMQ Erlang Process Usage\",\n \"type\": \"line\",\n \"params\": {\n \"addLegend\": true,\n \"addTimeMarker\": false,\n \"addTooltip\": true,\n \"defaultYExtents\": false,\n \"drawLinesBetweenPoints\": true,\n \"interpolate\": \"linear\",\n \"legendPosition\": \"top\",\n \"radiusRatio\": 9,\n \"scale\": \"linear\",\n \"setYExtents\": false,\n \"shareYAxis\": true,\n \"showCircles\": false,\n \"smoothLines\": true,\n \"times\": [],\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"rabbitmq.node.proc.used\",\n \"customLabel\": \"Used Process\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"custom\",\n \"customInterval\": \"30s\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"4\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"rabbitmq.node.name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Node name\"\n }\n }\n ],\n \"listeners\": {}\n}", + "description": "", + "title": "Erlang Process Usage [Metricbeat RabbitMQ]", + "uiStateJSON": "{}", + "version": 1, + "savedSearchId": "Metricbeat-Rabbitmq", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" } -} +} \ No newline at end of file diff --git a/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Memory-Usage.json b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Memory-Usage.json index 6dde99da1a8..9bca13bfd4d 100644 --- a/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Memory-Usage.json +++ b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Memory-Usage.json @@ -1,11 +1,11 @@ { - "title": "RabbitMQ Memory Usage", - "visState": "{\"title\":\"RabbitMQ Memory Usage\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"showCircles\":false,\"smoothLines\":true,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":true,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.mem.used.bytes\",\"json\":\"\",\"customLabel\":\"Used memory\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"rabbitmq.node.name.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Node name\"}}],\"listeners\":{}}", - "uiStateJSON": "{}", - "description": "", - "savedSearchId": "Metricbeat-Rabbitmq", - "version": 1, + "visState": "{\n \"title\": \"RabbitMQ Memory Usage\",\n \"type\": \"line\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"top\",\n \"showCircles\": false,\n \"smoothLines\": true,\n \"interpolate\": \"linear\",\n \"scale\": \"linear\",\n \"drawLinesBetweenPoints\": true,\n \"radiusRatio\": 9,\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": true,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"rabbitmq.node.mem.used.bytes\",\n \"json\": \"\",\n \"customLabel\": \"Used memory\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"custom\",\n \"customInterval\": \"30s\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"4\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"rabbitmq.node.name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Node name\"\n }\n }\n ],\n \"listeners\": {}\n}", + "description": "", + "title": "Memory Usage [Metricbeat RabbitMQ]", + "uiStateJSON": "{}", + "version": 1, + "savedSearchId": "Metricbeat-Rabbitmq", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" } -} +} \ No newline at end of file diff --git a/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Number-of-Nodes.json b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Number-of-Nodes.json index 960525ecd99..ce6bea2c84f 100644 --- a/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Number-of-Nodes.json +++ b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Number-of-Nodes.json @@ -1,11 +1,11 @@ { - "title": "RabbitMQ Number of Nodes", - "visState": "{\n \"title\": \"Rabbitmq-Number-of-Nodes\",\n \"type\": \"metric\",\n \"params\": {\n \"handleNoResults\": true,\n \"fontSize\": 60\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"rabbitmq.node.name.keyword\",\n \"customLabel\": \"RabbitMQ Nodes\"\n }\n }\n ],\n \"listeners\": {}\n}", - "uiStateJSON": "{}", - "description": "", - "savedSearchId": "Metricbeat-Rabbitmq", - "version": 1, + "visState": "{\n \"title\": \"Rabbitmq-Number-of-Nodes\",\n \"type\": \"metric\",\n \"params\": {\n \"handleNoResults\": true,\n \"fontSize\": 60\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"rabbitmq.node.name\",\n \"customLabel\": \"RabbitMQ Nodes\"\n }\n }\n ],\n \"listeners\": {}\n}", + "description": "", + "title": "Number of Nodes [Metricbeat RabbitMQ]", + "uiStateJSON": "{}", + "version": 1, + "savedSearchId": "Metricbeat-Rabbitmq", "kibanaSavedObjectMeta": { "searchSourceJSON": "{\n \"filter\": []\n}" } -} +} \ No newline at end of file diff --git a/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Queue-Index-Operations.json b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Queue-Index-Operations.json index 76094a228c3..1b7d5ec9340 100644 --- a/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Queue-Index-Operations.json +++ b/metricbeat/module/rabbitmq/_meta/kibana/5.x/visualization/Rabbitmq-Queue-Index-Operations.json @@ -1,11 +1,11 @@ { - "title": "RabbitMQ Queue Index Operations", - "visState": "{\"title\":\"RabbitMQ Queue Index Operations\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"showCircles\":false,\"smoothLines\":false,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.read.count\",\"customLabel\":\"Queue Index Read\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.journal_write.count\",\"customLabel\":\"Queue Index Jornal Write\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.write.count\",\"customLabel\":\"Queue Index Write\"}}],\"listeners\":{}}", - "uiStateJSON": "{}", - "description": "", - "savedSearchId": "Metricbeat-Rabbitmq", - "version": 1, + "visState": "{\"title\":\"RabbitMQ Queue Index Operations\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"showCircles\":false,\"smoothLines\":false,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.read.count\",\"customLabel\":\"Queue Index Read\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.journal_write.count\",\"customLabel\":\"Queue Index Jornal Write\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.write.count\",\"customLabel\":\"Queue Index Write\"}}],\"listeners\":{}}", + "description": "", + "title": "RabbitMQ Queue Index Operations", + "uiStateJSON": "{}", + "version": 1, + "savedSearchId": "Metricbeat-Rabbitmq", "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"filter\":[]}" } -} +} \ No newline at end of file diff --git a/metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-Rabbitmq.json b/metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-Rabbitmq.json deleted file mode 100644 index 8e90a1b563f..00000000000 --- a/metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-Rabbitmq.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "objects": [ - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "Metricbeat-Rabbitmq", - "title": "RabbitMQ Memory Usage", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"RabbitMQ Memory Usage\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"showCircles\":false,\"smoothLines\":true,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":true,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.mem.used.bytes\",\"json\":\"\",\"customLabel\":\"Used memory\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"rabbitmq.node.name.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Node name\"}}],\"listeners\":{}}" - }, - "col": 1, - "id": "RabbitMQ-Memory-Usage", - "panelIndex": 8, - "row": 1, - "size_x": 6, - "size_y": 3, - "type": "visualization", - "version": 9 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\n \"filter\": []\n}" - }, - "savedSearchId": "Metricbeat-Rabbitmq", - "title": "RabbitMQ Number of Nodes", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\n \"title\": \"Rabbitmq-Number-of-Nodes\",\n \"type\": \"metric\",\n \"params\": {\n \"handleNoResults\": true,\n \"fontSize\": 60\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"rabbitmq.node.name.keyword\",\n \"customLabel\": \"RabbitMQ Nodes\"\n }\n }\n ],\n \"listeners\": {}\n}" - }, - "col": 8, - "id": "Rabbitmq-Number-of-Nodes", - "panelIndex": 2, - "row": 1, - "size_x": 3, - "size_y": 3, - "type": "visualization", - "version": 7 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "Metricbeat-Rabbitmq", - "title": "RabbitMQ Erlang Process Usage", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"RabbitMQ Erlang Process Usage\",\"type\":\"line\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"legendPosition\":\"top\",\"radiusRatio\":9,\"scale\":\"linear\",\"setYExtents\":false,\"shareYAxis\":true,\"showCircles\":false,\"smoothLines\":true,\"times\":[],\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.proc.used\",\"customLabel\":\"Used Process\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"rabbitmq.node.name.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Node name\"}}],\"listeners\":{}}" - }, - "col": 1, - "id": "RabbitMQ-Erlang-Process-Usage", - "panelIndex": 10, - "row": 4, - "size_x": 6, - "size_y": 3, - "type": "visualization", - "version": 6 - }, - { - "attributes": { - "description": "", - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" - }, - "savedSearchId": "Metricbeat-Rabbitmq", - "title": "RabbitMQ Queue Index Operations", - "uiStateJSON": "{}", - "version": 1, - "visState": "{\"title\":\"RabbitMQ Queue Index Operations\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"showCircles\":false,\"smoothLines\":false,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.read.count\",\"customLabel\":\"Queue Index Read\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.journal_write.count\",\"customLabel\":\"Queue Index Jornal Write\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.write.count\",\"customLabel\":\"Queue Index Write\"}}],\"listeners\":{}}" - }, - "col": 7, - "id": "RabbitMQ-Queue-Index-Operations", - "panelIndex": 9, - "row": 4, - "size_x": 6, - "size_y": 3, - "type": "visualization", - "version": 5 - }, - { - "attributes": { - "description": "", - "hits": 0, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647},\"query\":{\"query_string\":{\"query\":\"metricset.module:rabbitmq\",\"analyze_wildcard\":true}}}" - }, - "sort": [ - "@timestamp", - "desc" - ], - "title": "Metricbeat-Rabbitmq", - "version": 1 - }, - "id": "Metricbeat-Rabbitmq", - "type": "search", - "version": 26 - } - ], - "version": "5.6.0-SNAPSHOT" -} \ No newline at end of file diff --git a/metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-rabbitmq-overview.json b/metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-rabbitmq-overview.json index 54942d2768b..7b64a8d7f0a 100644 --- a/metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-rabbitmq-overview.json +++ b/metricbeat/module/rabbitmq/_meta/kibana/default/dashboard/Metricbeat-rabbitmq-overview.json @@ -4,22 +4,17 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Metricbeat-Rabbitmq", - "title": "RabbitMQ Memory Usage", + "title": "Memory Usage [Metricbeat RabbitMQ]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"RabbitMQ Memory Usage\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"showCircles\":false,\"smoothLines\":true,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":true,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.mem.used.bytes\",\"json\":\"\",\"customLabel\":\"Used memory\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"rabbitmq.node.name.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Node name\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"RabbitMQ Memory Usage\",\n \"type\": \"line\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"top\",\n \"showCircles\": false,\n \"smoothLines\": true,\n \"interpolate\": \"linear\",\n \"scale\": \"linear\",\n \"drawLinesBetweenPoints\": true,\n \"radiusRatio\": 9,\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": true,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"rabbitmq.node.mem.used.bytes\",\n \"json\": \"\",\n \"customLabel\": \"Used memory\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"custom\",\n \"customInterval\": \"30s\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"4\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"rabbitmq.node.name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Node name\"\n }\n }\n ],\n \"listeners\": {}\n}" }, - "col": 1, "id": "RabbitMQ-Memory-Usage", - "panelIndex": 8, - "row": 1, - "size_x": 6, - "size_y": 3, "type": "visualization", - "version": 3 + "version": 2 }, { "attributes": { @@ -28,40 +23,30 @@ "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Metricbeat-Rabbitmq", - "title": "RabbitMQ Number of Nodes", + "title": "Number of Nodes [Metricbeat RabbitMQ]", "uiStateJSON": "{}", "version": 1, - "visState": "{\n \"title\": \"Rabbitmq-Number-of-Nodes\",\n \"type\": \"metric\",\n \"params\": {\n \"handleNoResults\": true,\n \"fontSize\": 60\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"rabbitmq.node.name.keyword\",\n \"customLabel\": \"RabbitMQ Nodes\"\n }\n }\n ],\n \"listeners\": {}\n}" + "visState": "{\n \"title\": \"Rabbitmq-Number-of-Nodes\",\n \"type\": \"metric\",\n \"params\": {\n \"handleNoResults\": true,\n \"fontSize\": 60\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"rabbitmq.node.name\",\n \"customLabel\": \"RabbitMQ Nodes\"\n }\n }\n ],\n \"listeners\": {}\n}" }, - "col": 8, "id": "Rabbitmq-Number-of-Nodes", - "panelIndex": 2, - "row": 1, - "size_x": 3, - "size_y": 3, "type": "visualization", - "version": 4 + "version": 2 }, { "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[]}" + "searchSourceJSON": "{\n \"filter\": []\n}" }, "savedSearchId": "Metricbeat-Rabbitmq", - "title": "RabbitMQ Erlang Process Usage", + "title": "Erlang Process Usage [Metricbeat RabbitMQ]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"RabbitMQ Erlang Process Usage\",\"type\":\"line\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"legendPosition\":\"top\",\"radiusRatio\":9,\"scale\":\"linear\",\"setYExtents\":false,\"shareYAxis\":true,\"showCircles\":false,\"smoothLines\":true,\"times\":[],\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.proc.used\",\"customLabel\":\"Used Process\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"rabbitmq.node.name.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Node name\"}}],\"listeners\":{}}" + "visState": "{\n \"title\": \"RabbitMQ Erlang Process Usage\",\n \"type\": \"line\",\n \"params\": {\n \"addLegend\": true,\n \"addTimeMarker\": false,\n \"addTooltip\": true,\n \"defaultYExtents\": false,\n \"drawLinesBetweenPoints\": true,\n \"interpolate\": \"linear\",\n \"legendPosition\": \"top\",\n \"radiusRatio\": 9,\n \"scale\": \"linear\",\n \"setYExtents\": false,\n \"shareYAxis\": true,\n \"showCircles\": false,\n \"smoothLines\": true,\n \"times\": [],\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"rabbitmq.node.proc.used\",\n \"customLabel\": \"Used Process\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"custom\",\n \"customInterval\": \"30s\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"4\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"rabbitmq.node.name\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Node name\"\n }\n }\n ],\n \"listeners\": {}\n}" }, - "col": 1, "id": "RabbitMQ-Erlang-Process-Usage", - "panelIndex": 10, - "row": 4, - "size_x": 6, - "size_y": 3, "type": "visualization", - "version": 3 + "version": 2 }, { "attributes": { @@ -70,19 +55,14 @@ "searchSourceJSON": "{\"filter\":[]}" }, "savedSearchId": "Metricbeat-Rabbitmq", - "title": "RabbitMQ Queue Index Operations", + "title": "Queue Index Operations [Metricbeat RabbitMQ]", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"RabbitMQ Queue Index Operations\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"showCircles\":false,\"smoothLines\":false,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.read.count\",\"customLabel\":\"Queue Index Read\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.journal_write.count\",\"customLabel\":\"Queue Index Jornal Write\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.write.count\",\"customLabel\":\"Queue Index Write\"}}],\"listeners\":{}}" + "visState": "{\"title\":\"Queue Index Operations [Metricbeat RabbitMQ]\",\"type\":\"line\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"top\",\"showCircles\":false,\"smoothLines\":false,\"interpolate\":\"linear\",\"scale\":\"linear\",\"drawLinesBetweenPoints\":true,\"radiusRatio\":9,\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{},\"type\":\"line\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"line\",\"mode\":\"normal\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.read.count\",\"customLabel\":\"Queue Index Read\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"custom\",\"customInterval\":\"30s\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.journal_write.count\",\"customLabel\":\"Queue Index Jornal Write\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"rabbitmq.node.queue.index.write.count\",\"customLabel\":\"Queue Index Write\"}}]}" }, - "col": 7, "id": "RabbitMQ-Queue-Index-Operations", - "panelIndex": 9, - "row": 4, - "size_x": 6, - "size_y": 3, "type": "visualization", - "version": 3 + "version": 2 }, { "attributes": { @@ -100,8 +80,26 @@ }, "id": "Metricbeat-Rabbitmq", "type": "search", - "version": 8 + "version": 1 + }, + { + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"lucene\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"default_field\":\"*\",\"query\":\"*\"}}}}" + }, + "optionsJSON": "{\"darkTheme\":false}", + "panelsJSON": "[{\"col\":1,\"id\":\"RabbitMQ-Memory-Usage\",\"panelIndex\":8,\"row\":1,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":8,\"id\":\"Rabbitmq-Number-of-Nodes\",\"panelIndex\":2,\"row\":1,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"RabbitMQ-Erlang-Process-Usage\",\"panelIndex\":10,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"RabbitMQ-Queue-Index-Operations\",\"panelIndex\":9,\"row\":4,\"size_x\":6,\"size_y\":3,\"type\":\"visualization\"}]", + "timeRestore": false, + "title": "[Metricbeat RabbitMQ] Overview", + "uiStateJSON": "{\"P-2\":{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}}", + "version": 1 + }, + "id": "AV4YobKIge1VCbKU_qVo", + "type": "dashboard", + "version": 2 } ], - "version": "5.6.0-SNAPSHOT" + "version": "6.0.0-beta1-SNAPSHOT" } \ No newline at end of file diff --git a/metricbeat/module/rabbitmq/module.yml b/metricbeat/module/rabbitmq/module.yml index 583b99796bf..42a37caaa63 100644 --- a/metricbeat/module/rabbitmq/module.yml +++ b/metricbeat/module/rabbitmq/module.yml @@ -1,3 +1,3 @@ dashboards: - - id: Metricbeat-Rabbitmq + - id: AV4YobKIge1VCbKU_qVo file: Metricbeat-rabbitmq-overview.json diff --git a/metricbeat/module/redis/_meta/kibana/default/dashboard/Metricbeat-mysql-overview.json b/metricbeat/module/redis/_meta/kibana/default/dashboard/Metricbeat-redis-overview.json similarity index 62% rename from metricbeat/module/redis/_meta/kibana/default/dashboard/Metricbeat-mysql-overview.json rename to metricbeat/module/redis/_meta/kibana/default/dashboard/Metricbeat-redis-overview.json index 371cde2c5ce..e0fa8e5a481 100644 --- a/metricbeat/module/redis/_meta/kibana/default/dashboard/Metricbeat-mysql-overview.json +++ b/metricbeat/module/redis/_meta/kibana/default/dashboard/Metricbeat-redis-overview.json @@ -7,10 +7,10 @@ "searchSourceJSON": "{\"filter\":[]}" }, "savedSearchId": "Metricbeat-Redis", - "title": "Clients Metrics [Metricbeat Redis]", + "title": "Clients [Metricbeat Redis]", "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}", "version": 1, - "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{\"customLabel\":\"Connected clients\",\"field\":\"redis.info.clients.connected\"},\"schema\":\"metric\",\"type\":\"max\"}],\"listeners\":{},\"params\":{\"addLegend\":false,\"addTooltip\":true,\"fontSize\":60,\"gauge\":{\"autoExtend\":false,\"backStyle\":\"Full\",\"colorSchema\":\"Green to Red\",\"colorsRange\":[{\"from\":0,\"to\":100}],\"gaugeColorMode\":\"None\",\"gaugeStyle\":\"Full\",\"gaugeType\":\"Metric\",\"invertColors\":false,\"labels\":{\"color\":\"black\",\"show\":true},\"orientation\":\"vertical\",\"percentageMode\":false,\"scale\":{\"color\":\"#333\",\"labels\":false,\"show\":false,\"width\":2},\"style\":{\"bgColor\":false,\"fontSize\":60,\"labelColor\":false,\"subText\":\"\"},\"type\":\"simple\",\"useRange\":false,\"verticalSplit\":false},\"handleNoResults\":true,\"type\":\"gauge\"},\"title\":\"Clients Metrics [Metricbeat Redis]\",\"type\":\"metric\"}" + "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{\"customLabel\":\"Connected clients\",\"field\":\"redis.info.clients.connected\"},\"schema\":\"metric\",\"type\":\"max\"}],\"listeners\":{},\"params\":{\"addLegend\":false,\"addTooltip\":true,\"fontSize\":60,\"gauge\":{\"autoExtend\":false,\"backStyle\":\"Full\",\"colorSchema\":\"Green to Red\",\"colorsRange\":[{\"from\":0,\"to\":100}],\"gaugeColorMode\":\"None\",\"gaugeStyle\":\"Full\",\"gaugeType\":\"Metric\",\"invertColors\":false,\"labels\":{\"color\":\"black\",\"show\":true},\"orientation\":\"vertical\",\"percentageMode\":false,\"scale\":{\"color\":\"#333\",\"labels\":false,\"show\":false,\"width\":2},\"style\":{\"bgColor\":false,\"fontSize\":60,\"labelColor\":false,\"subText\":\"\"},\"type\":\"simple\",\"useRange\":false,\"verticalSplit\":false},\"handleNoResults\":true,\"type\":\"gauge\"},\"title\":\"Clients [Metricbeat Redis]\",\"type\":\"metric\"}" }, "col": 1, "id": "Redis-Clients-Metrics", @@ -46,13 +46,13 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\n \"filter\": []\n}" + "searchSourceJSON": "{\"filter\":[]}" }, "savedSearchId": "Metricbeat-Redis", "title": "Hosts [Metricbeat Redis]", - "uiStateJSON": "{\n \"vis\": {\n \"params\": {\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n }\n }\n }\n}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", "version": 1, - "visState": "{\n \"title\": \"Redis hosts\",\n \"type\": \"table\",\n \"params\": {\n \"perPage\": 10,\n \"showPartialRows\": false,\n \"showMeticsAtAllLevels\": false,\n \"sort\": {\n \"columnIndex\": null,\n \"direction\": null\n },\n \"showTotal\": false,\n \"totalFunc\": \"sum\"\n },\n \"aggs\": [\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"bucket\",\n \"params\": {\n \"field\": \"metricset.host\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n },\n {\n \"id\": \"3\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"redis.info.server.uptime\",\n \"customLabel\": \"Uptime (s)\"\n }\n },\n {\n \"id\": \"6\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"redis.info.server.process_id\",\n \"customLabel\": \"PID\"\n }\n },\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"redis.info.memory.used.peak\",\n \"customLabel\": \"Memory\"\n }\n },\n {\n \"id\": \"4\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"redis.info.cpu.used.user\",\n \"customLabel\": \"CPU used (user)\"\n }\n },\n {\n \"id\": \"5\",\n \"enabled\": true,\n \"type\": \"max\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"redis.info.cpu.used.sys\",\n \"customLabel\": \"CPU used (system)\"\n }\n }\n ],\n \"listeners\": {}\n}" + "visState": "{\"title\":\"Hosts [Metricbeat Redis]\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"metricset.host\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.info.server.uptime\",\"customLabel\":\"Uptime (s)\"}},{\"id\":\"6\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.info.server.process_id\",\"customLabel\":\"PID\"}},{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.info.memory.used.peak\",\"customLabel\":\"Memory\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.info.cpu.used.user\",\"customLabel\":\"CPU used (user)\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"redis.info.cpu.used.sys\",\"customLabel\":\"CPU used (system)\"}}],\"listeners\":{}}" }, "col": 1, "id": "Redis-hosts", @@ -67,13 +67,13 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\n \"filter\": []\n}" + "searchSourceJSON": "{\"filter\":[]}" }, "savedSearchId": "Metricbeat-Redis", "title": "Server Versions [Metricbeat Redis]", "uiStateJSON": "{}", "version": 1, - "visState": "{\n \"title\": \"Redis Server Versions\",\n \"type\": \"pie\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"isDonut\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"metricset.host\",\n \"customLabel\": \"Hosts\"\n }\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"redis.info.server.version\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Multiplexing API\"\n }\n }\n ],\n \"listeners\": {}\n}" + "visState": "{\"title\":\"Server Versions [Metricbeat Redis]\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"metricset.host\",\"customLabel\":\"Hosts\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"redis.info.server.version\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Multiplexing API\"}}],\"listeners\":{}}" }, "col": 1, "id": "Redis-Server-Versions", @@ -88,13 +88,13 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\n \"filter\": []\n}" + "searchSourceJSON": "{\"filter\":[]}" }, "savedSearchId": "Metricbeat-Redis", "title": "Server mode [Metricbeat Redis]", "uiStateJSON": "{}", "version": 1, - "visState": "{\n \"title\": \"Redis server mode\",\n \"type\": \"pie\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"isDonut\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"metricset.host\",\n \"customLabel\": \"Hosts\"\n }\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"redis.info.server.mode\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Server mode\"\n }\n }\n ],\n \"listeners\": {}\n}" + "visState": "{\"title\":\"Server mode [Metricbeat Redis]\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"metricset.host\",\"customLabel\":\"Hosts\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"redis.info.server.mode\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Server mode\"}}],\"listeners\":{}}" }, "col": 5, "id": "Redis-server-mode", @@ -109,13 +109,13 @@ "attributes": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\n \"filter\": []\n}" + "searchSourceJSON": "{\"filter\":[]}" }, "savedSearchId": "Metricbeat-Redis", "title": "Multiplexing API [Metricbeat Redis]", "uiStateJSON": "{}", "version": 1, - "visState": "{\n \"title\": \"Redis multiplexing API\",\n \"type\": \"pie\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"legendPosition\": \"right\",\n \"isDonut\": false\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"enabled\": true,\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"metricset.host\",\n \"customLabel\": \"Hosts\"\n }\n },\n {\n \"id\": \"2\",\n \"enabled\": true,\n \"type\": \"terms\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"redis.info.server.multiplexing_api\",\n \"size\": 5,\n \"order\": \"desc\",\n \"orderBy\": \"1\",\n \"customLabel\": \"Multiplexing API\"\n }\n }\n ],\n \"listeners\": {}\n}" + "visState": "{\"title\":\"Multiplexing API [Metricbeat Redis]\",\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"metricset.host\",\"customLabel\":\"Hosts\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"redis.info.server.multiplexing_api\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Multiplexing API\"}}],\"listeners\":{}}" }, "col": 9, "id": "Redis-multiplexing-API", @@ -167,6 +167,24 @@ "id": "Metricbeat-Redis", "type": "search", "version": 7 + }, + { + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}],\"highlightAll\":true,\"version\":true}" + }, + "optionsJSON": "{\"darkTheme\":false}", + "panelsJSON": "[{\"col\":1,\"id\":\"Redis-Clients-Metrics\",\"panelIndex\":2,\"row\":1,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":4,\"id\":\"Redis-Connected-clients\",\"panelIndex\":1,\"row\":1,\"size_x\":5,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Redis-hosts\",\"panelIndex\":3,\"row\":4,\"size_x\":12,\"size_y\":2,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Redis-Server-Versions\",\"panelIndex\":4,\"row\":6,\"size_x\":4,\"size_y\":2,\"type\":\"visualization\"},{\"col\":5,\"id\":\"Redis-server-mode\",\"panelIndex\":5,\"row\":6,\"size_x\":4,\"size_y\":2,\"type\":\"visualization\"},{\"col\":9,\"id\":\"Redis-multiplexing-API\",\"panelIndex\":6,\"row\":6,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\"},{\"col\":9,\"id\":\"Redis-Keyspaces\",\"panelIndex\":7,\"row\":1,\"size_x\":4,\"size_y\":3,\"type\":\"visualization\"}]", + "timeRestore": false, + "title": "[Metricbeat Redis] Overview", + "uiStateJSON": "{\"P-3\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-4\":{\"vis\":{\"legendOpen\":true}},\"P-2\":{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}}", + "version": 1 + }, + "id": "AV4YjZ5pux-M-tCAunxK", + "type": "dashboard", + "version": 1 } ], "version": "5.6.0-SNAPSHOT" diff --git a/metricbeat/module/redis/module.yml b/metricbeat/module/redis/module.yml index 24c7b0ba045..6a4e4504f9c 100644 --- a/metricbeat/module/redis/module.yml +++ b/metricbeat/module/redis/module.yml @@ -1,3 +1,3 @@ dashboards: - - id: Metricbeat-Redis + - id: AV4YjZ5pux-M-tCAunxK file: Metricbeat-redis-overview.json From 6130ef3b464008b9cdfae9476bdcf03076e642fd Mon Sep 17 00:00:00 2001 From: Monica Sarbu Date: Fri, 25 Aug 2017 12:47:04 +0200 Subject: [PATCH 120/139] Make the index name configurable when loading the 6.x and 5.x dashboards (#4949) --- CHANGELOG.asciidoc | 1 + libbeat/dashboards/es_loader.go | 71 ++++++++++++------- libbeat/dashboards/kibana_loader.go | 25 +++++-- libbeat/dashboards/modify_json.go | 105 ++++++++++++++++++++++++++++ libbeat/setup/kibana/client.go | 11 ++- 5 files changed, 182 insertions(+), 31 deletions(-) create mode 100644 libbeat/dashboards/modify_json.go diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 59b1e929751..a99edfeebdb 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -78,6 +78,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Added `cloud.id` and `cloud.auth` settings, for simplifying using Beats with the Elastic Cloud. {issue}4959[4959] - Add lz4 compression support to kafka output. {pull}4977[4977] - Add newer kafka versions to kafka output. {pull}4977[4977] +- Configure the index name when loading the dashboards and the index pattern. {pull}4949[4949] *Auditbeat* diff --git a/libbeat/dashboards/es_loader.go b/libbeat/dashboards/es_loader.go index f14394662e0..8c2784138fc 100644 --- a/libbeat/dashboards/es_loader.go +++ b/libbeat/dashboards/es_loader.go @@ -87,7 +87,10 @@ func (loader ElasticsearchLoader) ImportIndex(file string) error { return err } var indexContent common.MapStr - json.Unmarshal(reader, &indexContent) + err = json.Unmarshal(reader, &indexContent) + if err != nil { + return fmt.Errorf("fail to unmarshal index content: %v", err) + } indexName, ok := indexContent["title"].(string) if !ok { @@ -117,7 +120,11 @@ func (loader ElasticsearchLoader) importJSONFile(fileType string, file string) e return fmt.Errorf("Failed to read %s. Error: %s", file, err) } var jsonContent map[string]interface{} - json.Unmarshal(reader, &jsonContent) + err = json.Unmarshal(reader, &jsonContent) + if err != nil { + return fmt.Errorf("fail to unmarshal json file: %v", err) + } + fileBase := strings.TrimSuffix(filepath.Base(file), filepath.Ext(file)) body, err := loader.client.LoadJSON(path+"/"+fileBase, jsonContent) @@ -149,10 +156,16 @@ func (loader ElasticsearchLoader) importPanelsFromDashboard(file string) (err er } var jsonContent record - json.Unmarshal(reader, &jsonContent) + err = json.Unmarshal(reader, &jsonContent) + if err != nil { + return fmt.Errorf("fail to unmarshal json content: %v", err) + } var widgets []panel - json.Unmarshal([]byte(jsonContent.PanelsJSON), &widgets) + err = json.Unmarshal([]byte(jsonContent.PanelsJSON), &widgets) + if err != nil { + return fmt.Errorf("fail to unmarshal panels content: %v", err) + } for _, widget := range widgets { if widget.Type == "visualization" { @@ -175,7 +188,26 @@ func (loader ElasticsearchLoader) importPanelsFromDashboard(file string) (err er func (loader ElasticsearchLoader) importVisualization(file string) error { loader.statusMsg("Import visualization %s", file) - if err := loader.importJSONFile("visualization", file); err != nil { + reader, err := ioutil.ReadFile(file) + if err != nil { + return err + } + var vizContent common.MapStr + err = json.Unmarshal(reader, &vizContent) + if err != nil { + return fmt.Errorf("fail to unmarshal vizualization content %s: %v", file, err) + } + + if loader.config.Index != "" { + if savedObject, ok := vizContent["kibanaSavedObjectMeta"].(map[string]interface{}); ok { + + vizContent["kibanaSavedObjectMeta"] = ReplaceIndexInSavedObject(loader.config.Index, savedObject) + } + } + + vizName := strings.TrimSuffix(filepath.Base(file), filepath.Ext(file)) + path := "/" + loader.config.KibanaIndex + "/visualization/" + vizName + if _, err := loader.client.LoadJSON(path, vizContent); err != nil { return err } @@ -192,29 +224,16 @@ func (loader ElasticsearchLoader) importSearch(file string) error { var searchContent common.MapStr err = json.Unmarshal(reader, &searchContent) if err != nil { - return fmt.Errorf("Failed to unmarshal search content %s: %v", searchName, err) + return fmt.Errorf("fail to unmarshal search content %s: %v", searchName, err) } if loader.config.Index != "" { + // change index pattern name if savedObject, ok := searchContent["kibanaSavedObjectMeta"].(map[string]interface{}); ok { - if source, ok := savedObject["searchSourceJSON"].(string); ok { - var record common.MapStr - err = json.Unmarshal([]byte(source), &record) - if err != nil { - return fmt.Errorf("Failed to unmarshal searchSourceJSON from search %s: %v", searchName, err) - } - - if _, ok := record["index"]; ok { - record["index"] = loader.config.Index - } - searchSourceJSON, err := json.Marshal(record) - if err != nil { - return fmt.Errorf("Failed to marshal searchSourceJSON: %v", err) - } - - savedObject["searchSourceJSON"] = string(searchSourceJSON) - } + + searchContent["kibanaSavedObjectMeta"] = ReplaceIndexInSavedObject(loader.config.Index, savedObject) + } } @@ -240,7 +259,11 @@ func (loader ElasticsearchLoader) importSearchFromVisualization(file string) err } var jsonContent record - json.Unmarshal(reader, &jsonContent) + err = json.Unmarshal(reader, &jsonContent) + if err != nil { + return fmt.Errorf("fail to unmarshal the search content: %v", err) + } + id := jsonContent.SavedSearchID if len(id) == 0 { // no search used diff --git a/libbeat/dashboards/kibana_loader.go b/libbeat/dashboards/kibana_loader.go index 882a606d28f..ba58a931b7e 100644 --- a/libbeat/dashboards/kibana_loader.go +++ b/libbeat/dashboards/kibana_loader.go @@ -1,7 +1,7 @@ package dashboards import ( - "bytes" + "encoding/json" "fmt" "io/ioutil" "net/url" @@ -48,12 +48,20 @@ func (loader KibanaLoader) ImportIndex(file string) error { params.Set("force", "true") //overwrite the existing dashboards // read json file - content, err := ioutil.ReadFile(file) + reader, err := ioutil.ReadFile(file) if err != nil { return fmt.Errorf("fail to read index-pattern: %v", err) } - return loader.client.ImportJSON(importAPI, params, bytes.NewBuffer(content)) + var indexContent common.MapStr + err = json.Unmarshal(reader, &indexContent) + if err != nil { + return fmt.Errorf("fail to unmarshal the index content: %v", err) + } + + indexContent = ReplaceIndexInIndexPattern(loader.config.Index, indexContent) + + return loader.client.ImportJSON(importAPI, params, indexContent) } func (loader KibanaLoader) ImportDashboard(file string) error { @@ -62,12 +70,19 @@ func (loader KibanaLoader) ImportDashboard(file string) error { params.Add("exclude", "index-pattern") //don't import the index pattern from the dashboards // read json file - content, err := ioutil.ReadFile(file) + reader, err := ioutil.ReadFile(file) if err != nil { return fmt.Errorf("fail to read index-pattern: %v", err) } + var content common.MapStr + err = json.Unmarshal(reader, &content) + if err != nil { + return fmt.Errorf("fail to unmarshal the index content: %v", err) + } + + content = ReplaceIndexInDashboardObject(loader.config.Index, content) - return loader.client.ImportJSON(importAPI, params, bytes.NewBuffer(content)) + return loader.client.ImportJSON(importAPI, params, content) } func (loader KibanaLoader) Close() error { diff --git a/libbeat/dashboards/modify_json.go b/libbeat/dashboards/modify_json.go new file mode 100644 index 00000000000..2a219bfdfeb --- /dev/null +++ b/libbeat/dashboards/modify_json.go @@ -0,0 +1,105 @@ +package dashboards + +import ( + "encoding/json" + "fmt" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/logp" +) + +type JSONObjectAttribute struct { + Description string `json:"description"` + KibanaSavedObjectMeta map[string]interface{} `json:"kibanaSavedObjectMeta"` + Title string `json:"title"` + Type string `json:"type"` +} + +type JSONObject struct { + Attributes JSONObjectAttribute `json:"attributes"` +} + +type JSONFormat struct { + Objects []JSONObject `json:"objects"` +} + +func ReplaceIndexInIndexPattern(index string, content common.MapStr) common.MapStr { + + if index != "" { + // change index pattern name + if objects, ok := content["objects"].([]interface{}); ok { + for i, object := range objects { + if objectMap, ok := object.(map[string]interface{}); ok { + objectMap["id"] = index + + if attributes, ok := objectMap["attributes"].(map[string]interface{}); ok { + attributes["title"] = index + objectMap["attributes"] = attributes + } + objects[i] = objectMap + } + } + content["objects"] = objects + } + } + + return content +} + +func replaceIndexInSearchObject(index string, savedObject string) (string, error) { + + var record common.MapStr + err := json.Unmarshal([]byte(savedObject), &record) + if err != nil { + return "", fmt.Errorf("fail to unmarshal searchSourceJSON from search : %v", err) + } + + if _, ok := record["index"]; ok { + record["index"] = index + } + searchSourceJSON, err := json.Marshal(record) + if err != nil { + return "", fmt.Errorf("fail to marshal searchSourceJSON: %v", err) + } + + return string(searchSourceJSON), nil +} + +func ReplaceIndexInSavedObject(index string, kibanaSavedObject map[string]interface{}) map[string]interface{} { + + if searchSourceJSON, ok := kibanaSavedObject["searchSourceJSON"].(string); ok { + searchSourceJSON, err := replaceIndexInSearchObject(index, searchSourceJSON) + if err != nil { + logp.Err("Fail to replace searchSourceJSON: %v", err) + return kibanaSavedObject + } + kibanaSavedObject["searchSourceJSON"] = searchSourceJSON + } + + return kibanaSavedObject +} + +func ReplaceIndexInDashboardObject(index string, content common.MapStr) common.MapStr { + + if index == "" { + return content + } + if objects, ok := content["objects"].([]interface{}); ok { + for i, object := range objects { + if objectMap, ok := object.(map[string]interface{}); ok { + if attributes, ok := objectMap["attributes"].(map[string]interface{}); ok { + + if kibanaSavedObject, ok := attributes["kibanaSavedObjectMeta"].(map[string]interface{}); ok { + + attributes["kibanaSavedObjectMeta"] = ReplaceIndexInSavedObject(index, kibanaSavedObject) + } + + objectMap["attributes"] = attributes + } + objects[i] = objectMap + } + } + content["objects"] = objects + } + return content +} diff --git a/libbeat/setup/kibana/client.go b/libbeat/setup/kibana/client.go index 85498206326..07baa9efe5a 100644 --- a/libbeat/setup/kibana/client.go +++ b/libbeat/setup/kibana/client.go @@ -196,8 +196,15 @@ func (client *Client) SetVersion() error { func (client *Client) GetVersion() string { return client.version } -func (client *Client) ImportJSON(url string, params url.Values, body io.Reader) error { - statusCode, response, err := client.Connection.Request("POST", url, params, body) +func (client *Client) ImportJSON(url string, params url.Values, jsonBody map[string]interface{}) error { + + body, err := json.Marshal(jsonBody) + if err != nil { + logp.Err("Failed to json encode body (%v): %#v", err, jsonBody) + return fmt.Errorf("fail to marshal the json content: %v", err) + } + + statusCode, response, err := client.Connection.Request("POST", url, params, bytes.NewBuffer(body)) if err != nil { return fmt.Errorf("%v. Response: %s", err, truncateString(response)) } From 366a584a916ed3b46f57ea1b42f89c380482f7b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Fri, 25 Aug 2017 13:31:59 +0200 Subject: [PATCH 121/139] Add registry for prospectors (#4980) From now on it is possible to register prospectors in `init` functions, just like in Metricbeat. Example: ``` func init() { err := prospectors.Register("log", NewProspector) if err != nil { panic(err) } } ``` --- filebeat/channel/interface.go | 4 +- filebeat/crawler/crawler.go | 10 ++-- filebeat/fileset/factory.go | 12 ++-- filebeat/include/list.go | 8 +++ filebeat/prospector/log/prospector.go | 21 ++++--- filebeat/prospector/prospector.go | 57 +++++++------------ filebeat/prospector/redis/prospector.go | 10 +++- .../{factory.go => registrarcontext.go} | 14 ++--- filebeat/prospector/registry.go | 45 +++++++++++++++ filebeat/prospector/registry_test.go | 57 +++++++++++++++++++ filebeat/prospector/stdin/prospector.go | 10 +++- filebeat/prospector/udp/prospector.go | 10 +++- 12 files changed, 191 insertions(+), 67 deletions(-) create mode 100644 filebeat/include/list.go rename filebeat/prospector/{factory.go => registrarcontext.go} (63%) create mode 100644 filebeat/prospector/registry.go create mode 100644 filebeat/prospector/registry_test.go diff --git a/filebeat/channel/interface.go b/filebeat/channel/interface.go index 2081ed16e01..99344d6a598 100644 --- a/filebeat/channel/interface.go +++ b/filebeat/channel/interface.go @@ -5,8 +5,8 @@ import ( "github.com/elastic/beats/libbeat/common" ) -// OutletFactory is used to create a new Outlet instance -type OutleterFactory func(*common.Config) (Outleter, error) +// Factory is used to create a new Outlet instance +type Factory func(*common.Config) (Outleter, error) // Outleter is the outlet for a prospector type Outleter interface { diff --git a/filebeat/crawler/crawler.go b/filebeat/crawler/crawler.go index 37a33d50d6a..b820d457c18 100644 --- a/filebeat/crawler/crawler.go +++ b/filebeat/crawler/crawler.go @@ -13,12 +13,14 @@ import ( "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/cfgwarn" "github.com/elastic/beats/libbeat/logp" + + _ "github.com/elastic/beats/filebeat/include" ) type Crawler struct { prospectors map[uint64]*prospector.Prospector prospectorConfigs []*common.Config - out channel.OutleterFactory + out channel.Factory wg sync.WaitGroup modulesReloader *cfgfile.Reloader prospectorsReloader *cfgfile.Reloader @@ -27,7 +29,7 @@ type Crawler struct { beatDone chan struct{} } -func New(out channel.OutleterFactory, prospectorConfigs []*common.Config, beatVersion string, beatDone chan struct{}, once bool) (*Crawler, error) { +func New(out channel.Factory, prospectorConfigs []*common.Config, beatVersion string, beatDone chan struct{}, once bool) (*Crawler, error) { return &Crawler{ out: out, prospectors: map[uint64]*prospector.Prospector{}, @@ -56,9 +58,9 @@ func (c *Crawler) Start(r *registrar.Registrar, configProspectors *common.Config cfgwarn.Beta("Loading separate prospectors is enabled.") c.prospectorsReloader = cfgfile.NewReloader(configProspectors) - prospectorsFactory := prospector.NewFactory(c.out, r, c.beatDone) + registrarContext := prospector.NewRegistrarContext(c.out, r, c.beatDone) go func() { - c.prospectorsReloader.Run(prospectorsFactory) + c.prospectorsReloader.Run(registrarContext) }() } diff --git a/filebeat/fileset/factory.go b/filebeat/fileset/factory.go index 8af2c423d0d..9f352c4b58b 100644 --- a/filebeat/fileset/factory.go +++ b/filebeat/fileset/factory.go @@ -4,7 +4,7 @@ import ( "github.com/mitchellh/hashstructure" "github.com/elastic/beats/filebeat/channel" - "github.com/elastic/beats/filebeat/prospector" + pros "github.com/elastic/beats/filebeat/prospector" "github.com/elastic/beats/filebeat/registrar" "github.com/elastic/beats/libbeat/cfgfile" "github.com/elastic/beats/libbeat/common" @@ -14,7 +14,7 @@ import ( // Factory for modules type Factory struct { - outlet channel.OutleterFactory + outlet channel.Factory registrar *registrar.Registrar beatVersion string pipelineLoaderFactory PipelineLoaderFactory @@ -25,12 +25,12 @@ type Factory struct { type prospectorsRunner struct { id uint64 moduleRegistry *ModuleRegistry - prospectors []*prospector.Prospector + prospectors []*pros.Prospector pipelineLoaderFactory PipelineLoaderFactory } // NewFactory instantiates a new Factory -func NewFactory(outlet channel.OutleterFactory, registrar *registrar.Registrar, beatVersion string, +func NewFactory(outlet channel.Factory, registrar *registrar.Registrar, beatVersion string, pipelineLoaderFactory PipelineLoaderFactory, beatDone chan struct{}) *Factory { return &Factory{ outlet: outlet, @@ -62,9 +62,9 @@ func (f *Factory) Create(c *common.Config) (cfgfile.Runner, error) { return nil, err } - prospectors := make([]*prospector.Prospector, len(pConfigs)) + prospectors := make([]*pros.Prospector, len(pConfigs)) for i, pConfig := range pConfigs { - prospectors[i], err = prospector.NewProspector(pConfig, f.outlet, f.beatDone, f.registrar.GetStates()) + prospectors[i], err = pros.NewProspector(pConfig, f.outlet, f.beatDone, f.registrar.GetStates()) if err != nil { logp.Err("Error creating prospector: %s", err) return nil, err diff --git a/filebeat/include/list.go b/filebeat/include/list.go new file mode 100644 index 00000000000..56765d42b0a --- /dev/null +++ b/filebeat/include/list.go @@ -0,0 +1,8 @@ +package include + +import ( + _ "github.com/elastic/beats/filebeat/prospector/log" + _ "github.com/elastic/beats/filebeat/prospector/redis" + _ "github.com/elastic/beats/filebeat/prospector/stdin" + _ "github.com/elastic/beats/filebeat/prospector/udp" +) diff --git a/filebeat/prospector/log/prospector.go b/filebeat/prospector/log/prospector.go index ea2cba339de..a58690aa3ea 100644 --- a/filebeat/prospector/log/prospector.go +++ b/filebeat/prospector/log/prospector.go @@ -12,6 +12,7 @@ import ( "github.com/elastic/beats/filebeat/channel" "github.com/elastic/beats/filebeat/harvester" "github.com/elastic/beats/filebeat/input/file" + "github.com/elastic/beats/filebeat/prospector" "github.com/elastic/beats/filebeat/util" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" @@ -28,6 +29,13 @@ var ( harvesterSkipped = monitoring.NewInt(nil, "filebeat.harvester.skipped") ) +func init() { + err := prospector.Register("log", NewProspector) + if err != nil { + panic(err) + } +} + // Prospector contains the prospector and its config type Prospector struct { cfg *common.Config @@ -42,10 +50,9 @@ type Prospector struct { // NewProspector instantiates a new Log func NewProspector( cfg *common.Config, - states []file.State, - outlet channel.OutleterFactory, - done, beatDone chan struct{}, -) (*Prospector, error) { + outlet channel.Factory, + context prospector.Context, +) (prospector.Prospectorer, error) { // Note: underlying output. // The prospector and harvester do have different requirements @@ -61,7 +68,7 @@ func NewProspector( // stateOut will only be unblocked if the beat is shut down. // otherwise it can block on a full publisher pipeline, so state updates // can be forwarded correctly to the registrar. - stateOut := channel.CloseOnSignal(channel.SubOutlet(out), beatDone) + stateOut := channel.CloseOnSignal(channel.SubOutlet(out), context.BeatDone) p := &Prospector{ config: defaultConfig, @@ -70,7 +77,7 @@ func NewProspector( outlet: out, stateOutlet: stateOut, states: &file.States{}, - done: done, + done: context.Done, } if err := cfg.Unpack(&p.config); err != nil { @@ -92,7 +99,7 @@ func NewProspector( return nil, fmt.Errorf("each prospector must have at least one path defined") } - err = p.loadStates(states) + err = p.loadStates(context.States) if err != nil { return nil, err } diff --git a/filebeat/prospector/prospector.go b/filebeat/prospector/prospector.go index 07631306c25..1661202d1fb 100644 --- a/filebeat/prospector/prospector.go +++ b/filebeat/prospector/prospector.go @@ -1,23 +1,24 @@ package prospector import ( - "fmt" "sync" "time" "github.com/mitchellh/hashstructure" "github.com/elastic/beats/filebeat/channel" - "github.com/elastic/beats/filebeat/harvester" "github.com/elastic/beats/filebeat/input/file" - "github.com/elastic/beats/filebeat/prospector/log" - "github.com/elastic/beats/filebeat/prospector/redis" - "github.com/elastic/beats/filebeat/prospector/stdin" - "github.com/elastic/beats/filebeat/prospector/udp" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" ) +// Prospectorer is the interface common to all prospectors +type Prospectorer interface { + Run() + Stop() + Wait() +} + // Prospector contains the prospector type Prospector struct { config prospectorConfig @@ -29,17 +30,10 @@ type Prospector struct { beatDone chan struct{} } -// Prospectorer is the interface common to all prospectors -type Prospectorer interface { - Run() - Stop() - Wait() -} - // NewProspector instantiates a new prospector func NewProspector( conf *common.Config, - outlet channel.OutleterFactory, + outlet channel.Factory, beatDone chan struct{}, states []file.State, ) (*Prospector, error) { @@ -63,38 +57,25 @@ func NewProspector( return nil, err } - err = prospector.initProspectorer(outlet, states, conf) + var f Factory + f, err = GetFactory(prospector.config.Type) if err != nil { return prospector, err } - return prospector, nil -} - -func (p *Prospector) initProspectorer(outlet channel.OutleterFactory, states []file.State, config *common.Config) error { - var prospectorer Prospectorer - var err error - - switch p.config.Type { - case harvester.StdinType: - prospectorer, err = stdin.NewProspector(config, outlet) - case harvester.RedisType: - prospectorer, err = redis.NewProspector(config, outlet) - case harvester.LogType: - prospectorer, err = log.NewProspector(config, states, outlet, p.done, p.beatDone) - case harvester.UdpType: - prospectorer, err = udp.NewProspector(config, outlet) - default: - return fmt.Errorf("invalid prospector type: %v. Change type", p.config.Type) + context := Context{ + States: states, + Done: prospector.done, + BeatDone: prospector.beatDone, } - + var prospectorer Prospectorer + prospectorer, err = f(conf, outlet, context) if err != nil { - return err + return prospector, err } + prospector.prospectorer = prospectorer - p.prospectorer = prospectorer - - return nil + return prospector, nil } // Start starts the prospector diff --git a/filebeat/prospector/redis/prospector.go b/filebeat/prospector/redis/prospector.go index 0a949ffbd5f..66d4f29dcaa 100644 --- a/filebeat/prospector/redis/prospector.go +++ b/filebeat/prospector/redis/prospector.go @@ -8,11 +8,19 @@ import ( "github.com/elastic/beats/filebeat/channel" "github.com/elastic/beats/filebeat/harvester" "github.com/elastic/beats/filebeat/input/file" + "github.com/elastic/beats/filebeat/prospector" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/cfgwarn" "github.com/elastic/beats/libbeat/logp" ) +func init() { + err := prospector.Register("redis", NewProspector) + if err != nil { + panic(err) + } +} + // Prospector is a prospector for redis type Prospector struct { started bool @@ -23,7 +31,7 @@ type Prospector struct { } // NewProspector creates a new redis prospector -func NewProspector(cfg *common.Config, outletFactory channel.OutleterFactory) (*Prospector, error) { +func NewProspector(cfg *common.Config, outletFactory channel.Factory, context prospector.Context) (prospector.Prospectorer, error) { cfgwarn.Experimental("Redis slowlog prospector is enabled.") config := defaultConfig diff --git a/filebeat/prospector/factory.go b/filebeat/prospector/registrarcontext.go similarity index 63% rename from filebeat/prospector/factory.go rename to filebeat/prospector/registrarcontext.go index c52776cf9da..678e370ebfe 100644 --- a/filebeat/prospector/factory.go +++ b/filebeat/prospector/registrarcontext.go @@ -8,16 +8,16 @@ import ( "github.com/elastic/beats/libbeat/logp" ) -// Factory is a factory for registrars -type Factory struct { - outlet channel.OutleterFactory +// RegistrarContext is a factory for registrars +type RegistrarContext struct { + outlet channel.Factory registrar *registrar.Registrar beatDone chan struct{} } -// NewFactory instantiates a new Factory -func NewFactory(outlet channel.OutleterFactory, registrar *registrar.Registrar, beatDone chan struct{}) *Factory { - return &Factory{ +// NewRegistrarContext instantiates a new RegistrarContext +func NewRegistrarContext(outlet channel.Factory, registrar *registrar.Registrar, beatDone chan struct{}) *RegistrarContext { + return &RegistrarContext{ outlet: outlet, registrar: registrar, beatDone: beatDone, @@ -25,7 +25,7 @@ func NewFactory(outlet channel.OutleterFactory, registrar *registrar.Registrar, } // Create creates a prospector based on a config -func (r *Factory) Create(c *common.Config) (cfgfile.Runner, error) { +func (r *RegistrarContext) Create(c *common.Config) (cfgfile.Runner, error) { p, err := NewProspector(c, r.outlet, r.beatDone, r.registrar.GetStates()) if err != nil { logp.Err("Error creating prospector: %s", err) diff --git a/filebeat/prospector/registry.go b/filebeat/prospector/registry.go new file mode 100644 index 00000000000..8585cef483f --- /dev/null +++ b/filebeat/prospector/registry.go @@ -0,0 +1,45 @@ +package prospector + +import ( + "fmt" + + "github.com/elastic/beats/filebeat/channel" + "github.com/elastic/beats/filebeat/input/file" + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/logp" +) + +type Context struct { + States []file.State + Done chan struct{} + BeatDone chan struct{} +} + +type Factory func(config *common.Config, outletFactory channel.Factory, context Context) (Prospectorer, error) + +var registry = make(map[string]Factory) + +func Register(name string, factory Factory) error { + logp.Info("Registering prospector factory") + if name == "" { + return fmt.Errorf("Error registering prospector: name cannot be empty") + } + if factory == nil { + return fmt.Errorf("Error registering prospector '%v': factory cannot be empty", name) + } + if _, exists := registry[name]; exists { + return fmt.Errorf("Error registering prospector '%v': already registered", name) + } + + registry[name] = factory + logp.Info("Succesfully registered prospector") + + return nil +} + +func GetFactory(name string) (Factory, error) { + if _, exists := registry[name]; !exists { + return nil, fmt.Errorf("Error retrieving factory for prospector '%v'", name) + } + return registry[name], nil +} diff --git a/filebeat/prospector/registry_test.go b/filebeat/prospector/registry_test.go new file mode 100644 index 00000000000..be8f793076d --- /dev/null +++ b/filebeat/prospector/registry_test.go @@ -0,0 +1,57 @@ +package prospector + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/filebeat/channel" + "github.com/elastic/beats/libbeat/common" +) + +var fakeFactory = func(config *common.Config, outletFactory channel.Factory, context Context) (Prospectorer, error) { + return nil, nil +} + +func TestAddFactoryEmptyName(t *testing.T) { + err := Register("", nil) + if assert.Error(t, err) { + assert.Equal(t, "Error registering prospector: name cannot be empty", err.Error()) + } +} + +func TestAddNilFactory(t *testing.T) { + err := Register("name", nil) + if assert.Error(t, err) { + assert.Equal(t, "Error registering prospector 'name': factory cannot be empty", err.Error()) + } +} + +func TestAddFactoryTwice(t *testing.T) { + var err error + err = Register("name", fakeFactory) + if err != nil { + t.Fatal(err) + } + + err = Register("name", fakeFactory) + if assert.Error(t, err) { + assert.Equal(t, "Error registering prospector 'name': already registered", err.Error()) + } +} + +func TestGetFactory(t *testing.T) { + f, err := GetFactory("name") + if err != nil { + t.Fatal(err) + } + assert.NotNil(t, f) +} + +func TestGetNonExistentFactory(t *testing.T) { + f, err := GetFactory("noSuchFactory") + assert.Nil(t, f) + if assert.Error(t, err) { + assert.Equal(t, "Error retrieving factory for prospector 'noSuchFactory'", err.Error()) + } +} diff --git a/filebeat/prospector/stdin/prospector.go b/filebeat/prospector/stdin/prospector.go index da2279789d4..a345fa4dbab 100644 --- a/filebeat/prospector/stdin/prospector.go +++ b/filebeat/prospector/stdin/prospector.go @@ -6,11 +6,19 @@ import ( "github.com/elastic/beats/filebeat/channel" "github.com/elastic/beats/filebeat/harvester" "github.com/elastic/beats/filebeat/input/file" + "github.com/elastic/beats/filebeat/prospector" "github.com/elastic/beats/filebeat/prospector/log" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" ) +func init() { + err := prospector.Register("stdin", NewProspector) + if err != nil { + panic(err) + } +} + // Prospector is a prospector for stdin type Prospector struct { harvester *log.Harvester @@ -22,7 +30,7 @@ type Prospector struct { // NewStdin creates a new stdin prospector // This prospector contains one harvester which is reading from stdin -func NewProspector(cfg *common.Config, outlet channel.OutleterFactory) (*Prospector, error) { +func NewProspector(cfg *common.Config, outlet channel.Factory, context prospector.Context) (prospector.Prospectorer, error) { out, err := outlet(cfg) if err != nil { return nil, err diff --git a/filebeat/prospector/udp/prospector.go b/filebeat/prospector/udp/prospector.go index c89d3b712fe..06e0fceb822 100644 --- a/filebeat/prospector/udp/prospector.go +++ b/filebeat/prospector/udp/prospector.go @@ -3,18 +3,26 @@ package udp import ( "github.com/elastic/beats/filebeat/channel" "github.com/elastic/beats/filebeat/harvester" + "github.com/elastic/beats/filebeat/prospector" "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/common/cfgwarn" "github.com/elastic/beats/libbeat/logp" ) +func init() { + err := prospector.Register("udp", NewProspector) + if err != nil { + panic(err) + } +} + type Prospector struct { harvester *Harvester started bool outlet channel.Outleter } -func NewProspector(cfg *common.Config, outlet channel.OutleterFactory) (*Prospector, error) { +func NewProspector(cfg *common.Config, outlet channel.Factory, context prospector.Context) (prospector.Prospectorer, error) { cfgwarn.Experimental("UDP prospector type is used") out, err := outlet(cfg) From 565719793cf4336fd527ee05633c2ed5408e67d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E9=92=B0=E8=BF=AA?= Date: Fri, 25 Aug 2017 22:56:04 +0800 Subject: [PATCH 122/139] Add ceph cluster status to metricbeat (#4990) The cluster_status will collect pgmap, osdmap, throughput and iops information of ceph cluster. --- metricbeat/docs/fields.asciidoc | 223 ++++++++++++++++++ metricbeat/docs/modules/ceph.asciidoc | 4 + .../docs/modules/ceph/cluster_status.asciidoc | 19 ++ metricbeat/include/list.go | 1 + .../testdata/status_sample_response.json | 189 +++++++++++++++ .../ceph/cluster_status/_meta/data.json | 55 +++++ .../ceph/cluster_status/_meta/docs.asciidoc | 3 + .../ceph/cluster_status/_meta/fields.yml | 113 +++++++++ .../ceph/cluster_status/cluster_status.go | 58 +++++ .../cluster_status_integration_test.go | 48 ++++ .../cluster_status/cluster_status_test.go | 101 ++++++++ metricbeat/module/ceph/cluster_status/data.go | 133 +++++++++++ 12 files changed, 947 insertions(+) create mode 100644 metricbeat/docs/modules/ceph/cluster_status.asciidoc create mode 100644 metricbeat/module/ceph/_meta/testdata/status_sample_response.json create mode 100644 metricbeat/module/ceph/cluster_status/_meta/data.json create mode 100644 metricbeat/module/ceph/cluster_status/_meta/docs.asciidoc create mode 100644 metricbeat/module/ceph/cluster_status/_meta/fields.yml create mode 100644 metricbeat/module/ceph/cluster_status/cluster_status.go create mode 100644 metricbeat/module/ceph/cluster_status/cluster_status_integration_test.go create mode 100644 metricbeat/module/ceph/cluster_status/cluster_status_test.go create mode 100644 metricbeat/module/ceph/cluster_status/data.go diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index cabf00631fa..115f056a4d7 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -857,6 +857,229 @@ type: keyword Status of the round +[float] +== cluster_status fields + +cluster_status + + + +[float] +=== `ceph.cluster_status.version` + +type: long + +Ceph Status version + + +[float] +=== `ceph.cluster_status.traffic.read_bytes` + +type: long + +format: bytes + +Cluster read throughput per second + + +[float] +=== `ceph.cluster_status.traffic.write_bytes` + +type: long + +format: bytes + +Cluster write throughput per second + + +[float] +=== `ceph.cluster_status.traffic.read_op_per_sec` + +type: long + +Cluster read iops per second + + +[float] +=== `ceph.cluster_status.traffic.write_op_per_sec` + +type: long + +Cluster write iops per second + + +[float] +=== `ceph.cluster_status.misplace.total` + +type: long + +Cluster misplace pg number + + +[float] +=== `ceph.cluster_status.misplace.objects` + +type: long + +Cluster misplace objects number + + +[float] +=== `ceph.cluster_status.misplace.ratio` + +type: scaled_float + +format: percent + +Cluster misplace ratio + + +[float] +=== `ceph.cluster_status.degraded.total` + +type: long + +Cluster degraded pg number + + +[float] +=== `ceph.cluster_status.degraded.objects` + +type: long + +Cluster degraded objects number + + +[float] +=== `ceph.cluster_status.degraded.ratio` + +type: scaled_float + +format: percent + +Cluster degraded ratio + + +[float] +=== `ceph.cluster_status.pg.data_bytes` + +type: long + +format: bytes + +Cluster pg data bytes + + +[float] +=== `ceph.cluster_status.pg.avail_bytes` + +type: long + +format: bytes + +Cluster available bytes + + +[float] +=== `ceph.cluster_status.pg.total_bytes` + +type: long + +format: bytes + +Cluster total bytes + + +[float] +=== `ceph.cluster_status.pg.used_bytes` + +type: long + +format: bytes + +Cluster used bytes + + +[float] +=== `ceph.cluster_status.pg_state.state_name` + +type: long + +Pg state description + + +[float] +=== `ceph.cluster_status.pg_state.count` + +type: long + +Shows how many pgs are in state of pg_state.state_name + + +[float] +=== `ceph.cluster_status.pg_state.version` + +type: long + +Cluster status version + + +[float] +=== `ceph.cluster_status.osd.full` + +type: bool + +Is osd full + + +[float] +=== `ceph.cluster_status.osd.nearfull` + +type: bool + +Is osd near full + + +[float] +=== `ceph.cluster_status.osd.num_osds` + +type: long + +Shows how many osds in the cluster + + +[float] +=== `ceph.cluster_status.osd.num_up_osds` + +type: long + +Shows how many osds are on the state of UP + + +[float] +=== `ceph.cluster_status.osd.num_in_osds` + +type: long + +Shows how many osds are on the state of IN + + +[float] +=== `ceph.cluster_status.osd.num_in_osds` + +type: long + +Shows how many osds are on the state of REMAPPED + + +[float] +=== `ceph.cluster_status.osd.epoch` + +type: long + +epoch number + + [float] == monitor_health fields diff --git a/metricbeat/docs/modules/ceph.asciidoc b/metricbeat/docs/modules/ceph.asciidoc index c011ad1e1dc..5b2843395c1 100644 --- a/metricbeat/docs/modules/ceph.asciidoc +++ b/metricbeat/docs/modules/ceph.asciidoc @@ -35,6 +35,8 @@ The following metricsets are available: * <> +* <> + * <> * <> @@ -43,6 +45,8 @@ include::ceph/cluster_disk.asciidoc[] include::ceph/cluster_health.asciidoc[] +include::ceph/cluster_status.asciidoc[] + include::ceph/monitor_health.asciidoc[] include::ceph/pool_disk.asciidoc[] diff --git a/metricbeat/docs/modules/ceph/cluster_status.asciidoc b/metricbeat/docs/modules/ceph/cluster_status.asciidoc new file mode 100644 index 00000000000..18de063875c --- /dev/null +++ b/metricbeat/docs/modules/ceph/cluster_status.asciidoc @@ -0,0 +1,19 @@ +//// +This file is generated! See scripts/docs_collector.py +//// + +[[metricbeat-metricset-ceph-cluster_status]] +include::../../../module/ceph/cluster_status/_meta/docs.asciidoc[] + + +==== Fields + +For a description of each field in the metricset, see the +<> section. + +Here is an example document generated by this metricset: + +[source,json] +---- +include::../../../module/ceph/cluster_status/_meta/data.json[] +---- diff --git a/metricbeat/include/list.go b/metricbeat/include/list.go index 880a6b196bf..dc9cff1a8a5 100644 --- a/metricbeat/include/list.go +++ b/metricbeat/include/list.go @@ -15,6 +15,7 @@ import ( _ "github.com/elastic/beats/metricbeat/module/ceph" _ "github.com/elastic/beats/metricbeat/module/ceph/cluster_disk" _ "github.com/elastic/beats/metricbeat/module/ceph/cluster_health" + _ "github.com/elastic/beats/metricbeat/module/ceph/cluster_status" _ "github.com/elastic/beats/metricbeat/module/ceph/monitor_health" _ "github.com/elastic/beats/metricbeat/module/ceph/pool_disk" _ "github.com/elastic/beats/metricbeat/module/couchbase" diff --git a/metricbeat/module/ceph/_meta/testdata/status_sample_response.json b/metricbeat/module/ceph/_meta/testdata/status_sample_response.json new file mode 100644 index 00000000000..a40b9ccada9 --- /dev/null +++ b/metricbeat/module/ceph/_meta/testdata/status_sample_response.json @@ -0,0 +1,189 @@ +{ + "output": { + "election_epoch": 24, + "fsid": "c8a2176b-630a-4a67-a142-54e23ad91f90", + "fsmap": { + "by_rank": [], + "epoch": 1 + }, + "health": { + "detail": [ + "mon.ceph1 addr 192.168.56.122:6789/0 clock skew 7133.3s > max 0.05s (latency 0.657497s)" + ], + "health": { + "health_services": [ + { + "mons": [ + { + "avail_percent": 87, + "health": "HEALTH_OK", + "kb_avail": 15581228, + "kb_total": 17811456, + "kb_used": 2230228, + "last_updated": "2017-08-24 00:04:09.783438", + "name": "ceph0", + "store_stats": { + "bytes_log": 2031616, + "bytes_misc": 65552, + "bytes_sst": 21914124, + "bytes_total": 24011292, + "last_updated": "0.000000" + } + } + ] + } + ] + }, + "overall_status": "HEALTH_ERR", + "summary": [ + { + "severity": "HEALTH_ERR", + "summary": "101 pgs are stuck inactive for more than 300 seconds" + }, + { + "severity": "HEALTH_WARN", + "summary": "265 pgs degraded" + }, + { + "severity": "HEALTH_WARN", + "summary": "80 pgs stuck degraded" + }, + { + "severity": "HEALTH_WARN", + "summary": "101 pgs stuck inactive" + }, + { + "severity": "HEALTH_WARN", + "summary": "320 pgs stuck unclean" + }, + { + "severity": "HEALTH_WARN", + "summary": "80 pgs stuck undersized" + }, + { + "severity": "HEALTH_WARN", + "summary": "265 pgs undersized" + }, + { + "severity": "HEALTH_WARN", + "summary": "recovery 294/768 objects degraded (38.281%)" + }, + { + "severity": "HEALTH_WARN", + "summary": "recovery 88/768 objects misplaced (11.458%)" + }, + { + "severity": "HEALTH_WARN", + "summary": "1/4 in osds are down" + }, + { + "severity": "HEALTH_WARN", + "summary": "1 mons down, quorum 0,1 ceph0,ceph1" + }, + { + "severity": "HEALTH_WARN", + "summary": "Monitor clock skew detected " + } + ], + "timechecks": { + "epoch": 24, + "mons": [ + { + "health": "HEALTH_OK", + "latency": 0.0, + "name": "ceph0", + "skew": 0.0 + }, + { + "details": "clock skew 7133.3s > max 0.05s", + "health": "HEALTH_WARN", + "latency": 0.657497, + "name": "ceph1", + "skew": 7133.303939 + } + ], + "round": 8, + "round_status": "finished" + } + }, + "monmap": { + "created": "2017-08-22 03:27:23.660293", + "epoch": 1, + "fsid": "c8a2176b-630a-4a67-a142-54e23ad91f90", + "modified": "2017-08-22 03:27:23.660293", + "mons": [ + { + "addr": "192.168.56.121:6789/0", + "name": "ceph0", + "rank": 0 + }, + { + "addr": "192.168.56.122:6789/0", + "name": "ceph1", + "rank": 1 + }, + { + "addr": "192.168.56.123:6789/0", + "name": "ceph2", + "rank": 2 + } + ] + }, + "osdmap": { + "osdmap": { + "epoch": 264, + "full": false, + "nearfull": false, + "num_in_osds": 4, + "num_osds": 6, + "num_remapped_pgs": 240, + "num_up_osds": 3 + } + }, + "pgmap": { + "read_bytes_sec": 55667788, + "read_op_per_sec": 1234, + "write_bytes_sec": 11996158, + "write_op_per_sec": 10, + "bytes_avail": 9965821952, + "bytes_total": 12838682624, + "bytes_used": 2872860672, + "data_bytes": 1054023794, + "degraded_objects": 294, + "degraded_ratio": 0.382812, + "degraded_total": 768, + "misplaced_objects": 88, + "misplaced_ratio": 0.114583, + "misplaced_total": 768, + "num_pgs": 320, + "pgs_by_state": [ + { + "count": 109, + "state_name": "active+undersized+degraded" + }, + { + "count": 101, + "state_name": "undersized+degraded+peered" + }, + { + "count": 55, + "state_name": "active+remapped" + }, + { + "count": 55, + "state_name": "active+undersized+degraded+remapped" + } + ], + "version": 813 + }, + "quorum": [ + 0, + 1 + ], + "quorum_names": [ + "ceph0", + "ceph1" + ] + }, + "status": "OK" +} diff --git a/metricbeat/module/ceph/cluster_status/_meta/data.json b/metricbeat/module/ceph/cluster_status/_meta/data.json new file mode 100644 index 00000000000..766dec281c0 --- /dev/null +++ b/metricbeat/module/ceph/cluster_status/_meta/data.json @@ -0,0 +1,55 @@ +{ + "@timestamp": "2017-08-24T03:14:20.525Z", + "ceph": { + "cluster_status": { + "version": 796, + "osd": { + "full": false, + "nearfull": false, + "num_osds": 6, + "num_up_osds": 4, + "num_in_osds": 4, + "num_remapped_pgs": 211, + "epoch": 272 + }, + "traffic": { + "read_bytes_sec": 55667788, + "read_op_per_sec": 1234, + "write_bytes_sec": 11996158, + "write_op_per_sec": 10 + }, + "misplace": { + "total": 753, + "objects": 71, + "ratio": 0.09429 + }, + "degraded": { + "ratio": 0.146082, + "total": 753, + "objects": 110 + }, + "pg": { + "data_bytes": 1033052274, + "bytes_avail": 10016411648, + "bytes_total": 12838682624, + "bytes_used": 2822270976 + }, + "pg_state": { + "state_name": "undersized+degraded+peered", + "version": 856, + "count": 214 + } + } + }, + "metricset": { + "name": "cluster_status", + "host": "192.168.56.133:5000", + "rtt": 305059002, + "module": "ceph" + }, + "beat": { + "name": "centos7gui", + "hostname": "centos7gui", + "version": "7.0.0-alpha1" + } +} diff --git a/metricbeat/module/ceph/cluster_status/_meta/docs.asciidoc b/metricbeat/module/ceph/cluster_status/_meta/docs.asciidoc new file mode 100644 index 00000000000..49146921f64 --- /dev/null +++ b/metricbeat/module/ceph/cluster_status/_meta/docs.asciidoc @@ -0,0 +1,3 @@ +=== Ceph cluster_health metricset + +This is the `cluster_status` metricset of the Ceph module. \ No newline at end of file diff --git a/metricbeat/module/ceph/cluster_status/_meta/fields.yml b/metricbeat/module/ceph/cluster_status/_meta/fields.yml new file mode 100644 index 00000000000..98c76635b7a --- /dev/null +++ b/metricbeat/module/ceph/cluster_status/_meta/fields.yml @@ -0,0 +1,113 @@ +- name: cluster_status + type: group + description: > + cluster_status + fields: + - name: version + type: long + description: > + Ceph Status version + - name: traffic.read_bytes + type: long + format: bytes + description: > + Cluster read throughput per second + - name: traffic.write_bytes + type: long + format: bytes + description: > + Cluster write throughput per second + - name: traffic.read_op_per_sec + type: long + description: > + Cluster read iops per second + - name: traffic.write_op_per_sec + type: long + description: > + Cluster write iops per second + - name: misplace.total + type: long + description: > + Cluster misplace pg number + - name: misplace.objects + type: long + description: > + Cluster misplace objects number + - name: misplace.ratio + type: scaled_float + format: percent + description: > + Cluster misplace ratio + - name: degraded.total + type: long + description: > + Cluster degraded pg number + - name: degraded.objects + type: long + description: > + Cluster degraded objects number + - name: degraded.ratio + type: scaled_float + format: percent + description: > + Cluster degraded ratio + - name: pg.data_bytes + type: long + format: bytes + description: > + Cluster pg data bytes + - name: pg.avail_bytes + type: long + format: bytes + description: > + Cluster available bytes + - name: pg.total_bytes + type: long + format: bytes + description: > + Cluster total bytes + - name: pg.used_bytes + type: long + format: bytes + description: > + Cluster used bytes + - name: pg_state.state_name + type: long + description: > + Pg state description + - name: pg_state.count + type: long + description: > + Shows how many pgs are in state of pg_state.state_name + - name: pg_state.version + type: long + description: > + Cluster status version + - name: osd.full + type: bool + description: > + Is osd full + - name: osd.nearfull + type: bool + description: > + Is osd near full + - name: osd.num_osds + type: long + description: > + Shows how many osds in the cluster + - name: osd.num_up_osds + type: long + description: > + Shows how many osds are on the state of UP + - name: osd.num_in_osds + type: long + description: > + Shows how many osds are on the state of IN + - name: osd.num_in_osds + type: long + description: > + Shows how many osds are on the state of REMAPPED + - name: osd.epoch + type: long + description: > + epoch number \ No newline at end of file diff --git a/metricbeat/module/ceph/cluster_status/cluster_status.go b/metricbeat/module/ceph/cluster_status/cluster_status.go new file mode 100644 index 00000000000..2ebf64e286d --- /dev/null +++ b/metricbeat/module/ceph/cluster_status/cluster_status.go @@ -0,0 +1,58 @@ +package cluster_status + +import ( + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/common/cfgwarn" + "github.com/elastic/beats/metricbeat/helper" + "github.com/elastic/beats/metricbeat/mb" + "github.com/elastic/beats/metricbeat/mb/parse" +) + +const ( + defaultScheme = "http" + defaultPath = "/api/v0.1/status" +) + +var ( + hostParser = parse.URLHostParserBuilder{ + DefaultScheme: defaultScheme, + DefaultPath: defaultPath, + }.Build() +) + +func init() { + if err := mb.Registry.AddMetricSet("ceph", "cluster_status", New, hostParser); err != nil { + panic(err) + } +} + +type MetricSet struct { + mb.BaseMetricSet + *helper.HTTP +} + +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The ceph cluster_status metricset is beta") + + http := helper.NewHTTP(base) + http.SetHeader("Accept", "application/json") + + return &MetricSet{ + base, + http, + }, nil +} + +func (m *MetricSet) Fetch() ([]common.MapStr, error) { + content, err := m.HTTP.FetchContent() + if err != nil { + return nil, err + } + + events, err := eventsMapping(content) + if err != nil { + return nil, err + } + + return events, nil +} diff --git a/metricbeat/module/ceph/cluster_status/cluster_status_integration_test.go b/metricbeat/module/ceph/cluster_status/cluster_status_integration_test.go new file mode 100644 index 00000000000..6ac2bcae7f9 --- /dev/null +++ b/metricbeat/module/ceph/cluster_status/cluster_status_integration_test.go @@ -0,0 +1,48 @@ +package cluster_status + +import ( + "fmt" + "os" + "testing" + + mbtest "github.com/elastic/beats/metricbeat/mb/testing" +) + +func TestData(t *testing.T) { + f := mbtest.NewEventsFetcher(t, getConfig()) + err := mbtest.WriteEvents(f, t) + if err != nil { + t.Fatal("write", err) + } +} + +func getConfig() map[string]interface{} { + return map[string]interface{}{ + "module": "ceph", + "metricsets": []string{"cluster_status"}, + "hosts": getTestCephHost(), + } +} + +const ( + cephDefaultHost = "127.0.0.1" + cephDefaultPort = "5000" +) + +func getTestCephHost() string { + return fmt.Sprintf("%v:%v", + getenv("CEPH_HOST", cephDefaultHost), + getenv("CEPH_PORT", cephDefaultPort), + ) +} + +func getenv(name, defaultValue string) string { + return strDefault(os.Getenv(name), defaultValue) +} + +func strDefault(a, defaults string) string { + if len(a) == 0 { + return defaults + } + return a +} diff --git a/metricbeat/module/ceph/cluster_status/cluster_status_test.go b/metricbeat/module/ceph/cluster_status/cluster_status_test.go new file mode 100644 index 00000000000..5d84059e234 --- /dev/null +++ b/metricbeat/module/ceph/cluster_status/cluster_status_test.go @@ -0,0 +1,101 @@ +package cluster_status + +import ( + "io/ioutil" + "net/http" + "net/http/httptest" + "path/filepath" + "testing" + + "github.com/elastic/beats/libbeat/common" + mbtest "github.com/elastic/beats/metricbeat/mb/testing" + + "github.com/stretchr/testify/assert" +) + +func TestFetchEventContents(t *testing.T) { + absPath, err := filepath.Abs("../_meta/testdata/") + assert.NoError(t, err) + + response, err := ioutil.ReadFile(absPath + "/status_sample_response.json") + assert.NoError(t, err) + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + w.Header().Set("Content-Type", "application/json;") + w.Write([]byte(response)) + })) + defer server.Close() + + config := map[string]interface{}{ + "module": "ceph", + "metricsets": []string{"cluster_status"}, + "hosts": []string{server.URL}, + } + + f := mbtest.NewEventsFetcher(t, config) + events, err := f.Fetch() + event := events[0] + + t.Logf("%s/%s event: %+v", f.Module().Name(), f.Name(), event.StringToPrint()) + + //check status version number + assert.EqualValues(t, 813, event["version"]) + + //check osd info + osdmap := event["osd"].(common.MapStr) + assert.EqualValues(t, false, osdmap["full"]) + assert.EqualValues(t, false, osdmap["nearfull"]) + assert.EqualValues(t, 6, osdmap["osd_count"]) + assert.EqualValues(t, 3, osdmap["up_osd_count"]) + assert.EqualValues(t, 4, osdmap["in_osd_count"]) + assert.EqualValues(t, 240, osdmap["remapped_pg_count"]) + assert.EqualValues(t, 264, osdmap["epoch"]) + + //check traffic info + trafficInfo := event["traffic"].(common.MapStr) + assert.EqualValues(t, 55667788, trafficInfo["read_bytes"]) + assert.EqualValues(t, 1234, trafficInfo["read_op_per_sec"]) + assert.EqualValues(t, 11996158, trafficInfo["write_bytes"]) + assert.EqualValues(t, 10, trafficInfo["write_op_per_sec"]) + + //check misplace info + misplaceInfo := event["misplace"].(common.MapStr) + assert.EqualValues(t, 768, misplaceInfo["total"]) + assert.EqualValues(t, 88, misplaceInfo["objects"]) + assert.EqualValues(t, 0.114583, misplaceInfo["pct"]) + + //check degraded info + degradedInfo := event["degraded"].(common.MapStr) + assert.EqualValues(t, 768, degradedInfo["total"]) + assert.EqualValues(t, 294, degradedInfo["objects"]) + assert.EqualValues(t, 0.382812, degradedInfo["pct"]) + + //check pg info + pgInfo := event["pg"].(common.MapStr) + assert.EqualValues(t, 1054023794, pgInfo["data_bytes"]) + assert.EqualValues(t, 9965821952, pgInfo["avail_bytes"]) + assert.EqualValues(t, 12838682624, pgInfo["total_bytes"]) + assert.EqualValues(t, 2872860672, pgInfo["used_bytes"]) + + //check pg_state info + pg_stateInfo := events[1]["pg_state"].(common.MapStr) + assert.EqualValues(t, "active+undersized+degraded", pg_stateInfo["state_name"]) + assert.EqualValues(t, 109, pg_stateInfo["count"]) + assert.EqualValues(t, 813, pg_stateInfo["version"]) + + pg_stateInfo = events[2]["pg_state"].(common.MapStr) + assert.EqualValues(t, "undersized+degraded+peered", pg_stateInfo["state_name"]) + assert.EqualValues(t, 101, pg_stateInfo["count"]) + assert.EqualValues(t, 813, pg_stateInfo["version"]) + + pg_stateInfo = events[3]["pg_state"].(common.MapStr) + assert.EqualValues(t, "active+remapped", pg_stateInfo["state_name"]) + assert.EqualValues(t, 55, pg_stateInfo["count"]) + assert.EqualValues(t, 813, pg_stateInfo["version"]) + + pg_stateInfo = events[4]["pg_state"].(common.MapStr) + assert.EqualValues(t, "active+undersized+degraded+remapped", pg_stateInfo["state_name"]) + assert.EqualValues(t, 55, pg_stateInfo["count"]) + assert.EqualValues(t, 813, pg_stateInfo["version"]) +} diff --git a/metricbeat/module/ceph/cluster_status/data.go b/metricbeat/module/ceph/cluster_status/data.go new file mode 100644 index 00000000000..58be2931c9d --- /dev/null +++ b/metricbeat/module/ceph/cluster_status/data.go @@ -0,0 +1,133 @@ +package cluster_status + +import ( + "encoding/json" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/logp" +) + +type PgState struct { + Count int64 `json:"count"` + StateName string `json:"state_name"` +} + +type Pgmap struct { + AvailByte int64 `json:"bytes_avail"` + TotalByte int64 `json:"bytes_total"` + UsedByte int64 `json:"bytes_used"` + DataByte int64 `json:"data_bytes"` + + DegradedObjs int64 `json:"degraded_objects"` + DegradedRatio float64 `json:"degraded_ratio"` + DegradedTotal int64 `json:"degraded_total"` + + MisplacedObjs int64 `json:"misplaced_objects"` + MisplacedRatio float64 `json:"misplaced_ratio"` + MisplacedTotal int64 `json:"misplaced_total"` + + ReadByteSec int64 `json:"read_bytes_sec"` + ReadOpSec int64 `json:"read_op_per_sec"` + WriteByteSec int64 `json:"write_bytes_sec"` + WriteOpSec int64 `json:"write_op_per_sec"` + Version int64 `json:"version"` + + PgNum int64 `json:"num_pgs"` + PgStates []PgState `json:"pgs_by_state"` +} + +type Osdmap struct { + Epoch int64 `json:"epoch"` + Full bool `json:"full"` + Nearfull bool `json:"nearfull"` + OsdNum int64 `json:"num_osds"` + UpOsds int64 `json:"num_up_osds"` + InOsds int64 `json:"num_in_osds"` + RemapedPgs int64 `json:"num_remapped_pgs"` +} + +type Osdmap_ struct { + Osdmap Osdmap `json:"osdmap"` +} + +type Output struct { + Pgmap Pgmap `json:"pgmap"` + Osdmap Osdmap_ `json:"osdmap"` +} + +type HealthRequest struct { + Status string `json:"status"` + Output Output `json:"output"` +} + +func eventsMapping(content []byte) ([]common.MapStr, error) { + var d HealthRequest + err := json.Unmarshal(content, &d) + if err != nil { + logp.Err("Error: ", err) + return nil, err + } + + //osd map info + osdmap := d.Output.Osdmap.Osdmap + + osdState := common.MapStr{} + osdState["epoch"] = osdmap.Epoch + osdState["full"] = osdmap.Full + osdState["nearfull"] = osdmap.Nearfull + osdState["osd_count"] = osdmap.OsdNum + osdState["up_osd_count"] = osdmap.UpOsds + osdState["in_osd_count"] = osdmap.InOsds + osdState["remapped_pg_count"] = osdmap.RemapedPgs + + //pg map info + pgmap := d.Output.Pgmap + + traffic := common.MapStr{} + traffic["read_bytes"] = pgmap.ReadByteSec + traffic["read_op_per_sec"] = pgmap.ReadOpSec + traffic["write_bytes"] = pgmap.WriteByteSec + traffic["write_op_per_sec"] = pgmap.WriteOpSec + + misplace := common.MapStr{} + misplace["objects"] = pgmap.MisplacedObjs + misplace["pct"] = pgmap.MisplacedRatio + misplace["total"] = pgmap.MisplacedTotal + + degraded := common.MapStr{} + degraded["objects"] = pgmap.DegradedObjs + degraded["pct"] = pgmap.DegradedRatio + degraded["total"] = pgmap.DegradedTotal + + pg := common.MapStr{} + pg["avail_bytes"] = pgmap.AvailByte + pg["total_bytes"] = pgmap.TotalByte + pg["used_bytes"] = pgmap.UsedByte + pg["data_bytes"] = pgmap.DataByte + + state_event := common.MapStr{} + state_event["osd"] = osdState + state_event["traffic"] = traffic + state_event["misplace"] = misplace + state_event["degraded"] = degraded + state_event["pg"] = pg + state_event["version"] = pgmap.Version + + events := []common.MapStr{} + events = append(events, state_event) + + //pg state info + for _, state := range pgmap.PgStates { + state_evn := common.MapStr{ + "count": state.Count, + "state_name": state.StateName, + "version": pgmap.Version, + } + evt := common.MapStr{ + "pg_state": state_evn, + } + events = append(events, evt) + } + + return events, nil +} From 4ac68d2863971db5b8ffdf5a3a88fa38db960b21 Mon Sep 17 00:00:00 2001 From: Sven Woltmann Date: Fri, 25 Aug 2017 19:17:05 +0200 Subject: [PATCH 123/139] add_kubernetes_metadata processor: add support for "/var/log/containers/" log path (#4981) * add_kubernetes_metadata processor supports '/var/log/containers/' log path The add_kubernetes_metadata processor's LogPathMatcher could extract a Docker container ID - and hence enrich a log document with Kubernetes metadata - only if the log path was '/var/lib/docker/containers/'. With this commit, the LogPathMatcher can extract the container ID also from a '/var/log/containers/' log path (Kubernetes symlinks). --- CHANGELOG.asciidoc | 1 + .../add_kubernetes_metadata/indexing.go | 36 ++++++++--- .../add_kubernetes_metadata/indexing_test.go | 63 +++++++++++++++---- 3 files changed, 81 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index a99edfeebdb..673ddfb7c25 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -89,6 +89,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Add PostgreSQL module with slowlog support. {pull}4763[4763] - Add Kafka log module. {pull}4885[4885] +- Add support for `/var/log/containers/` log path in `add_kubernetes_metadata` processor. {pull}4981[4981] *Heartbeat* diff --git a/filebeat/processor/add_kubernetes_metadata/indexing.go b/filebeat/processor/add_kubernetes_metadata/indexing.go index df23c2b4409..f7a62492d23 100644 --- a/filebeat/processor/add_kubernetes_metadata/indexing.go +++ b/filebeat/processor/add_kubernetes_metadata/indexing.go @@ -43,23 +43,45 @@ func newLogsPathMatcher(cfg common.Config) (add_kubernetes_metadata.Matcher, err logPath = logPath + "/" } + logp.Debug("kubernetes", "logs_path matcher log path: %s", logPath) + return &LogPathMatcher{LogsPath: logPath}, nil } +// Docker container ID is a 64-character-long hexadecimal string +const containerIdLen = 64 + func (f *LogPathMatcher) MetadataIndex(event common.MapStr) string { if value, ok := event["source"]; ok { source := value.(string) - logp.Debug("kubernetes", "Incoming source value: ", source) - cid := "" - if strings.Contains(source, f.LogsPath) { - //Docker container is 64 chars in length - cid = source[len(f.LogsPath) : len(f.LogsPath)+64] + logp.Debug("kubernetes", "Incoming source value: %s", source) + + if !strings.Contains(source, f.LogsPath) { + logp.Debug("kubernetes", "Error extracting container id - source value does not contain matcher's logs_path '%s'.", f.LogsPath) + return "" + } + + sourceLen := len(source) + logsPathLen := len(f.LogsPath) + + // In case of the Kubernetes log path "/var/log/containers/", + // the container ID will be located right before the ".log" extension. + if strings.HasPrefix(f.LogsPath, "/var/log/containers/") && strings.HasSuffix(source, ".log") && sourceLen >= containerIdLen+4 { + containerIdEnd := sourceLen - 4 + cid := source[containerIdEnd-containerIdLen : containerIdEnd] + logp.Debug("kubernetes", "Using container id: %s", cid) + return cid } - logp.Debug("kubernetes", "Using container id: ", cid) - if cid != "" { + // In any other case, we assume the container ID will follow right after the log path. + // However we need to check the length to prevent "slice bound out of range" runtime errors. + if sourceLen >= logsPathLen+containerIdLen { + cid := source[logsPathLen : logsPathLen+containerIdLen] + logp.Debug("kubernetes", "Using container id: %s", cid) return cid } + + logp.Debug("kubernetes", "Error extracting container id - source value contains matcher's logs_path, however it is too short to contain a Docker container ID.") } return "" diff --git a/filebeat/processor/add_kubernetes_metadata/indexing_test.go b/filebeat/processor/add_kubernetes_metadata/indexing_test.go index 87d2c28b529..087b60954ae 100644 --- a/filebeat/processor/add_kubernetes_metadata/indexing_test.go +++ b/filebeat/processor/add_kubernetes_metadata/indexing_test.go @@ -9,24 +9,63 @@ import ( "github.com/elastic/beats/libbeat/common" ) -func TestLogsPathMatcher(t *testing.T) { +// A random container ID that we use for our tests +const cid = "0069869de9adf97f574c62029aeba65d1ecd85a2a112e87fbc28afe4dec2b843" + +func TestLogsPathMatcher_InvalidSource1(t *testing.T) { + cfgLogsPath := "" // use the default matcher configuration + source := "/var/log/messages" + expectedResult := "" + executeTest(t, cfgLogsPath, source, expectedResult) +} + +func TestLogsPathMatcher_InvalidSource2(t *testing.T) { + cfgLogsPath := "" // use the default matcher configuration + source := "/var/lib/docker/containers/01234567/89abcdef-json.log" + expectedResult := "" + executeTest(t, cfgLogsPath, source, expectedResult) +} + +func TestLogsPathMatcher_InvalidSource3(t *testing.T) { + cfgLogsPath := "/var/log/containers/" + source := "/var/log/containers/pod_ns_container_01234567.log" + expectedResult := "" + executeTest(t, cfgLogsPath, source, expectedResult) +} + +func TestLogsPathMatcher_VarLibDockerContainers(t *testing.T) { + cfgLogsPath := "" // use the default matcher configuration + source := fmt.Sprintf("/var/lib/docker/containers/%s/%s-json.log", cid, cid) + expectedResult := cid + executeTest(t, cfgLogsPath, source, expectedResult) +} + +func TestLogsPathMatcher_VarLogContainers(t *testing.T) { + cfgLogsPath := "/var/log/containers/" + source := fmt.Sprintf("/var/log/containers/kube-proxy-4d7nt_kube-system_kube-proxy-%s.log", cid) + expectedResult := cid + executeTest(t, cfgLogsPath, source, expectedResult) +} + +func TestLogsPathMatcher_AnotherLogDir(t *testing.T) { + cfgLogsPath := "/var/log/other/" + source := fmt.Sprintf("/var/log/other/%s.log", cid) + expectedResult := cid + executeTest(t, cfgLogsPath, source, expectedResult) +} + +func executeTest(t *testing.T, cfgLogsPath string, source string, expectedResult string) { var testConfig = common.NewConfig() + if cfgLogsPath != "" { + testConfig.SetString("logs_path", -1, cfgLogsPath) + } logMatcher, err := newLogsPathMatcher(*testConfig) assert.Nil(t, err) - cid := "0069869de9adf97f574c62029aeba65d1ecd85a2a112e87fbc28afe4dec2b843" - logPath := fmt.Sprintf("/var/lib/docker/containers/%s/%s-json.log", cid, cid) - input := common.MapStr{ - "source": "/var/log/messages", + "source": source, } - output := logMatcher.MetadataIndex(input) - assert.Equal(t, output, "") - - input["source"] = logPath - output = logMatcher.MetadataIndex(input) - - assert.Equal(t, output, cid) + assert.Equal(t, output, expectedResult) } From df0f7ff08f503af9bb64af13a86b0465b7fdd72c Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Tue, 29 Aug 2017 12:21:10 +0200 Subject: [PATCH 124/139] Fix /usr/bin/beatname script to accept -d "*" (#5043) Fixes #5040. Credit to @exekias for finding the solution. --- CHANGELOG.asciidoc | 1 + dev-tools/packer/platforms/centos/beatname.sh.j2 | 2 +- dev-tools/packer/platforms/debian/beatname.sh.j2 | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 673ddfb7c25..a0ac456e466 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -40,6 +40,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Eliminate deprecated _default_ mapping in 6.x {pull}4864[4864] - Register kubernetes `field_format` matcher and remove logger in `Encode` API {pull}4888[4888] - Add support for `initContainers` in `add_kubernetes_metadata` processor. {issue}4825[4825] +- Fix the `/usr/bin/beatname` script to accept `-d "*"` as a parameter. {issue}5040[5040] *Auditbeat* diff --git a/dev-tools/packer/platforms/centos/beatname.sh.j2 b/dev-tools/packer/platforms/centos/beatname.sh.j2 index 4f380ae8ea4..9bb9c23da63 100644 --- a/dev-tools/packer/platforms/centos/beatname.sh.j2 +++ b/dev-tools/packer/platforms/centos/beatname.sh.j2 @@ -8,4 +8,4 @@ -path.config /etc/{{.beat_name}} \ -path.data /var/lib/{{.beat_name}} \ -path.logs /var/log/{{.beat_name}} \ - $@ + "$@" diff --git a/dev-tools/packer/platforms/debian/beatname.sh.j2 b/dev-tools/packer/platforms/debian/beatname.sh.j2 index c1214749adf..e37b7df26f1 100644 --- a/dev-tools/packer/platforms/debian/beatname.sh.j2 +++ b/dev-tools/packer/platforms/debian/beatname.sh.j2 @@ -8,4 +8,4 @@ -path.config /etc/{{.beat_name}} \ -path.data /var/lib/{{.beat_name}} \ -path.logs /var/log/{{.beat_name}} \ - $@ + "$@" From 0fc4dea78907c9a11cc1da0bb2904c26cbaea279 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Tue, 29 Aug 2017 07:07:07 -0400 Subject: [PATCH 125/139] Reduce perfmon memory allocations (#5036) In `PdhGetFormattedCounterArray` the code was allocating memory for `bufferSize` x `sizeof(PdhCounterValueItem)`, but it only needed to allocated `bufferSize`. The buffer size is provided by Windows and already accounts for the sizeof PdhCounterValueItem. Made an improvement to create regexp objects once at startup instead of on every use. Moved config validation to startup for non-wildcard counter paths. This allows the check to only be performed one time and for any errors to be returned during the config test. Fixes #5035 --- CHANGELOG.asciidoc | 1 + .../windows/perfmon/defs_pdh_windows.go | 4 - .../windows/perfmon/defs_pdh_windows_386.go | 10 -- .../windows/perfmon/defs_pdh_windows_amd64.go | 10 -- .../module/windows/perfmon/mkpdh_defs.go | 4 - .../perfmon/pdh_integration_windows_test.go | 14 +-- .../module/windows/perfmon/pdh_windows.go | 116 ++++++++++-------- metricbeat/module/windows/perfmon/perfmon.go | 10 +- metricbeat/module/windows/perfmon/run.go | 2 +- .../module/windows/perfmon/zpdh_windows.go | 4 +- 10 files changed, 81 insertions(+), 94 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index a0ac456e466..62ec6a17480 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -61,6 +61,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di - Added missing mongodb configuration file to the `modules.d` folder. {pull}4870[4870] - Fix wrong MySQL CRUD queries timelion visualization {pull}4857[4857] - Add new metrics to CPU metricsset {pull}4969[4969] +- Fix a memory allocation issue where more memory was allocated than needed in the windows-perfmon metricset. {issue}5035[5035] *Packetbeat* diff --git a/metricbeat/module/windows/perfmon/defs_pdh_windows.go b/metricbeat/module/windows/perfmon/defs_pdh_windows.go index 2dec84412d9..57484b4b3b2 100644 --- a/metricbeat/module/windows/perfmon/defs_pdh_windows.go +++ b/metricbeat/module/windows/perfmon/defs_pdh_windows.go @@ -219,10 +219,6 @@ const ( // PdhCounterValue is the structure that receives the counter value. type PdhCounterValue C.PDH_FMT_COUNTERVALUE -type PdhCounterValueItem C.PDH_FMT_COUNTERVALUE_ITEM - -type PdhRawCounterItem C.PDH_RAW_COUNTER_ITEM - // PdhRawCounter is the structure that receives the raw counter. type PdhRawCounter C.PDH_RAW_COUNTER diff --git a/metricbeat/module/windows/perfmon/defs_pdh_windows_386.go b/metricbeat/module/windows/perfmon/defs_pdh_windows_386.go index 5f41f6ddcb8..3503c0e597e 100644 --- a/metricbeat/module/windows/perfmon/defs_pdh_windows_386.go +++ b/metricbeat/module/windows/perfmon/defs_pdh_windows_386.go @@ -206,16 +206,6 @@ type PdhCounterValue struct { Pad_cgo_1 [4]byte } -type PdhCounterValueItem struct { - SzName *int8 - FmtValue PdhCounterValue -} - -type PdhRawCounterItem struct { - SzName *int8 - RawValue PdhRawCounter -} - type PdhRawCounter struct { CStatus uint32 TimeStamp PdhFileTime diff --git a/metricbeat/module/windows/perfmon/defs_pdh_windows_amd64.go b/metricbeat/module/windows/perfmon/defs_pdh_windows_amd64.go index 5f41f6ddcb8..3503c0e597e 100644 --- a/metricbeat/module/windows/perfmon/defs_pdh_windows_amd64.go +++ b/metricbeat/module/windows/perfmon/defs_pdh_windows_amd64.go @@ -206,16 +206,6 @@ type PdhCounterValue struct { Pad_cgo_1 [4]byte } -type PdhCounterValueItem struct { - SzName *int8 - FmtValue PdhCounterValue -} - -type PdhRawCounterItem struct { - SzName *int8 - RawValue PdhRawCounter -} - type PdhRawCounter struct { CStatus uint32 TimeStamp PdhFileTime diff --git a/metricbeat/module/windows/perfmon/mkpdh_defs.go b/metricbeat/module/windows/perfmon/mkpdh_defs.go index 25621004833..1ce18058c86 100644 --- a/metricbeat/module/windows/perfmon/mkpdh_defs.go +++ b/metricbeat/module/windows/perfmon/mkpdh_defs.go @@ -81,10 +81,6 @@ const ( // PdhCounterValue is the structure that receives the counter value. type PdhCounterValue C.PDH_FMT_COUNTERVALUE -type PdhCounterValueItem C.PDH_FMT_COUNTERVALUE_ITEM - -type PdhRawCounterItem C.PDH_RAW_COUNTER_ITEM - // PdhRawCounter is the structure that receives the raw counter. type PdhRawCounter C.PDH_RAW_COUNTER diff --git a/metricbeat/module/windows/perfmon/pdh_integration_windows_test.go b/metricbeat/module/windows/perfmon/pdh_integration_windows_test.go index 621cdc2d838..c41411e4c56 100644 --- a/metricbeat/module/windows/perfmon/pdh_integration_windows_test.go +++ b/metricbeat/module/windows/perfmon/pdh_integration_windows_test.go @@ -57,7 +57,7 @@ func TestQuery(t *testing.T) { } defer q.Close() - err = q.AddCounter(processorTimeCounter, FloatFlormat, nil) + err = q.AddCounter(processorTimeCounter, FloatFlormat, "") if err != nil { t.Fatal(err) } @@ -145,7 +145,7 @@ func TestLongOutputFormat(t *testing.T) { } defer query.Close() - err = query.AddCounter(processorTimeCounter, LongFormat, nil) + err = query.AddCounter(processorTimeCounter, LongFormat, "") if err != nil && err != PDH_NO_MORE_DATA { t.Fatal(err) } @@ -179,7 +179,7 @@ func TestFloatOutputFormat(t *testing.T) { } defer query.Close() - err = query.AddCounter(processorTimeCounter, FloatFlormat, nil) + err = query.AddCounter(processorTimeCounter, FloatFlormat, "") if err != nil && err != PDH_NO_MORE_DATA { t.Fatal(err) } @@ -213,7 +213,7 @@ func TestRawValues(t *testing.T) { } defer query.Close() - err = query.AddCounter(processorTimeCounter, FloatFlormat, nil) + err = query.AddCounter(processorTimeCounter, FloatFlormat, "") if err != nil && err != PDH_NO_MORE_DATA { t.Fatal(err) } @@ -221,13 +221,11 @@ func TestRawValues(t *testing.T) { var values []float64 for i := 0; i < 2; i++ { - if err = query.Execute(); err != nil { t.Fatal(err) } _, rawvalue1, err := PdhGetRawCounterValue(query.counters[processorTimeCounter].handle) - if err != nil { t.Fatal(err) } @@ -239,19 +237,16 @@ func TestRawValues(t *testing.T) { } _, rawvalue2, err := PdhGetRawCounterValue(query.counters[processorTimeCounter].handle) - if err != nil { t.Fatal(err) } value, err := PdhCalculateCounterFromRawValue(query.counters[processorTimeCounter].handle, PdhFmtDouble|PdhFmtNoCap100, rawvalue2, rawvalue1) - if err != nil { t.Fatal(err) } values = append(values, *(*float64)(unsafe.Pointer(&value.LongValue))) - } t.Log(values) @@ -274,7 +269,6 @@ func TestWildcardQuery(t *testing.T) { time.Sleep(time.Millisecond * 1000) values, err = handle.Read() - if err != nil { t.Fatal(err) } diff --git a/metricbeat/module/windows/perfmon/pdh_windows.go b/metricbeat/module/windows/perfmon/pdh_windows.go index 1c70f7d17c8..34016d29128 100644 --- a/metricbeat/module/windows/perfmon/pdh_windows.go +++ b/metricbeat/module/windows/perfmon/pdh_windows.go @@ -3,6 +3,7 @@ package perfmon import ( + "bytes" "regexp" "strconv" "syscall" @@ -14,6 +15,7 @@ import ( "golang.org/x/sys/windows" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/winlogbeat/sys" ) // Windows API calls @@ -21,13 +23,19 @@ import ( //sys _PdhAddCounter(query PdhQueryHandle, counterPath string, userData uintptr, counter *PdhCounterHandle) (errcode error) [failretval!=0] = pdh.PdhAddEnglishCounterW //sys _PdhCollectQueryData(query PdhQueryHandle) (errcode error) [failretval!=0] = pdh.PdhCollectQueryData //sys _PdhGetFormattedCounterValue(counter PdhCounterHandle, format PdhCounterFormat, counterType *uint32, value *PdhCounterValue) (errcode error) [failretval!=0] = pdh.PdhGetFormattedCounterValue -//sys _PdhGetFormattedCounterArray(counter PdhCounterHandle, format PdhCounterFormat, bufferSize *uint32, bufferCount *uint32, itemBuffer *PdhCounterValueItem) (errcode error) [failretval!=0] = pdh.PdhGetFormattedCounterArrayW +//sys _PdhGetFormattedCounterArray(counter PdhCounterHandle, format PdhCounterFormat, bufferSize *uint32, bufferCount *uint32, itemBuffer *byte) (errcode error) [failretval!=0] = pdh.PdhGetFormattedCounterArrayW //sys _PdhGetRawCounterValue(counter PdhCounterHandle, counterType *uint32, value *PdhRawCounter) (errcode error) [failretval!=0] = pdh.PdhGetRawCounterValue -//sys _PdhGetRawCounterArray(counter PdhCounterHandle, bufferSize *uint32, bufferCount *uint32, itemBuffer *PdhRawCounterItem) (errcode error) [failretval!=0] = pdh.PdhGetRawCounterArray +//sys _PdhGetRawCounterArray(counter PdhCounterHandle, bufferSize *uint32, bufferCount *uint32, itemBuffer *pdhRawCounterItem) (errcode error) [failretval!=0] = pdh.PdhGetRawCounterArray //sys _PdhCalculateCounterFromRawValue(counter PdhCounterHandle, format PdhCounterFormat, rawValue1 *PdhRawCounter, rawValue2 *PdhRawCounter, value *PdhCounterValue) (errcode error) [failretval!=0] = pdh.PdhCalculateCounterFromRawValue //sys _PdhFormatFromRawValue(counterType uint32, format PdhCounterFormat, timeBase *uint64, rawValue1 *PdhRawCounter, rawValue2 *PdhRawCounter, value *PdhCounterValue) (errcode error) [failretval!=0] = pdh.PdhFormatFromRawValue //sys _PdhCloseQuery(query PdhQueryHandle) (errcode error) [failretval!=0] = pdh.PdhCloseQuery +var ( + sizeofPdhCounterValueItem = (int)(unsafe.Sizeof(pdhCounterValueItem{})) + wildcardRegexp = regexp.MustCompile(`.*\(\*\).*`) + instanceNameRegexp = regexp.MustCompile(`.*\((.*)\).*`) +) + type PdhQueryHandle uintptr var InvalidQueryHandle = ^PdhQueryHandle(0) @@ -36,6 +44,16 @@ type PdhCounterHandle uintptr var InvalidCounterHandle = ^PdhCounterHandle(0) +type pdhCounterValueItem struct { + SzName uintptr + FmtValue PdhCounterValue +} + +type pdhRawCounterItem struct { + SzName uintptr + RawValue PdhRawCounter +} + type CounterValueItem struct { Name string Value PdhCounterValue @@ -91,35 +109,36 @@ func PdhGetFormattedCounterArray(counter PdhCounterHandle, format PdhCounterForm var bufferCount uint32 if err := _PdhGetFormattedCounterArray(counter, format, &bufferSize, &bufferCount, nil); err != nil { - //From MSDN: You should call this function twice, the first time to get the required buffer size (set ItemBuffer to NULL and lpdwBufferSize to 0), and the second time to get the data. - if PdhErrno(err.(syscall.Errno)) == PDH_MORE_DATA { - pdhValues := make([]PdhCounterValueItem, bufferSize) - if err := _PdhGetFormattedCounterArray(counter, format, &bufferSize, &bufferCount, &pdhValues[0]); err != nil { - return nil, PdhErrno(err.(syscall.Errno)) - } + // From MSDN: You should call this function twice, the first time to get the required + // buffer size (set ItemBuffer to NULL and lpdwBufferSize to 0), and the second time to get the data. + if PdhErrno(err.(syscall.Errno)) != PDH_MORE_DATA { + return nil, PdhErrno(err.(syscall.Errno)) + } + + // Buffer holds PdhCounterValueItems at the beginning and then null-terminated + // strings at the end. + buffer := make([]byte, bufferSize) + if err := _PdhGetFormattedCounterArray(counter, format, &bufferSize, &bufferCount, &buffer[0]); err != nil { + return nil, PdhErrno(err.(syscall.Errno)) + } - values := make([]CounterValueItem, bufferCount) - var i uint32 + values := make([]CounterValueItem, bufferCount) + nameBuffer := new(bytes.Buffer) + for i := 0; i < len(values); i++ { + pdhValueItem := (*pdhCounterValueItem)(unsafe.Pointer(&buffer[i*sizeofPdhCounterValueItem])) - for i = 0; i < bufferCount; i++ { - value := CounterValueItem{} - a := (*[1<<30 - 1]uint16)(unsafe.Pointer(pdhValues[i].SzName)) - size := 0 - for ; size < len(a); size++ { - if a[size] == uint16(0) { - break - } - } - runes := utf16.Decode(a[:size]) - name := string(runes) - value.Name = name - value.Value = pdhValues[i].FmtValue - values[i] = value + // The strings are appended to the end of the buffer. + nameOffset := pdhValueItem.SzName - (uintptr)(unsafe.Pointer(&buffer[0])) + nameBuffer.Reset() + if err := sys.UTF16ToUTF8Bytes(buffer[nameOffset:], nameBuffer); err != nil { + return nil, err } - return values, nil + values[i].Name = nameBuffer.String() + values[i].Value = pdhValueItem.FmtValue } - return nil, PdhErrno(err.(syscall.Errno)) + + return values, nil } return nil, nil @@ -166,7 +185,8 @@ func PdhCloseQuery(query PdhQueryHandle) error { type Counter struct { handle PdhCounterHandle format PdhCounterFormat - instanceName *string + instanceName string + wildcard bool // wildcard indicates that the path contains a wildcard. } type Counters map[string]*Counter @@ -195,7 +215,7 @@ func NewQuery(dataSource string) (*Query, error) { }, nil } -func (q *Query) AddCounter(counterPath string, format Format, instanceName *string) error { +func (q *Query) AddCounter(counterPath string, format Format, instanceName string) error { if _, found := q.counters[counterPath]; found { return errors.New("counter already added") } @@ -205,8 +225,22 @@ func (q *Query) AddCounter(counterPath string, format Format, instanceName *stri return errors.Wrapf(err, `failed to add counter (path="%v")`, counterPath) } - q.counters[counterPath] = &Counter{handle: h} - q.counters[counterPath].instanceName = instanceName + wildcard := wildcardRegexp.MatchString(counterPath) + + // Extract the instance name from the counterPath for non-wildcard paths. + if !wildcard && instanceName == "" { + matches := instanceNameRegexp.FindStringSubmatch(counterPath) + if len(matches) != 2 { + return errors.New("query doesn't contain an instance name. In this case you have to define 'instance_name'") + } + instanceName = matches[1] + } + + q.counters[counterPath] = &Counter{ + handle: h, + instanceName: instanceName, + wildcard: wildcard, + } switch format { case FloatFlormat: q.counters[counterPath].format = PdhFmtDouble @@ -230,8 +264,7 @@ func (q *Query) Values() (map[string][]Value, error) { rtn := make(map[string][]Value, len(q.counters)) for path, counter := range q.counters { - - if match, _ := regexp.MatchString(".*\\(\\*\\)\\.*", path); match { + if counter.wildcard { values, err := PdhGetFormattedCounterArray(counter.handle, counter.format|PdhFmtNoCap100) if err != nil { rtn[path] = append(rtn[path], Value{Err: err}) @@ -249,7 +282,6 @@ func (q *Query) Values() (map[string][]Value, error) { } rtn[path] = append(rtn[path], Value{Instance: values[i].Name, Measurement: val}) - } } else { _, value, err := PdhGetFormattedCounterValue(counter.handle, counter.format|PdhFmtNoCap100) @@ -258,23 +290,11 @@ func (q *Query) Values() (map[string][]Value, error) { continue } - var name string - if counter.instanceName != nil { - name = *counter.instanceName - } else { - re := regexp.MustCompile("\\((.*)\\)") - match := re.FindStringSubmatch(path) - if cap(match) <= 0 { - return nil, errors.New("Your query doesn't contain an instance name. In this case you have to define one per `instance_name`") - } - name = match[1] - } - switch counter.format { case PdhFmtDouble: - rtn[path] = append(rtn[path], Value{Measurement: *(*float64)(unsafe.Pointer(&value.LongValue)), Instance: name}) + rtn[path] = append(rtn[path], Value{Measurement: *(*float64)(unsafe.Pointer(&value.LongValue)), Instance: counter.instanceName}) case PdhFmtLarge: - rtn[path] = append(rtn[path], Value{Measurement: *(*int64)(unsafe.Pointer(&value.LongValue)), Instance: name}) + rtn[path] = append(rtn[path], Value{Measurement: *(*int64)(unsafe.Pointer(&value.LongValue)), Instance: counter.instanceName}) } } } @@ -339,7 +359,7 @@ func (r *PerfmonReader) Read() ([]common.MapStr, error) { } // Write the values into the map. - result := []common.MapStr{} + result := make([]common.MapStr, 0, len(values)) var errs multierror.Errors for counterPath, counter := range values { diff --git a/metricbeat/module/windows/perfmon/perfmon.go b/metricbeat/module/windows/perfmon/perfmon.go index c7034eeab91..29bc10048ae 100644 --- a/metricbeat/module/windows/perfmon/perfmon.go +++ b/metricbeat/module/windows/perfmon/perfmon.go @@ -14,11 +14,11 @@ import ( ) type CounterConfig struct { - InstanceLabel string `config:"instance_label" validate:"required"` - InstanceName *string `config:"instance_name"` - MeasurementLabel string `config:"measurement_label" validate:"required"` - Query string `config:"query" validate:"required"` - Format string `config:"format"` + InstanceLabel string `config:"instance_label" validate:"required"` + InstanceName string `config:"instance_name"` + MeasurementLabel string `config:"measurement_label" validate:"required"` + Query string `config:"query" validate:"required"` + Format string `config:"format"` } func init() { diff --git a/metricbeat/module/windows/perfmon/run.go b/metricbeat/module/windows/perfmon/run.go index 004eddefd7c..8f5a9c9d36d 100644 --- a/metricbeat/module/windows/perfmon/run.go +++ b/metricbeat/module/windows/perfmon/run.go @@ -36,7 +36,7 @@ func run() error { cmd.Env = os.Environ() if *goarch != "" { - cmd.Env = append(cmd.Env, "GOARCH"+*goarch) + cmd.Env = append(cmd.Env, "GOARCH="+*goarch) } if *output != "" { diff --git a/metricbeat/module/windows/perfmon/zpdh_windows.go b/metricbeat/module/windows/perfmon/zpdh_windows.go index 7b5345063ee..55b694aae8f 100644 --- a/metricbeat/module/windows/perfmon/zpdh_windows.go +++ b/metricbeat/module/windows/perfmon/zpdh_windows.go @@ -92,7 +92,7 @@ func _PdhGetFormattedCounterValue(counter PdhCounterHandle, format PdhCounterFor return } -func _PdhGetFormattedCounterArray(counter PdhCounterHandle, format PdhCounterFormat, bufferSize *uint32, bufferCount *uint32, itemBuffer *PdhCounterValueItem) (errcode error) { +func _PdhGetFormattedCounterArray(counter PdhCounterHandle, format PdhCounterFormat, bufferSize *uint32, bufferCount *uint32, itemBuffer *byte) (errcode error) { r0, _, _ := syscall.Syscall6(procPdhGetFormattedCounterArrayW.Addr(), 5, uintptr(counter), uintptr(format), uintptr(unsafe.Pointer(bufferSize)), uintptr(unsafe.Pointer(bufferCount)), uintptr(unsafe.Pointer(itemBuffer)), 0) if r0 != 0 { errcode = syscall.Errno(r0) @@ -108,7 +108,7 @@ func _PdhGetRawCounterValue(counter PdhCounterHandle, counterType *uint32, value return } -func _PdhGetRawCounterArray(counter PdhCounterHandle, bufferSize *uint32, bufferCount *uint32, itemBuffer *PdhRawCounterItem) (errcode error) { +func _PdhGetRawCounterArray(counter PdhCounterHandle, bufferSize *uint32, bufferCount *uint32, itemBuffer *pdhRawCounterItem) (errcode error) { r0, _, _ := syscall.Syscall6(procPdhGetRawCounterArray.Addr(), 4, uintptr(counter), uintptr(unsafe.Pointer(bufferSize)), uintptr(unsafe.Pointer(bufferCount)), uintptr(unsafe.Pointer(itemBuffer)), 0, 0) if r0 != 0 { errcode = syscall.Errno(r0) From aecf1eb1cc0e5b431b1e5e1150bed98d5004c12b Mon Sep 17 00:00:00 2001 From: Steffen Siering Date: Tue, 29 Aug 2017 13:31:31 +0200 Subject: [PATCH 126/139] Modify events dropping on Close (#5044) Update the publisher pipeline to only drop events from the queue on beat.Client close when: guaranteed mode is set and no global ACK handler is registered. --- libbeat/publisher/pipeline/pipeline.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libbeat/publisher/pipeline/pipeline.go b/libbeat/publisher/pipeline/pipeline.go index 1e80a0586bf..fee988641e3 100644 --- a/libbeat/publisher/pipeline/pipeline.go +++ b/libbeat/publisher/pipeline/pipeline.go @@ -283,8 +283,9 @@ func (p *Pipeline) Connect() (beat.Client, error) { // the appropriate fields in the passed ClientConfig. func (p *Pipeline) ConnectWith(cfg beat.ClientConfig) (beat.Client, error) { var ( - canDrop bool - eventFlags publisher.EventFlags + canDrop bool + dropOnCancel bool + eventFlags publisher.EventFlags ) err := validateClientConfig(&cfg) @@ -299,6 +300,7 @@ func (p *Pipeline) ConnectWith(cfg beat.ClientConfig) (beat.Client, error) { switch cfg.PublishMode { case beat.GuaranteedSend: eventFlags = publisher.GuaranteedSend + dropOnCancel = true case beat.DropIfFull: canDrop = true } @@ -319,9 +321,9 @@ func (p *Pipeline) ConnectWith(cfg beat.ClientConfig) (beat.Client, error) { acker := p.makeACKer(processors != nil, &cfg, waitClose) producerCfg := queue.ProducerConfig{ - // only cancel events from queue if acker is configured - // and no pipeline-wide ACK handler is registered - DropOnCancel: acker != nil && p.eventer.cb == nil, + // Cancel events from queue if acker is configured + // and no pipeline-wide ACK handler is registered. + DropOnCancel: dropOnCancel && acker != nil && p.eventer.cb == nil, } if reportEvents || cfg.Events != nil { From 083834b53caec727b4bfacebf7f64be3139a6146 Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Tue, 29 Aug 2017 13:39:38 +0200 Subject: [PATCH 127/139] Added the beta2 changelog to the master branch (#5033) This should be merged together with #5031, so the changelog in the two branches stays similar, which will simplify backports. --- CHANGELOG.asciidoc | 95 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 62ec6a17480..51db444da79 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -8,21 +8,14 @@ // Template, add newest changes here === Beats version HEAD -https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD diff] +https://github.com/elastic/beats/compare/v6.0.0-beta2...master[Check the HEAD diff] ==== Breaking changes *Affecting all Beats* -- The log directory (`path.log`) for Windows services is now set to `C:\ProgramData\[beatname]\logs`. {issue}4764[4764] -- Fail if removed setting output.X.flush_interval is explicitly configured. -- Rename the `/usr/bin/beatname.sh` script (e.g. `metricbeat.sh`) to `/usr/bin/beatname`. {pull}4933[4933] -- Beat does not start if elasticsearch index pattern was modified but not the template name and pattern. {issue}4769[4769] - *Auditbeat* -- Changed file metricset config to make `file.paths` a list instead of a dictionary. {pull}4796[4796] - *Filebeat* *Heartbeat* @@ -44,17 +37,10 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Auditbeat* -- Fix `file.max_file_size` config option for the audit file metricset. {pull}4796[4796] - *Filebeat* -- Fix issue where the `fileset.module` could have the wrong value. {issue}4761[4761] - *Heartbeat* -- Fix monitor.name being empty by default. {issue}4852[4852] -- Fix wrong event timestamps. {issue}4851[4851] - *Metricbeat* - Support `npipe` protocol (Windows) in Docker module. {pull}4751[4751] @@ -65,28 +51,16 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Packetbeat* -- Update flow timestamp on each packet being received. {issue}4895[4895] - *Winlogbeat* ==== Added *Affecting all Beats* -- Add setting to enable/disable the slow start in logstash output. {pull}4972[4972] -- Update init scripts to use the `test config` subcommand instead of the deprecated `-configtest` flag. {issue}4600[4600] -- Get by default the credentials for connecting to Kibana from the Elasticsearch output configuration. {pull}4867[4867] - Move TCP UDP start up into `server.Start()` {pull}4903[4903] -- Added `cloud.id` and `cloud.auth` settings, for simplifying using Beats with the Elastic Cloud. {issue}4959[4959] -- Add lz4 compression support to kafka output. {pull}4977[4977] -- Add newer kafka versions to kafka output. {pull}4977[4977] -- Configure the index name when loading the dashboards and the index pattern. {pull}4949[4949] *Auditbeat* -- Added `file.hash_types` config option for controlling the hash types. {pull}4796[4796] -- Added the ability to specify byte unit suffixes to `file.max_file_size`. {pull}4796[4796] - *Filebeat* - Add PostgreSQL module with slowlog support. {pull}4763[4763] @@ -97,12 +71,10 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di *Metricbeat* -- Add support to exclude labels from kubernetes pod metadata. {pull}4757[4757] - Add graphite protocol metricbeat module. {pull}4734[4734] - Add http server metricset to support push metrics via http. {pull}4770[4770] - Make config object public for graphite and http server {pull}4820[4820] - Add system uptime metricset. {issue}[4848[4848] -- Add `filesystem.ignore_types` to system module for ignoring filesystem types. {issue}4685[4685] *Packetbeat* @@ -131,6 +103,70 @@ https://github.com/elastic/beats/compare/v6.0.0-beta1...master[Check the HEAD di //////////////////////////////////////////////////////////// +[[release-notes-6.0.0-beta2]] +=== Beats version 6.0.0-beta2 +https://github.com/elastic/beats/compare/v6.0.0-beta1...v6.0.0-beta2[View commits] + +==== Breaking changes + +*Affecting all Beats* + +- The log directory (`path.log`) for Windows services is now set to `C:\ProgramData\[beatname]\logs`. {issue}4764[4764] +- The _all field is disabled in Elasticsearch 6.0. This means that searching by individual + words only work on text fields. {issue}4901[4901] +- Fail if removed setting output.X.flush_interval is explicitly configured. +- Rename the `/usr/bin/beatname.sh` script (e.g. `metricbeat.sh`) to `/usr/bin/beatname`. {pull}4933[4933] +- Beat does not start if elasticsearch index pattern was modified but not the template name and pattern. {issue}4769[4769] +- Fail if removed setting output.X.flush_interval is explicitly configured. {pull}4880[4880] + +==== Bugfixes + +*Affecting all Beats* + +- Register kubernetes `field_format` matcher and remove logger in `Encode` API {pull}4888[4888] +- Fix go plugins not loaded when beat starts {pull}4799[4799] +- Add support for `initContainers` in `add_kubernetes_metadata` processor. {issue}4825[4825] +- Eliminate deprecated _default_ mapping in 6.x {pull}4864[4864] + +*Heartbeat* + +- Fix monitor.name being empty by default. {issue}4852[4852] +- Fix wrong event timestamps. {issue}4851[4851] + +*Metricbeat* + +- Added missing mongodb configuration file to the `modules.d` folder. {pull}4870[4870] +- Fix wrong MySQL CRUD queries timelion visualization {pull}4857[4857] +- Add new metrics to CPU metricsset {pull}4969[4969] + +*Packetbeat* + +- Update flow timestamp on each packet being received. {issue}4895[4895] + +==== Added + +*Affecting all Beats* + +- Add setting to enable/disable the slow start in logstash output. {pull}4972[4972] +- Update init scripts to use the `test config` subcommand instead of the deprecated `-configtest` flag. {issue}4600[4600] +- Get by default the credentials for connecting to Kibana from the Elasticsearch output configuration. {pull}4867[4867] +- Added `cloud.id` and `cloud.auth` settings, for simplifying using Beats with the Elastic Cloud. {issue}4959[4959] +- Add lz4 compression support to kafka output. {pull}4977[4977] +- Add newer kafka versions to kafka output. {pull}4977[4977] +- Configure the index name when loading the dashboards and the index pattern. {pull}4949[4949] + +*Metricbeat* + +- Add `filesystem.ignore_types` to system module for ignoring filesystem types. {issue}4685[4685] +- Add support to exclude labels from kubernetes pod metadata. {pull}4757[4757] + +==== Deprecated + +*Affecting all Beats* + +- Fix pod name indexer to use both namespace, pod name to frame index key {pull}4775[4775] + + [[release-notes-6.0.0-beta1]] === Beats version 6.0.0-beta1 https://github.com/elastic/beats/compare/v6.0.0-alpha2...v6.0.0-beta1[View commits] @@ -230,6 +266,7 @@ https://github.com/elastic/beats/compare/v6.0.0-alpha2...v6.0.0-beta1[View commi - Vsphere module: collect custom fields from virtual machines. {issue}4464[4464] - Add `test modules` command, to test modules expected output. {pull}4656[4656] - Add `processors` setting to metricbeat modules. {pull}4699[4699] +- Support `npipe` protocol (Windows) in Docker module. {pull}4751[4751] *Packetbeat* From e6e743266c846c3fd067d14b53a721f8f949f190 Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Tue, 29 Aug 2017 14:30:43 +0200 Subject: [PATCH 128/139] Fix make index-template command (#5034) Implementation of the index template generation changed slightly in a recent PR, but the generation command was not updated accordingly. --- dev-tools/cmd/index_template/index_template.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/cmd/index_template/index_template.go b/dev-tools/cmd/index_template/index_template.go index 46c819eadaa..78d04daa204 100644 --- a/dev-tools/cmd/index_template/index_template.go +++ b/dev-tools/cmd/index_template/index_template.go @@ -40,7 +40,7 @@ func main() { *version = "2.0.0" } - tmpl, err := template.New(beatVersion, *version, *index, template.TemplateSettings{}) + tmpl, err := template.New(beatVersion, *index, *version, template.TemplateConfig{}) if err != nil { fmt.Fprintf(os.Stderr, "Error generating template: %+v", err) os.Exit(1) From 1faf77838e5b9d971281b2bea2a28c306afd8c51 Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Tue, 29 Aug 2017 14:35:35 +0200 Subject: [PATCH 129/139] Fix invalid filter error in packetbeat (#5041) Looks like after a refactoring, the code was changed to always return an error. Fixes #5039. * Fix test case: use an invalid BPF filter instead of invalid device --- packetbeat/sniffer/sniffer.go | 5 ++++- packetbeat/tests/system/config/packetbeat.yml.j2 | 4 ++++ packetbeat/tests/system/test_0026_test_config.py | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packetbeat/sniffer/sniffer.go b/packetbeat/sniffer/sniffer.go index d19df7be9c8..2f7bf8deeef 100644 --- a/packetbeat/sniffer/sniffer.go +++ b/packetbeat/sniffer/sniffer.go @@ -258,7 +258,10 @@ func validatePcapFilter(expr string) error { defer p.Close() _, err = p.NewBPF(expr) - return fmt.Errorf("invalid filter: %s", err) + if err != nil { + return fmt.Errorf("invalid filter '%s': %v", expr, err) + } + return nil } func openPcap(filter string, cfg *config.InterfacesConfig) (snifferHandle, error) { diff --git a/packetbeat/tests/system/config/packetbeat.yml.j2 b/packetbeat/tests/system/config/packetbeat.yml.j2 index fe36c259301..354958c38d3 100644 --- a/packetbeat/tests/system/config/packetbeat.yml.j2 +++ b/packetbeat/tests/system/config/packetbeat.yml.j2 @@ -4,6 +4,10 @@ # keyword to sniff on all connected interfaces. packetbeat.interfaces.device: {{ iface_device|default("any") }} +{% if bpf_filter %} +packetbeat.interfaces.bpf_filter: {{ bpf_filter }} +{% endif %} + {% if flows %} #================================== Flows ===================================== # Set network flow timeout. Flow is killed if no packet is received before being diff --git a/packetbeat/tests/system/test_0026_test_config.py b/packetbeat/tests/system/test_0026_test_config.py index 438d75e50db..81011b74162 100644 --- a/packetbeat/tests/system/test_0026_test_config.py +++ b/packetbeat/tests/system/test_0026_test_config.py @@ -27,6 +27,6 @@ def test_config_error(self): return a non-zero error code. """ self.render_config_template( - iface_device="NoSuchDevice" + bpf_filter="invalid BPF filter" ) self.start_packetbeat(extra_args=["-configtest"]).check_wait(exit_code=1) From 753cf9e93673a9d85825b7f8869349d3ecd99c80 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Tue, 29 Aug 2017 10:33:16 -0400 Subject: [PATCH 130/139] Improvements to beatname.sh (#5051) Use `exec` with the command to start the beat so that it replaces the shell process leaving only the beat process. This is nicer because you don't have the "beatname.sh" process showing up in `ps` output. Change the hashbang to `#!/usr/bin/env bash` instead of `#!/bin/bash`. This is generally more portable. --- CHANGELOG.asciidoc | 2 ++ dev-tools/packer/platforms/centos/beatname.sh.j2 | 4 ++-- dev-tools/packer/platforms/debian/beatname.sh.j2 | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 51db444da79..9219cc47444 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -58,6 +58,8 @@ https://github.com/elastic/beats/compare/v6.0.0-beta2...master[Check the HEAD di *Affecting all Beats* - Move TCP UDP start up into `server.Start()` {pull}4903[4903] +- Changed the hashbang used in the beat helper script from `/bin/bash` to `/usr/bin/env bash`. {pull}5051[5051] +- Changed beat helper script to use `exec` when running the beat. {pull}5051[5051] *Auditbeat* diff --git a/dev-tools/packer/platforms/centos/beatname.sh.j2 b/dev-tools/packer/platforms/centos/beatname.sh.j2 index 9bb9c23da63..2601507722c 100644 --- a/dev-tools/packer/platforms/centos/beatname.sh.j2 +++ b/dev-tools/packer/platforms/centos/beatname.sh.j2 @@ -1,9 +1,9 @@ -#!/bin/bash +#!/usr/bin/env bash # Script to run {.beat_name} in foreground with the same path settings that # the init script / systemd unit file would do. -/usr/share/{{.beat_name}}/bin/{{.beat_name}} \ +exec /usr/share/{{.beat_name}}/bin/{{.beat_name}} \ -path.home /usr/share/{{.beat_name}} \ -path.config /etc/{{.beat_name}} \ -path.data /var/lib/{{.beat_name}} \ diff --git a/dev-tools/packer/platforms/debian/beatname.sh.j2 b/dev-tools/packer/platforms/debian/beatname.sh.j2 index e37b7df26f1..fc36a268b83 100644 --- a/dev-tools/packer/platforms/debian/beatname.sh.j2 +++ b/dev-tools/packer/platforms/debian/beatname.sh.j2 @@ -1,9 +1,9 @@ -#!/bin/bash +#!/usr/bin/env bash # Script to run {{.beat_name}} in foreground with the same path settings that # the init script / systemd unit file would do. -/usr/share/{{.beat_name}}/bin/{{.beat_name}} \ +exec /usr/share/{{.beat_name}}/bin/{{.beat_name}} \ -path.home /usr/share/{{.beat_name}} \ -path.config /etc/{{.beat_name}} \ -path.data /var/lib/{{.beat_name}} \ From 0bb4c0e01f3d72d0df7cca6d91aaf34a5ca9befd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20P=C3=A9rez-Aradros=20Herce?= Date: Wed, 30 Aug 2017 14:34:10 +0200 Subject: [PATCH 131/139] Fix accidental removal of `--setup` flag (#5060) Fixes #5059 --- libbeat/cmd/run.go | 1 + libbeat/tests/system/test_cmd.py | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/libbeat/cmd/run.go b/libbeat/cmd/run.go index 19ae9a117d0..4ba2ecb742a 100644 --- a/libbeat/cmd/run.go +++ b/libbeat/cmd/run.go @@ -28,6 +28,7 @@ func genRunCmd(name, version string, beatCreator beat.Creator, runFlags *pflag.F runCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("httpprof")) runCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("cpuprofile")) runCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("memprofile")) + runCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("setup")) // TODO deprecate in favor of subcommands (7.0): runCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("configtest")) diff --git a/libbeat/tests/system/test_cmd.py b/libbeat/tests/system/test_cmd.py index a6efb6c5036..4e72666fddf 100644 --- a/libbeat/tests/system/test_cmd.py +++ b/libbeat/tests/system/test_cmd.py @@ -67,6 +67,41 @@ def test_setup_template(self): assert exit_code == 0 assert len(self.es.cat.templates(name='mockbeat-*', h='name')) > 0 + @unittest.skipUnless(INTEGRATION_TESTS, "integration test") + @attr('integration') + def test_setup_flag(self): + """ + Test --setup flag on run command + """ + # Delete any existing template + try: + self.es.indices.delete_template('mockbeat-*') + except: + pass + + assert len(self.es.cat.templates(name='mockbeat-*', h='name')) == 0 + + shutil.copy(self.beat_path + "/_meta/config.yml", + os.path.join(self.working_dir, "libbeat.yml")) + shutil.copy(self.beat_path + "/fields.yml", + os.path.join(self.working_dir, "fields.yml")) + + proc = self.start_beat( + extra_args=["--setup", + "--path.config", self.working_dir, + "-E", "setup.dashboards.file=" + + os.path.join("../../dashboards/testdata", "testbeat-dashboards.zip"), + "-E", "setup.dashboards.beat=testbeat", + "-E", "setup.kibana.protocol=http", + "-E", "setup.kibana.host=" + self.get_kibana_host(), + "-E", "setup.kibana.port=" + self.get_kibana_port(), + "-E", "output.elasticsearch.hosts=['" + self.get_host() + "']"], + config="libbeat.yml") + + self.wait_until(lambda: self.es.cat.templates(name='mockbeat-*', h='name') > 0) + self.wait_until(lambda: self.log_contains("Kibana dashboards successfully loaded")) + proc.check_kill_and_wait() + @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @attr('integration') def test_test_config(self): @@ -170,3 +205,9 @@ def test_test_wrong_output(self): def get_host(self): return os.getenv('ES_HOST', 'localhost') + ':' + os.getenv('ES_PORT', '9200') + + def get_kibana_host(self): + return os.getenv('KIBANA_HOST', 'localhost') + + def get_kibana_port(self): + return os.getenv('KIBANA_PORT', '5601') From a26cd254903330489dcd3babb0a608b9839b0159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Fri, 25 Aug 2017 16:22:06 +0200 Subject: [PATCH 132/139] beats: generalize import generation for filebeat, packetbeat, metricbeat --- filebeat/Makefile | 8 ++- filebeat/include/list.go | 7 +++ filebeat/scripts/generate_imports_helper.py | 20 ++++++++ generator/metricbeat/Makefile | 10 ++++ metricbeat/Makefile | 2 +- metricbeat/scripts/generate_imports.py | 51 ------------------- metricbeat/scripts/generate_imports_helper.py | 26 ++++++++++ packetbeat/Makefile | 2 +- packetbeat/scripts/generate_imports.py | 43 ---------------- packetbeat/scripts/generate_imports_helper.py | 19 +++++++ script/generate_imports.py | 37 ++++++++++++++ 11 files changed, 128 insertions(+), 97 deletions(-) create mode 100644 filebeat/scripts/generate_imports_helper.py delete mode 100644 metricbeat/scripts/generate_imports.py create mode 100644 metricbeat/scripts/generate_imports_helper.py delete mode 100644 packetbeat/scripts/generate_imports.py create mode 100644 packetbeat/scripts/generate_imports_helper.py create mode 100644 script/generate_imports.py diff --git a/filebeat/Makefile b/filebeat/Makefile index 040c27b8965..697fd7bd9df 100644 --- a/filebeat/Makefile +++ b/filebeat/Makefile @@ -51,9 +51,15 @@ collect-docs: python-env @mkdir -p docs/modules @${PYTHON_ENV}/bin/python ${ES_BEATS}/filebeat/scripts/docs_collector.py --beat ${BEAT_NAME} +# Generate imports for prospectors +.PHONY: imports +imports: python-env + @mkdir -p include + @${PYTHON_ENV}/bin/python ${ES_BEATS}/script/generate_imports.py ${BEAT_PATH} + # Runs all collection steps and updates afterwards .PHONY: collect -collect: fields kibana modules configs collect-docs +collect: fields kibana modules configs collect-docs imports # Creates a new fileset. Requires the params MODULE and FILESET .PHONY: create-fileset diff --git a/filebeat/include/list.go b/filebeat/include/list.go index 56765d42b0a..514ef8da727 100644 --- a/filebeat/include/list.go +++ b/filebeat/include/list.go @@ -1,6 +1,13 @@ +/* +Package include imports all prospector packages so that they register +their factories with the global registry. This package can be imported in the +main package to automatically register all of the standard supported prospectors +modules. +*/ package include import ( + // This list is automatically generated by `make imports` _ "github.com/elastic/beats/filebeat/prospector/log" _ "github.com/elastic/beats/filebeat/prospector/redis" _ "github.com/elastic/beats/filebeat/prospector/stdin" diff --git a/filebeat/scripts/generate_imports_helper.py b/filebeat/scripts/generate_imports_helper.py new file mode 100644 index 00000000000..7104812886b --- /dev/null +++ b/filebeat/scripts/generate_imports_helper.py @@ -0,0 +1,20 @@ +from os.path import abspath, isdir, join +from os import listdir + + +comment = """Package include imports all prospector packages so that they register +their factories with the global registry. This package can be imported in the +main package to automatically register all of the standard supported prospectors +modules.""" + + +def get_importable_lines(go_beat_path, import_line): + path = abspath("prospector") + + imported_prospector_lines = [] + prospectors = [p for p in listdir(path) if isdir(join(path, p))] + for prospector in sorted(prospectors): + prospector_import = import_line.format(beat_path=go_beat_path, module="prospector", name=prospector) + imported_prospector_lines.append(prospector_import) + + return imported_prospector_lines diff --git a/generator/metricbeat/Makefile b/generator/metricbeat/Makefile index 06eaa872631..76bf0a2f084 100644 --- a/generator/metricbeat/Makefile +++ b/generator/metricbeat/Makefile @@ -2,3 +2,13 @@ BEAT_TYPE=metricbeat PREPARE_COMMAND=MODULE=elastic METRICSET=test make create-metricset ; include ../common/Makefile + +prepare-test: python-env + mkdir -p ${BUILD_DIR}/src/github.com/elastic/beats/ + rsync -a --exclude=build ${PWD}/../../* ${BUILD_DIR}/src/github.com/elastic/beats/ + + mkdir -p ${BEAT_PATH}/scripts + rsync -a --exclude=build ${PWD}/../../metricbeat/scripts/generate_imports_helper.py ${BEAT_PATH}/scripts + + export GOPATH=${PWD}/build ; \ + . ${PYTHON_ENV}/bin/activate && python ${PWD}/build/src/github.com/elastic/beats/script/generate.py --type=${BEAT_TYPE} --project_name=Testbeat --github_name=ruflin --beat_path=beatpath/testbeat --full_name="Nicolas Ruflin" diff --git a/metricbeat/Makefile b/metricbeat/Makefile index b69e7b1914f..1d5de463bde 100644 --- a/metricbeat/Makefile +++ b/metricbeat/Makefile @@ -55,7 +55,7 @@ configs: python-env .PHONY: imports imports: python-env @mkdir -p include - @${PYTHON_ENV}/bin/python ${ES_BEATS}/metricbeat/scripts/generate_imports.py ${BEAT_PATH} > include/list.go + @${PYTHON_ENV}/bin/python ${ES_BEATS}/script/generate_imports.py ${BEAT_PATH} # This is called by the beats packer before building starts .PHONY: before-build diff --git a/metricbeat/scripts/generate_imports.py b/metricbeat/scripts/generate_imports.py deleted file mode 100644 index c8a7d49f620..00000000000 --- a/metricbeat/scripts/generate_imports.py +++ /dev/null @@ -1,51 +0,0 @@ -import os -import sys - -# Generates the file list.go with all modules and metricsets - -header = """/* -Package include imports all Module and MetricSet packages so that they register -their factories with the global registry. This package can be imported in the -main package to automatically register all of the standard supported Metricbeat -modules. -*/ -package include - -import ( -\t// This list is automatically generated by `make imports` -""" - - -def generate(go_beat_path): - - base_dir = "module" - path = os.path.abspath("module") - list_file = header - - # Fetch all modules - for module in sorted(os.listdir(base_dir)): - - if os.path.isfile(path + "/" + module) or module == "_meta": - continue - - list_file += ' _ "' + go_beat_path + '/module/' + module + '"\n' - - # Fetch all metricsets - for metricset in sorted(os.listdir(base_dir + "/" + module)): - if os.path.isfile(base_dir + "/" + module + "/" + metricset) or metricset == "_meta" or metricset == "vendor": - continue - - list_file += ' _ "' + go_beat_path + '/module/' + module + '/' + metricset + '"\n' - - list_file += ")" - - # output string so it can be concatenated - print(list_file) - - -if __name__ == "__main__": - # First argument is the beat path under GOPATH. - # (e.g. github.com/elastic/beats/metricbeat) - go_beat_path = sys.argv[1] - - generate(go_beat_path) diff --git a/metricbeat/scripts/generate_imports_helper.py b/metricbeat/scripts/generate_imports_helper.py new file mode 100644 index 00000000000..1de1909c417 --- /dev/null +++ b/metricbeat/scripts/generate_imports_helper.py @@ -0,0 +1,26 @@ +from os.path import abspath, isdir, join +from os import listdir + +comment = """Package include imports all Module and MetricSet packages so that they register +their factories with the global registry. This package can be imported in the +main package to automatically register all of the standard supported Metricbeat +modules.""" + + +def get_importable_lines(go_beat_path, import_line): + path = abspath("module") + + imported_lines = [] + modules = [m for m in listdir(path) if isdir(join(path, m)) and m != "_meta"] + for module in modules: + module_import = import_line.format(beat_path=go_beat_path, module="module", name=module) + imported_lines.append(module_import) + + module_path = join(path, module) + metricsets = [m for m in listdir(module_path) if isdir(join(module_path, m)) and m not in ["_meta", "vendor"]] + for metricset in metricsets: + metricset_name = "{}/{}".format(module, metricset) + metricset_import = import_line.format(beat_path=go_beat_path, module="module", name=metricset_name) + imported_lines.append(metricset_import) + + return sorted(imported_lines) diff --git a/packetbeat/Makefile b/packetbeat/Makefile index b79f8c91d8a..7c54de38c2c 100644 --- a/packetbeat/Makefile +++ b/packetbeat/Makefile @@ -42,4 +42,4 @@ create-tcp-protocol: python-env imports: python-env @mkdir -p include @mkdir -p protos - @${PYTHON_ENV}/bin/python ${ES_BEATS}/packetbeat/scripts/generate_imports.py ${BEAT_PATH} > include/list.go + @${PYTHON_ENV}/bin/python ${ES_BEATS}/script/generate_imports.py ${BEAT_PATH} diff --git a/packetbeat/scripts/generate_imports.py b/packetbeat/scripts/generate_imports.py deleted file mode 100644 index 0ecc9c4abf1..00000000000 --- a/packetbeat/scripts/generate_imports.py +++ /dev/null @@ -1,43 +0,0 @@ -import os -import sys - -# Generates the file list.go with all modules and metricsets - -header = """/* -Package include imports all protos packages so that they register with the global -registry. This package can be imported in the main package to automatically register -all of the standard supported Packetbeat protocols. -*/ -package include - -import ( -\t// This list is automatically generated by `make imports` -""" - - -def generate(go_beat_path): - - base_dir = "protos" - path = os.path.abspath("protos") - list_file = header - - # Fetch all protocols - for protocol in sorted(os.listdir(base_dir)): - - if os.path.isfile(path + "/" + protocol): - continue - - list_file += ' _ "' + go_beat_path + '/protos/' + protocol + '"\n' - - list_file += ")" - - # output string so it can be concatenated - print(list_file) - - -if __name__ == "__main__": - # First argument is the beat path under GOPATH. - # (e.g. github.com/elastic/beats/packetbeat) - go_beat_path = sys.argv[1] - - generate(go_beat_path) diff --git a/packetbeat/scripts/generate_imports_helper.py b/packetbeat/scripts/generate_imports_helper.py new file mode 100644 index 00000000000..9f00b9b8811 --- /dev/null +++ b/packetbeat/scripts/generate_imports_helper.py @@ -0,0 +1,19 @@ +from os.path import abspath, isdir, join +from os import listdir + + +comment = """Package include imports all protos packages so that they register with the global +registry. This package can be imported in the main package to automatically register +all of the standard supported Packetbeat protocols.""" + + +def get_importable_lines(go_beat_path, import_line): + path = abspath("protos") + + imported_protocol_lines = [] + protocols = [p for p in listdir(path) if isdir(join(path, p))] + for protocol in sorted(protocols): + proto_import = import_line.format(beat_path=go_beat_path, module="protos", name=protocol) + imported_protocol_lines.append(proto_import) + + return imported_protocol_lines diff --git a/script/generate_imports.py b/script/generate_imports.py new file mode 100644 index 00000000000..43a6940f57f --- /dev/null +++ b/script/generate_imports.py @@ -0,0 +1,37 @@ +import sys +from os import listdir, getcwd +from os.path import abspath, isdir, join +from argparse import ArgumentParser + +sys.path.append(abspath("scripts")) +from generate_imports_helper import comment, get_importable_lines + + +import_line_format = "\t_ \"{beat_path}/{module}/{name}\"" +include_list_path = "include/list.go" +import_template = """/* +{comment} +*/ +package include + +import ( +\t// This list is automatically generated by `make imports` +{imports} +) +""" + + +def generate_and_write_to_file(go_beat_path): + imported_beat_lines = get_importable_lines(go_beat_path, import_line_format) + imported_lines = "\n".join(imported_beat_lines) + list_go = import_template.format(imports=imported_lines, comment=comment) + with open(include_list_path, "w") as output: + output.write(list_go) + + +if __name__ == "__main__": + parser = ArgumentParser(description="Generate imports for Beats packages") + parser.add_argument("beats_path") + args = parser.parse_args() + + generate_and_write_to_file(args.beats_path) From 5305cc6f3e062181ea1e75fd48e05c0bda8c65ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Fri, 25 Aug 2017 16:22:22 +0200 Subject: [PATCH 133/139] filebeat: add plugin to prospectors --- filebeat/prospector/plugin.go | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 filebeat/prospector/plugin.go diff --git a/filebeat/prospector/plugin.go b/filebeat/prospector/plugin.go new file mode 100644 index 00000000000..0467736026d --- /dev/null +++ b/filebeat/prospector/plugin.go @@ -0,0 +1,38 @@ +package prospector + +import ( + "errors" + + "github.com/elastic/beats/libbeat/plugin" +) + +type prospectorPlugin struct { + name string + factory Factory +} + +const pluginKey = "filebeat.prospector" + +func init() { + plugin.MustRegisterLoader(pluginKey, func(ifc interface{}) error { + p, ok := ifc.(prospectorPlugin) + if !ok { + return errors.New("plugin does not match filebeat prospector plugin type") + } + + if p.factory != nil { + if err := Register(p.name, p.factory); err != nil { + return err + } + } + + return nil + }) +} + +func Plugin( + module string, + factory Factory, +) map[string][]interface{} { + return plugin.MakePlugin(pluginKey, prospectorPlugin{module, factory}) +} From 803b88703b367339a557bf44d4942ba826fefa21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Mon, 28 Aug 2017 13:58:49 +0200 Subject: [PATCH 134/139] filebeat: rename registrarcontext to runnerfactory --- filebeat/crawler/crawler.go | 6 +++--- filebeat/fileset/factory.go | 8 ++++---- filebeat/prospector/prospector.go | 2 +- .../{registrarcontext.go => runnerfactory.go} | 14 +++++++------- 4 files changed, 15 insertions(+), 15 deletions(-) rename filebeat/prospector/{registrarcontext.go => runnerfactory.go} (58%) diff --git a/filebeat/crawler/crawler.go b/filebeat/crawler/crawler.go index b820d457c18..9031d986acc 100644 --- a/filebeat/crawler/crawler.go +++ b/filebeat/crawler/crawler.go @@ -58,9 +58,9 @@ func (c *Crawler) Start(r *registrar.Registrar, configProspectors *common.Config cfgwarn.Beta("Loading separate prospectors is enabled.") c.prospectorsReloader = cfgfile.NewReloader(configProspectors) - registrarContext := prospector.NewRegistrarContext(c.out, r, c.beatDone) + runnerFactory := prospector.NewRunnerFactory(c.out, r, c.beatDone) go func() { - c.prospectorsReloader.Run(registrarContext) + c.prospectorsReloader.Run(runnerFactory) }() } @@ -83,7 +83,7 @@ func (c *Crawler) startProspector(config *common.Config, states []file.State) er if !config.Enabled() { return nil } - p, err := prospector.NewProspector(config, c.out, c.beatDone, states) + p, err := prospector.New(config, c.out, c.beatDone, states) if err != nil { return fmt.Errorf("Error in initing prospector: %s", err) } diff --git a/filebeat/fileset/factory.go b/filebeat/fileset/factory.go index 9f352c4b58b..d3350982f13 100644 --- a/filebeat/fileset/factory.go +++ b/filebeat/fileset/factory.go @@ -4,7 +4,7 @@ import ( "github.com/mitchellh/hashstructure" "github.com/elastic/beats/filebeat/channel" - pros "github.com/elastic/beats/filebeat/prospector" + "github.com/elastic/beats/filebeat/prospector" "github.com/elastic/beats/filebeat/registrar" "github.com/elastic/beats/libbeat/cfgfile" "github.com/elastic/beats/libbeat/common" @@ -25,7 +25,7 @@ type Factory struct { type prospectorsRunner struct { id uint64 moduleRegistry *ModuleRegistry - prospectors []*pros.Prospector + prospectors []*prospector.Prospector pipelineLoaderFactory PipelineLoaderFactory } @@ -62,9 +62,9 @@ func (f *Factory) Create(c *common.Config) (cfgfile.Runner, error) { return nil, err } - prospectors := make([]*pros.Prospector, len(pConfigs)) + prospectors := make([]*prospector.Prospector, len(pConfigs)) for i, pConfig := range pConfigs { - prospectors[i], err = pros.NewProspector(pConfig, f.outlet, f.beatDone, f.registrar.GetStates()) + prospectors[i], err = prospector.New(pConfig, f.outlet, f.beatDone, f.registrar.GetStates()) if err != nil { logp.Err("Error creating prospector: %s", err) return nil, err diff --git a/filebeat/prospector/prospector.go b/filebeat/prospector/prospector.go index 1661202d1fb..5ed9fc77187 100644 --- a/filebeat/prospector/prospector.go +++ b/filebeat/prospector/prospector.go @@ -31,7 +31,7 @@ type Prospector struct { } // NewProspector instantiates a new prospector -func NewProspector( +func New( conf *common.Config, outlet channel.Factory, beatDone chan struct{}, diff --git a/filebeat/prospector/registrarcontext.go b/filebeat/prospector/runnerfactory.go similarity index 58% rename from filebeat/prospector/registrarcontext.go rename to filebeat/prospector/runnerfactory.go index 678e370ebfe..5747c74f945 100644 --- a/filebeat/prospector/registrarcontext.go +++ b/filebeat/prospector/runnerfactory.go @@ -8,16 +8,16 @@ import ( "github.com/elastic/beats/libbeat/logp" ) -// RegistrarContext is a factory for registrars -type RegistrarContext struct { +// RunnerFactory is a factory for registrars +type RunnerFactory struct { outlet channel.Factory registrar *registrar.Registrar beatDone chan struct{} } -// NewRegistrarContext instantiates a new RegistrarContext -func NewRegistrarContext(outlet channel.Factory, registrar *registrar.Registrar, beatDone chan struct{}) *RegistrarContext { - return &RegistrarContext{ +// NewRunnerFactory instantiates a new RunnerFactory +func NewRunnerFactory(outlet channel.Factory, registrar *registrar.Registrar, beatDone chan struct{}) *RunnerFactory { + return &RunnerFactory{ outlet: outlet, registrar: registrar, beatDone: beatDone, @@ -25,8 +25,8 @@ func NewRegistrarContext(outlet channel.Factory, registrar *registrar.Registrar, } // Create creates a prospector based on a config -func (r *RegistrarContext) Create(c *common.Config) (cfgfile.Runner, error) { - p, err := NewProspector(c, r.outlet, r.beatDone, r.registrar.GetStates()) +func (r *RunnerFactory) Create(c *common.Config) (cfgfile.Runner, error) { + p, err := New(c, r.outlet, r.beatDone, r.registrar.GetStates()) if err != nil { logp.Err("Error creating prospector: %s", err) // In case of error with loading state, prospector is still returned From 6ddb530f58aebaa5fc5c1ebe2d7cb8229584bf0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20P=C3=A9rez-Aradros=20Herce?= Date: Tue, 29 Aug 2017 15:49:15 +0200 Subject: [PATCH 135/139] Add new docker-compose management framework This allows tests to define what services from docker-compose.yml they need. Instead of launching all at the beginning, the new framework takes care of start/stop the right services on demand. Python tests can use COMPOSE_SERVICES field to define the list of needed services. Go tests can use compose.EnsureUp to do the same. --- dev-tools/generate_notice.py | 2 +- libbeat/scripts/Makefile | 15 +- libbeat/tests/compose/compose.go | 249 +++++++++++++++++++++++ libbeat/tests/system/beat/beat.py | 11 +- libbeat/tests/system/beat/compose.py | 65 ++++++ libbeat/tests/system/requirements.txt | 1 + metricbeat/tests/system/requirements.txt | 1 + 7 files changed, 337 insertions(+), 7 deletions(-) create mode 100644 libbeat/tests/compose/compose.go create mode 100644 libbeat/tests/system/beat/compose.py create mode 100644 metricbeat/tests/system/requirements.txt diff --git a/dev-tools/generate_notice.py b/dev-tools/generate_notice.py index f2c764d655a..3fdbf34a622 100644 --- a/dev-tools/generate_notice.py +++ b/dev-tools/generate_notice.py @@ -224,7 +224,7 @@ def detect_license_summary(content): help="copyright owner") parser.add_argument("--csv", dest="csvfile", help="Output to a csv file") - parser.add_argument("-e", "--excludes", default=["dev-tools"], + parser.add_argument("-e", "--excludes", default=["dev-tools", "build"], help="List of top directories to exclude") parser.add_argument("-s", "--skip-notice", default=[], help="List of NOTICE files to skip") diff --git a/libbeat/scripts/Makefile b/libbeat/scripts/Makefile index 1b757bedad1..4d49a3f869f 100755 --- a/libbeat/scripts/Makefile +++ b/libbeat/scripts/Makefile @@ -31,6 +31,7 @@ COVERAGE_DIR=${BUILD_DIR}/coverage COVERAGE_TOOL=${BEAT_GOPATH}/bin/gotestcover COVERAGE_TOOL_REPO=github.com/elastic/beats/vendor/github.com/pierrre/gotestcover TESTIFY_TOOL_REPO=github.com/elastic/beats/vendor/github.com/stretchr/testify +LIBCOMPOSE_TOOL_REPO=github.com/docker/libcompose GOIMPORTS=goimports GOIMPORTS_REPO=golang.org/x/tools/cmd/goimports GOIMPORTS_LOCAL_PREFIX?=github.com/elastic @@ -117,6 +118,7 @@ lint: .PHONY: clean clean:: ## @build Cleans up all files generated by the build steps @rm -rf build + @rm -f docker-compose.yml.lock @rm -f ${BEAT_NAME} ${BEAT_NAME}.test ${BEAT_NAME}.exe ${BEAT_NAME}.test.exe @rm -f _meta/fields.generated.yml fields.yml @rm -f $(PWD)/_meta/kibana/index-pattern/${BEAT_NAME}.json @@ -137,8 +139,10 @@ prepare-tests: mkdir -p ${COVERAGE_DIR} # gotestcover is needed to fetch coverage for multiple packages go get ${COVERAGE_TOOL_REPO} - # testify is needed to for unit and integration tests + # testify is needed for unit and integration tests go get ${TESTIFY_TOOL_REPO} + # libcompose is needed for integration tests + go get ${LIBCOMPOSE_TOOL_REPO} .PHONY: unit-tests unit-tests: ## @testing Runs the unit tests with coverage. Race is not enabled for unit tests because tests run much slower. @@ -154,6 +158,7 @@ unit: ## @testing Runs the unit tests without coverage reports. .PHONY: integration-tests integration-tests: ## @testing Run integration tests. Unit tests are run as part of the integration tests. integration-tests: prepare-tests + rm -f docker-compose.yml.lock go test -i ${GOPACKAGES} $(COVERAGE_TOOL) -tags=integration $(RACE) -coverprofile=${COVERAGE_DIR}/integration.cov ${GOPACKAGES} @@ -161,20 +166,20 @@ integration-tests: prepare-tests .PHONY: integration-tests-environment integration-tests-environment: ## @testing Runs the integration inside a virtual environment. This can be run on any docker-machine (local, remote) integration-tests-environment: prepare-tests build-image - ${DOCKER_COMPOSE} run beat make integration-tests RACE_DETECTOR=$(RACE_DETECTOR) + ${DOCKER_COMPOSE} run beat make integration-tests RACE_DETECTOR=$(RACE_DETECTOR) DOCKER_COMPOSE_PROJECT_NAME=${DOCKER_COMPOSE_PROJECT_NAME} # Runs the system tests .PHONY: system-tests system-tests: ## @testing Runs the system tests -system-tests: ${BEAT_NAME}.test prepare-tests python-env ${ES_BEATS}/dev-tools/cmd/dashboards/export_dashboards - . ${PYTHON_ENV}/bin/activate; INTEGRATION_TESTS=${INTEGRATION_TESTS} TESTING_ENVIRONMENT=${TESTING_ENVIRONMENT} nosetests -w tests/system ${NOSETESTS_OPTIONS} +system-tests: prepare-tests ${BEAT_NAME}.test python-env ${ES_BEATS}/dev-tools/cmd/dashboards/export_dashboards + . ${PYTHON_ENV}/bin/activate; INTEGRATION_TESTS=${INTEGRATION_TESTS} TESTING_ENVIRONMENT=${TESTING_ENVIRONMENT} DOCKER_COMPOSE_PROJECT_NAME=${DOCKER_COMPOSE_PROJECT_NAME} nosetests -w tests/system ${NOSETESTS_OPTIONS} python ${ES_BEATS}/dev-tools/aggregate_coverage.py -o ${COVERAGE_DIR}/system.cov ./build/system-tests/run # Runs the system tests .PHONY: system-tests-environment system-tests-environment: ## @testing Runs the system tests inside a virtual environment. This can be run on any docker-machine (local, remote) system-tests-environment: prepare-tests build-image - ${DOCKER_COMPOSE} run -e INTEGRATION_TESTS=1 -e TESTING_ENVIRONMENT=${TESTING_ENVIRONMENT} beat make system-tests + ${DOCKER_COMPOSE} run -e INTEGRATION_TESTS=1 -e TESTING_ENVIRONMENT=${TESTING_ENVIRONMENT} -e DOCKER_COMPOSE_PROJECT_NAME=${DOCKER_COMPOSE_PROJECT_NAME} beat make system-tests .PHONY: fast-system-tests diff --git a/libbeat/tests/compose/compose.go b/libbeat/tests/compose/compose.go new file mode 100644 index 00000000000..0901b131100 --- /dev/null +++ b/libbeat/tests/compose/compose.go @@ -0,0 +1,249 @@ +package compose + +import ( + "context" + "errors" + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + "testing" + "time" + + "github.com/docker/libcompose/docker" + "github.com/docker/libcompose/docker/ctx" + "github.com/docker/libcompose/project" + "github.com/docker/libcompose/project/options" +) + +// docker-compose project wrapper +type composeProject struct { + p project.APIProject + file string +} + +type serviceInfo struct { + Name string + Running bool + Healthy bool + // Has been up for too long?: + Old bool +} + +// Regexp matching state to flag container as old +var oldRegexp = regexp.MustCompile("minute") + +// EnsureUp starts all the requested services (must be defined in docker-compose.yml) +// with a default timeout of 60 seconds +func EnsureUp(t *testing.T, services ...string) { + EnsureUpWithTimeout(t, 60, services...) +} + +// EnsureUpWithTimeout starts all the requested services (must be defined in docker-compose.yml) +// Wait for `timeout` seconds for health +func EnsureUpWithTimeout(t *testing.T, timeout int, services ...string) { + compose, err := getComposeProject() + if err != nil { + t.Fatal(err) + } + + // Kill no longer used containers + compose.KillOld(services) + + for _, service := range services { + err = compose.Start(service) + if err != nil { + t.Fatal(err) + } + } + + // Wait for health + err = compose.Wait(timeout, services...) + if err != nil { + t.Fatal(err) + } +} + +// Start the container, unless it's running already +func (c *composeProject) Start(service string) error { + servicesStatus, err := c.getServices(service) + if err != nil { + return err + } + + if servicesStatus[service] != nil { + if servicesStatus[service].Running { + // Someone is running it + return nil + } + } + + c.Lock() + defer c.Unlock() + + return c.p.Up(context.Background(), options.Up{ + Create: options.Create{ + ForceBuild: true, + }, + }, service) +} + +// Ensure all wanted services are healthy. Wait loop (60s timeout) +func (c *composeProject) Wait(seconds int, services ...string) error { + healthy := false + for !healthy && seconds > 0 { + healthy = true + + servicesStatus, err := c.getServices(services...) + if err != nil { + return err + } + + for _, s := range servicesStatus { + if !s.Healthy { + healthy = false + break + } + } + + time.Sleep(1 * time.Second) + seconds-- + } + + if !healthy { + return errors.New("Timeout waiting for services to be healthy") + } + return nil +} + +func (c *composeProject) Kill(service string) { + c.Lock() + defer c.Unlock() + + c.p.Kill(context.Background(), "KILL", service) +} + +func (c *composeProject) KillOld(except []string) error { + // Do not kill ourselves or elasticsearch :) + except = append(except, "beat", "elasticsearch") + + servicesStatus, err := c.getServices() + if err != nil { + return err + } + + for _, s := range servicesStatus { + // Ignore the ones we want + if contains(except, s.Name) { + continue + } + + if s.Old { + c.Kill(s.Name) + } + } + + return nil +} + +// Lock acquires the lock (30s) timeout +func (c *composeProject) Lock() { + seconds := 30 + for seconds > 0 { + file, err := os.OpenFile(c.file+".lock", os.O_CREATE|os.O_EXCL, 0500) + file.Close() + if err != nil { + fmt.Println("docker-compose.yml is locked, waiting") + time.Sleep(1 * time.Second) + seconds-- + continue + } + return + } + + // This should rarely happen as we lock for start only, less than a second + panic(errors.New("Timeout waiting for lock, please remove docker-comose.yml.lock")) +} + +func (c *composeProject) Unlock() { + os.Remove(c.file + ".lock") +} + +func (c *composeProject) getServices(filter ...string) (map[string]*serviceInfo, error) { + c.Lock() + defer c.Unlock() + + result := make(map[string]*serviceInfo) + services, err := c.p.Ps(context.Background(), filter...) + if err != nil { + return nil, err + } + + containers, err := c.p.Containers(context.Background(), project.Filter{State: project.Running}, filter...) + if err != nil { + return nil, err + } + + for _, c := range services { + name := strings.Split(c["Name"], "_")[1] + // In case of several (stopped) containers, always prefer info about running ones + if result[name] != nil { + if result[name].Running { + continue + } + } + + service := &serviceInfo{ + Name: name, + } + // fill details: + service.Healthy = strings.Contains(c["State"], "(healthy)") + service.Running = contains(containers, c["Id"]) + if service.Healthy { + service.Old = oldRegexp.MatchString(c["State"]) + } + result[name] = service + } + return result, nil +} + +func contains(list []string, item string) bool { + for _, i := range list { + if item == i { + return true + } + } + return false +} + +func getComposeProject() (*composeProject, error) { + // find docker-compose + path, err := os.Getwd() + if err != nil { + return nil, err + } + for { + if path == "/" { + return nil, errors.New("docker-compose.yml not found") + } + + if _, err = os.Stat(path + "/docker-compose.yml"); err != nil { + path = filepath.Dir(path) + } else { + break + } + } + + project, err := docker.NewProject(&ctx.Context{ + Context: project.Context{ + ProjectName: os.Getenv("DOCKER_COMPOSE_PROJECT_NAME"), + ComposeFiles: []string{path + "/docker-compose.yml"}, + }, + }, nil) + if err != nil { + return nil, err + } + + return &composeProject{project, path + "/docker-compose.yml"}, nil +} diff --git a/libbeat/tests/system/beat/beat.py b/libbeat/tests/system/beat/beat.py index 988653d60ca..5de15eaf83c 100644 --- a/libbeat/tests/system/beat/beat.py +++ b/libbeat/tests/system/beat/beat.py @@ -11,6 +11,8 @@ import yaml from datetime import datetime, timedelta +from .compose import ComposeMixin + BEAT_REQUIRED_FIELDS = ["@timestamp", "beat.name", "beat.hostname", "beat.version"] @@ -102,7 +104,7 @@ def __del__(self): pass -class TestCase(unittest.TestCase): +class TestCase(unittest.TestCase, ComposeMixin): @classmethod def setUpClass(self): @@ -122,6 +124,13 @@ def setUpClass(self): build_dir = self.beat_path + "/build" self.build_path = build_dir + "/system-tests/" + # Start the containers needed to run these tests + self.compose_up() + + @classmethod + def tearDownClass(self): + self.compose_down() + def run_beat(self, cmd=None, config=None, diff --git a/libbeat/tests/system/beat/compose.py b/libbeat/tests/system/beat/compose.py new file mode 100644 index 00000000000..41047a2bde8 --- /dev/null +++ b/libbeat/tests/system/beat/compose.py @@ -0,0 +1,65 @@ +from __future__ import absolute_import +import os +import time + + +INTEGRATION_TESTS = os.environ.get('INTEGRATION_TESTS', False) + + +if INTEGRATION_TESTS: + from compose.cli.command import get_project + from compose.service import BuildAction + + +class ComposeMixin(object): + """ + Manage docker-compose to ensure that needed services are running during tests + """ + + # List of required services to run INTEGRATION_TESTS + COMPOSE_SERVICES = [] + + # docker-compose.yml dir path + COMPOSE_PROJECT_DIR = '.' + + # timeout waiting for health (seconds) + COMPOSE_TIMEOUT = 60 + + @classmethod + def compose_up(cls): + """ + Ensure *only* the services defined under `COMPOSE_SERVICES` are running and healthy + """ + if INTEGRATION_TESTS and cls.COMPOSE_SERVICES: + cls.compose_project().up( + service_names=cls.COMPOSE_SERVICES, + do_build=BuildAction.force, + timeout=30) + + # Wait for them to be healthy + healthy = False + seconds = cls.COMPOSE_TIMEOUT + while not healthy and seconds > 0: + print("Seconds: %d".format(seconds)) + seconds -= 1 + time.sleep(1) + healthy = True + for container in cls.compose_project().containers(service_names=cls.COMPOSE_SERVICES): + if container.inspect()['State']['Health']['Status'] != 'healthy': + healthy = False + break + + if not healthy: + raise Exception('Timeout while waiting for healthy docker-compose services') + + @classmethod + def compose_down(cls): + """ + Stop all running containers + """ + if INTEGRATION_TESTS and cls.COMPOSE_SERVICES: + cls.compose_project().kill(service_names=cls.COMPOSE_SERVICES) + + @classmethod + def compose_project(cls): + return get_project(cls.COMPOSE_PROJECT_DIR, project_name=os.environ.get('DOCKER_COMPOSE_PROJECT_NAME')) diff --git a/libbeat/tests/system/requirements.txt b/libbeat/tests/system/requirements.txt index 056b0fb3b58..b6445d94786 100644 --- a/libbeat/tests/system/requirements.txt +++ b/libbeat/tests/system/requirements.txt @@ -8,3 +8,4 @@ elasticsearch requests autopep8 six +docker-compose diff --git a/metricbeat/tests/system/requirements.txt b/metricbeat/tests/system/requirements.txt new file mode 100644 index 00000000000..d328a914259 --- /dev/null +++ b/metricbeat/tests/system/requirements.txt @@ -0,0 +1 @@ +kafka-python From e227860041d742808215d5417af6003a6830540a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20P=C3=A9rez-Aradros=20Herce?= Date: Tue, 29 Aug 2017 15:52:30 +0200 Subject: [PATCH 136/139] Fix Dockerfile healthchecks and unify timing params --- metricbeat/module/aerospike/_meta/Dockerfile | 2 +- metricbeat/module/apache/_meta/Dockerfile | 2 +- metricbeat/module/ceph/_meta/Dockerfile | 3 +-- metricbeat/module/couchbase/_meta/Dockerfile | 2 +- metricbeat/module/dropwizard/_meta/Dockerfile | 2 +- metricbeat/module/elasticsearch/_meta/Dockerfile | 2 ++ metricbeat/module/haproxy/_meta/Dockerfile | 2 +- metricbeat/module/http/_meta/Dockerfile | 3 +-- metricbeat/module/jolokia/_meta/Dockerfile | 2 +- metricbeat/module/kafka/_meta/Dockerfile | 3 +-- metricbeat/module/kibana/_meta/Dockerfile | 2 ++ metricbeat/module/kubernetes/_meta/Dockerfile | 2 +- metricbeat/module/kubernetes/_meta/Dockerfile.kube-state | 2 ++ metricbeat/module/memcached/_meta/Dockerfile | 2 +- metricbeat/module/mongodb/_meta/Dockerfile | 2 +- metricbeat/module/mysql/_meta/Dockerfile | 2 +- metricbeat/module/nginx/_meta/Dockerfile | 2 +- metricbeat/module/php_fpm/_meta/Dockerfile | 2 +- metricbeat/module/postgresql/_meta/Dockerfile | 2 +- metricbeat/module/prometheus/_meta/Dockerfile | 2 +- metricbeat/module/rabbitmq/_meta/Dockerfile | 2 +- metricbeat/module/redis/_meta/Dockerfile | 2 +- metricbeat/module/zookeeper/_meta/Dockerfile | 2 +- 23 files changed, 26 insertions(+), 23 deletions(-) create mode 100644 metricbeat/module/elasticsearch/_meta/Dockerfile create mode 100644 metricbeat/module/kibana/_meta/Dockerfile diff --git a/metricbeat/module/aerospike/_meta/Dockerfile b/metricbeat/module/aerospike/_meta/Dockerfile index 038cb31fca5..9693bbde4c2 100644 --- a/metricbeat/module/aerospike/_meta/Dockerfile +++ b/metricbeat/module/aerospike/_meta/Dockerfile @@ -1,4 +1,4 @@ FROM aerospike:3.9.0 RUN apt-get update && apt-get install -y netcat -HEALTHCHECK CMD nc -z localhost 3000 +HEALTHCHECK --interval=1s --retries=90 CMD nc -z localhost 3000 diff --git a/metricbeat/module/apache/_meta/Dockerfile b/metricbeat/module/apache/_meta/Dockerfile index f52ded8b8fe..b6239b871f9 100644 --- a/metricbeat/module/apache/_meta/Dockerfile +++ b/metricbeat/module/apache/_meta/Dockerfile @@ -1,4 +1,4 @@ FROM httpd:2.4.20 RUN apt-get update && apt-get install -y curl -HEALTHCHECK CMD curl -f http://localhost +HEALTHCHECK --interval=1s --retries=90 CMD curl -f http://localhost COPY ./httpd.conf /usr/local/apache2/conf/httpd.conf diff --git a/metricbeat/module/ceph/_meta/Dockerfile b/metricbeat/module/ceph/_meta/Dockerfile index 5676d0a9af1..f9e4ac091df 100644 --- a/metricbeat/module/ceph/_meta/Dockerfile +++ b/metricbeat/module/ceph/_meta/Dockerfile @@ -3,6 +3,5 @@ FROM ceph/demo:tag-build-master-jewel-centos-7 ENV MON_IP 0.0.0.0 ENV CEPH_PUBLIC_NETWORK 0.0.0.0/0 -RUN yum install -y nc && yum clean all -HEALTHCHECK CMD nc -w 1 -v 127.0.0.1 5000 > /usr/local/etc/php-fpm.d/www.conf ADD ./php-fpm.conf /etc/nginx/sites-enabled -HEALTHCHECK CMD curl -f http://localhost:81 +HEALTHCHECK --interval=1s --retries=90 CMD curl -f http://localhost:81 EXPOSE 81 diff --git a/metricbeat/module/postgresql/_meta/Dockerfile b/metricbeat/module/postgresql/_meta/Dockerfile index 0af2c484072..d19a113138c 100644 --- a/metricbeat/module/postgresql/_meta/Dockerfile +++ b/metricbeat/module/postgresql/_meta/Dockerfile @@ -1,2 +1,2 @@ FROM postgres:9.5.3 -HEALTHCHECK CMD psql -h localhost -U postgres -l +HEALTHCHECK --interval=10s --retries=6 CMD psql -h localhost -U postgres -l diff --git a/metricbeat/module/prometheus/_meta/Dockerfile b/metricbeat/module/prometheus/_meta/Dockerfile index 2293eac51e0..836c8777f62 100644 --- a/metricbeat/module/prometheus/_meta/Dockerfile +++ b/metricbeat/module/prometheus/_meta/Dockerfile @@ -1,3 +1,3 @@ FROM prom/prometheus:v1.5.1 -HEALTHCHECK CMD nc -w 1 localhost 9090 Date: Tue, 29 Aug 2017 15:53:29 +0200 Subject: [PATCH 137/139] Adapt Metricbeat system tests to new compose framework --- metricbeat/docker-compose.yml | 183 ++++++------------ metricbeat/module/kubernetes/_meta/env | 2 +- metricbeat/tests/system/test_aerospike.py | 2 + metricbeat/tests/system/test_apache.py | 2 + metricbeat/tests/system/test_ceph.py | 2 + metricbeat/tests/system/test_couchbase.py | 2 + metricbeat/tests/system/test_docker.py | 13 -- metricbeat/tests/system/test_dropwizard.py | 2 + metricbeat/tests/system/test_elasticsearch.py | 2 + metricbeat/tests/system/test_haproxy.py | 2 + metricbeat/tests/system/test_http.py | 2 + metricbeat/tests/system/test_jolokia.py | 2 + metricbeat/tests/system/test_kafka.py | 9 + metricbeat/tests/system/test_kibana.py | 4 + metricbeat/tests/system/test_kubernetes.py | 5 + metricbeat/tests/system/test_memcached.py | 2 + metricbeat/tests/system/test_mongodb.py | 2 + metricbeat/tests/system/test_mysql.py | 2 + metricbeat/tests/system/test_phpfpm.py | 2 + metricbeat/tests/system/test_postgresql.py | 2 + metricbeat/tests/system/test_prometheus.py | 2 + metricbeat/tests/system/test_redis.py | 2 + metricbeat/tests/system/test_zookeeper.py | 2 + 23 files changed, 109 insertions(+), 141 deletions(-) diff --git a/metricbeat/docker-compose.yml b/metricbeat/docker-compose.yml index add5a447292..884930ee8f4 100644 --- a/metricbeat/docker-compose.yml +++ b/metricbeat/docker-compose.yml @@ -1,132 +1,83 @@ -version: '2.1' +version: '2' services: beat: - build: ${PWD}/. + build: . environment: - TEST_ENVIRONMENT=false working_dir: /go/src/github.com/elastic/beats/metricbeat volumes: - - ${PWD}/..:/go/src/github.com/elastic/beats/ - # This is required for the docker module tests + - ./..:/go/src/github.com/elastic/beats/ + # This is required to on-demand launching the rest on containers for tests & also docker module tests: - /var/run/docker.sock:/var/run/docker.sock command: make - - # Wait for all services to be up and healthy. - depends_on: - - proxy_dep1 - - proxy_dep2 - - proxy_dep3 - env_file: - - ${PWD}/module/aerospike/_meta/env - - ${PWD}/module/apache/_meta/env - - ${PWD}/module/ceph/_meta/env - - ${PWD}/module/couchbase/_meta/env - - ${PWD}/module/dropwizard/_meta/env - - ${PWD}/module/elasticsearch/_meta/env - - ${PWD}/module/haproxy/_meta/env - - ${PWD}/module/http/_meta/env - - ${PWD}/module/jolokia/_meta/env - - ${PWD}/module/kafka/_meta/env - - ${PWD}/module/kibana/_meta/env - - ${PWD}/module/kubernetes/_meta/env - - ${PWD}/module/memcached/_meta/env - - ${PWD}/module/mongodb/_meta/env - - ${PWD}/module/mysql/_meta/env - - ${PWD}/module/nginx/_meta/env - - ${PWD}/module/php_fpm/_meta/env - - ${PWD}/module/postgresql/_meta/env - - ${PWD}/module/prometheus/_meta/env - - ${PWD}/module/rabbitmq/_meta/env - - ${PWD}/module/redis/_meta/env - - ${PWD}/module/zookeeper/_meta/env - - # This is a proxy used to block beats until all services are healthy. - # See: https://github.com/docker/compose/issues/4369 - proxy_dep1: - image: busybox - depends_on: - aerospike: { condition: service_healthy } - apache: { condition: service_healthy } - ceph: { condition: service_healthy } - couchbase: { condition: service_healthy } - dropwizard: { condition: service_healthy } - elasticsearch: { condition: service_healthy } - haproxy: { condition: service_healthy } - http: { condition: service_healthy } - - - proxy_dep2: - image: busybox - depends_on: - jolokia: { condition: service_healthy } - kafka: { condition: service_healthy } - kibana: { condition: service_healthy } - kubernetes: { condition: service_healthy } - kube-state: { condition: service_started } - memcached: { condition: service_healthy } - mongodb: { condition: service_healthy } - - proxy_dep3: - image: busybox - depends_on: - mysql: { condition: service_healthy } - nginx: { condition: service_healthy } - phpfpm: { condition: service_healthy } - postgresql: { condition: service_healthy } - prometheus: { condition: service_healthy } - rabbitmq: { condition: service_healthy } - redis: { condition: service_healthy } - zookeeper: { condition: service_healthy } + - ./module/aerospike/_meta/env + - ./module/apache/_meta/env + - ./module/ceph/_meta/env + - ./module/couchbase/_meta/env + - ./module/dropwizard/_meta/env + - ./module/elasticsearch/_meta/env + - ./module/haproxy/_meta/env + - ./module/http/_meta/env + - ./module/jolokia/_meta/env + - ./module/kafka/_meta/env + - ./module/kibana/_meta/env + - ./module/kubernetes/_meta/env + - ./module/memcached/_meta/env + - ./module/mongodb/_meta/env + - ./module/mysql/_meta/env + - ./module/nginx/_meta/env + - ./module/php_fpm/_meta/env + - ./module/postgresql/_meta/env + - ./module/prometheus/_meta/env + - ./module/rabbitmq/_meta/env + - ./module/redis/_meta/env + - ./module/zookeeper/_meta/env # Modules aerospike: - build: ${PWD}/module/aerospike/_meta + build: ./module/aerospike/_meta apache: - build: ${PWD}/module/apache/_meta + build: ./module/apache/_meta ceph: - build: ${PWD}/module/ceph/_meta + build: ./module/ceph/_meta couchbase: - build: ${PWD}/module/couchbase/_meta + build: ./module/couchbase/_meta dropwizard: - build: ${PWD}/module/dropwizard/_meta + build: ./module/dropwizard/_meta elasticsearch: - extends: - file: ${ES_BEATS}/testing/environments/${TESTING_ENVIRONMENT}.yml - service: elasticsearch + build: ./module/elasticsearch/_meta environment: - "ES_JAVA_OPTS=-Xms90m -Xmx90m" + - "network.host=" + - "transport.host=127.0.0.1" + - "http.host=0.0.0.0" + - "xpack.security.enabled=false" haproxy: - build: ${PWD}/module/haproxy/_meta + build: ./module/haproxy/_meta http: - build: ${PWD}/module/http/_meta + build: ./module/http/_meta jolokia: - build: ${PWD}/module/jolokia/_meta - depends_on: - - proxy_dep1 + build: ./module/jolokia/_meta kafka: - build: ${PWD}/module/kafka/_meta - depends_on: - - proxy_dep1 + build: ./module/kafka/_meta kibana: - extends: - file: ${ES_BEATS}/testing/environments/${TESTING_ENVIRONMENT}.yml - service: kibana + build: ./module/kibana/_meta depends_on: - - proxy_dep1 + - elasticsearch kubernetes: - build: ${PWD}/module/kubernetes/_meta + build: ./module/kubernetes/_meta network_mode: host pid: host privileged: true @@ -135,62 +86,40 @@ services: - /sys:/sys - /var/lib/docker:/var/lib/docker - /var/run:/var/run - depends_on: - - proxy_dep1 - kube-state: + kubestate: build: - context: ${PWD}/module/kubernetes/_meta/ + context: ./module/kubernetes/_meta/ dockerfile: Dockerfile.kube-state depends_on: - - proxy_dep1 + - kubernetes memcached: - build: ${PWD}/module/memcached/_meta - depends_on: - - proxy_dep1 + build: ./module/memcached/_meta mongodb: - build: ${PWD}/module/mongodb/_meta - depends_on: - - proxy_dep1 + build: ./module/mongodb/_meta mysql: - build: ${PWD}/module/mysql/_meta - depends_on: - - proxy_dep2 + build: ./module/mysql/_meta nginx: - build: ${PWD}/module/nginx/_meta - depends_on: - - proxy_dep2 + build: ./module/nginx/_meta phpfpm: - build: ${PWD}/module/php_fpm/_meta - depends_on: - - proxy_dep2 + build: ./module/php_fpm/_meta postgresql: - build: ${PWD}/module/postgresql/_meta - depends_on: - - proxy_dep2 + build: ./module/postgresql/_meta prometheus: - build: ${PWD}/module/prometheus/_meta - depends_on: - - proxy_dep2 + build: ./module/prometheus/_meta rabbitmq: - build: ${PWD}/module/rabbitmq/_meta - depends_on: - - proxy_dep2 + build: ./module/rabbitmq/_meta redis: - build: ${PWD}/module/redis/_meta - depends_on: - - proxy_dep2 + build: ./module/redis/_meta zookeeper: - build: ${PWD}/module/zookeeper/_meta - depends_on: - - proxy_dep2 + build: ./module/zookeeper/_meta diff --git a/metricbeat/module/kubernetes/_meta/env b/metricbeat/module/kubernetes/_meta/env index b8fa8ca0a05..03cff050efa 100644 --- a/metricbeat/module/kubernetes/_meta/env +++ b/metricbeat/module/kubernetes/_meta/env @@ -1,4 +1,4 @@ KUBELET_HOST=172.17.0.1 KUBELET_PORT=10255 -KUBE_STATE_METRICS_HOST=kube-state +KUBE_STATE_METRICS_HOST=kubestate KUBE_STATE_METRICS_PORT=8080 diff --git a/metricbeat/tests/system/test_aerospike.py b/metricbeat/tests/system/test_aerospike.py index 6106a6c6e1d..5abbc8b99fd 100644 --- a/metricbeat/tests/system/test_aerospike.py +++ b/metricbeat/tests/system/test_aerospike.py @@ -8,6 +8,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['aerospike'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") def test_namespace(self): """ diff --git a/metricbeat/tests/system/test_apache.py b/metricbeat/tests/system/test_apache.py index 77d2f47f7b8..21f32c1516a 100644 --- a/metricbeat/tests/system/test_apache.py +++ b/metricbeat/tests/system/test_apache.py @@ -18,6 +18,8 @@ class ApacheStatusTest(metricbeat.BaseTest): + COMPOSE_SERVICES = ['apache'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") @attr('integration') def test_output(self): diff --git a/metricbeat/tests/system/test_ceph.py b/metricbeat/tests/system/test_ceph.py index a4303cd25f7..f64ebae1283 100644 --- a/metricbeat/tests/system/test_ceph.py +++ b/metricbeat/tests/system/test_ceph.py @@ -5,6 +5,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['ceph'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") def test_cluster_disk(self): """ diff --git a/metricbeat/tests/system/test_couchbase.py b/metricbeat/tests/system/test_couchbase.py index 8fb209f95bb..bfb7416d372 100644 --- a/metricbeat/tests/system/test_couchbase.py +++ b/metricbeat/tests/system/test_couchbase.py @@ -5,6 +5,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['couchbase'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") def test_bucket(self): """ diff --git a/metricbeat/tests/system/test_docker.py b/metricbeat/tests/system/test_docker.py index 3110594cca3..53629f4e1f2 100644 --- a/metricbeat/tests/system/test_docker.py +++ b/metricbeat/tests/system/test_docker.py @@ -12,16 +12,6 @@ def test_container_fields(self): """ test container fields """ - - test_env = os.environ.get('DOCKER_COMPOSE_PROJECT_NAME') - processors = None - if test_env: - processors = [{ - "drop_event": { - "when.not": "contains.docker.container.name: " + test_env, - }, - }] - self.render_config_template( modules=[{ "name": "docker", @@ -29,7 +19,6 @@ def test_container_fields(self): "hosts": ["unix:///var/run/docker.sock"], "period": "10s", }], - processors=processors, ) proc = self.start_beat() @@ -38,8 +27,6 @@ def test_container_fields(self): self.assert_no_logged_warnings(["WARN Container stopped when recovering stats", "ERR An error occurred while getting docker stats"]) - print(os.environ.get('TESTING_ENVIRONMENT')) - output = self.read_output_json() evt = output[0] diff --git a/metricbeat/tests/system/test_dropwizard.py b/metricbeat/tests/system/test_dropwizard.py index 0fd8b1132df..a9ab7dbbe8d 100644 --- a/metricbeat/tests/system/test_dropwizard.py +++ b/metricbeat/tests/system/test_dropwizard.py @@ -5,6 +5,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['dropwizard'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") def test_dropwizard(self): """ diff --git a/metricbeat/tests/system/test_elasticsearch.py b/metricbeat/tests/system/test_elasticsearch.py index 32ea7705769..1ece3ce3800 100644 --- a/metricbeat/tests/system/test_elasticsearch.py +++ b/metricbeat/tests/system/test_elasticsearch.py @@ -5,6 +5,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['elasticsearch'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") def test_node(self): """ diff --git a/metricbeat/tests/system/test_haproxy.py b/metricbeat/tests/system/test_haproxy.py index 7fa4b4207ec..b1f8f586615 100644 --- a/metricbeat/tests/system/test_haproxy.py +++ b/metricbeat/tests/system/test_haproxy.py @@ -8,6 +8,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['haproxy'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") def test_info(self): """ diff --git a/metricbeat/tests/system/test_http.py b/metricbeat/tests/system/test_http.py index 562869b84b8..8d52393356f 100644 --- a/metricbeat/tests/system/test_http.py +++ b/metricbeat/tests/system/test_http.py @@ -8,6 +8,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['http'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") def test_json(self): """ diff --git a/metricbeat/tests/system/test_jolokia.py b/metricbeat/tests/system/test_jolokia.py index 18a19d84901..189dcc911e4 100644 --- a/metricbeat/tests/system/test_jolokia.py +++ b/metricbeat/tests/system/test_jolokia.py @@ -6,6 +6,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['jolokia'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") def test_jmx(self): """ diff --git a/metricbeat/tests/system/test_kafka.py b/metricbeat/tests/system/test_kafka.py index a86f4b36a88..55893dec9bd 100644 --- a/metricbeat/tests/system/test_kafka.py +++ b/metricbeat/tests/system/test_kafka.py @@ -6,11 +6,15 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['kafka'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") def test_partition(self): """ kafka partition metricset test """ + self.create_topic() + self.render_config_template(modules=[{ "name": "kafka", "metricsets": ["partition"], @@ -28,6 +32,11 @@ def test_partition(self): self.assert_fields_are_documented(evt) + def create_topic(self): + from kafka import KafkaProducer + producer = KafkaProducer(bootstrap_servers=self.get_hosts()[0]) + producer.send('foobar', b'some_message_bytes') + def get_hosts(self): return [os.getenv('KAFKA_HOST', 'localhost') + ':' + os.getenv('KAFKA_PORT', '9092')] diff --git a/metricbeat/tests/system/test_kibana.py b/metricbeat/tests/system/test_kibana.py index 268047302cc..18d212527f4 100644 --- a/metricbeat/tests/system/test_kibana.py +++ b/metricbeat/tests/system/test_kibana.py @@ -6,6 +6,10 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['elasticsearch', 'kibana'] + + COMPOSE_TIMEOUT = 120 + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") def test_status(self): """ diff --git a/metricbeat/tests/system/test_kubernetes.py b/metricbeat/tests/system/test_kubernetes.py index f70971dadca..4861734e5c4 100644 --- a/metricbeat/tests/system/test_kubernetes.py +++ b/metricbeat/tests/system/test_kubernetes.py @@ -7,6 +7,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['kubernetes'] # 'kubestate'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") def test_kubelet_node(self): """ Kubernetes kubelet node metricset tests """ @@ -28,16 +30,19 @@ def test_kubelet_container(self): self._test_metricset('container', 1, self.get_kubelet_hosts()) @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") + @unittest.skip("flacky kube-state-metrics container healthcheck") def test_state_node(self): """ Kubernetes state node metricset tests """ self._test_metricset('state_node', 1, self.get_kube_state_hosts()) @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") + @unittest.skip("flacky kube-state-metrics container healthcheck") def test_state_pod(self): """ Kubernetes state pod metricset tests """ self._test_metricset('state_pod', 1, self.get_kube_state_hosts()) @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") + @unittest.skip("flacky kube-state-metrics container healthcheck") def test_state_container(self): """ Kubernetes state container metricset tests """ self._test_metricset('state_container', 1, self.get_kube_state_hosts()) diff --git a/metricbeat/tests/system/test_memcached.py b/metricbeat/tests/system/test_memcached.py index 1a1c7c733b4..ede980b0581 100644 --- a/metricbeat/tests/system/test_memcached.py +++ b/metricbeat/tests/system/test_memcached.py @@ -5,6 +5,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['memcached'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") def test_stats(self): """ diff --git a/metricbeat/tests/system/test_mongodb.py b/metricbeat/tests/system/test_mongodb.py index 9497346cd6c..3a8493584a4 100644 --- a/metricbeat/tests/system/test_mongodb.py +++ b/metricbeat/tests/system/test_mongodb.py @@ -8,6 +8,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['mongodb'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") @attr('integration') def test_status(self): diff --git a/metricbeat/tests/system/test_mysql.py b/metricbeat/tests/system/test_mysql.py index e7271f43e14..987da6eb88a 100644 --- a/metricbeat/tests/system/test_mysql.py +++ b/metricbeat/tests/system/test_mysql.py @@ -11,6 +11,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['mysql'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") @attr('integration') def test_status(self): diff --git a/metricbeat/tests/system/test_phpfpm.py b/metricbeat/tests/system/test_phpfpm.py index 475a8c3ec90..edb5405a404 100644 --- a/metricbeat/tests/system/test_phpfpm.py +++ b/metricbeat/tests/system/test_phpfpm.py @@ -7,6 +7,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['phpfpm'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") def test_info(self): """ diff --git a/metricbeat/tests/system/test_postgresql.py b/metricbeat/tests/system/test_postgresql.py index ca21bb786e4..52c59e1a628 100644 --- a/metricbeat/tests/system/test_postgresql.py +++ b/metricbeat/tests/system/test_postgresql.py @@ -6,6 +6,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['postgresql'] + def common_checks(self, output): # Ensure no errors or warnings exist in the log. log = self.get_log() diff --git a/metricbeat/tests/system/test_prometheus.py b/metricbeat/tests/system/test_prometheus.py index 4e9eae4d263..535395460df 100644 --- a/metricbeat/tests/system/test_prometheus.py +++ b/metricbeat/tests/system/test_prometheus.py @@ -7,6 +7,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['prometheus'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") def test_stats(self): """ diff --git a/metricbeat/tests/system/test_redis.py b/metricbeat/tests/system/test_redis.py index dfd0d80f9e8..b7fa706f243 100644 --- a/metricbeat/tests/system/test_redis.py +++ b/metricbeat/tests/system/test_redis.py @@ -20,6 +20,8 @@ class Test(metricbeat.BaseTest): + COMPOSE_SERVICES = ['redis'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") @attr('integration') def test_info(self): diff --git a/metricbeat/tests/system/test_zookeeper.py b/metricbeat/tests/system/test_zookeeper.py index 0dd3a4c191b..7871b2d1797 100644 --- a/metricbeat/tests/system/test_zookeeper.py +++ b/metricbeat/tests/system/test_zookeeper.py @@ -14,6 +14,8 @@ class ZooKeeperMntrTest(metricbeat.BaseTest): + COMPOSE_SERVICES = ['zookeeper'] + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") @attr('integration') def test_output(self): From b0c6aee9879f225fa0496ebac85ba1b9f5611e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20P=C3=A9rez-Aradros=20Herce?= Date: Tue, 29 Aug 2017 15:54:19 +0200 Subject: [PATCH 138/139] Adapt Metricbeat integration tests to new compose framework --- .../aerospike/namespace/namespace_integration_test.go | 3 +++ metricbeat/module/apache/status/status_integration_test.go | 5 +++++ .../dropwizard/collector/collector_integration_test.go | 5 +++++ .../module/elasticsearch/node/node_integration_test.go | 5 +++++ .../node_stats/node_stats_integration_test.go | 5 +++++ metricbeat/module/http/json/json_integration_test.go | 5 +++++ metricbeat/module/jolokia/jmx/jmx_integration_test.go | 3 +++ .../module/kafka/partition/partition_integration_test.go | 5 +++++ metricbeat/module/kibana/status/status_integration_test.go | 5 +++++ .../module/memcached/stats/stats_integration_test.go | 3 +++ .../module/mongodb/dbstats/dbstats_integration_test.go | 5 +++++ .../module/mongodb/status/status_integration_test.go | 5 +++++ metricbeat/module/mysql/mysql_integration_test.go | 3 +++ metricbeat/module/mysql/status/status_integration_test.go | 5 +++++ .../module/nginx/stubstatus/stubstatus_integration_test.go | 3 +++ metricbeat/module/php_fpm/pool/pool_integration_test.go | 3 +++ .../postgresql/activity/activity_integration_test.go | 4 ++++ .../postgresql/bgwriter/bgwriter_integration_test.go | 5 +++++ .../postgresql/database/database_integration_test.go | 5 +++++ .../prometheus/collector/collector_integration_test.go | 5 +++++ .../module/prometheus/stats/stats_integration_test.go | 5 +++++ metricbeat/module/rabbitmq/node/node_integration_test.go | 5 +++++ metricbeat/module/redis/info/info_integration_test.go | 7 +++++++ .../module/redis/keyspace/keyspace_integration_test.go | 5 +++++ metricbeat/module/zookeeper/mntr/mntr_integration_test.go | 5 +++++ 25 files changed, 114 insertions(+) diff --git a/metricbeat/module/aerospike/namespace/namespace_integration_test.go b/metricbeat/module/aerospike/namespace/namespace_integration_test.go index 954541fc40a..0f4b4ec2b85 100644 --- a/metricbeat/module/aerospike/namespace/namespace_integration_test.go +++ b/metricbeat/module/aerospike/namespace/namespace_integration_test.go @@ -5,11 +5,14 @@ package namespace import ( "testing" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/beats/metricbeat/module/aerospike" ) func TestData(t *testing.T) { + compose.EnsureUp(t, "aerospike") + f := mbtest.NewEventsFetcher(t, getConfig()) err := mbtest.WriteEvents(f, t) if err != nil { diff --git a/metricbeat/module/apache/status/status_integration_test.go b/metricbeat/module/apache/status/status_integration_test.go index e3a4a807c06..23408a3f360 100644 --- a/metricbeat/module/apache/status/status_integration_test.go +++ b/metricbeat/module/apache/status/status_integration_test.go @@ -5,6 +5,7 @@ package status import ( "testing" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/beats/metricbeat/module/apache" @@ -12,6 +13,8 @@ import ( ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "apache") + f := mbtest.NewEventFetcher(t, getConfig()) event, err := f.Fetch() if !assert.NoError(t, err) { @@ -27,6 +30,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "apache") + f := mbtest.NewEventFetcher(t, getConfig()) err := mbtest.WriteEvent(f, t) diff --git a/metricbeat/module/dropwizard/collector/collector_integration_test.go b/metricbeat/module/dropwizard/collector/collector_integration_test.go index 59fd36fbadb..7b26d9d71de 100644 --- a/metricbeat/module/dropwizard/collector/collector_integration_test.go +++ b/metricbeat/module/dropwizard/collector/collector_integration_test.go @@ -9,10 +9,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "dropwizard") + f := mbtest.NewEventsFetcher(t, getConfig()) events, err := f.Fetch() @@ -55,6 +58,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "dropwizard") + f := mbtest.NewEventsFetcher(t, getConfig()) err := mbtest.WriteEvents(f, t) if err != nil { diff --git a/metricbeat/module/elasticsearch/node/node_integration_test.go b/metricbeat/module/elasticsearch/node/node_integration_test.go index caa161d0353..042f7261883 100644 --- a/metricbeat/module/elasticsearch/node/node_integration_test.go +++ b/metricbeat/module/elasticsearch/node/node_integration_test.go @@ -5,6 +5,7 @@ package node import ( "testing" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/beats/metricbeat/module/elasticsearch" @@ -12,6 +13,8 @@ import ( ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "elasticsearch") + f := mbtest.NewEventsFetcher(t, elasticsearch.GetConfig("node")) event, err := f.Fetch() if !assert.NoError(t, err) { @@ -23,6 +26,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "elasticsearch") + f := mbtest.NewEventsFetcher(t, elasticsearch.GetConfig("node")) err := mbtest.WriteEvents(f, t) if err != nil { diff --git a/metricbeat/module/elasticsearch/node_stats/node_stats_integration_test.go b/metricbeat/module/elasticsearch/node_stats/node_stats_integration_test.go index 0a2866e8cfc..1832ec18f34 100644 --- a/metricbeat/module/elasticsearch/node_stats/node_stats_integration_test.go +++ b/metricbeat/module/elasticsearch/node_stats/node_stats_integration_test.go @@ -5,6 +5,7 @@ package node_stats import ( "testing" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/beats/metricbeat/module/elasticsearch" @@ -12,6 +13,8 @@ import ( ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "elasticsearch") + f := mbtest.NewEventsFetcher(t, elasticsearch.GetConfig("node_stats")) event, err := f.Fetch() if !assert.NoError(t, err) { @@ -23,6 +26,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "elasticsearch") + f := mbtest.NewEventsFetcher(t, elasticsearch.GetConfig("node_stats")) err := mbtest.WriteEvents(f, t) if err != nil { diff --git a/metricbeat/module/http/json/json_integration_test.go b/metricbeat/module/http/json/json_integration_test.go index b3c404ae3ea..30c7361e173 100644 --- a/metricbeat/module/http/json/json_integration_test.go +++ b/metricbeat/module/http/json/json_integration_test.go @@ -8,10 +8,13 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "http") + f := mbtest.NewEventFetcher(t, getConfig()) event, err := f.Fetch() if !assert.NoError(t, err) { @@ -22,6 +25,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "http") + f := mbtest.NewEventFetcher(t, getConfig()) err := mbtest.WriteEvent(f, t) if err != nil { diff --git a/metricbeat/module/jolokia/jmx/jmx_integration_test.go b/metricbeat/module/jolokia/jmx/jmx_integration_test.go index af369a56da9..9dcd54927ca 100644 --- a/metricbeat/module/jolokia/jmx/jmx_integration_test.go +++ b/metricbeat/module/jolokia/jmx/jmx_integration_test.go @@ -8,10 +8,13 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "jolokia") + f := mbtest.NewEventFetcher(t, getConfig()) event, err := f.Fetch() if !assert.NoError(t, err) { diff --git a/metricbeat/module/kafka/partition/partition_integration_test.go b/metricbeat/module/kafka/partition/partition_integration_test.go index af420ba3926..893c644ac85 100644 --- a/metricbeat/module/kafka/partition/partition_integration_test.go +++ b/metricbeat/module/kafka/partition/partition_integration_test.go @@ -15,6 +15,7 @@ import ( "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" ) @@ -24,6 +25,8 @@ const ( ) func TestData(t *testing.T) { + compose.EnsureUp(t, "kafka") + generateKafkaData(t, "metricbeat-generate-data") f := mbtest.NewEventsFetcher(t, getConfig("")) @@ -34,6 +37,8 @@ func TestData(t *testing.T) { } func TestTopic(t *testing.T) { + compose.EnsureUp(t, "kafka") + if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"kafka"}) } diff --git a/metricbeat/module/kibana/status/status_integration_test.go b/metricbeat/module/kibana/status/status_integration_test.go index 49268824cc6..017c9a2a687 100644 --- a/metricbeat/module/kibana/status/status_integration_test.go +++ b/metricbeat/module/kibana/status/status_integration_test.go @@ -8,10 +8,13 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" ) func TestFetch(t *testing.T) { + compose.EnsureUpWithTimeout(t, 120, "elasticsearch", "kibana") + f := mbtest.NewEventFetcher(t, getConfig()) event, err := f.Fetch() if !assert.NoError(t, err) { @@ -22,6 +25,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "elasticsearch", "kibana") + f := mbtest.NewEventFetcher(t, getConfig()) err := mbtest.WriteEvent(f, t) if err != nil { diff --git a/metricbeat/module/memcached/stats/stats_integration_test.go b/metricbeat/module/memcached/stats/stats_integration_test.go index 1300579e7aa..02d75af8c3c 100644 --- a/metricbeat/module/memcached/stats/stats_integration_test.go +++ b/metricbeat/module/memcached/stats/stats_integration_test.go @@ -6,10 +6,13 @@ import ( "os" "testing" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" ) func TestData(t *testing.T) { + compose.EnsureUp(t, "memcached") + f := mbtest.NewEventFetcher(t, getConfig()) err := mbtest.WriteEvent(f, t) if err != nil { diff --git a/metricbeat/module/mongodb/dbstats/dbstats_integration_test.go b/metricbeat/module/mongodb/dbstats/dbstats_integration_test.go index 1ae2a641928..ed44c3269b1 100644 --- a/metricbeat/module/mongodb/dbstats/dbstats_integration_test.go +++ b/metricbeat/module/mongodb/dbstats/dbstats_integration_test.go @@ -7,11 +7,14 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/beats/metricbeat/module/mongodb" ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "mongodb") + f := mbtest.NewEventsFetcher(t, getConfig()) events, err := f.Fetch() if !assert.NoError(t, err) { @@ -56,6 +59,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "mongodb") + f := mbtest.NewEventsFetcher(t, getConfig()) err := mbtest.WriteEvents(f, t) if err != nil { diff --git a/metricbeat/module/mongodb/status/status_integration_test.go b/metricbeat/module/mongodb/status/status_integration_test.go index 530f475889c..2aa9610384c 100644 --- a/metricbeat/module/mongodb/status/status_integration_test.go +++ b/metricbeat/module/mongodb/status/status_integration_test.go @@ -8,11 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/beats/metricbeat/module/mongodb" ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "mongodb") + f := mbtest.NewEventFetcher(t, getConfig()) event, err := f.Fetch() if !assert.NoError(t, err) { @@ -33,6 +36,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "mongodb") + f := mbtest.NewEventFetcher(t, getConfig()) err := mbtest.WriteEvent(f, t) if err != nil { diff --git a/metricbeat/module/mysql/mysql_integration_test.go b/metricbeat/module/mysql/mysql_integration_test.go index ef97613c606..297ba1cb6fc 100644 --- a/metricbeat/module/mysql/mysql_integration_test.go +++ b/metricbeat/module/mysql/mysql_integration_test.go @@ -7,10 +7,13 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/libbeat/tests/compose" _ "github.com/elastic/beats/metricbeat/mb/testing" ) func TestNewDB(t *testing.T) { + compose.EnsureUp(t, "mysql") + db, err := NewDB(GetMySQLEnvDSN()) assert.NoError(t, err) diff --git a/metricbeat/module/mysql/status/status_integration_test.go b/metricbeat/module/mysql/status/status_integration_test.go index 76e6976ad3f..54078ad9d3b 100644 --- a/metricbeat/module/mysql/status/status_integration_test.go +++ b/metricbeat/module/mysql/status/status_integration_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/beats/metricbeat/module/mysql" @@ -13,6 +14,8 @@ import ( ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "mysql") + f := mbtest.NewEventFetcher(t, getConfig(false)) event, err := f.Fetch() if !assert.NoError(t, err) { @@ -35,6 +38,8 @@ func TestFetch(t *testing.T) { } func TestFetchRaw(t *testing.T) { + compose.EnsureUp(t, "mysql") + f := mbtest.NewEventFetcher(t, getConfig(true)) event, err := f.Fetch() if !assert.NoError(t, err) { diff --git a/metricbeat/module/nginx/stubstatus/stubstatus_integration_test.go b/metricbeat/module/nginx/stubstatus/stubstatus_integration_test.go index 9a0b3aba4f9..2214c727ca2 100644 --- a/metricbeat/module/nginx/stubstatus/stubstatus_integration_test.go +++ b/metricbeat/module/nginx/stubstatus/stubstatus_integration_test.go @@ -5,6 +5,7 @@ package stubstatus import ( "testing" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/beats/metricbeat/module/nginx" @@ -12,6 +13,8 @@ import ( ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "nginx") + f := mbtest.NewEventFetcher(t, getConfig()) event, err := f.Fetch() if !assert.NoError(t, err) { diff --git a/metricbeat/module/php_fpm/pool/pool_integration_test.go b/metricbeat/module/php_fpm/pool/pool_integration_test.go index f914d316d4c..b91547a1d9c 100644 --- a/metricbeat/module/php_fpm/pool/pool_integration_test.go +++ b/metricbeat/module/php_fpm/pool/pool_integration_test.go @@ -6,10 +6,13 @@ import ( "os" "testing" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" ) func TestData(t *testing.T) { + compose.EnsureUp(t, "phpfpm") + f := mbtest.NewEventFetcher(t, getConfig()) err := mbtest.WriteEvent(f, t) if err != nil { diff --git a/metricbeat/module/postgresql/activity/activity_integration_test.go b/metricbeat/module/postgresql/activity/activity_integration_test.go index 4c7d61d9e20..c0c36fb01d7 100644 --- a/metricbeat/module/postgresql/activity/activity_integration_test.go +++ b/metricbeat/module/postgresql/activity/activity_integration_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/beats/metricbeat/module/postgresql" @@ -13,6 +14,8 @@ import ( ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "postgresql") + f := mbtest.NewEventsFetcher(t, getConfig()) events, err := f.Fetch() if !assert.NoError(t, err) { @@ -38,6 +41,7 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "postgresql") f := mbtest.NewEventsFetcher(t, getConfig()) err := mbtest.WriteEvents(f, t) diff --git a/metricbeat/module/postgresql/bgwriter/bgwriter_integration_test.go b/metricbeat/module/postgresql/bgwriter/bgwriter_integration_test.go index 09e11da0f5c..be033ebd0d9 100644 --- a/metricbeat/module/postgresql/bgwriter/bgwriter_integration_test.go +++ b/metricbeat/module/postgresql/bgwriter/bgwriter_integration_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/beats/metricbeat/module/postgresql" @@ -13,6 +14,8 @@ import ( ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "postgresql") + f := mbtest.NewEventFetcher(t, getConfig()) event, err := f.Fetch() if !assert.NoError(t, err) { @@ -40,6 +43,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "postgresql") + f := mbtest.NewEventFetcher(t, getConfig()) err := mbtest.WriteEvent(f, t) diff --git a/metricbeat/module/postgresql/database/database_integration_test.go b/metricbeat/module/postgresql/database/database_integration_test.go index 0f1f0f3c73b..4a64be0febd 100644 --- a/metricbeat/module/postgresql/database/database_integration_test.go +++ b/metricbeat/module/postgresql/database/database_integration_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/beats/metricbeat/module/postgresql" @@ -13,6 +14,8 @@ import ( ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "postgresql") + f := mbtest.NewEventsFetcher(t, getConfig()) events, err := f.Fetch() if !assert.NoError(t, err) { @@ -40,6 +43,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "postgresql") + f := mbtest.NewEventsFetcher(t, getConfig()) err := mbtest.WriteEvents(f, t) diff --git a/metricbeat/module/prometheus/collector/collector_integration_test.go b/metricbeat/module/prometheus/collector/collector_integration_test.go index 6d0bdbe2f8c..0d1b8b327e0 100644 --- a/metricbeat/module/prometheus/collector/collector_integration_test.go +++ b/metricbeat/module/prometheus/collector/collector_integration_test.go @@ -6,6 +6,7 @@ import ( "os" "testing" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/stretchr/testify/assert" @@ -15,6 +16,8 @@ import ( // Every prometheus exporter should work here. func TestFetch(t *testing.T) { + compose.EnsureUp(t, "prometheus") + f := mbtest.NewEventsFetcher(t, getConfig()) event, err := f.Fetch() if !assert.NoError(t, err) { @@ -25,6 +28,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "prometheus") + f := mbtest.NewEventsFetcher(t, getConfig()) err := mbtest.WriteEvents(f, t) diff --git a/metricbeat/module/prometheus/stats/stats_integration_test.go b/metricbeat/module/prometheus/stats/stats_integration_test.go index 5c1f70a5d20..fedbca0f683 100644 --- a/metricbeat/module/prometheus/stats/stats_integration_test.go +++ b/metricbeat/module/prometheus/stats/stats_integration_test.go @@ -7,12 +7,15 @@ import ( "testing" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/stretchr/testify/assert" ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "prometheus") + f := mbtest.NewEventFetcher(t, getConfig()) event, err := f.Fetch() if !assert.NoError(t, err) { @@ -27,6 +30,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "prometheus") + f := mbtest.NewEventFetcher(t, getConfig()) err := mbtest.WriteEvent(f, t) diff --git a/metricbeat/module/rabbitmq/node/node_integration_test.go b/metricbeat/module/rabbitmq/node/node_integration_test.go index b89cbde9ff9..f7565534616 100644 --- a/metricbeat/module/rabbitmq/node/node_integration_test.go +++ b/metricbeat/module/rabbitmq/node/node_integration_test.go @@ -1,3 +1,5 @@ +// +build integration + package node import ( @@ -5,10 +7,13 @@ import ( "os" "testing" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" ) func TestData(t *testing.T) { + compose.EnsureUp(t, "rabbitmq") + f := mbtest.NewEventsFetcher(t, getConfig()) err := mbtest.WriteEvents(f, t) if err != nil { diff --git a/metricbeat/module/redis/info/info_integration_test.go b/metricbeat/module/redis/info/info_integration_test.go index 783b8037ddd..9606105b35b 100644 --- a/metricbeat/module/redis/info/info_integration_test.go +++ b/metricbeat/module/redis/info/info_integration_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/beats/metricbeat/module/redis" @@ -20,6 +21,8 @@ const ( var redisHost = redis.GetRedisEnvHost() + ":" + redis.GetRedisEnvPort() func TestFetch(t *testing.T) { + compose.EnsureUp(t, "redis") + f := mbtest.NewEventFetcher(t, getConfig("")) event, err := f.Fetch() if err != nil { @@ -35,6 +38,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "redis") + f := mbtest.NewEventFetcher(t, getConfig("")) err := mbtest.WriteEvent(f, t) @@ -44,6 +49,8 @@ func TestData(t *testing.T) { } func TestPasswords(t *testing.T) { + compose.EnsureUp(t, "redis") + // Add password and ensure it gets reset defer func() { err := resetPassword(redisHost, password) diff --git a/metricbeat/module/redis/keyspace/keyspace_integration_test.go b/metricbeat/module/redis/keyspace/keyspace_integration_test.go index 5db1d645e31..6df01f6e081 100644 --- a/metricbeat/module/redis/keyspace/keyspace_integration_test.go +++ b/metricbeat/module/redis/keyspace/keyspace_integration_test.go @@ -6,6 +6,7 @@ import ( "strings" "testing" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/beats/metricbeat/module/redis" @@ -16,6 +17,8 @@ import ( var host = redis.GetRedisEnvHost() + ":" + redis.GetRedisEnvPort() func TestFetch(t *testing.T) { + compose.EnsureUp(t, "redis") + addEntry(t) // Fetch data @@ -39,6 +42,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "redis") + addEntry(t) f := mbtest.NewEventsFetcher(t, getConfig()) diff --git a/metricbeat/module/zookeeper/mntr/mntr_integration_test.go b/metricbeat/module/zookeeper/mntr/mntr_integration_test.go index 065eda1971e..7a7b3535798 100644 --- a/metricbeat/module/zookeeper/mntr/mntr_integration_test.go +++ b/metricbeat/module/zookeeper/mntr/mntr_integration_test.go @@ -8,11 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/tests/compose" mbtest "github.com/elastic/beats/metricbeat/mb/testing" "github.com/elastic/beats/metricbeat/module/zookeeper" ) func TestFetch(t *testing.T) { + compose.EnsureUp(t, "zookeeper") + f := mbtest.NewEventFetcher(t, getConfig()) event, err := f.Fetch() if !assert.NoError(t, err) { @@ -37,6 +40,8 @@ func TestFetch(t *testing.T) { } func TestData(t *testing.T) { + compose.EnsureUp(t, "zookeeper") + f := mbtest.NewEventFetcher(t, getConfig()) err := mbtest.WriteEvent(f, t) From 25ce8a9636613713d9f0e703a30df9905361859d Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Thu, 31 Aug 2017 09:28:58 +0200 Subject: [PATCH 139/139] Improve log message for metrics endpoint (#5038) The previous log message was too crpytic. --- libbeat/api/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbeat/api/server.go b/libbeat/api/server.go index 59f3ff8143f..1da3d3f4348 100644 --- a/libbeat/api/server.go +++ b/libbeat/api/server.go @@ -28,7 +28,7 @@ func Start(cfg *common.Config, info beat.Info) { mux.HandleFunc("/stats", statsHandler) url := config.Host + ":" + strconv.Itoa(config.Port) - logp.Info("URL: %s", url) + logp.Info("Metrics endpoint listening on: %s", url) endpoint := http.ListenAndServe(url, mux) logp.Info("finished starting stats endpoint: %v", endpoint) }()