diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 652cca03629c..b6f0ac1848a0 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -165,6 +165,7 @@ https://github.com/elastic/beats/compare/v6.6.0...6.x[Check the HEAD diff] - Remove experimental tag from ceph metricsets. {pull}9708[9708] - Add `key` metricset to the Redis module. {issue}9582[9582] {pull}9657[9657] - Add DeDot for kubernetes labels and annotations. {issue}9860[9860] {pull}9939[9939] +- Add docker `event` metricset. {pull}9856[9856] - Release Ceph module as GA. {pull}10202[10202] - Release windows Metricbeat module as GA. {pull}10163[10163] - Release traefik Metricbeat module as GA. {pull}10166[10166] diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 420f64f2ed6f..10841227375a 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -2996,6 +2996,90 @@ type: scaled_float Number of reads and writes per second +-- + +[float] +== event fields + +Docker event + + + +*`docker.event.status`*:: ++ +-- +type: keyword + +Event status + + +-- + +*`docker.event.id`*:: ++ +-- +type: keyword + +Event id when available + + +-- + +*`docker.event.from`*:: ++ +-- +type: keyword + +Event source + + +-- + +*`docker.event.type`*:: ++ +-- +type: keyword + +The type of object emitting the event + + +-- + +*`docker.event.action`*:: ++ +-- +type: keyword + +The type of event + + +-- + +[float] +== actor fields + +Actor + + + +*`docker.event.actor.id`*:: ++ +-- +type: keyword + +The ID of the object emitting the event + + +-- + +*`docker.event.actor.attributes`*:: ++ +-- +type: object + +Various key/value attributes of the object, depending on its type + + -- [float] diff --git a/metricbeat/docs/modules/docker.asciidoc b/metricbeat/docs/modules/docker.asciidoc index 689b1d31de11..b6c042364751 100644 --- a/metricbeat/docs/modules/docker.asciidoc +++ b/metricbeat/docs/modules/docker.asciidoc @@ -38,6 +38,7 @@ metricbeat.modules: - "container" - "cpu" - "diskio" + - "event" - "healthcheck" - "info" #- "image" @@ -71,6 +72,8 @@ The following metricsets are available: * <> +* <> + * <> * <> @@ -87,6 +90,8 @@ include::docker/cpu.asciidoc[] include::docker/diskio.asciidoc[] +include::docker/event.asciidoc[] + include::docker/healthcheck.asciidoc[] include::docker/image.asciidoc[] diff --git a/metricbeat/docs/modules/docker/event.asciidoc b/metricbeat/docs/modules/docker/event.asciidoc new file mode 100644 index 000000000000..fd187b0fb3bf --- /dev/null +++ b/metricbeat/docs/modules/docker/event.asciidoc @@ -0,0 +1,21 @@ +//// +This file is generated! See scripts/docs_collector.py +//// + +[[metricbeat-metricset-docker-event]] +=== Docker event metricset + +include::../../../module/docker/event/_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/docker/event/_meta/data.json[] +---- diff --git a/metricbeat/docs/modules_list.asciidoc b/metricbeat/docs/modules_list.asciidoc index 89bfb8900c1c..4e87e4ad0085 100644 --- a/metricbeat/docs/modules_list.asciidoc +++ b/metricbeat/docs/modules_list.asciidoc @@ -22,9 +22,10 @@ This file is generated! See scripts/docs_collector.py |<> |<> |<> |image:./images/icon-yes.png[Prebuilt dashboards are available] | -.8+| .8+| |<> +.9+| .9+| |<> |<> |<> +|<> |<> |<> |<> diff --git a/metricbeat/include/list.go b/metricbeat/include/list.go index e2afb2060f6a..f08861b04c21 100644 --- a/metricbeat/include/list.go +++ b/metricbeat/include/list.go @@ -46,6 +46,7 @@ import ( _ "github.com/elastic/beats/metricbeat/module/docker/container" _ "github.com/elastic/beats/metricbeat/module/docker/cpu" _ "github.com/elastic/beats/metricbeat/module/docker/diskio" + _ "github.com/elastic/beats/metricbeat/module/docker/event" _ "github.com/elastic/beats/metricbeat/module/docker/healthcheck" _ "github.com/elastic/beats/metricbeat/module/docker/image" _ "github.com/elastic/beats/metricbeat/module/docker/info" diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index 7ad5f978baef..7a1aeb670555 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -167,6 +167,7 @@ metricbeat.modules: - "container" - "cpu" - "diskio" + - "event" - "healthcheck" - "info" #- "image" diff --git a/metricbeat/module/docker/_meta/config.reference.yml b/metricbeat/module/docker/_meta/config.reference.yml index 2ac7c913ab32..f651b1385afa 100644 --- a/metricbeat/module/docker/_meta/config.reference.yml +++ b/metricbeat/module/docker/_meta/config.reference.yml @@ -3,6 +3,7 @@ - "container" - "cpu" - "diskio" + - "event" - "healthcheck" - "info" #- "image" diff --git a/metricbeat/module/docker/_meta/config.yml b/metricbeat/module/docker/_meta/config.yml index 44d6b61b58b7..340f2106bfc5 100644 --- a/metricbeat/module/docker/_meta/config.yml +++ b/metricbeat/module/docker/_meta/config.yml @@ -3,6 +3,7 @@ # - container # - cpu # - diskio + # - event # - healthcheck # - info # - memory diff --git a/metricbeat/module/docker/event/_meta/data.json b/metricbeat/module/docker/event/_meta/data.json new file mode 100644 index 000000000000..57d7046a35c9 --- /dev/null +++ b/metricbeat/module/docker/event/_meta/data.json @@ -0,0 +1,29 @@ +{ + "@timestamp": "2017-10-12T08:05:34.853Z", + "agent": { + "hostname": "host.example.com", + "name": "host.example.com" + }, + "docker": { + "event": { + "action": "pull", + "actor": { + "attributes": { + "name": "busybox" + }, + "id": "busybox:latest" + }, + "from": "", + "id": "busybox:latest", + "status": "pull", + "type": "image" + } + }, + "event": { + "dataset": "event", + "module": "docker" + }, + "service": { + "type": "docker" + } +} \ No newline at end of file diff --git a/metricbeat/module/docker/event/_meta/docs.asciidoc b/metricbeat/module/docker/event/_meta/docs.asciidoc new file mode 100644 index 000000000000..0d4cc7a3db3f --- /dev/null +++ b/metricbeat/module/docker/event/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the event metricset of the module docker. diff --git a/metricbeat/module/docker/event/_meta/fields.yml b/metricbeat/module/docker/event/_meta/fields.yml new file mode 100644 index 000000000000..d765fad81e7d --- /dev/null +++ b/metricbeat/module/docker/event/_meta/fields.yml @@ -0,0 +1,40 @@ +- name: event + type: group + description: > + Docker event + release: ga + fields: + - name: status + type: keyword + description: > + Event status + - name: id + type: keyword + description: > + Event id when available + - name: from + type: keyword + description: > + Event source + - name: type + type: keyword + description: > + The type of object emitting the event + - name: action + type: keyword + description: > + The type of event + - name: actor + type: group + description: > + Actor + fields: + - name: id + type: keyword + description: > + The ID of the object emitting the event + - name: attributes + type: object + object_type: keyword + description: > + Various key/value attributes of the object, depending on its type diff --git a/metricbeat/module/docker/event/event.go b/metricbeat/module/docker/event/event.go new file mode 100644 index 000000000000..cae7ceaa561e --- /dev/null +++ b/metricbeat/module/docker/event/event.go @@ -0,0 +1,137 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package event + +import ( + "context" + "fmt" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/events" + "github.com/docker/docker/client" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/metricbeat/mb" + "github.com/elastic/beats/metricbeat/module/docker" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet("docker", "event", New, + mb.WithHostParser(docker.HostParser), + mb.DefaultMetricSet(), + ) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + dockerClient *client.Client + dedot bool + logger *logp.Logger +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + config := docker.DefaultConfig() + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + + client, err := docker.NewDockerClient(base.HostData().URI, config) + if err != nil { + return nil, err + } + + return &MetricSet{ + BaseMetricSet: base, + dockerClient: client, + dedot: config.DeDot, + logger: logp.NewLogger("docker"), + }, nil +} + +// Run listens for docker events and reports them +func (m *MetricSet) Run(reporter mb.PushReporterV2) { + ctx, cancel := context.WithCancel(context.Background()) + options := types.EventsOptions{ + Since: fmt.Sprintf("%d", time.Now().Unix()), + } + + defer m.dockerClient.Close() + + for { + events, errors := m.dockerClient.Events(ctx, options) + + WATCH: + for { + select { + case event := <-events: + m.logger.Debug("Got a new docker event: %v", event) + m.reportEvent(reporter, event) + + case err := <-errors: + // Restart watch call + m.logger.Error("Error watching for docker events: %v", err) + time.Sleep(1 * time.Second) + break WATCH + + case <-reporter.Done(): + m.logger.Debug("docker", "event watcher stopped") + cancel() + return + } + } + } +} + +func (m *MetricSet) reportEvent(reporter mb.PushReporterV2, event events.Message) { + time := time.Unix(event.Time, 0) + + attributes := make(map[string]string, len(event.Actor.Attributes)) + for k, v := range event.Actor.Attributes { + if m.dedot { + k = common.DeDot(k) + } + attributes[k] = v + } + + reporter.Event(mb.Event{ + Timestamp: time, + MetricSetFields: common.MapStr{ + "id": event.ID, + "type": event.Type, + "action": event.Action, + "status": event.Status, + "from": event.From, + "actor": common.MapStr{ + "id": event.Actor.ID, + "attributes": attributes, + }, + }, + }) +} diff --git a/metricbeat/module/docker/event/event_integration_test.go b/metricbeat/module/docker/event/event_integration_test.go new file mode 100644 index 000000000000..361cb0e5c95a --- /dev/null +++ b/metricbeat/module/docker/event/event_integration_test.go @@ -0,0 +1,102 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// +build integration + +package event + +import ( + "io" + "os" + "testing" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/client" + "golang.org/x/net/context" + + "github.com/elastic/beats/auditbeat/core" + "github.com/elastic/beats/metricbeat/mb" + mbtest "github.com/elastic/beats/metricbeat/mb/testing" +) + +func TestData(t *testing.T) { + ms := mbtest.NewPushMetricSetV2(t, getConfig()) + var events []mb.Event + done := make(chan interface{}) + go func() { + events = mbtest.RunPushMetricSetV2(10*time.Second, 1, ms) + close(done) + }() + + createEvent(t) + <-done + + if len(events) == 0 { + t.Fatal("received no events") + } + assertNoErrors(t, events) + + beatEvent := mbtest.StandardizeEvent(ms, events[0], core.AddDatasetToEvent) + mbtest.WriteEventToDataJSON(t, beatEvent, "") +} + +func assertNoErrors(t *testing.T, events []mb.Event) { + t.Helper() + + for _, e := range events { + t.Log(e) + + if e.Error != nil { + t.Errorf("received error: %+v", e.Error) + } + } +} + +func createEvent(t *testing.T) { + client, err := client.NewEnvClient() + if err != nil { + t.Fatal(err) + } + defer client.Close() + + reader, err := client.ImagePull(context.Background(), "busybox", types.ImagePullOptions{}) + if err != nil { + t.Fatal(err) + } + io.Copy(os.Stdout, reader) + reader.Close() + + resp, err := client.ContainerCreate(context.Background(), &container.Config{ + Image: "busybox", + Cmd: []string{"echo", "foo"}, + }, nil, nil, "") + if err != nil { + t.Fatal(err) + } + + client.ContainerRemove(context.Background(), resp.ID, types.ContainerRemoveOptions{}) +} + +func getConfig() map[string]interface{} { + return map[string]interface{}{ + "module": "docker", + "metricsets": []string{"event"}, + "hosts": []string{"unix:///var/run/docker.sock"}, + } +} diff --git a/metricbeat/module/docker/fields.go b/metricbeat/module/docker/fields.go index 328b9faee890..7f4db8ce4e65 100644 --- a/metricbeat/module/docker/fields.go +++ b/metricbeat/module/docker/fields.go @@ -31,5 +31,5 @@ func init() { // Asset returns asset data func Asset() string { - return "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" + return "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" } diff --git a/metricbeat/modules.d/docker.yml.disabled b/metricbeat/modules.d/docker.yml.disabled index a8349d7372a7..d613799a844b 100644 --- a/metricbeat/modules.d/docker.yml.disabled +++ b/metricbeat/modules.d/docker.yml.disabled @@ -6,6 +6,7 @@ # - container # - cpu # - diskio + # - event # - healthcheck # - info # - memory diff --git a/metricbeat/tests/system/test_docker.py b/metricbeat/tests/system/test_docker.py index df0e615e8743..c757eea06f64 100644 --- a/metricbeat/tests/system/test_docker.py +++ b/metricbeat/tests/system/test_docker.py @@ -210,6 +210,32 @@ def test_image_fields(self): self.assert_fields_are_documented(evt) + @unittest.skipUnless(metricbeat.INTEGRATION_TESTS, "integration test") + def test_event_fields(self): + """ + test event fields + """ + self.render_config_template(modules=[{ + "name": "docker", + "metricsets": ["event"], + "hosts": ["unix:///var/run/docker.sock"], + "period": "10s", + }]) + + proc = self.start_beat() + self.wait_until(lambda: self.output_lines() > 0, max_timeout=20) + proc.check_kill_and_wait() + self.assert_no_logged_warnings(["Container stopped when recovering stats", + "An error occurred while getting docker stats"]) + + output = self.read_output_json() + evt = output[0] + + if 'attributes' in evt["docker"]["event"]["actor"]: + del evt["docker"]["event"]["actor"]["attributes"] + + self.assert_fields_are_documented(evt) + def remove_labels(self, evt): if 'labels' in evt["docker"]["container"]: diff --git a/x-pack/metricbeat/metricbeat.reference.yml b/x-pack/metricbeat/metricbeat.reference.yml index f5d0c180d03f..845bc706fd16 100644 --- a/x-pack/metricbeat/metricbeat.reference.yml +++ b/x-pack/metricbeat/metricbeat.reference.yml @@ -167,6 +167,7 @@ metricbeat.modules: - "container" - "cpu" - "diskio" + - "event" - "healthcheck" - "info" #- "image"