From 059917ec6025fe5214ec4ed4ae3efa81f6a62d47 Mon Sep 17 00:00:00 2001 From: beats-jenkins Date: Fri, 8 Feb 2019 10:02:22 +0100 Subject: [PATCH 1/6] [Metricbeat] Simplify testing http Metricbeat modules Currently most modules are tested against a docker container. This leads to long setup times and potentially flakyness. Also it requires additional setup to test actual changes on a module without running CI. The goal of this PR is to reduce this overhead, make it possible to easily test new data sets without having to write go code. Expected files were added to verify that changes had no effect on the generated data. The tests with the environment are still needed but should become less critical during development. The structure and logic is inspired by the testing of the Filebeat modules. So far 3 metricsets were convert to test the implementation. It's all based on conventions: * Tests outputs from a JSON endpoint must go int `_meta/testdata` * A `testdata/config.yml` file must exists to specify url under which the testdata should be served * A golden files is generated by adding `-expected.json`. For a metricset to be converted it must have the reporter interface, be http and json based and only have 1 endpoint requested at the time. All metricsets should be converted to the reporter interface. As there is now a more global view on the testing of a metricset, this code can potentially also take over the check to make sure that all fields are documented or at least the generated files can be used to do these checks. To support metricsets which generate one or multiple events the output is always an array of JSON objects. These arrays can also contain errors, meaning also invalid data can be tested. The `data.json` we had so far was hard to update and changed every time it was updated because it was pulled from a life instance. For the metricsets that are switched over to this testing, it's not the case anymore. The `data.json` is generated from the first event in the `docs.json`. This is by convention and allows to have a `docs.json` with a specially interesting event. This should make condition checks for which event should be shown also partially obsolete. Future work: * Support multiple endpoints: Elasticsearch metricsets do not work with the above model yet as they need multiple endpoints to be available at the same time. Config options for this could be introduced. * Support more then .json: Currently only .json is supported. More config options could be added to support other data formats for example for the apache module * Support other protocols then http: Not all modules are http based, 2-3 other comments protocols could be added. * Extend with additional config options: Some metricsets need additional config options to be set for testing. It should be possible to pass these as part of the config.yml file. The overall goal of all the above is to have Metricbeat modules more and more config based instead of golang code based. --- metricbeat/mb/testing/data_generator.go | 5 - metricbeat/mb/testing/data_test.go | 164 ++++++++++++++++++ .../module/kibana/status/_meta/data.json | 18 +- .../kibana/status/_meta/testdata/config.yml | 1 + .../kibana/status/_meta/testdata/docs.json | 95 ++++++++++ .../kibana/status/status_integration_test.go | 11 -- .../rabbitmq/connection/_meta/data.json | 8 +- .../connection/_meta/testdata/config.yml | 1 + .../connection/_meta/testdata/docs.json | 116 +++++++++++++ .../rabbitmq/connection/connection_test.go | 11 -- .../module/traefik/health/_meta/data.json | 28 +-- .../traefik/health/_meta/testdata/config.yml | 2 + .../traefik/health/_meta/testdata/docs.json | 18 ++ .../traefik/health/health_integration_test.go | 10 -- 14 files changed, 422 insertions(+), 66 deletions(-) create mode 100644 metricbeat/mb/testing/data_test.go create mode 100644 metricbeat/module/kibana/status/_meta/testdata/config.yml create mode 100644 metricbeat/module/kibana/status/_meta/testdata/docs.json create mode 100644 metricbeat/module/rabbitmq/connection/_meta/testdata/config.yml create mode 100644 metricbeat/module/rabbitmq/connection/_meta/testdata/docs.json create mode 100644 metricbeat/module/traefik/health/_meta/testdata/config.yml create mode 100644 metricbeat/module/traefik/health/_meta/testdata/docs.json diff --git a/metricbeat/mb/testing/data_generator.go b/metricbeat/mb/testing/data_generator.go index 2d327507dec2..7677b0dd05cb 100644 --- a/metricbeat/mb/testing/data_generator.go +++ b/metricbeat/mb/testing/data_generator.go @@ -149,11 +149,6 @@ func StandardizeEvent(ms mb.MetricSet, e mb.Event, modifiers ...mb.EventModifier fullEvent := e.BeatEvent(ms.Module().Name(), ms.Name(), modifiers...) - fullEvent.Fields["agent"] = common.MapStr{ - "name": "host.example.com", - "hostname": "host.example.com", - } - return fullEvent } diff --git a/metricbeat/mb/testing/data_test.go b/metricbeat/mb/testing/data_test.go new file mode 100644 index 000000000000..150d901e7414 --- /dev/null +++ b/metricbeat/mb/testing/data_test.go @@ -0,0 +1,164 @@ +package testing + +import ( + "encoding/json" + "flag" + "io/ioutil" + "log" + "net/http" + "net/http/httptest" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "gopkg.in/yaml.v2" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/metricbeat/mb" + + // TODO: generate include file for these tests automatically moving forward + _ "github.com/elastic/beats/metricbeat/module/kibana/status" + _ "github.com/elastic/beats/metricbeat/module/rabbitmq/connection" + _ "github.com/elastic/beats/metricbeat/module/traefik/health" +) + +var ( + // Use `go test -generate` to update files. + generateFlag = flag.Bool("generate", false, "Write golden files") +) + +type Config struct { + Type string + URL string +} + +func TestAll(t *testing.T) { + + configFiles, _ := filepath.Glob("../../module/*/*/_meta/testdata/config.yml") + + for _, f := range configFiles { + // get module and metricset name from path + s := strings.Split(f, "/") + moduleName := s[3] + metricSetName := s[4] + + configFile, err := ioutil.ReadFile(f) + if err != nil { + log.Printf("yamlFile.Get err #%v ", err) + } + var config Config + err = yaml.Unmarshal(configFile, &config) + if err != nil { + log.Fatalf("Unmarshal: %v", err) + } + + getTestdataFiles(t, config.URL, moduleName, metricSetName) + } +} + +func getTestdataFiles(t *testing.T, url, module, metricSet string) { + + ff, _ := filepath.Glob("../../module/" + module + "/" + metricSet + "/_meta/testdata/*.json") + var files []string + for _, f := range ff { + // Exclude all the expected files + if strings.HasSuffix(f, "-expected.json") { + continue + } + files = append(files, f) + } + + for _, f := range files { + t.Run(f, func(t *testing.T) { + runTest(t, f, module, metricSet, url) + }) + } +} + +func runTest(t *testing.T, file string, module, metricSetName, url string) { + + // starts a server serving the given file under the given url + s := server(t, file, url) + defer s.Close() + + metricSet := NewReportingMetricSetV2(t, getConfig(module, metricSetName, s.URL)) + events, errs := ReportingFetchV2(metricSet) + + // Gather errors to build also error events + for _, e := range errs { + // TODO: for errors strip out and standardise the URL error as it would create a different diff every time + events = append(events, mb.Event{Error: e}) + } + + var data []common.MapStr + + for _, e := range events { + beatEvent := StandardizeEvent(metricSet, e, mb.AddMetricSetInfo) + // Overwrite service.address as the port changes every time + beatEvent.Fields.Put("service.address", "127.0.0.1:55555") + data = append(data, beatEvent.Fields) + } + + output, err := json.MarshalIndent(&data, "", " ") + if err != nil { + t.Fatal(err) + } + + // Overwrites the golden files if run with -generate + if *generateFlag { + if err = ioutil.WriteFile(file+"-expected.json", output, 0644); err != nil { + t.Fatal(err) + } + } + + // Read expected file + expected, err := ioutil.ReadFile(file + "-expected.json") + if err != nil { + t.Fatalf("could not read file: %s", err) + } + + assert.Equal(t, string(expected), string(output)) + + if strings.HasSuffix(file, "docs.json") { + writeDataJSON(t, data[0], module, metricSetName) + } +} + +func writeDataJSON(t *testing.T, data common.MapStr, module, metricSet string) { + // Add hardcoded timestamp + data.Put("@timestamp", "2019-03-01T08:05:34.853Z") + output, err := json.MarshalIndent(&data, "", " ") + if err = ioutil.WriteFile("../../module/"+module+"/"+metricSet+"/_meta/data.json", output, 0644); err != nil { + t.Fatal(err) + } +} + +// GetConfig returns config for elasticsearch module +func getConfig(module, metricSet, url string) map[string]interface{} { + return map[string]interface{}{ + "module": module, + "metricsets": []string{metricSet}, + "hosts": []string{url}, + } +} + +// server starts a server with a mock output +func server(t *testing.T, path string, url string) *httptest.Server { + + body, err := ioutil.ReadFile(path) + if err != nil { + t.Fatalf("could not read file: %s", err) + } + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == url { + w.Header().Set("Content-Type", "application/json;") + w.WriteHeader(200) + w.Write(body) + } else { + w.WriteHeader(404) + } + })) + return server +} diff --git a/metricbeat/module/kibana/status/_meta/data.json b/metricbeat/module/kibana/status/_meta/data.json index 107ec83ab2c9..a83c38e3ee06 100644 --- a/metricbeat/module/kibana/status/_meta/data.json +++ b/metricbeat/module/kibana/status/_meta/data.json @@ -1,9 +1,5 @@ { - "@timestamp": "2017-10-12T08:05:34.853Z", - "agent": { - "hostname": "host.example.com", - "name": "host.example.com" - }, + "@timestamp": "2019-03-01T08:05:34.853Z", "event": { "dataset": "kibana.status", "duration": 115000, @@ -12,13 +8,13 @@ "kibana": { "status": { "metrics": { - "concurrent_connections": 0, + "concurrent_connections": 12, "requests": { - "disconnects": 0, - "total": 0 + "disconnects": 3, + "total": 241 } }, - "name": "Shaunaks-MBP-2", + "name": "ruflin", "status": { "overall": { "state": "green" @@ -30,10 +26,10 @@ "name": "status" }, "service": { - "address": "127.0.0.1:5601", + "address": "127.0.0.1:55555", "id": "5b2de169-2785-441b-ae8c-186a1936b17d", "name": "kibana", "type": "kibana", - "version": "7.0.0" + "version": "6.0.0-alpha1" } } \ No newline at end of file diff --git a/metricbeat/module/kibana/status/_meta/testdata/config.yml b/metricbeat/module/kibana/status/_meta/testdata/config.yml new file mode 100644 index 000000000000..3ed2bfeb2a3d --- /dev/null +++ b/metricbeat/module/kibana/status/_meta/testdata/config.yml @@ -0,0 +1 @@ +url: /api/status diff --git a/metricbeat/module/kibana/status/_meta/testdata/docs.json b/metricbeat/module/kibana/status/_meta/testdata/docs.json new file mode 100644 index 000000000000..9d7f53ba7a2d --- /dev/null +++ b/metricbeat/module/kibana/status/_meta/testdata/docs.json @@ -0,0 +1,95 @@ +{ + "name": "ruflin", + "uuid": "5b2de169-2785-441b-ae8c-186a1936b17d", + "version": { + "number": "6.0.0-alpha1", + "build_hash": "6cb7fec4e154faa0a4a3fee4b33dfef91b9870d9", + "build_number": 8467, + "build_snapshot": false + }, + "status": { + "overall": { + "state": "green", + "title": "Green", + "nickname": "Looking good", + "icon": "success", + "since": "2017-02-17T13:03:36.960Z" + }, + "statuses": [ + { + "id": "ui settings", + "state": "green", + "icon": "success", + "message": "Ready", + "since": "2017-02-17T13:03:40.088Z" + }, + { + "id": "plugin:kibana@6.0.0-alpha1", + "state": "green", + "icon": "success", + "message": "Ready", + "since": "2017-02-17T13:03:36.960Z" + }, + { + "id": "plugin:elasticsearch@6.0.0-alpha1", + "state": "green", + "icon": "success", + "message": "Kibana index ready", + "since": "2017-02-17T13:03:37.265Z" + }, + { + "id": "plugin:thor@6.0.0-alpha1", + "state": "green", + "icon": "success", + "message": "Ready", + "since": "2017-02-17T13:03:37.162Z" + }, + { + "id": "plugin:console@6.0.0-alpha1", + "state": "green", + "icon": "success", + "message": "Ready", + "since": "2017-02-17T13:03:37.210Z" + }, + { + "id": "plugin:timelion@6.0.0-alpha1", + "state": "green", + "icon": "success", + "message": "Ready", + "since": "2017-02-17T13:03:40.047Z" + } + ] + }, + "metrics": { + "last_updated": "2017-02-17T13:05:00.083Z", + "collection_interval_in_millis": 5000, + "uptime_in_millis": 90637, + "process": { + "mem": { + "heap_max_in_bytes": 150245376, + "heap_used_in_bytes": 114918592 + } + }, + "os": { + "cpu": { + "load_average": { + "1m": 7.412109375, + "5m": 5.3896484375, + "15m": 5.3896484375 + } + } + }, + "response_times": { + "avg_in_millis": null, + "max_in_millis": 0 + }, + "requests": { + "total": 241, + "disconnects": 3, + "status_codes": { + + } + }, + "concurrent_connections": 12 + } +} \ No newline at end of file diff --git a/metricbeat/module/kibana/status/status_integration_test.go b/metricbeat/module/kibana/status/status_integration_test.go index 0da01196ff61..a358b27b3ed9 100644 --- a/metricbeat/module/kibana/status/status_integration_test.go +++ b/metricbeat/module/kibana/status/status_integration_test.go @@ -43,14 +43,3 @@ func TestFetch(t *testing.T) { t.Logf("%s/%s event: %+v", f.Module().Name(), f.Name(), events[0].BeatEvent("kibana", "status").Fields.StringToPrint()) } - -func TestData(t *testing.T) { - compose.EnsureUp(t, "elasticsearch", "kibana") - - config := mtest.GetConfig("status") - f := mbtest.NewReportingMetricSetV2(t, config) - err := mbtest.WriteEventsReporterV2(f, t, "") - if err != nil { - t.Fatal("write", err) - } -} diff --git a/metricbeat/module/rabbitmq/connection/_meta/data.json b/metricbeat/module/rabbitmq/connection/_meta/data.json index 73557f2cd696..bc4e2860f3db 100644 --- a/metricbeat/module/rabbitmq/connection/_meta/data.json +++ b/metricbeat/module/rabbitmq/connection/_meta/data.json @@ -1,9 +1,5 @@ { - "@timestamp": "2017-10-12T08:05:34.853Z", - "agent": { - "hostname": "host.example.com", - "name": "host.example.com" - }, + "@timestamp": "2019-03-01T08:05:34.853Z", "event": { "dataset": "rabbitmq.connection", "duration": 115000, @@ -41,7 +37,7 @@ "vhost": "/" }, "service": { - "address": "127.0.0.1:53939", + "address": "127.0.0.1:55555", "type": "rabbitmq" }, "user": { diff --git a/metricbeat/module/rabbitmq/connection/_meta/testdata/config.yml b/metricbeat/module/rabbitmq/connection/_meta/testdata/config.yml new file mode 100644 index 000000000000..dc57676601df --- /dev/null +++ b/metricbeat/module/rabbitmq/connection/_meta/testdata/config.yml @@ -0,0 +1 @@ +url: /api/connections diff --git a/metricbeat/module/rabbitmq/connection/_meta/testdata/docs.json b/metricbeat/module/rabbitmq/connection/_meta/testdata/docs.json new file mode 100644 index 000000000000..f3516fd9dc37 --- /dev/null +++ b/metricbeat/module/rabbitmq/connection/_meta/testdata/docs.json @@ -0,0 +1,116 @@ +[ + { + "reductions_details": { + "rate": 94.8 + }, + "reductions": 356914, + "recv_oct_details": { + "rate": 0 + }, + "recv_oct": 3764, + "send_oct_details": { + "rate": 0 + }, + "send_oct": 3840, + "connected_at": 1519397210964, + "client_properties": { + "product": "https://github.com/streadway/amqp", + "version": "β", + "capabilities": { + "consumer_cancel_notify": true, + "connection.blocked": true + } + }, + "channel_max": 65535, + "frame_max": 131072, + "timeout": 10, + "vhost": "/", + "user": "guest", + "protocol": "AMQP 0-9-1", + "ssl_hash": null, + "ssl_cipher": null, + "ssl_key_exchange": null, + "ssl_protocol": null, + "auth_mechanism": "PLAIN", + "peer_cert_validity": null, + "peer_cert_issuer": null, + "peer_cert_subject": null, + "ssl": false, + "peer_host": "::1", + "host": "::1", + "peer_port": 60938, + "port": 5672, + "name": "[::1]:60938 -> [::1]:5672", + "node": "nodename", + "type": "network", + "garbage_collection": { + "minor_gcs": 228, + "fullsweep_after": 65535, + "min_heap_size": 233, + "min_bin_vheap_size": 46422, + "max_heap_size": 0 + }, + "channels": 8, + "state": "running", + "send_pend": 0, + "send_cnt": 376, + "recv_cnt": 376 + }, + { + "reductions_details": { + "rate": 94.8 + }, + "reductions": 354441, + "recv_oct_details": { + "rate": 0 + }, + "recv_oct": 3057, + "send_oct_details": { + "rate": 0 + }, + "send_oct": 3344, + "connected_at": 1519397211051, + "client_properties": { + "product": "https://github.com/streadway/amqp", + "version": "β", + "capabilities": { + "connection.blocked": true, + "consumer_cancel_notify": true + } + }, + "channel_max": 65535, + "frame_max": 131072, + "timeout": 10, + "vhost": "/", + "user": "guest", + "protocol": "AMQP 0-9-1", + "ssl_hash": null, + "ssl_cipher": null, + "ssl_key_exchange": null, + "ssl_protocol": null, + "auth_mechanism": "PLAIN", + "peer_cert_validity": null, + "peer_cert_issuer": null, + "peer_cert_subject": null, + "ssl": false, + "peer_host": "::1", + "host": "::1", + "peer_port": 60940, + "port": 5672, + "name": "[::1]:60940 -> [::1]:5672", + "node": "nodename", + "type": "network", + "garbage_collection": { + "minor_gcs": 197, + "fullsweep_after": 65535, + "min_heap_size": 233, + "min_bin_vheap_size": 46422, + "max_heap_size": 0 + }, + "channels": 2, + "state": "running", + "send_pend": 0, + "send_cnt": 352, + "recv_cnt": 352 + } +] diff --git a/metricbeat/module/rabbitmq/connection/connection_test.go b/metricbeat/module/rabbitmq/connection/connection_test.go index af5e5ea7d982..37942e237ef3 100644 --- a/metricbeat/module/rabbitmq/connection/connection_test.go +++ b/metricbeat/module/rabbitmq/connection/connection_test.go @@ -65,17 +65,6 @@ func TestFetchEventContents(t *testing.T) { assert.EqualValues(t, 60938, peer["port"]) } -func TestData(t *testing.T) { - server := mtest.Server(t, mtest.DefaultServerConfig) - defer server.Close() - - ms := mbtest.NewReportingMetricSetV2(t, getConfig(server.URL)) - err := mbtest.WriteEventsReporterV2(ms, t, "") - if err != nil { - t.Fatal("write", err) - } -} - func getConfig(url string) map[string]interface{} { return map[string]interface{}{ "module": "rabbitmq", diff --git a/metricbeat/module/traefik/health/_meta/data.json b/metricbeat/module/traefik/health/_meta/data.json index 4ec5ad9edeaa..63c20177aa86 100644 --- a/metricbeat/module/traefik/health/_meta/data.json +++ b/metricbeat/module/traefik/health/_meta/data.json @@ -1,28 +1,32 @@ { - "@timestamp": "2017-10-12T08:05:34.853Z", - "beat": { - "hostname": "host.example.com", - "name": "host.example.com" + "@timestamp": "2019-03-01T08:05:34.853Z", + "event": { + "dataset": "traefik.health", + "duration": 115000, + "module": "traefik" }, "metricset": { - "host": "127.0.0.1:8080", - "module": "traefik", - "name": "health", - "rtt": 115 + "name": "health" + }, + "service": { + "address": "127.0.0.1:55555", + "name": "traefik", + "type": "traefik" }, "traefik": { "health": { "response": { "avg_time": { - "us": 32 + "us": 15 }, - "count": 15, + "count": 18, "status_codes": { - "404": 15 + "200": 17, + "404": 1 } }, "uptime": { - "sec": 1944 + "sec": 64283 } } } diff --git a/metricbeat/module/traefik/health/_meta/testdata/config.yml b/metricbeat/module/traefik/health/_meta/testdata/config.yml new file mode 100644 index 000000000000..bd19b1bff609 --- /dev/null +++ b/metricbeat/module/traefik/health/_meta/testdata/config.yml @@ -0,0 +1,2 @@ +type: http +url: "/health" diff --git a/metricbeat/module/traefik/health/_meta/testdata/docs.json b/metricbeat/module/traefik/health/_meta/testdata/docs.json new file mode 100644 index 000000000000..3cb72a73d726 --- /dev/null +++ b/metricbeat/module/traefik/health/_meta/testdata/docs.json @@ -0,0 +1,18 @@ +{ + "pid": 1, + "uptime": "17h51m23.252891567s", + "uptime_sec": 64283.252891567, + "time": "2018-06-27 22:07:28.966768969 +0000 UTC m=+64283.314491879", + "unixtime": 1530137248, + "status_code_count": {}, + "total_status_code_count": { + "200": 17, + "404": 1 + }, + "count": 0, + "total_count": 18, + "total_response_time": "272.119µs", + "total_response_time_sec": 0.000272119, + "average_response_time": "15.117µs", + "average_response_time_sec": 1.5117e-05 +} diff --git a/metricbeat/module/traefik/health/health_integration_test.go b/metricbeat/module/traefik/health/health_integration_test.go index 388921bdd3d2..7147b590c525 100644 --- a/metricbeat/module/traefik/health/health_integration_test.go +++ b/metricbeat/module/traefik/health/health_integration_test.go @@ -64,13 +64,3 @@ func TestFetch(t *testing.T) { badResponseCount, _ := event.MetricSetFields.GetValue("response.status_codes.404") assert.True(t, badResponseCount.(float64) >= 1) } - -func TestData(t *testing.T) { - compose.EnsureUp(t, "traefik") - - ms := mbtest.NewReportingMetricSetV2(t, mtest.GetConfig("health")) - err := mbtest.WriteEventsReporterV2(ms, t, "") - if err != nil { - t.Fatal("write", err) - } -} From 06f0d1f28d4ef8efebad0d0347335df9379c9026 Mon Sep 17 00:00:00 2001 From: beats-jenkins Date: Fri, 8 Feb 2019 15:30:45 +0100 Subject: [PATCH 2/6] add missing files and headers --- metricbeat/mb/testing/data_test.go | 17 + .../kibana/status/_meta/testdata/7.0.0.json | 381 ++++++++++++++++++ .../_meta/testdata/7.0.0.json-expected.json | 36 ++ .../_meta/testdata/docs.json-expected.json | 36 ++ .../_meta/testdata/docs.json-expected.json | 92 +++++ .../_meta/testdata/docs.json-expected.json | 34 ++ 6 files changed, 596 insertions(+) create mode 100644 metricbeat/module/kibana/status/_meta/testdata/7.0.0.json create mode 100644 metricbeat/module/kibana/status/_meta/testdata/7.0.0.json-expected.json create mode 100644 metricbeat/module/kibana/status/_meta/testdata/docs.json-expected.json create mode 100644 metricbeat/module/rabbitmq/connection/_meta/testdata/docs.json-expected.json create mode 100644 metricbeat/module/traefik/health/_meta/testdata/docs.json-expected.json diff --git a/metricbeat/mb/testing/data_test.go b/metricbeat/mb/testing/data_test.go index 150d901e7414..3c49aa2215d7 100644 --- a/metricbeat/mb/testing/data_test.go +++ b/metricbeat/mb/testing/data_test.go @@ -1,3 +1,20 @@ +// 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 testing import ( diff --git a/metricbeat/module/kibana/status/_meta/testdata/7.0.0.json b/metricbeat/module/kibana/status/_meta/testdata/7.0.0.json new file mode 100644 index 000000000000..a5b2e2f0ba11 --- /dev/null +++ b/metricbeat/module/kibana/status/_meta/testdata/7.0.0.json @@ -0,0 +1,381 @@ +{ + "name": "kibana", + "uuid": "8faaec19-e37d-410c-9335-377b016c7aa3", + "version": { + "number": "7.0.0", + "build_hash": "daf19f8a5a4f93632c57f6ec79e81eb53b47118c", + "build_number": 22405, + "build_snapshot": true + }, + "status": { + "overall": { + "state": "green", + "title": "Green", + "nickname": "Looking good", + "icon": "success", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.088Z" + }, + "statuses": [ + { + "id": "plugin:kibana@7.0.0-SNAPSHOT", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.088Z" + }, + { + "id": "plugin:elasticsearch@7.0.0-SNAPSHOT", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:40.099Z" + }, + { + "id": "plugin:xpack_main@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.385Z" + }, + { + "id": "plugin:graph@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.386Z" + }, + { + "id": "plugin:monitoring@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.149Z" + }, + { + "id": "plugin:spaces@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:47.714Z" + }, + { + "id": "plugin:security@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.420Z" + }, + { + "id": "plugin:searchprofiler@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.388Z" + }, + { + "id": "plugin:ml@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.388Z" + }, + { + "id": "plugin:tilemap@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.389Z" + }, + { + "id": "plugin:watcher@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.389Z" + }, + { + "id": "plugin:grokdebugger@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.390Z" + }, + { + "id": "plugin:dashboard_mode@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.257Z" + }, + { + "id": "plugin:logstash@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.391Z" + }, + { + "id": "plugin:beats_management@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.391Z" + }, + { + "id": "plugin:apm@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.298Z" + }, + { + "id": "plugin:tile_map@7.0.0-SNAPSHOT", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.301Z" + }, + { + "id": "plugin:maps@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.420Z" + }, + { + "id": "plugin:interpreter@7.0.0-SNAPSHOT", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.679Z" + }, + { + "id": "plugin:canvas@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.695Z" + }, + { + "id": "plugin:license_management@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.704Z" + }, + { + "id": "plugin:index_management@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.392Z" + }, + { + "id": "plugin:console@7.0.0-SNAPSHOT", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.768Z" + }, + { + "id": "plugin:console_extensions@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.772Z" + }, + { + "id": "plugin:notifications@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.778Z" + }, + { + "id": "plugin:index_lifecycle_management@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.393Z" + }, + { + "id": "plugin:infra@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.844Z" + }, + { + "id": "plugin:task_manager@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.846Z" + }, + { + "id": "plugin:rollup@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.393Z" + }, + { + "id": "plugin:remote_clusters@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.394Z" + }, + { + "id": "plugin:cross_cluster_replication@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:41.395Z" + }, + { + "id": "plugin:upgrade_assistant@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.873Z" + }, + { + "id": "plugin:uptime@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.889Z" + }, + { + "id": "plugin:oss_telemetry@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.893Z" + }, + { + "id": "plugin:metrics@7.0.0-SNAPSHOT", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:39.903Z" + }, + { + "id": "plugin:timelion@7.0.0-SNAPSHOT", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:40.087Z" + }, + { + "id": "plugin:reporting@7.0.0", + "state": "green", + "icon": "success", + "message": "Ready", + "uiColor": "secondary", + "since": "2019-02-08T10:28:45.912Z" + } + ] + }, + "metrics": { + "last_updated": "2019-02-08T10:31:02.548Z", + "collection_interval_in_millis": 5000, + "process": { + "memory": { + "heap": { + "total_in_bytes": 248803328, + "used_in_bytes": 160534512, + "size_limit": 1526909922 + }, + "resident_set_size_in_bytes": 348438528 + }, + "event_loop_delay": 0.14169999957084656, + "pid": 1, + "uptime_in_millis": 171299 + }, + "os": { + "load": { + "1m": 1.73681640625, + "5m": 1.23046875, + "15m": 0.50830078125 + }, + "memory": { + "total_in_bytes": 6246756352, + "free_in_bytes": 1520041984, + "used_in_bytes": 4726714368 + }, + "uptime_in_millis": 122915000, + "platform": "linux", + "platformRelease": "linux-4.9.125-linuxkit", + "distro": "Centos", + "distroRelease": "Centos-7.6.1810", + "cgroup": { + "cpuacct": { + "control_group": "/", + "usage_nanos": 46639670629 + }, + "cpu": { + "control_group": "/", + "cfs_period_micros": 100000, + "cfs_quota_micros": -1, + "stat": { + "number_of_elapsed_periods": 0, + "number_of_times_throttled": 0, + "time_throttled_nanos": 0 + } + } + } + }, + "response_times": { + "avg_in_millis": 7, + "max_in_millis": 9 + }, + "requests": { + "disconnects": 0, + "statusCodes": {}, + "total": 4, + "status_codes": { + "200": 4 + } + }, + "concurrent_connections": 0 + } +} diff --git a/metricbeat/module/kibana/status/_meta/testdata/7.0.0.json-expected.json b/metricbeat/module/kibana/status/_meta/testdata/7.0.0.json-expected.json new file mode 100644 index 000000000000..3ff02d217992 --- /dev/null +++ b/metricbeat/module/kibana/status/_meta/testdata/7.0.0.json-expected.json @@ -0,0 +1,36 @@ +[ + { + "event": { + "dataset": "kibana.status", + "duration": 115000, + "module": "kibana" + }, + "kibana": { + "status": { + "metrics": { + "concurrent_connections": 0, + "requests": { + "disconnects": 0, + "total": 4 + } + }, + "name": "kibana", + "status": { + "overall": { + "state": "green" + } + } + } + }, + "metricset": { + "name": "status" + }, + "service": { + "address": "127.0.0.1:55555", + "id": "8faaec19-e37d-410c-9335-377b016c7aa3", + "name": "kibana", + "type": "kibana", + "version": "7.0.0" + } + } +] \ No newline at end of file diff --git a/metricbeat/module/kibana/status/_meta/testdata/docs.json-expected.json b/metricbeat/module/kibana/status/_meta/testdata/docs.json-expected.json new file mode 100644 index 000000000000..e8243ddc0ec5 --- /dev/null +++ b/metricbeat/module/kibana/status/_meta/testdata/docs.json-expected.json @@ -0,0 +1,36 @@ +[ + { + "event": { + "dataset": "kibana.status", + "duration": 115000, + "module": "kibana" + }, + "kibana": { + "status": { + "metrics": { + "concurrent_connections": 12, + "requests": { + "disconnects": 3, + "total": 241 + } + }, + "name": "ruflin", + "status": { + "overall": { + "state": "green" + } + } + } + }, + "metricset": { + "name": "status" + }, + "service": { + "address": "127.0.0.1:55555", + "id": "5b2de169-2785-441b-ae8c-186a1936b17d", + "name": "kibana", + "type": "kibana", + "version": "6.0.0-alpha1" + } + } +] \ No newline at end of file diff --git a/metricbeat/module/rabbitmq/connection/_meta/testdata/docs.json-expected.json b/metricbeat/module/rabbitmq/connection/_meta/testdata/docs.json-expected.json new file mode 100644 index 000000000000..be42aafd8466 --- /dev/null +++ b/metricbeat/module/rabbitmq/connection/_meta/testdata/docs.json-expected.json @@ -0,0 +1,92 @@ +[ + { + "event": { + "dataset": "rabbitmq.connection", + "duration": 115000, + "module": "rabbitmq" + }, + "metricset": { + "name": "connection" + }, + "rabbitmq": { + "connection": { + "channel_max": 65535, + "channels": 8, + "frame_max": 131072, + "host": "::1", + "name": "[::1]:60938 -\u003e [::1]:5672", + "octet_count": { + "received": 3764, + "sent": 3840 + }, + "packet_count": { + "pending": 0, + "received": 376, + "sent": 376 + }, + "peer": { + "host": "::1", + "port": 60938 + }, + "port": 5672, + "type": "network" + }, + "node": { + "name": "nodename" + }, + "vhost": "/" + }, + "service": { + "address": "127.0.0.1:55555", + "type": "rabbitmq" + }, + "user": { + "name": "guest" + } + }, + { + "event": { + "dataset": "rabbitmq.connection", + "duration": 115000, + "module": "rabbitmq" + }, + "metricset": { + "name": "connection" + }, + "rabbitmq": { + "connection": { + "channel_max": 65535, + "channels": 2, + "frame_max": 131072, + "host": "::1", + "name": "[::1]:60940 -\u003e [::1]:5672", + "octet_count": { + "received": 3057, + "sent": 3344 + }, + "packet_count": { + "pending": 0, + "received": 352, + "sent": 352 + }, + "peer": { + "host": "::1", + "port": 60940 + }, + "port": 5672, + "type": "network" + }, + "node": { + "name": "nodename" + }, + "vhost": "/" + }, + "service": { + "address": "127.0.0.1:55555", + "type": "rabbitmq" + }, + "user": { + "name": "guest" + } + } +] \ No newline at end of file diff --git a/metricbeat/module/traefik/health/_meta/testdata/docs.json-expected.json b/metricbeat/module/traefik/health/_meta/testdata/docs.json-expected.json new file mode 100644 index 000000000000..4ae2adae93f8 --- /dev/null +++ b/metricbeat/module/traefik/health/_meta/testdata/docs.json-expected.json @@ -0,0 +1,34 @@ +[ + { + "event": { + "dataset": "traefik.health", + "duration": 115000, + "module": "traefik" + }, + "metricset": { + "name": "health" + }, + "service": { + "address": "127.0.0.1:55555", + "name": "traefik", + "type": "traefik" + }, + "traefik": { + "health": { + "response": { + "avg_time": { + "us": 15 + }, + "count": 18, + "status_codes": { + "200": 17, + "404": 1 + } + }, + "uptime": { + "sec": 64283 + } + } + } + } +] \ No newline at end of file From bf7b30d6453c7773ada91ca29606115397359e1c Mon Sep 17 00:00:00 2001 From: beats-jenkins Date: Tue, 12 Feb 2019 10:32:38 +0100 Subject: [PATCH 3/6] apply review feedback --- metricbeat/mb/testing/data_test.go | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/metricbeat/mb/testing/data_test.go b/metricbeat/mb/testing/data_test.go index 3c49aa2215d7..cfc5e4141ec4 100644 --- a/metricbeat/mb/testing/data_test.go +++ b/metricbeat/mb/testing/data_test.go @@ -40,6 +40,10 @@ import ( _ "github.com/elastic/beats/metricbeat/module/traefik/health" ) +const ( + expectedExtension = "-expected.json" +) + var ( // Use `go test -generate` to update files. generateFlag = flag.Bool("generate", false, "Write golden files") @@ -52,11 +56,11 @@ type Config struct { func TestAll(t *testing.T) { - configFiles, _ := filepath.Glob("../../module/*/*/_meta/testdata/config.yml") + configFiles, _ := filepath.Glob(getModulesPath() + "/*/*/_meta/testdata/config.yml") for _, f := range configFiles { // get module and metricset name from path - s := strings.Split(f, "/") + s := strings.Split(f, filepath.ToSlash("/")) moduleName := s[3] metricSetName := s[4] @@ -76,11 +80,11 @@ func TestAll(t *testing.T) { func getTestdataFiles(t *testing.T, url, module, metricSet string) { - ff, _ := filepath.Glob("../../module/" + module + "/" + metricSet + "/_meta/testdata/*.json") + ff, _ := filepath.Glob(getMetricsetPath(module, metricSet) + "/_meta/testdata/*.json") var files []string for _, f := range ff { // Exclude all the expected files - if strings.HasSuffix(f, "-expected.json") { + if strings.HasSuffix(f, expectedExtension) { continue } files = append(files, f) @@ -124,13 +128,13 @@ func runTest(t *testing.T, file string, module, metricSetName, url string) { // Overwrites the golden files if run with -generate if *generateFlag { - if err = ioutil.WriteFile(file+"-expected.json", output, 0644); err != nil { + if err = ioutil.WriteFile(file+expectedExtension, output, 0644); err != nil { t.Fatal(err) } } // Read expected file - expected, err := ioutil.ReadFile(file + "-expected.json") + expected, err := ioutil.ReadFile(file + expectedExtension) if err != nil { t.Fatalf("could not read file: %s", err) } @@ -146,7 +150,7 @@ func writeDataJSON(t *testing.T, data common.MapStr, module, metricSet string) { // Add hardcoded timestamp data.Put("@timestamp", "2019-03-01T08:05:34.853Z") output, err := json.MarshalIndent(&data, "", " ") - if err = ioutil.WriteFile("../../module/"+module+"/"+metricSet+"/_meta/data.json", output, 0644); err != nil { + if err = ioutil.WriteFile(getMetricsetPath(module, metricSet)+"/_meta/data.json", output, 0644); err != nil { t.Fatal(err) } } @@ -179,3 +183,15 @@ func server(t *testing.T, path string, url string) *httptest.Server { })) return server } + +func getModulesPath() string { + return "../../module" +} + +func getModulePath(module string) string { + return getModulePath() + "/" + module +} + +func getMetricsetPath(module, metricSet string) string { + return getModulePath(module) + "/" + metricSet +} From 976e12cec2ef4d46cd4b31fe5c9f54e68e4853b1 Mon Sep 17 00:00:00 2001 From: beats-jenkins Date: Fri, 15 Feb 2019 22:17:44 +0100 Subject: [PATCH 4/6] fix typo --- metricbeat/mb/testing/data_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metricbeat/mb/testing/data_test.go b/metricbeat/mb/testing/data_test.go index cfc5e4141ec4..46e74f226f63 100644 --- a/metricbeat/mb/testing/data_test.go +++ b/metricbeat/mb/testing/data_test.go @@ -189,7 +189,7 @@ func getModulesPath() string { } func getModulePath(module string) string { - return getModulePath() + "/" + module + return getModulesPath() + "/" + module } func getMetricsetPath(module, metricSet string) string { From 243a617ab2ecf8323c3a387345aac80d5be5b856 Mon Sep 17 00:00:00 2001 From: beats-jenkins Date: Tue, 5 Mar 2019 10:38:54 +0100 Subject: [PATCH 5/6] debug windows --- metricbeat/mb/testing/data_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/metricbeat/mb/testing/data_test.go b/metricbeat/mb/testing/data_test.go index 46e74f226f63..340a26c7464d 100644 --- a/metricbeat/mb/testing/data_test.go +++ b/metricbeat/mb/testing/data_test.go @@ -20,6 +20,7 @@ package testing import ( "encoding/json" "flag" + "fmt" "io/ioutil" "log" "net/http" @@ -60,6 +61,8 @@ func TestAll(t *testing.T) { for _, f := range configFiles { // get module and metricset name from path + fmt.Println("AAA") + fmt.Println(f) s := strings.Split(f, filepath.ToSlash("/")) moduleName := s[3] metricSetName := s[4] From e17d977dd48d4ef333db2c16f1b7523d83f29a3b Mon Sep 17 00:00:00 2001 From: beats-jenkins Date: Tue, 5 Mar 2019 11:15:24 +0100 Subject: [PATCH 6/6] use path seperator --- metricbeat/mb/testing/data_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/metricbeat/mb/testing/data_test.go b/metricbeat/mb/testing/data_test.go index 340a26c7464d..bc8cc8ab6396 100644 --- a/metricbeat/mb/testing/data_test.go +++ b/metricbeat/mb/testing/data_test.go @@ -20,11 +20,11 @@ package testing import ( "encoding/json" "flag" - "fmt" "io/ioutil" "log" "net/http" "net/http/httptest" + "os" "path/filepath" "strings" "testing" @@ -61,9 +61,7 @@ func TestAll(t *testing.T) { for _, f := range configFiles { // get module and metricset name from path - fmt.Println("AAA") - fmt.Println(f) - s := strings.Split(f, filepath.ToSlash("/")) + s := strings.Split(f, string(os.PathSeparator)) moduleName := s[3] metricSetName := s[4]