From cfc9d4c8043d489269e8d6678b6a567505962b9f Mon Sep 17 00:00:00 2001 From: stuart nelson Date: Wed, 11 Aug 2021 03:13:03 +0200 Subject: [PATCH 01/14] fix output for elastic-agent (#5922) --- beater/otlp/grpc.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/beater/otlp/grpc.go b/beater/otlp/grpc.go index c3d7bca6c2a..4f12ec9f851 100644 --- a/beater/otlp/grpc.go +++ b/beater/otlp/grpc.go @@ -101,6 +101,9 @@ func setCurrentMonitoredConsumer(c *otel.Consumer) { } func collectMetricsMonitoring(mode monitoring.Mode, V monitoring.Visitor) { + V.OnRegistryStart() + defer V.OnRegistryFinished() + currentMonitoredConsumerMu.RLock() c := currentMonitoredConsumer currentMonitoredConsumerMu.RUnlock() @@ -108,9 +111,6 @@ func collectMetricsMonitoring(mode monitoring.Mode, V monitoring.Visitor) { return } - V.OnRegistryStart() - defer V.OnRegistryFinished() - stats := c.Stats() monitoring.ReportInt(V, "unsupported_dropped", stats.UnsupportedMetricsDropped) } From 114d7d62c0c0a8ac0b60d07822cf5efd2ca9cedd Mon Sep 17 00:00:00 2001 From: Andrew Wilkins Date: Wed, 11 Aug 2021 21:37:37 +0800 Subject: [PATCH 02/14] Add `data_streams.wait_for_integration` (#5928) --- beater/beater.go | 96 ++++++++++++++++++++++++++--- beater/config/config_test.go | 11 ++++ beater/config/data_streams.go | 21 ++++++- beater/server_test.go | 42 +++++++++++++ changelogs/head.asciidoc | 1 + docs/configuration-process.asciidoc | 19 ++++++ 6 files changed, 182 insertions(+), 8 deletions(-) diff --git a/beater/beater.go b/beater/beater.go index 8b9ff158514..f25b29b4be5 100644 --- a/beater/beater.go +++ b/beater/beater.go @@ -18,8 +18,11 @@ package beater import ( + "bytes" "context" + "encoding/json" "fmt" + "io/ioutil" "net" "net/http" "os" @@ -28,7 +31,6 @@ import ( "sync" "time" - "github.com/elastic/beats/v7/libbeat/common/fleetmode" "github.com/elastic/beats/v7/libbeat/common/transport" "github.com/elastic/beats/v7/libbeat/common/transport/tlscommon" "github.com/elastic/go-ucfg" @@ -121,9 +123,6 @@ func NewCreator(args CreatorParams) beat.Creator { if b.Manager != nil && b.Manager.Enabled() { return nil, errors.New("data streams must be enabled when the server is managed") } - } else if bt.config.DataStreams.Enabled && !fleetmode.Enabled() { - // not supported only available for development purposes - bt.logger.Errorf("Started apm-server with data streams enabled but no active fleet management mode was specified") } if err := bt.registerPipelineCallback(b); err != nil { @@ -265,7 +264,11 @@ func (r *reloader) reload(rawConfig *common.Config, namespace string, fleetConfi if err != nil { return err } - go runner.run() + go func() { + if err := runner.run(); err != nil { + r.args.Logger.Error(err) + } + }() // If the old runner exists, cancel it if r.runner != nil { r.runner.cancelRunServerContext() @@ -355,19 +358,42 @@ func (s *serverRunner) run() error { Namespace: s.namespace, } + var kibanaClient kibana_client.Client + if s.config.Kibana.Enabled { + kibanaClient = kibana_client.NewConnectingClient(&s.config.Kibana) + } + cfg := ucfg.Config(*s.rawConfig) parentCfg := cfg.Parent() // Check for an environment variable set when running in a cloud environment if eac := os.Getenv("ELASTIC_AGENT_CLOUD"); eac != "" && s.config.Kibana.Enabled { // Don't block server startup sending the config. go func() { - c := kibana_client.NewConnectingClient(&s.config.Kibana) - if err := kibana_client.SendConfig(s.runServerContext, c, parentCfg); err != nil { + if err := kibana_client.SendConfig(s.runServerContext, kibanaClient, parentCfg); err != nil { s.logger.Infof("failed to upload config to kibana: %v", err) } }() } + fleetManaged := s.beat.Manager != nil && s.beat.Manager.Enabled() + if !fleetManaged && s.config.DataStreams.Enabled && s.config.DataStreams.WaitForIntegration { + // TODO(axw) we should also try querying Elasticsearch in parallel + // (e.g. check for an index template created), for the case where + // there is no Kibana configuration. + if !s.config.Kibana.Enabled { + return errors.New("cannot wait for integration without Kibana config") + } + if err := waitForIntegration( + s.runServerContext, + kibanaClient, + s.config.DataStreams.WaitForIntegrationInterval, + s.tracer, + s.logger, + ); err != nil { + return errors.Wrap(err, "error waiting for integration") + } + } + var sourcemapStore *sourcemap.Store if s.config.RumConfig.Enabled && s.config.RumConfig.SourceMapping.Enabled { store, err := newSourcemapStore(s.beat.Info, s.config.RumConfig.SourceMapping, s.fleetConfig) @@ -674,3 +700,59 @@ func (p *reporterBatchProcessor) ProcessBatch(ctx context.Context, batch *model. disableTracing, _ := ctx.Value(disablePublisherTracingKey{}).(bool) return p.reporter(ctx, publish.PendingReq{Transformable: batch, Trace: !disableTracing}) } + +// waitForIntegration waits for the APM integration to be installed by querying Kibana, +// or for the context to be cancelled. +func waitForIntegration( + ctx context.Context, + kibanaClient kibana_client.Client, + interval time.Duration, + tracer *apm.Tracer, + logger *logp.Logger, +) error { + logger.Info("waiting for integration package to be installed") + tx := tracer.StartTransaction("wait_for_integration", "init") + ctx = apm.ContextWithTransaction(ctx, tx) + var ticker *time.Ticker + for { + if ticker == nil { + ticker = time.NewTicker(interval) + defer ticker.Stop() + } else { + select { + case <-ctx.Done(): + return ctx.Err() + case <-ticker.C: + } + } + if checkIntegrationInstalled(ctx, kibanaClient, logger) { + return nil + } + } +} + +func checkIntegrationInstalled(ctx context.Context, kibanaClient kibana_client.Client, logger *logp.Logger) bool { + resp, err := kibanaClient.Send(ctx, "GET", "/api/fleet/epm/packages/apm", nil, nil, nil) + if err != nil { + logger.Errorf("error querying integration package status: %s", err) + return false + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + body, _ := ioutil.ReadAll(resp.Body) + logger.Errorf("unexpected status querying integration package status: %s (%s)", resp.Status, bytes.TrimSpace(body)) + return false + } + var result struct { + Response struct { + Status string `json:"status"` + } `json:"response"` + } + if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { + logger.Errorf("error decoding integration package response: %s", err) + return false + } + logger.Infof("integration package status: %s", result.Response.Status) + return result.Response.Status == "installed" +} diff --git a/beater/config/config_test.go b/beater/config/config_test.go index b316352f553..c095d3ae617 100644 --- a/beater/config/config_test.go +++ b/beater/config/config_test.go @@ -289,6 +289,11 @@ func TestUnpackConfig(t *testing.T) { }, }, DefaultServiceEnvironment: "overridden", + DataStreams: DataStreamsConfig{ + Enabled: false, + WaitForIntegration: true, + WaitForIntegrationInterval: 5 * time.Second, + }, }, }, "merge config with default": { @@ -342,6 +347,7 @@ func TestUnpackConfig(t *testing.T) { "interval": "2m", "ingest_rate_decay": 1.0, }, + "data_streams.wait_for_integration": false, }, outCfg: &Config{ Host: "localhost:3000", @@ -472,6 +478,11 @@ func TestUnpackConfig(t *testing.T) { TTL: 30 * time.Minute, }, }, + DataStreams: DataStreamsConfig{ + Enabled: false, + WaitForIntegration: false, + WaitForIntegrationInterval: 5 * time.Second, + }, }, }, "kibana trailing slash": { diff --git a/beater/config/data_streams.go b/beater/config/data_streams.go index 1faf6144617..a9771e984e0 100644 --- a/beater/config/data_streams.go +++ b/beater/config/data_streams.go @@ -17,11 +17,30 @@ package config +import "time" + // DataStreamsConfig holds data streams configuration. type DataStreamsConfig struct { Enabled bool `config:"enabled"` + + // WaitForIntegration controls whether APM Server waits for the Fleet + // integration package to be installed before indexing events. + // + // This requires a connection to Kibana, and is ignored when running + // under Elastic Agent; it is intended for running APM Server standalone, + // relying on Fleet to install the integration for creating Elasticsearch + // index templates, ILM policies, and ingest pipelines. + WaitForIntegration bool `config:"wait_for_integration"` + + // WaitForIntegrationInterval holds the interval for checks when waiting + // for the integration package to be installed. + WaitForIntegrationInterval time.Duration `config:"wait_for_integration_interval"` } func defaultDataStreamsConfig() DataStreamsConfig { - return DataStreamsConfig{Enabled: false} + return DataStreamsConfig{ + Enabled: false, + WaitForIntegration: true, + WaitForIntegrationInterval: 5 * time.Second, + } } diff --git a/beater/server_test.go b/beater/server_test.go index 9bb6c2fab32..c191891fb44 100644 --- a/beater/server_test.go +++ b/beater/server_test.go @@ -24,6 +24,7 @@ import ( "io/ioutil" "net" "net/http" + "net/http/httptest" "net/url" "os" "reflect" @@ -522,6 +523,47 @@ func TestServerConfigReload(t *testing.T) { assert.Error(t, err) } +func TestServerWaitForIntegration(t *testing.T) { + if testing.Short() { + t.Skip("skipping slow test") + } + + var requests int + mux := http.NewServeMux() + mux.HandleFunc("/api/status", func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(`{"version":{"number":"1.2.3"}}`)) + }) + mux.HandleFunc("/api/fleet/epm/packages/apm", func(w http.ResponseWriter, r *http.Request) { + requests++ + switch requests { + case 1: + w.WriteHeader(500) + case 2: + fmt.Fprintln(w, `{"response":{"status":"not_installed"}}`) + case 3: + fmt.Fprintln(w, `{"response":{"status":"installed"}}`) + } + }) + srv := httptest.NewServer(mux) + defer srv.Close() + + cfg := common.MustNewConfigFrom(map[string]interface{}{ + "data_streams.enabled": true, + "data_streams.wait_for_integration_interval": "100ms", + "kibana.enabled": true, + "kibana.host": srv.URL, + }) + + beat, cfg := newBeat(t, cfg, nil, nil) + tb, err := newTestBeater(t, beat, cfg, nil) + require.NoError(t, err) + tb.start() + + _, err = tb.waitListenAddr(30 * time.Second) + require.NoError(t, err) + assert.Equal(t, 3, requests) +} + type chanClient struct { done chan struct{} Channel chan beat.Event diff --git a/changelogs/head.asciidoc b/changelogs/head.asciidoc index ced33151739..9ff42d6d070 100644 --- a/changelogs/head.asciidoc +++ b/changelogs/head.asciidoc @@ -22,6 +22,7 @@ https://github.com/elastic/apm-server/compare/7.13\...master[View commits] ==== Added - `service_destination` span metrics now take into account composite spans {pull}5896[5896] - add zero-downtime config reloads via `SO_REUSEPORT` {pull}5911[5911] +- experimental support for writing data streams in standalone mode {pull}5928[5928] [float] ==== Deprecated diff --git a/docs/configuration-process.asciidoc b/docs/configuration-process.asciidoc index 0304be8889e..148c2986ab2 100644 --- a/docs/configuration-process.asciidoc +++ b/docs/configuration-process.asciidoc @@ -184,3 +184,22 @@ Default value is 1 second. ==== `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. + +[float] +=== Configuration options: `data_streams` + +experimental::[] + +[[data_streams.enabled]] +[float] +==== `enabled` +Write events to Elasticsearch data streams instead of indices. +Events will be written to `traces-*`, `logs-*`, and `metrics-*` data streams. +Enabling data streams disables the setup of index templates, ILM policies, and ingest pipelines. +Defaults to false. + +[[data_streams.wait_for_integration]] +[float] +==== `wait_for_integration` +Wait for the `apm` Fleet integration to be installed by Kibana. Requires <>. +Defaults to true. From 7e7da2db113b2639f18b7189bdc900dda9240543 Mon Sep 17 00:00:00 2001 From: Andrew Wilkins Date: Fri, 13 Aug 2021 11:38:48 +0800 Subject: [PATCH 03/14] Wait for integration using Elasticsearch queries (#5934) * Wait for integration using Elasticsearch queries Extend `data_streams.wait_for_integration` to use either Kibana or Elasticsearch queries, depending on what is available. If Kibana config is defined, and Kibana can be successfully queried, then it will be used. Otherwise if the Elasticsearch output is configured, Elasticsearch queries will be made to check the presence of index templates which imply the integration has been installed. * Add comment, remove comment --- beater/beater.go | 79 +++------------ beater/config/data_streams.go | 9 +- beater/server_test.go | 46 +++++++-- beater/waitintegration.go | 150 ++++++++++++++++++++++++++++ docs/configuration-process.asciidoc | 3 +- 5 files changed, 208 insertions(+), 79 deletions(-) create mode 100644 beater/waitintegration.go diff --git a/beater/beater.go b/beater/beater.go index f25b29b4be5..9664738b9df 100644 --- a/beater/beater.go +++ b/beater/beater.go @@ -18,11 +18,8 @@ package beater import ( - "bytes" "context" - "encoding/json" "fmt" - "io/ioutil" "net" "net/http" "os" @@ -377,15 +374,25 @@ func (s *serverRunner) run() error { fleetManaged := s.beat.Manager != nil && s.beat.Manager.Enabled() if !fleetManaged && s.config.DataStreams.Enabled && s.config.DataStreams.WaitForIntegration { - // TODO(axw) we should also try querying Elasticsearch in parallel - // (e.g. check for an index template created), for the case where - // there is no Kibana configuration. - if !s.config.Kibana.Enabled { - return errors.New("cannot wait for integration without Kibana config") + var esClient elasticsearch.Client + if cfg := elasticsearchOutputConfig(s.beat); cfg != nil { + esConfig := elasticsearch.DefaultConfig() + err := cfg.Unpack(&esConfig) + if err != nil { + return err + } + esClient, err = elasticsearch.NewClient(esConfig) + if err != nil { + return err + } + } + if kibanaClient == nil && esClient == nil { + return errors.New("cannot wait for integration without either Kibana or Elasticsearch config") } if err := waitForIntegration( s.runServerContext, kibanaClient, + esClient, s.config.DataStreams.WaitForIntegrationInterval, s.tracer, s.logger, @@ -700,59 +707,3 @@ func (p *reporterBatchProcessor) ProcessBatch(ctx context.Context, batch *model. disableTracing, _ := ctx.Value(disablePublisherTracingKey{}).(bool) return p.reporter(ctx, publish.PendingReq{Transformable: batch, Trace: !disableTracing}) } - -// waitForIntegration waits for the APM integration to be installed by querying Kibana, -// or for the context to be cancelled. -func waitForIntegration( - ctx context.Context, - kibanaClient kibana_client.Client, - interval time.Duration, - tracer *apm.Tracer, - logger *logp.Logger, -) error { - logger.Info("waiting for integration package to be installed") - tx := tracer.StartTransaction("wait_for_integration", "init") - ctx = apm.ContextWithTransaction(ctx, tx) - var ticker *time.Ticker - for { - if ticker == nil { - ticker = time.NewTicker(interval) - defer ticker.Stop() - } else { - select { - case <-ctx.Done(): - return ctx.Err() - case <-ticker.C: - } - } - if checkIntegrationInstalled(ctx, kibanaClient, logger) { - return nil - } - } -} - -func checkIntegrationInstalled(ctx context.Context, kibanaClient kibana_client.Client, logger *logp.Logger) bool { - resp, err := kibanaClient.Send(ctx, "GET", "/api/fleet/epm/packages/apm", nil, nil, nil) - if err != nil { - logger.Errorf("error querying integration package status: %s", err) - return false - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - body, _ := ioutil.ReadAll(resp.Body) - logger.Errorf("unexpected status querying integration package status: %s (%s)", resp.Status, bytes.TrimSpace(body)) - return false - } - var result struct { - Response struct { - Status string `json:"status"` - } `json:"response"` - } - if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { - logger.Errorf("error decoding integration package response: %s", err) - return false - } - logger.Infof("integration package status: %s", result.Response.Status) - return result.Response.Status == "installed" -} diff --git a/beater/config/data_streams.go b/beater/config/data_streams.go index a9771e984e0..703fa530431 100644 --- a/beater/config/data_streams.go +++ b/beater/config/data_streams.go @@ -26,10 +26,11 @@ type DataStreamsConfig struct { // WaitForIntegration controls whether APM Server waits for the Fleet // integration package to be installed before indexing events. // - // This requires a connection to Kibana, and is ignored when running - // under Elastic Agent; it is intended for running APM Server standalone, - // relying on Fleet to install the integration for creating Elasticsearch - // index templates, ILM policies, and ingest pipelines. + // This config is ignored when running under Elastic Agent; it is intended + // for running APM Server standalone, relying on Fleet to install the integration + // for creating Elasticsearch index templates, ILM policies, and ingest pipelines. + // + // This configuration requires either a connection to Kibana or Elasticsearch. WaitForIntegration bool `config:"wait_for_integration"` // WaitForIntegrationInterval holds the interval for checks when waiting diff --git a/beater/server_test.go b/beater/server_test.go index c191891fb44..9db35191b49 100644 --- a/beater/server_test.go +++ b/beater/server_test.go @@ -27,8 +27,10 @@ import ( "net/http/httptest" "net/url" "os" + "path" "reflect" "runtime" + "sync" "testing" "time" @@ -523,11 +525,7 @@ func TestServerConfigReload(t *testing.T) { assert.Error(t, err) } -func TestServerWaitForIntegration(t *testing.T) { - if testing.Short() { - t.Skip("skipping slow test") - } - +func TestServerWaitForIntegrationKibana(t *testing.T) { var requests int mux := http.NewServeMux() mux.HandleFunc("/api/status", func(w http.ResponseWriter, r *http.Request) { @@ -553,15 +551,43 @@ func TestServerWaitForIntegration(t *testing.T) { "kibana.enabled": true, "kibana.host": srv.URL, }) + _, err := setupServer(t, cfg, nil, nil) + require.NoError(t, err) + assert.Equal(t, 3, requests) +} + +func TestServerWaitForIntegrationElasticsearch(t *testing.T) { + var mu sync.Mutex + templateRequests := make(map[string]int) + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("X-Elastic-Product", "Elasticsearch") + }) + mux.HandleFunc("/_index_template/", func(w http.ResponseWriter, r *http.Request) { + mu.Lock() + defer mu.Unlock() + template := path.Base(r.URL.Path) + templateRequests[template]++ + if template == "traces-apm" && templateRequests[template] == 1 { + w.WriteHeader(404) + } + }) + srv := httptest.NewServer(mux) + defer srv.Close() - beat, cfg := newBeat(t, cfg, nil, nil) - tb, err := newTestBeater(t, beat, cfg, nil) + cfg := common.MustNewConfigFrom(map[string]interface{}{ + "data_streams.enabled": true, + "data_streams.wait_for_integration_interval": "100ms", + }) + var beatConfig beat.BeatConfig + err := beatConfig.Output.Unpack(common.MustNewConfigFrom(map[string]interface{}{ + "elasticsearch.hosts": []string{srv.URL}, + })) require.NoError(t, err) - tb.start() - _, err = tb.waitListenAddr(30 * time.Second) + _, err = setupServer(t, cfg, &beatConfig, nil) require.NoError(t, err) - assert.Equal(t, 3, requests) + assert.Equal(t, 2, templateRequests["traces-apm"]) } type chanClient struct { diff --git a/beater/waitintegration.go b/beater/waitintegration.go new file mode 100644 index 00000000000..95f1899350e --- /dev/null +++ b/beater/waitintegration.go @@ -0,0 +1,150 @@ +// 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 beater + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "time" + + "github.com/pkg/errors" + "go.elastic.co/apm" + "golang.org/x/sync/errgroup" + + "github.com/elastic/beats/v7/libbeat/logp" + + "github.com/elastic/apm-server/elasticsearch" + "github.com/elastic/apm-server/kibana" + "github.com/elastic/go-elasticsearch/v7/esapi" +) + +// waitForIntegration waits for the APM integration to be installed by querying Kibana, +// or for the context to be cancelled. +func waitForIntegration( + ctx context.Context, + kibanaClient kibana.Client, + esClient elasticsearch.Client, + interval time.Duration, + tracer *apm.Tracer, + logger *logp.Logger, +) error { + logger.Info("waiting for integration package to be installed") + tx := tracer.StartTransaction("wait_for_integration", "init") + ctx = apm.ContextWithTransaction(ctx, tx) + var ticker *time.Ticker + for { + if ticker == nil { + // We start the ticker on the first iteration, rather than + // before the loop, so we don't have to wait for a tick + // (5 seconds by default) before peforming the first check. + ticker = time.NewTicker(interval) + defer ticker.Stop() + } else { + select { + case <-ctx.Done(): + return ctx.Err() + case <-ticker.C: + } + } + if kibanaClient != nil { + installed, err := checkIntegrationInstalledKibana(ctx, kibanaClient, logger) + if err != nil { + logger.Errorf("error querying Kibana for integration package status: %s", err) + } else { + if installed { + return nil + } + // We were able to query Kibana, but the package is not yet installed. + // We should continue querying the package status via Kibana, as it is + // more authoritative than checking for index template installation. + continue + } + } + if esClient != nil { + installed, err := checkIntegrationInstalledElasticsearch(ctx, esClient, logger) + if err != nil { + logger.Errorf("error querying Elasticsearch for integration index templates: %s", err) + } else if installed { + return nil + } + } + } +} + +// checkIntegrationInstalledKibana checks if the APM integration package +// is installed by querying Kibana. +func checkIntegrationInstalledKibana(ctx context.Context, kibanaClient kibana.Client, logger *logp.Logger) (bool, error) { + resp, err := kibanaClient.Send(ctx, "GET", "/api/fleet/epm/packages/apm", nil, nil, nil) + if err != nil { + return false, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + body, _ := ioutil.ReadAll(resp.Body) + return false, fmt.Errorf("unexpected HTTP status: %s (%s)", resp.Status, bytes.TrimSpace(body)) + } + var result struct { + Response struct { + Status string `json:"status"` + } `json:"response"` + } + if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { + return false, errors.Wrap(err, "error decoding integration package response") + } + logger.Infof("integration package status: %s", result.Response.Status) + return result.Response.Status == "installed", nil +} + +func checkIntegrationInstalledElasticsearch(ctx context.Context, esClient elasticsearch.Client, logger *logp.Logger) (bool, error) { + // TODO(axw) generate the list of expected index templates. + templates := []string{ + "traces-apm", + "traces-sampled", + "metrics-apm.app", + "metrics-apm.internal", + "logs-apm.error", + } + // IndicesGetIndexTemplateRequest accepts a slice of template names, + // but the REST API expects just one index template name. Query them + // in parallel. + g, ctx := errgroup.WithContext(ctx) + for _, template := range templates { + template := template // copy for closure + g.Go(func() error { + req := esapi.IndicesGetIndexTemplateRequest{Name: []string{template}} + resp, err := req.Do(ctx, esClient) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.IsError() { + body, _ := ioutil.ReadAll(resp.Body) + return fmt.Errorf("unexpected HTTP status: %s (%s)", resp.Status(), bytes.TrimSpace(body)) + } + return nil + }) + } + err := g.Wait() + return err == nil, err +} diff --git a/docs/configuration-process.asciidoc b/docs/configuration-process.asciidoc index 148c2986ab2..0878c668203 100644 --- a/docs/configuration-process.asciidoc +++ b/docs/configuration-process.asciidoc @@ -201,5 +201,6 @@ Defaults to false. [[data_streams.wait_for_integration]] [float] ==== `wait_for_integration` -Wait for the `apm` Fleet integration to be installed by Kibana. Requires <>. +Wait for the `apm` Fleet integration to be installed by Kibana. Requires either <> +or for the <> to be configured. Defaults to true. From c581b5b5e4476b7811f3cd7465eaac7b396d0165 Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Fri, 13 Aug 2021 03:07:40 -0400 Subject: [PATCH 04/14] Update to elastic/beats@f144f63593df (#5940) Co-authored-by: apmmachine --- NOTICE.txt | 28 ++++++++++++++-------------- go.mod | 15 ++++++++------- go.sum | 28 +++++++++++++++++----------- 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/NOTICE.txt b/NOTICE.txt index ec27dffbe9b..e16cc44aa3d 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -576,11 +576,11 @@ SOFTWARE. -------------------------------------------------------------------------------- Dependency : github.com/elastic/beats/v7 -Version: v7.0.0-alpha2.0.20210805202431-9c57b1ec68c1 +Version: v7.0.0-alpha2.0.20210812232037-f144f63593df Licence type (autodetected): Elastic -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/elastic/beats/v7@v7.0.0-alpha2.0.20210805202431-9c57b1ec68c1/LICENSE.txt: +Contents of probable licence file $GOMODCACHE/github.com/elastic/beats/v7@v7.0.0-alpha2.0.20210812232037-f144f63593df/LICENSE.txt: Source code in this repository is variously licensed under the Apache License Version 2.0, an Apache compatible license, or the Elastic License. Outside of @@ -4864,11 +4864,11 @@ THE SOFTWARE. -------------------------------------------------------------------------------- Dependency : go.uber.org/zap -Version: v1.18.1 +Version: v1.19.0 Licence type (autodetected): MIT -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/go.uber.org/zap@v1.18.1/LICENSE.txt: +Contents of probable licence file $GOMODCACHE/go.uber.org/zap@v1.19.0/LICENSE.txt: Copyright (c) 2016-2017 Uber Technologies, Inc. @@ -5004,11 +5004,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : google.golang.org/grpc -Version: v1.39.1 +Version: v1.40.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/google.golang.org/grpc@v1.39.1/LICENSE: +Contents of probable licence file $GOMODCACHE/google.golang.org/grpc@v1.40.0/LICENSE: Apache License @@ -18787,11 +18787,11 @@ THE SOFTWARE. -------------------------------------------------------------------------------- Dependency : golang.org/x/crypto -Version: v0.0.0-20210711020723-a769d52b0f97 +Version: v0.0.0-20210812204632-0ba0e8f03122 Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/golang.org/x/crypto@v0.0.0-20210711020723-a769d52b0f97/LICENSE: +Contents of probable licence file $GOMODCACHE/golang.org/x/crypto@v0.0.0-20210812204632-0ba0e8f03122/LICENSE: Copyright (c) 2009 The Go Authors. All rights reserved. @@ -18861,11 +18861,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : golang.org/x/sys -Version: v0.0.0-20210806184541-e5e7981a1069 +Version: v0.0.0-20210809222454-d867a43fc93e Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/golang.org/x/sys@v0.0.0-20210806184541-e5e7981a1069/LICENSE: +Contents of probable licence file $GOMODCACHE/golang.org/x/sys@v0.0.0-20210809222454-d867a43fc93e/LICENSE: Copyright (c) 2009 The Go Authors. All rights reserved. @@ -18935,11 +18935,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : golang.org/x/text -Version: v0.3.6 +Version: v0.3.7 Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/golang.org/x/text@v0.3.6/LICENSE: +Contents of probable licence file $GOMODCACHE/golang.org/x/text@v0.3.7/LICENSE: Copyright (c) 2009 The Go Authors. All rights reserved. @@ -18972,11 +18972,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : google.golang.org/genproto -Version: v0.0.0-20210805201207-89edb61ffb67 +Version: v0.0.0-20210811021853-ddbe55d93216 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/google.golang.org/genproto@v0.0.0-20210805201207-89edb61ffb67/LICENSE: +Contents of probable licence file $GOMODCACHE/google.golang.org/genproto@v0.0.0-20210811021853-ddbe55d93216/LICENSE: Apache License diff --git a/go.mod b/go.mod index edbf19657ae..94da41b77d2 100644 --- a/go.mod +++ b/go.mod @@ -9,11 +9,11 @@ require ( github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e github.com/dgraph-io/badger/v2 v2.2007.3-0.20201012072640-f5a7e0a1c83b github.com/dlclark/regexp2 v1.4.0 // indirect - github.com/dop251/goja v0.0.0-20210804101310-32956a348b49 // indirect + github.com/dop251/goja v0.0.0-20210810150349-acd0507c3d6f // indirect github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7 // indirect github.com/dustin/go-humanize v1.0.0 github.com/elastic/apm-server/approvaltest v0.0.0-00010101000000-000000000000 - github.com/elastic/beats/v7 v7.0.0-alpha2.0.20210805202431-9c57b1ec68c1 + github.com/elastic/beats/v7 v7.0.0-alpha2.0.20210812232037-f144f63593df github.com/elastic/ecs v1.10.0 github.com/elastic/gmux v0.1.0 github.com/elastic/go-elasticsearch/v7 v7.5.1-0.20210728153421-6462d8b84e7d @@ -59,15 +59,16 @@ require ( go.opentelemetry.io/collector/model v0.30.0 go.uber.org/atomic v1.9.0 go.uber.org/multierr v1.7.0 // indirect - go.uber.org/zap v1.18.1 - golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect + go.uber.org/zap v1.19.0 + golang.org/x/crypto v0.0.0-20210812204632-0ba0e8f03122 // indirect golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect + golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect + golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 golang.org/x/tools v0.1.5 - google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67 // indirect - google.golang.org/grpc v1.39.1 + google.golang.org/genproto v0.0.0-20210811021853-ddbe55d93216 // indirect + google.golang.org/grpc v1.40.0 gopkg.in/yaml.v2 v2.4.0 gotest.tools/gotestsum v1.7.0 howett.net/plist v0.0.0-20201203080718-1454fab16a06 // indirect diff --git a/go.sum b/go.sum index cad0a287ffc..cfe6553791d 100644 --- a/go.sum +++ b/go.sum @@ -358,8 +358,8 @@ github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFP github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= github.com/eclipse/paho.mqtt.golang v1.2.1-0.20200121105743-0d940dd29fd2/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/elastic/beats/v7 v7.0.0-alpha2.0.20210805202431-9c57b1ec68c1 h1:Jtn0MpR/cBgXywkOvO4bO/KDvAjOCR8EkXZV04/tvNg= -github.com/elastic/beats/v7 v7.0.0-alpha2.0.20210805202431-9c57b1ec68c1/go.mod h1:ED2nkXUnn992/a1GT7EoLKTuszoFEZtLJcWgzzjmnq4= +github.com/elastic/beats/v7 v7.0.0-alpha2.0.20210812232037-f144f63593df h1:FWo72q/ieWY8Y6ZTV9IyBQrMuXqkItRuE7u6uMB+5JU= +github.com/elastic/beats/v7 v7.0.0-alpha2.0.20210812232037-f144f63593df/go.mod h1:bQhZQAnx5IXAtB63Ah2JIt9u7ZI75gmQCwxS5uI1/J4= github.com/elastic/ecs v1.10.0 h1:C+0ZidF/eh5DKYAZBir3Hq9Q6aMXcwpgEuQnj4bRzKA= github.com/elastic/ecs v1.10.0/go.mod h1:pgiLbQsijLOJvFR8OTILLu0Ni/R/foUNg0L+T6mU9b4= github.com/elastic/elastic-agent-client/v7 v7.0.0-20210727140539-f0905d9377f6 h1:nFvXHBjYK3e9+xF0WKDeAKK4aOO51uC28s+L9rBmilo= @@ -641,6 +641,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -1006,6 +1007,7 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= @@ -1087,6 +1089,7 @@ github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQ github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olivere/elastic v6.2.35+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.5.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -1534,8 +1537,9 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.18.1 h1:CSUJ2mjFszzEWt4CdKISEuChVIXGBn3lAPwkRGyVrc4= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE= +go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180505025534-4ec37c66abab/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1569,8 +1573,8 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210812204632-0ba0e8f03122 h1:AOT7vJYHE32m61R8d1WlcqhOO1AocesDsKpcMq+UOaA= +golang.org/x/crypto v0.0.0-20210812204632-0ba0e8f03122/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1814,8 +1818,8 @@ golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= @@ -1829,8 +1833,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1938,8 +1943,8 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67 h1:VmMSf20ssFK0+u1dscyTH9bU4/M4y+X/xNfkvD6kGtM= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210811021853-ddbe55d93216 h1:qnrhhl4uoNFepTqE28u11llFcDH07Z6r/cQxpGR97A4= +google.golang.org/genproto v0.0.0-20210811021853-ddbe55d93216/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -1974,8 +1979,9 @@ google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1 h1:f37vZbBVTiJ6jKG5mWz8ySOBxNqy6ViPgyhSdVnxF3E= google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/examples v0.0.0-20201010204749-3c400e7fcc87 h1:JA56ipSuANY2Fwx4OITOAj+QXlHyCJEma6VVWTRBG+k= google.golang.org/grpc/examples v0.0.0-20201010204749-3c400e7fcc87/go.mod h1:Lh55/1hxmVHEkOvSIQ2uj0P12QyOCUNyRwnUlSS13hw= From 04c5355e2f758c8f02e60c37a4b662f8901eddbf Mon Sep 17 00:00:00 2001 From: Brandon Morelli Date: Fri, 13 Aug 2021 08:01:42 -0700 Subject: [PATCH 05/14] docs: Anonymous authentication (#5930) --- docs/apm-package/apm-input-settings.asciidoc | 70 ++++++++++++++---- docs/apm-package/input-apm.asciidoc | 19 ++++- docs/configuration-anonymous.asciidoc | 78 ++++++++++++++++++++ docs/configuration-rum.asciidoc | 75 ++++++++++++------- docs/configuring.asciidoc | 3 + docs/data-ingestion.asciidoc | 9 ++- docs/secure-communication-agents.asciidoc | 24 +++++- 7 files changed, 229 insertions(+), 49 deletions(-) create mode 100644 docs/configuration-anonymous.asciidoc diff --git a/docs/apm-package/apm-input-settings.asciidoc b/docs/apm-package/apm-input-settings.asciidoc index 5348efe4d09..81b89dafe2e 100644 --- a/docs/apm-package/apm-input-settings.asciidoc +++ b/docs/apm-package/apm-input-settings.asciidoc @@ -38,7 +38,8 @@ Use `unix:/path/to.sock` to listen on a unix domain socket. | (string) Authorization token for sending APM data. The same token must also be set in each APM agent. This token is not used for RUM endpoints. -By default, no authorization token is set. + +*Default:* No secret token set // end::secret_token-setting[] // ============================================================================= @@ -133,29 +134,68 @@ Configured values are appended to the default list and used as the value for the // ============================================================================= -// tag::rum_event_rate_limit-setting[] +// tag::anonymous_enabled-setting[] +| +[id="input-{input-type}-anonymous_enabled-setting"] +`anonymous_enabled` + +| (bool) Enable or disable anonymous authentication. + +*Default:* `true` (enabled) +// end::anonymous_enabled-setting[] + +// ============================================================================= + +// tag::anonymous_allow_agent-setting[] +| +[id="input-{input-type}-anonymous_allow_agent-setting"] +`anonymous_allow_agent` + +| (array) A list of permitted APM agent names for anonymous authentication. +Names in this list must match the agent's `agent.name`. + +*Default:* `[rum-js, js-base, iOS/swift]` (only RUM and iOS/Swift agent events are accepted) +// end::anonymous_allow_agent-setting[] + +// ============================================================================= + +// tag::anonymous_allow_service-setting[] +| +[id="input-{input-type}-anonymous_allow_service-setting"] +`anonymous_allow_service` + +| (array) A list of permitted service names for anonymous authentication. +Names in this list must match the agent's `service.name`. +This can be used to limit the number of service-specific indices or data streams created. + +*Default:* Not set (any service name is accepted) +// end::anonymous_allow_service-setting[] + +// ============================================================================= + +// tag::anonymous_rate_limit_event_limit-setting[] | -[id="input-{input-type}-rum_event_rate_limit-setting"] -`rum_event_rate_limit` +[id="input-{input-type}-anonymous_rate_limit_event_limit-setting"] +`anonymous_rate_limit_event_limit` -| (int) Defines the maximum amount of events allowed to be sent to the APM Server RUM endpoint per ip per second. +| (int) The maximum amount of events allowed to be sent to the APM Server anonymous auth endpoint per IP per second. -*Default:* `300` -// end::rum_event_rate_limit-setting[] +*Default:* `10` +// end::anonymous_rate_limit_event_limit-setting[] // ============================================================================= -// tag::rum_event_rate_lru_size-setting[] +// tag::anonymous_rate_limit_ip_limit-setting[] | -[id="input-{input-type}-rum_event_rate_lru_size-setting"] -`rum_event_rate_lru_size` +[id="input-{input-type}-anonymous_rate_limit_ip_limit-setting"] +`anonymous_rate_limit_ip_limit` -| (int) An LRU cache is used to keep a rate limit per IP for the most recently seen IPs. -This setting defines the number of unique IPs that can be tracked in the cache. -Sites with many concurrent clients should consider increasing this limit. +| (int) The number of unique IP addresses to track in an LRU cache. +IP addresses in the cache will be rate limited according to the `anonymous_rate_limit_event_limit` setting. +Consider increasing this default if your application has many concurrent clients. -*Default:* `1000` -// end::rum_event_rate_lru_size-setting[] +*Default:* `10000` +// end::anonymous_rate_limit_ip_limit-setting[] // ============================================================================= diff --git a/docs/apm-package/input-apm.asciidoc b/docs/apm-package/input-apm.asciidoc index fd8fc23f881..d1e47cd58cb 100644 --- a/docs/apm-package/input-apm.asciidoc +++ b/docs/apm-package/input-apm.asciidoc @@ -10,7 +10,7 @@ beta::[] To edit the APM integration input settings, open {kib} and select: -**Fleet** / **Integrations** / **Elastic APM** / **Add Elastic APM**. +**Integrations** > **Elastic APM** > **Add Elastic APM**. Expand the carrot to view all settings. A limited number of settings are currently supported. @@ -38,6 +38,21 @@ include::./apm-input-settings.asciidoc[tag=capture_personal_data-setting] |=== +[float] +[[apm-input-anon-auth-settings]] +=== Anonymous authentication settings + +[cols="2*Anonymous authentication +++++ + +Elastic APM agents can send unauthenticated (anonymous) events to the APM Server. +This is useful for agents that run on clients, like the Real User Monitoring (RUM) agent running in a browser, +or the iOS/Swift agent running in a user application. + +Example configuration: + +["source","yaml"] +---- +apm-server.auth.anonymous.enabled: true +apm-server.auth.anonymous.allow_agent: [rum-js] +apm-server.auth.anonymous.allow_service: [my_service_name] +apm-server.auth.anonymous.rate_limit.event_limit: 300 +apm-server.auth.anonymous.rate_limit.ip_limit: 1000 +---- + +[float] +[[config-auth-anon-rum]] +=== Real User Monitoring (RUM) + +Anonymous authentication must be enabled to collect RUM data. +For this reason, anonymous auth will be enabled automatically if <> +is set to `true`, and <> is not explicitly defined. + +See <> for additional RUM configuration options. + +[float] +[[config-auth-anon]] +=== Configuration reference + +Specify the following options in the `apm-server.auth.anonymous` section of the `apm-server.yml` config file: + +[float] +[[config-auth-anon-enabled]] +==== `enabled` + +Enable or disable anonymous authentication. + +Default: `false` (disabled) + +[float] +[[config-auth-anon-allow-agent]] +==== `allow_agent` +A list of permitted APM agent names for anonymous authentication. +Names in this list must match the agent's `agent.name`. + +Default: `[rum-js, js-base]` (only RUM agent events are accepted) + +[float] +[[config-auth-anon-allow-service]] +==== `allow_service` +A list of permitted service names for anonymous authentication. +Names in this list must match the agent's `service.name`. +This can be used to limit the number of service-specific indices or data streams created. + +Default: Not set (any service name is accepted) + +[float] +[[config-auth-anon-ip-limit]] +==== `rate_limit.ip_limit` +The number of unique IP addresses to track in an LRU cache. +IP addresses in the cache will be rate limited according to the <> setting. +Consider increasing this default if your application has many concurrent clients. + +Default: `1000` + +[float] +[[config-auth-anon-event-limit]] +==== `rate_limit.event_limit` +The maximum number of events allowed per second, per agent IP address. + +Default: `300` diff --git a/docs/configuration-rum.asciidoc b/docs/configuration-rum.asciidoc index 1e86b5fa656..218211cf214 100644 --- a/docs/configuration-rum.asciidoc +++ b/docs/configuration-rum.asciidoc @@ -5,24 +5,23 @@ Real User Monitoring (RUM) ++++ -Real User Monitoring captures user interaction with clients such as web browsers. -The {apm-rum-ref-v}/index.html[JavaScript Agent] is Elastic's RUM Agent. - -By default, Real User Monitoring is disabled. To enable it, -set `apm-server.rum.enabled` to `true` in your APM Server configuration file. +The {apm-rum-ref-v}/index.html[Real User Monitoring (RUM) agent] captures user interactions with clients such as web browsers. +These interactions are sent as events to the APM Server. +Because the RUM agent runs on the client side, the connection between agent and server is unauthenticated. +As a security precaution, RUM is therefore disabled by default. +To enable it, set `apm-server.rum.enabled` to `true` in your APM Server configuration file. In addition, if APM Server is deployed in an origin different than the page’s origin, you will need to configure {apm-rum-ref-v}/configuring-cors.html[Cross-Origin Resource Sharing (CORS)] in the Agent. -A full list of APM Server configuration options is available in the <>. - Example config with RUM enabled: ["source","yaml"] ---- apm-server.rum.enabled: true -apm-server.rum.event_rate.limit: 300 -apm-server.rum.event_rate.lru_size: 1000 +apm-server.auth.anonymous.rate_limit.event_limit: 300 +apm-server.auth.anonymous.rate_limit.ip_limit: 1000 +apm-server.auth.anonymous.allow_service: [your_service_name] apm-server.rum.allow_origins: ['*'] apm-server.rum.allow_headers: ["header1", "header2"] apm-server.rum.library_pattern: "node_modules|bower_components|~" @@ -34,7 +33,9 @@ apm-server.rum.source_mapping.index_pattern: "apm-*-sourcemap*" [float] [[enable-rum-support]] -=== Configuration +=== Configuration reference + +Specify the following options in the `apm-server.rum` section of the `apm-server.yml` config file: [[rum-enable]] [float] @@ -42,26 +43,41 @@ apm-server.rum.source_mapping.index_pattern: "apm-*-sourcemap*" To enable RUM support, set `apm-server.rum.enabled` to `true`. By default this is disabled. +NOTE: Enabling RUM support automatically enables <>. +Anonymous access is required as the RUM agent runs in end users' browsers. + [float] [[event_rate.limit]] ==== `event_rate.limit` -Defines the maximum amount of events allowed to be sent to the APM Server RUM endpoint per ip per second. -Defaults to 300. + +deprecated::[7.15.0, Replaced by <>.] + +The maximum number of events allowed per second, per agent IP address. + +Default: `300` [float] ==== `event_rate.lru_size` -An LRU cache is used to keep a rate limit per IP for the most recently seen IPs. -This setting defines the number of unique IPs that can be tracked in the cache. -Sites with many concurrent clients should consider increasing this limit. -Defaults to 1000. + +deprecated::[7.15.0, Replaced by <>.] + +The number of unique IP addresses to track in an LRU cache. +IP addresses in the cache will be rate limited according to the <> setting. +Consider increasing this default if your site has many concurrent clients. + +Default: `1000` [float] [[rum-allow-service-names]] ==== `allow_service_names` + +deprecated::[7.15.0, Replaced by <>.] A list of permitted service names for RUM support. +Names in this list must match the agent's `service.name`. This can be set to restrict RUM events to those with one of a set of known service names, in order to limit the number of service-specific indices or data streams created. -By default this is not set, allowing any service name. + +Default: Not set (any service name is accepted) [float] [[rum-allow-origins]] @@ -70,17 +86,20 @@ A list of permitted origins for RUM support. User-agents send an Origin header that will be validated against this list. This is done automatically by modern browsers as part of the https://www.w3.org/TR/cors/[CORS specification]. An origin is made of a protocol scheme, host and port, without the URL path. -Default value is set to `['*']`, which allows everything. + +Default: `['*']` (allows everything) [float] [[rum-allow-headers]] ==== `allow_headers` -By default, HTTP requests made from the RUM agent to the APM Server are limited in the HTTP headers they are allowed to have. +HTTP requests made from the RUM agent to the APM Server are limited in the HTTP headers they are allowed to have. If any other headers are added, the request will be rejected by the browser due to Cross-Origin Resource Sharing (CORS) restrictions. -If you need to add extra headers to these requests, you can use this configuration to allow additional headers. -The default list of values includes "Content-Type", "Content-Encoding", and "Accept"; +Use this setting to allow additional headers. +The default list of allowed headers includes "Content-Type", "Content-Encoding", and "Accept"; custom values configured here are appended to the default list and used as the value for the `Access-Control-Allow-Headers` header. +Default: `[]` + [float] [[rum-library-pattern]] ==== `library_pattern` @@ -89,19 +108,22 @@ If the RegExp matches, the stacktrace frame is considered to be a library frame. When source mapping is applied, the `error.culprit` is set to reflect the _function_ and the _filename_ of the first non library frame. This aims to provide an entry point for identifying issues. -Default value is `"node_modules|bower_components|~"`. + +Default: `"node_modules|bower_components|~"` [float] ==== `exclude_from_grouping` RegExp to be matched against a stacktrace frame's `file_name`. If the RegExp matches, the stacktrace frame is excluded from being used for calculating error groups. -The default pattern excludes stacktrace frames that have a filename starting with `/webpack`. + +Default: `"^/webpack"` (excludes stacktrace frames that have a filename starting with `/webpack`) [[config-sourcemapping-enabled]] [float] ==== `source_mapping.enabled` Used to enable/disable <> for RUM events. -Defaults to `true`. + +Default: `true` [[config-sourcemapping-elasticsearch]] [float] @@ -117,13 +139,16 @@ If a source map has been uploaded to the APM Server, <> is automatically applied to documents sent to the RUM endpoint. Source maps are fetched from Elasticsearch and then kept in an in-memory cache for the configured time. Values configured without a time unit are treated as seconds. -Default value is 5 minutes. + +Default: `5m` (5 minutes) [float] ==== `source_mapping.index_pattern` Source maps are stored in a separate index `apm-%{[observer.version]}-sourcemap` by default. If changed, a matching index pattern needs to be specified here. +Default: `"apm-*-sourcemap*"` + [float] === Ingest pipelines diff --git a/docs/configuring.asciidoc b/docs/configuring.asciidoc index 03422d5bde3..10ba3e373c4 100644 --- a/docs/configuring.asciidoc +++ b/docs/configuring.asciidoc @@ -10,6 +10,7 @@ include::{libbeat-dir}/shared/configuring-intro.asciidoc[] * <> +* <> * <> * <> * <> @@ -28,6 +29,8 @@ include::{libbeat-dir}/shared/configuring-intro.asciidoc[] include::./configuration-process.asciidoc[] +include::./configuration-anonymous.asciidoc[] + include::{libbeat-dir}/template-config.asciidoc[] include::./ilm-reference.asciidoc[] diff --git a/docs/data-ingestion.asciidoc b/docs/data-ingestion.asciidoc index 924bd56af1e..f658c41d3b7 100644 --- a/docs/data-ingestion.asciidoc +++ b/docs/data-ingestion.asciidoc @@ -72,13 +72,14 @@ Read more in the {apm-agents-ref}/index.html[agents documentation]. [[adjust-event-rate]] [float] -==== Adjust RUM event rate limit +==== Adjust anonymous auth rate limit -Agents make use of long running requests and flush as many events over a single request as possible. Thus, the rate limiter for RUM is bound to the number of _events_ sent per second, per IP. +Agents make use of long running requests and flush as many events over a single request as possible. +Thus, the rate limiter for anonymous authentication is bound to the number of _events_ sent per second, per IP. -If the rate limit is hit while events on an established request are sent, the request is not immediately terminated. The intake of events is only throttled to <>, which means that events are queued and processed slower. Only when the allowed buffer queue is also full, does the request get terminated with a `429 - rate limit exceeded` HTTP response. If an agent tries to establish a new request, but the rate limit is already hit, a `429` will be sent immediately. +If the event rate limit is hit while events on an established request are sent, the request is not immediately terminated. The intake of events is only throttled to <>, which means that events are queued and processed slower. Only when the allowed buffer queue is also full, does the request get terminated with a `429 - rate limit exceeded` HTTP response. If an agent tries to establish a new request, but the rate limit is already hit, a `429` will be sent immediately. -Increasing the <> default value will help avoid `rate limit exceeded` errors. +Increasing the <> default value will help avoid `rate limit exceeded` errors. [[tune-es]] === Tune Elasticsearch diff --git a/docs/secure-communication-agents.asciidoc b/docs/secure-communication-agents.asciidoc index 840416d3b9e..ffcb1bcaece 100644 --- a/docs/secure-communication-agents.asciidoc +++ b/docs/secure-communication-agents.asciidoc @@ -15,9 +15,10 @@ In addition, since both mechanisms involve sending a secret as plain text, they should be used in combination with SSL/TLS encryption. As soon as an authenticated communication is enabled, requests without a valid token or API key will be denied by APM Server. -As RUM endpoints cannot be secured through these mechanisms, they are exempt from this rule. +An exception to this rule can be configured with <>, +which is useful for APM agents running on the client side, like the Real User Monitoring (RUM) agent. -In addition, there is a less straightforward and more restrictive way to authenticate clients through +There is a less straightforward and more restrictive way to authenticate clients through <>, which is currently a mainstream option only for the RUM agent (through the browser) and the Jaeger agent. @@ -527,3 +528,22 @@ This ensures encryption, but does not verify that you are sending data to the co * *Python agent*: {apm-py-ref}/configuration.html#config-verify-server-cert[`verify_server_cert`] * *Ruby agent*: {apm-ruby-ref}/configuration.html#config-verify-server-cert[`verify_server_cert`] * *NodeJS agent*: {apm-node-ref}/configuration.html#validate-server-cert[`verifyServerCert`] + +[[secure-communication-unauthenticated]] +=== Anonymous authentication + +Elastic APM agents can send unauthenticated (anonymous) events to the APM Server. +This is useful for agents that run on clients, like the Real User Monitoring (RUM) agent running in a browser, +or the iOS/Swift agent running in a user application. +Incoming requests are considered to be anonymous if no authentication token can be extracted from the incoming request. +By default, these anonymous requests are rejected and an authentication error is returned. + +Anonymous authentication must be enabled to collect RUM data. +To enable anonymous access, set either <> or +<> to `true`. + +Because anyone can send anonymous events to the APM Server, +additional configuration variables are available to rate limit the number anonymous events the APM Server processes; +throughput is equal to the `rate_limit.ip_limit` times the `rate_limit.event_limit`. + +See <> for a complete list of options and a sample configuration file. From a8012e7fb96e034e133f747725cec08f4ed945db Mon Sep 17 00:00:00 2001 From: Brandon Morelli Date: Fri, 13 Aug 2021 08:03:35 -0700 Subject: [PATCH 06/14] docs: add sourcemap upload notes (#5935) --- docs/apm-package/apm-integration.asciidoc | 2 +- docs/sourcemap-api.asciidoc | 3 +++ docs/sourcemaps.asciidoc | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/apm-package/apm-integration.asciidoc b/docs/apm-package/apm-integration.asciidoc index b1f7ced7b3c..4aaaf41a832 100644 --- a/docs/apm-package/apm-integration.asciidoc +++ b/docs/apm-package/apm-integration.asciidoc @@ -103,7 +103,7 @@ Changes are automatically propagated to your APM agents, so there’s no need to === Package versioning The APM package is versioned separately from the Elastic Stack. -The current version is `0.1.0`. In the future, we may align with Elastic Stack versioning. +In the future, we may align with Elastic Stack versioning. [discrete] [[apm-integration-learn-more]] diff --git a/docs/sourcemap-api.asciidoc b/docs/sourcemap-api.asciidoc index a9b805c99ce..c7cca257a54 100644 --- a/docs/sourcemap-api.asciidoc +++ b/docs/sourcemap-api.asciidoc @@ -10,6 +10,9 @@ IMPORTANT: You must <> in the APM Server f The APM Server exposes an API endpoint to upload source maps for real user monitoring (RUM). See the <> guide to get started. +If you're using the <>, +you must use the Kibana {kibana-ref}/rum-sourcemap-api.html[source map upload API] instead. + [[sourcemap-endpoint]] [float] === Upload endpoint diff --git a/docs/sourcemaps.asciidoc b/docs/sourcemaps.asciidoc index e3b067bdc59..9b9eb962de1 100644 --- a/docs/sourcemaps.asciidoc +++ b/docs/sourcemaps.asciidoc @@ -5,6 +5,9 @@ Create and upload source maps (RUM) ++++ +NOTE: This guide is only for standalone APM Server users. Users running the <> +need to use the Kibana {kibana-ref}/rum-sourcemap-api.html[source map upload API] instead. + Minifying JavaScript bundles in production is a common practice; it can greatly improve the load time and network latency of your applications. The problem with minifying code is that it can be hard to debug. From fe1b40af77795fd7381e230305daaf31cddbdecf Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Mon, 16 Aug 2021 01:54:37 -0400 Subject: [PATCH 07/14] [Automation] Update elastic stack version to 8.0.0-2e89a578 for testing (#5944) Co-authored-by: apmmachine --- docker-compose.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index fbeceb3e589..c84538ad1c5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,7 +32,7 @@ services: kibana: { condition: service_healthy } elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:8.0.0-e8455215-SNAPSHOT + image: docker.elastic.co/elasticsearch/elasticsearch:8.0.0-2e89a578-SNAPSHOT ports: - 9200:9200 healthcheck: @@ -61,7 +61,7 @@ services: - "./testing/docker/elasticsearch/users_roles:/usr/share/elasticsearch/config/users_roles" kibana: - image: docker.elastic.co/kibana/kibana:8.0.0-e8455215-SNAPSHOT + image: docker.elastic.co/kibana/kibana:8.0.0-2e89a578-SNAPSHOT ports: - 5601:5601 healthcheck: @@ -85,7 +85,7 @@ services: package-registry: { condition: service_healthy } fleet-server: - image: docker.elastic.co/beats/elastic-agent:8.0.0-e8455215-SNAPSHOT + image: docker.elastic.co/beats/elastic-agent:8.0.0-2e89a578-SNAPSHOT ports: - 8220:8220 healthcheck: From c60c8c5cd1af8553cee370bca376baab18aeda53 Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Mon, 16 Aug 2021 02:53:21 -0400 Subject: [PATCH 08/14] Update to elastic/beats@84b4cea96755 (#5946) Co-authored-by: apmmachine --- NOTICE.txt | 20 ++++++++++---------- go.mod | 11 ++++++----- go.sum | 29 +++++++++++++++-------------- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/NOTICE.txt b/NOTICE.txt index e16cc44aa3d..93ad8187f83 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -576,11 +576,11 @@ SOFTWARE. -------------------------------------------------------------------------------- Dependency : github.com/elastic/beats/v7 -Version: v7.0.0-alpha2.0.20210812232037-f144f63593df +Version: v7.0.0-alpha2.0.20210815221626-84b4cea96755 Licence type (autodetected): Elastic -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/elastic/beats/v7@v7.0.0-alpha2.0.20210812232037-f144f63593df/LICENSE.txt: +Contents of probable licence file $GOMODCACHE/github.com/elastic/beats/v7@v7.0.0-alpha2.0.20210815221626-84b4cea96755/LICENSE.txt: Source code in this repository is variously licensed under the Apache License Version 2.0, an Apache compatible license, or the Elastic License. Outside of @@ -4893,11 +4893,11 @@ THE SOFTWARE. -------------------------------------------------------------------------------- Dependency : golang.org/x/net -Version: v0.0.0-20210805182204-aaa1db679c0d +Version: v0.0.0-20210813160813-60bc85c4be6d Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/golang.org/x/net@v0.0.0-20210805182204-aaa1db679c0d/LICENSE: +Contents of probable licence file $GOMODCACHE/golang.org/x/net@v0.0.0-20210813160813-60bc85c4be6d/LICENSE: Copyright (c) 2009 The Go Authors. All rights reserved. @@ -18787,11 +18787,11 @@ THE SOFTWARE. -------------------------------------------------------------------------------- Dependency : golang.org/x/crypto -Version: v0.0.0-20210812204632-0ba0e8f03122 +Version: v0.0.0-20210813211128-0a44fdfbc16e Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/golang.org/x/crypto@v0.0.0-20210812204632-0ba0e8f03122/LICENSE: +Contents of probable licence file $GOMODCACHE/golang.org/x/crypto@v0.0.0-20210813211128-0a44fdfbc16e/LICENSE: Copyright (c) 2009 The Go Authors. All rights reserved. @@ -18861,11 +18861,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : golang.org/x/sys -Version: v0.0.0-20210809222454-d867a43fc93e +Version: v0.0.0-20210816032535-30e4713e60e3 Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/golang.org/x/sys@v0.0.0-20210809222454-d867a43fc93e/LICENSE: +Contents of probable licence file $GOMODCACHE/golang.org/x/sys@v0.0.0-20210816032535-30e4713e60e3/LICENSE: Copyright (c) 2009 The Go Authors. All rights reserved. @@ -18972,11 +18972,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : google.golang.org/genproto -Version: v0.0.0-20210811021853-ddbe55d93216 +Version: v0.0.0-20210813162853-db860fec028c Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/google.golang.org/genproto@v0.0.0-20210811021853-ddbe55d93216/LICENSE: +Contents of probable licence file $GOMODCACHE/google.golang.org/genproto@v0.0.0-20210813162853-db860fec028c/LICENSE: Apache License diff --git a/go.mod b/go.mod index 94da41b77d2..6cea68367db 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7 // indirect github.com/dustin/go-humanize v1.0.0 github.com/elastic/apm-server/approvaltest v0.0.0-00010101000000-000000000000 - github.com/elastic/beats/v7 v7.0.0-alpha2.0.20210812232037-f144f63593df + github.com/elastic/beats/v7 v7.0.0-alpha2.0.20210815221626-84b4cea96755 github.com/elastic/ecs v1.10.0 github.com/elastic/gmux v0.1.0 github.com/elastic/go-elasticsearch/v7 v7.5.1-0.20210728153421-6462d8b84e7d @@ -60,14 +60,15 @@ require ( go.uber.org/atomic v1.9.0 go.uber.org/multierr v1.7.0 // indirect go.uber.org/zap v1.19.0 - golang.org/x/crypto v0.0.0-20210812204632-0ba0e8f03122 // indirect - golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d + golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e // indirect + golang.org/x/mod v0.5.0 // indirect + golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect + golang.org/x/sys v0.0.0-20210816032535-30e4713e60e3 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 golang.org/x/tools v0.1.5 - google.golang.org/genproto v0.0.0-20210811021853-ddbe55d93216 // indirect + google.golang.org/genproto v0.0.0-20210813162853-db860fec028c // indirect google.golang.org/grpc v1.40.0 gopkg.in/yaml.v2 v2.4.0 gotest.tools/gotestsum v1.7.0 diff --git a/go.sum b/go.sum index cfe6553791d..f485653b0c5 100644 --- a/go.sum +++ b/go.sum @@ -356,10 +356,10 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1 github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= -github.com/eclipse/paho.mqtt.golang v1.2.1-0.20200121105743-0d940dd29fd2/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= +github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/elastic/beats/v7 v7.0.0-alpha2.0.20210812232037-f144f63593df h1:FWo72q/ieWY8Y6ZTV9IyBQrMuXqkItRuE7u6uMB+5JU= -github.com/elastic/beats/v7 v7.0.0-alpha2.0.20210812232037-f144f63593df/go.mod h1:bQhZQAnx5IXAtB63Ah2JIt9u7ZI75gmQCwxS5uI1/J4= +github.com/elastic/beats/v7 v7.0.0-alpha2.0.20210815221626-84b4cea96755 h1:2g+hA3TTS/dtzA1P4Ju0Jg2+v8f00rhn72wpqiXMow4= +github.com/elastic/beats/v7 v7.0.0-alpha2.0.20210815221626-84b4cea96755/go.mod h1:7svB+J5d8rV5h8ddVgicXFefp62361uHbg+cm/5WljI= github.com/elastic/ecs v1.10.0 h1:C+0ZidF/eh5DKYAZBir3Hq9Q6aMXcwpgEuQnj4bRzKA= github.com/elastic/ecs v1.10.0/go.mod h1:pgiLbQsijLOJvFR8OTILLu0Ni/R/foUNg0L+T6mU9b4= github.com/elastic/elastic-agent-client/v7 v7.0.0-20210727140539-f0905d9377f6 h1:nFvXHBjYK3e9+xF0WKDeAKK4aOO51uC28s+L9rBmilo= @@ -936,7 +936,6 @@ github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPR github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/knadh/koanf v1.1.1 h1:doO5UBvSXcmngdr/u54HKe+Uz4ZZw0/YHVzSsnE3vD4= github.com/knadh/koanf v1.1.1/go.mod h1:xpPTwMhsA/aaQLAilyCCqfpEiY1gpa160AiCuWHJUjY= -github.com/kolide/osquery-go v0.0.0-20200604192029-b019be7063ac/go.mod h1:rp36fokOKgd/5mOgbvv4fkpdaucQ43mnvb+8BR62Xo8= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1135,6 +1134,7 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= +github.com/osquery/osquery-go v0.0.0-20210622151333-99b4efa62ec5/go.mod h1:JKR5QhjsYdnIPY7hakgas5sxf8qlA/9wQnLqaMfWdcg= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= @@ -1573,8 +1573,8 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210812204632-0ba0e8f03122 h1:AOT7vJYHE32m61R8d1WlcqhOO1AocesDsKpcMq+UOaA= -golang.org/x/crypto v0.0.0-20210812204632-0ba0e8f03122/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e h1:VvfwVmMH40bpMeizC9/K7ipM5Qjucuu16RWfneFPyhQ= +golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1614,8 +1614,9 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1657,6 +1658,7 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -1683,8 +1685,8 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190130055435-99b60b757ec1/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1716,7 +1718,6 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cO golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180815093151-14742f9018cd/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1818,8 +1819,8 @@ golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816032535-30e4713e60e3 h1:7hHxyYeKyS0AU/brXAMuc+9BxCO/a4vL1DoUVLDTVIo= +golang.org/x/sys v0.0.0-20210816032535-30e4713e60e3/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= @@ -1943,8 +1944,8 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210811021853-ddbe55d93216 h1:qnrhhl4uoNFepTqE28u11llFcDH07Z6r/cQxpGR97A4= -google.golang.org/genproto v0.0.0-20210811021853-ddbe55d93216/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c h1:iLQakcwWG3k/++1q/46apVb1sUQ3IqIdn9yUE6eh/xA= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= From 03d49076fb298e89be4444d3b9f978ec9139eb88 Mon Sep 17 00:00:00 2001 From: Andrew Wilkins Date: Mon, 16 Aug 2021 19:38:44 +0800 Subject: [PATCH 09/14] apmpackage: copy full field hierarchy (#5947) Copy the full field hierarchy to the integration package, instead of just leaf fields. Copying only leaf fields means we miss inherited group properties such as `dynamic`. Set a default `dynamic` property for each data stream mapping. --- .../app_metrics/fields/base-fields.yml | 3 + .../data_stream/app_metrics/fields/ecs.yml | 547 ++++++++------ .../data_stream/app_metrics/fields/fields.yml | 440 ++++++----- .../apm/data_stream/app_metrics/manifest.yml | 7 + .../error_logs/fields/base-fields.yml | 3 + .../apm/data_stream/error_logs/fields/ecs.yml | 692 ++++++++++------- .../data_stream/error_logs/fields/fields.yml | 377 ++++++---- .../apm/data_stream/error_logs/manifest.yml | 8 + .../internal_metrics/fields/base-fields.yml | 3 + .../internal_metrics/fields/ecs.yml | 573 ++++++++------ .../internal_metrics/fields/fields.yml | 612 +++++++++------ .../data_stream/internal_metrics/manifest.yml | 6 + .../profile_metrics/fields/base-fields.yml | 3 + .../profile_metrics/fields/ecs.yml | 547 ++++++++------ .../profile_metrics/fields/fields.yml | 379 ++++++---- .../data_stream/profile_metrics/manifest.yml | 6 + .../sampled_traces/fields/base-fields.yml | 3 + .../data_stream/sampled_traces/manifest.yml | 4 + .../data_stream/traces/fields/base-fields.yml | 3 + .../apm/data_stream/traces/fields/ecs.yml | 705 ++++++++++-------- .../apm/data_stream/traces/fields/fields.yml | 602 +++++++++------ .../apm/data_stream/traces/manifest.yml | 8 + apmpackage/apm/docs/README.md | 21 +- apmpackage/cmd/gen-package/field.go | 38 +- apmpackage/cmd/gen-package/gendocs.go | 20 +- apmpackage/cmd/gen-package/genfields.go | 261 +++---- changelogs/head.asciidoc | 1 + 27 files changed, 3482 insertions(+), 2390 deletions(-) diff --git a/apmpackage/apm/data_stream/app_metrics/fields/base-fields.yml b/apmpackage/apm/data_stream/app_metrics/fields/base-fields.yml index bef973826be..bf9b70e13de 100644 --- a/apmpackage/apm/data_stream/app_metrics/fields/base-fields.yml +++ b/apmpackage/apm/data_stream/app_metrics/fields/base-fields.yml @@ -10,3 +10,6 @@ - name: data_stream.namespace type: constant_keyword description: Data stream namespace. +- name: ecs.version + type: keyword + description: ECS version the event conforms to. diff --git a/apmpackage/apm/data_stream/app_metrics/fields/ecs.yml b/apmpackage/apm/data_stream/app_metrics/fields/ecs.yml index e73d8f46a16..5a95c5dc42b 100644 --- a/apmpackage/apm/data_stream/app_metrics/fields/ecs.yml +++ b/apmpackage/apm/data_stream/app_metrics/fields/ecs.yml @@ -1,122 +1,173 @@ -- name: agent.ephemeral_id - type: keyword - description: | - The Ephemeral ID identifies a running process. -- name: agent.name - type: keyword - description: | - Name of the agent used. -- name: agent.version - type: keyword - description: | - Version of the agent used. -- name: client.domain - type: keyword - description: | - Client domain. - ignore_above: 1024 -- name: client.ip - type: ip - description: | - IP address of the client of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. -- name: client.port - type: long - description: | - Port of the client. -- name: cloud.account.id - level: extended - type: keyword - description: Cloud account ID - ignore_above: 1024 -- name: cloud.account.name - level: extended - type: keyword - description: Cloud account name - ignore_above: 1024 -- name: cloud.availability_zone - level: extended - type: keyword - description: Cloud availability zone name - ignore_above: 1024 -- name: cloud.instance.id - level: extended - type: keyword - description: Cloud instance/machine ID - ignore_above: 1024 -- name: cloud.instance.name - level: extended - type: keyword - description: Cloud instance/machine name - ignore_above: 1024 -- name: cloud.machine.type - level: extended - type: keyword - description: Cloud instance/machine type - ignore_above: 1024 -- name: cloud.project.id - level: extended - type: keyword - description: Cloud project ID - ignore_above: 1024 -- name: cloud.project.name - level: extended - type: keyword - description: Cloud project name - ignore_above: 1024 -- name: cloud.provider - level: extended - type: keyword - description: Cloud provider name - ignore_above: 1024 -- name: cloud.region - level: extended - type: keyword - description: Cloud region name - ignore_above: 1024 -- name: cloud.service.name - level: extended - type: keyword - description: | - Cloud service name, intended to distinguish services running on different platforms within a provider. - ignore_above: 1024 -- name: container.id - type: keyword - description: | - Unique container id. -- name: destination.address - level: extended - type: keyword - description: Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is. - ignore_above: 1024 -- name: destination.ip - level: core - type: ip - description: IP addess of the destination. Can be one of multiple IPv4 or IPv6 addresses. -- name: destination.port - level: core - type: long - format: string - description: Port of the destination. -- name: host.architecture - type: keyword - description: | - The architecture of the host the event was recorded on. -- name: host.hostname - type: keyword - description: | - The hostname of the host the event was recorded on. -- name: host.ip - type: ip - description: | - IP of the host that records the event. -- name: host.name - type: keyword - description: | - Name of the host the event was recorded on. It can contain same information as host.hostname or a name specified by the user. -- name: host.os.platform - type: keyword - description: | - The platform of the host the event was recorded on. +- name: agent + type: group + fields: + - name: ephemeral_id + type: keyword + description: | + The Ephemeral ID identifies a running process. + - name: name + type: keyword + description: | + Name of the agent used. + - name: version + type: keyword + description: | + Version of the agent used. +- name: client + type: group + fields: + - name: domain + type: keyword + description: | + Client domain. + ignore_above: 1024 + - name: ip + type: ip + description: | + IP address of the client of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. + - name: port + type: long + description: | + Port of the client. +- name: cloud + title: Cloud + type: group + description: | + Cloud metadata reported by agents + fields: + - name: account + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud account ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud account name + ignore_above: 1024 + - name: availability_zone + level: extended + type: keyword + description: Cloud availability zone name + ignore_above: 1024 + - name: instance + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud instance/machine ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud instance/machine name + ignore_above: 1024 + - name: machine + type: group + fields: + - name: type + level: extended + type: keyword + description: Cloud instance/machine type + ignore_above: 1024 + - name: project + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud project ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud project name + ignore_above: 1024 + - name: provider + level: extended + type: keyword + description: Cloud provider name + ignore_above: 1024 + - name: region + level: extended + type: keyword + description: Cloud region name + ignore_above: 1024 + - name: service + type: group + fields: + - name: name + level: extended + type: keyword + description: | + Cloud service name, intended to distinguish services running on different platforms within a provider. + ignore_above: 1024 +- name: container + title: Container + type: group + description: | + Container fields are used for meta information about the specific container that is the source of information. These fields help correlate data based containers from any runtime. + fields: + - name: id + type: keyword + description: | + Unique container id. +- name: destination + title: Destination + type: group + description: |- + Destination fields describe details about the destination of a packet/event. + Destination fields are usually populated in conjunction with source fields. + fields: + - name: address + level: extended + type: keyword + description: Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is. + ignore_above: 1024 + - name: ip + level: core + type: ip + description: IP addess of the destination. Can be one of multiple IPv4 or IPv6 addresses. + - name: port + level: core + type: long + format: string + description: Port of the destination. +- name: host + type: group + description: | + Optional host fields. + fields: + - name: architecture + type: keyword + description: | + The architecture of the host the event was recorded on. + - name: hostname + type: keyword + description: | + The hostname of the host the event was recorded on. + - name: ip + type: ip + description: | + IP of the host that records the event. + - name: name + type: keyword + description: | + Name of the host the event was recorded on. It can contain same information as host.hostname or a name specified by the user. + - name: os + title: Operating System + type: group + description: | + The OS fields contain information about the operating system. + fields: + - name: platform + type: keyword + description: | + The platform of the host the event was recorded on. - name: labels type: object description: | @@ -127,112 +178,152 @@ - object_type: boolean - object_type: scaled_float scaling_factor: 1000000 -- name: observer.hostname - type: keyword - description: | - Hostname of the APM Server. -- name: observer.type - type: keyword - description: | - The type will be set to `apm-server`. -- name: observer.version - type: keyword - description: | - APM Server version. -- name: process.args - level: extended - type: keyword - description: | - Process arguments. May be filtered to protect sensitive information. -- name: process.pid - type: long - description: | - Numeric process ID of the service process. -- name: process.ppid - type: long - description: | - Numeric ID of the service's parent process. -- name: process.title - type: keyword - description: | - Service process title. -- name: service.name - type: keyword - description: | - Immutable name of the service emitting this event. -- name: service.node.name - type: keyword - description: | - Unique meaningful name of the service node. -- name: service.version - type: keyword - description: | - Version of the service emitting this event. -- name: source.domain - type: keyword - description: | - Source domain. - ignore_above: 1024 -- name: source.ip - type: ip - description: | - IP address of the source of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. -- name: source.port - type: long - description: | - Port of the source. -- name: user.email - type: keyword - description: | - Email of the logged in user. -- name: user.id - type: keyword - description: | - Identifier of the logged in user. -- name: user.name - type: keyword - description: | - The username of the logged in user. -- name: user_agent.device.name - type: keyword - description: | - Name of the device. -- name: user_agent.name - type: keyword - description: | - Name of the user agent. -- name: user_agent.original - type: keyword - description: | - Unparsed version of the user_agent. - multi_fields: - - name: text - type: text -- name: user_agent.os.family - type: keyword - description: | - OS family (such as redhat, debian, freebsd, windows). -- name: user_agent.os.full - type: keyword - description: | - Operating system name, including the version or code name. -- name: user_agent.os.kernel - type: keyword - description: | - Operating system kernel version as a raw string. -- name: user_agent.os.name - type: keyword - description: | - Operating system name, without the version. -- name: user_agent.os.platform - type: keyword - description: | - Operating system platform (such centos, ubuntu, windows). -- name: user_agent.os.version - type: keyword - description: | - Operating system version as a raw string. -- name: user_agent.version - type: keyword - description: | - Version of the user agent. +- name: observer + type: group + fields: + - name: hostname + type: keyword + description: | + Hostname of the APM Server. + - name: type + type: keyword + description: | + The type will be set to `apm-server`. + - name: version + type: keyword + description: | + APM Server version. +- name: process + type: group + description: | + Information pertaining to the running process where the data was collected + fields: + - name: args + level: extended + type: keyword + description: | + Process arguments. May be filtered to protect sensitive information. + - name: pid + type: long + description: | + Numeric process ID of the service process. + - name: ppid + type: long + description: | + Numeric ID of the service's parent process. + - name: title + type: keyword + description: | + Service process title. +- name: service + type: group + description: | + Service fields. + fields: + - name: name + type: keyword + description: | + Immutable name of the service emitting this event. + - name: node + type: group + fields: + - name: name + type: keyword + description: | + Unique meaningful name of the service node. + - name: version + type: keyword + description: | + Version of the service emitting this event. +- name: source + type: group + fields: + - name: domain + type: keyword + description: | + Source domain. + ignore_above: 1024 + - name: ip + type: ip + description: | + IP address of the source of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. + - name: port + type: long + description: | + Port of the source. +- name: user + type: group + fields: + - name: email + type: keyword + description: | + Email of the logged in user. + - name: id + type: keyword + description: | + Identifier of the logged in user. + - name: name + type: keyword + description: | + The username of the logged in user. +- name: user_agent + title: User agent + type: group + description: | + The user_agent fields normally come from a browser request. They often show up in web service logs coming from the parsed user agent string. + fields: + - name: device + title: Device + type: group + description: | + Information concerning the device. + fields: + - name: name + type: keyword + description: | + Name of the device. + - name: name + type: keyword + description: | + Name of the user agent. + - name: original + type: keyword + description: | + Unparsed version of the user_agent. + multi_fields: + - name: text + type: text + - name: os + title: Operating System + type: group + description: | + The OS fields contain information about the operating system. + fields: + - name: family + type: keyword + description: | + OS family (such as redhat, debian, freebsd, windows). + - name: full + type: keyword + description: | + Operating system name, including the version or code name. + - name: kernel + type: keyword + description: | + Operating system kernel version as a raw string. + - name: name + type: keyword + description: | + Operating system name, without the version. + - name: platform + type: keyword + description: | + Operating system platform (such centos, ubuntu, windows). + - name: version + type: keyword + description: | + Operating system version as a raw string. + - name: version + type: keyword + description: | + Version of the user agent. diff --git a/apmpackage/apm/data_stream/app_metrics/fields/fields.yml b/apmpackage/apm/data_stream/app_metrics/fields/fields.yml index ccc72f337c2..6c51811b12c 100644 --- a/apmpackage/apm/data_stream/app_metrics/fields/fields.yml +++ b/apmpackage/apm/data_stream/app_metrics/fields/fields.yml @@ -4,185 +4,289 @@ dynamic: true - name: histogram type: histogram -- name: kubernetes.namespace - type: keyword - description: | - Kubernetes namespace -- name: kubernetes.node.name - type: keyword - description: | - Kubernetes node name -- name: kubernetes.pod.name - type: keyword - description: | - Kubernetes pod name -- name: kubernetes.pod.uid - type: keyword +- name: kubernetes + title: Kubernetes + type: group description: | - Kubernetes Pod UID -- name: metricset.name - type: keyword - description: | - Name of the set of metrics. + Kubernetes metadata reported by agents + fields: + - name: namespace + type: keyword + description: | + Kubernetes namespace + - name: node + type: group + fields: + - name: name + type: keyword + description: | + Kubernetes node name + - name: pod + type: group + fields: + - name: name + type: keyword + description: | + Kubernetes pod name + - name: uid + type: keyword + description: | + Kubernetes Pod UID +- name: metricset + type: group + fields: + - name: name + type: keyword + description: | + Name of the set of metrics. - name: metricset.period type: long description: Current data collection period for this event in milliseconds. unit: ms -- name: network.carrier.icc - type: keyword - description: | - ISO country code, eg. US -- name: network.carrier.mcc - type: keyword +- name: network + type: group description: | - Mobile country code -- name: network.carrier.mnc - type: keyword - description: | - Mobile network code -- name: network.carrier.name - type: keyword - description: | - Carrier name, eg. Vodafone, T-Mobile, etc. -- name: network.connection.subtype - type: keyword - description: | - Detailed network connection sub-type, e.g. "LTE", "CDMA" -- name: network.connection.type - type: keyword - description: | - Network connection type, eg. "wifi", "cell" -- name: observer.listening - type: keyword - description: | - Address the server is listening on. -- name: observer.version_major - type: byte - description: | - Major version number of the observer + Optional network fields + fields: + - name: carrier + type: group + description: | + Network operator + fields: + - name: icc + type: keyword + description: | + ISO country code, eg. US + - name: mcc + type: keyword + description: | + Mobile country code + - name: mnc + type: keyword + description: | + Mobile network code + - name: name + type: keyword + description: | + Carrier name, eg. Vodafone, T-Mobile, etc. + - name: connection + type: group + description: | + Network connection details + fields: + - name: subtype + type: keyword + description: | + Detailed network connection sub-type, e.g. "LTE", "CDMA" + - name: type + type: keyword + description: | + Network connection type, eg. "wifi", "cell" +- name: observer + type: group + fields: + - name: listening + type: keyword + description: | + Address the server is listening on. + - name: version_major + type: byte + description: | + Major version number of the observer - name: processor.event type: keyword description: Processor event. - name: processor.name type: keyword description: Processor name. -- name: service.environment - type: keyword - description: | - Service environment. -- name: service.framework.name - type: keyword +- name: service + type: group description: | - Name of the framework used. -- name: service.framework.version - type: keyword - description: | - Version of the framework used. -- name: service.language.name - type: keyword - description: | - Name of the programming language used. -- name: service.language.version - type: keyword - description: | - Version of the programming language used. -- name: service.runtime.name - type: keyword - description: | - Name of the runtime used. -- name: service.runtime.version - type: keyword - description: | - Version of the runtime used. -- name: system.cpu.total.norm.pct - type: scaled_float - format: percent - description: | - The percentage of CPU time spent by the process since the last event. This value is normalized by the number of CPU cores and it ranges from 0 to 100%. - metric_type: gauge - unit: percent -- name: system.memory.actual.free - type: long - format: bytes - description: | - Actual free memory in bytes. It is calculated based on the OS. On Linux it consists of the free memory plus caches and buffers. On OSX it is a sum of free memory and the inactive memory. On Windows, it is equal to `system.memory.free`. - metric_type: gauge - unit: byte -- name: system.memory.total - type: long - format: bytes - description: | - Total memory. - metric_type: gauge - unit: byte -- name: system.process.cgroup.cpu.cfs.period.us - type: long - description: CFS period in microseconds. - metric_type: gauge - unit: micros -- name: system.process.cgroup.cpu.cfs.quota.us - type: long - description: CFS quota in microseconds. - metric_type: gauge - unit: micros -- name: system.process.cgroup.cpu.id - type: keyword - description: ID for the current cgroup CPU. -- name: system.process.cgroup.cpu.stats.periods - type: long - description: Number of periods seen by the CPU. - metric_type: counter -- name: system.process.cgroup.cpu.stats.throttled.ns - type: long - description: Nanoseconds spent throttled seen by the CPU. - metric_type: counter - unit: nanos -- name: system.process.cgroup.cpu.stats.throttled.periods - type: long - description: Number of throttled periods seen by the CPU. - metric_type: counter -- name: system.process.cgroup.cpuacct.id - type: keyword - description: ID for the current cgroup CPU. -- name: system.process.cgroup.cpuacct.total.ns - type: long - description: Total CPU time for the current cgroup CPU in nanoseconds. - metric_type: counter - unit: nanos -- name: system.process.cgroup.memory.mem.limit.bytes - type: long - format: bytes - description: Memory limit for the current cgroup slice. - metric_type: gauge - unit: byte -- name: system.process.cgroup.memory.mem.usage.bytes - type: long - format: bytes - description: Memory usage by the current cgroup slice. - metric_type: gauge - unit: byte -- name: system.process.cpu.total.norm.pct - type: scaled_float - format: percent - description: | - The percentage of CPU time spent by the process since the last event. This value is normalized by the number of CPU cores and it ranges from 0 to 100%. - metric_type: gauge - unit: percent -- name: system.process.memory.rss.bytes - type: long - format: bytes - description: | - The Resident Set Size. The amount of memory the process occupied in main memory (RAM). - metric_type: gauge - unit: byte -- name: system.process.memory.size - type: long - format: bytes - description: | - The total virtual memory the process has. - metric_type: gauge - unit: byte -- name: timestamp.us - type: long + Service fields. + fields: + - name: environment + type: keyword + description: | + Service environment. + - name: framework + type: group + fields: + - name: name + type: keyword + description: | + Name of the framework used. + - name: version + type: keyword + description: | + Version of the framework used. + - name: language + type: group + fields: + - name: name + type: keyword + description: | + Name of the programming language used. + - name: version + type: keyword + description: | + Version of the programming language used. + - name: runtime + type: group + fields: + - name: name + type: keyword + description: | + Name of the runtime used. + - name: version + type: keyword + description: | + Version of the runtime used. +- name: system + type: group description: | - Timestamp of the event in microseconds since Unix epoch. + `system` contains local system metrics. + fields: + - name: cpu + type: group + description: | + `cpu` contains local CPU stats. + fields: + - name: total.norm.pct + type: scaled_float + format: percent + description: | + The percentage of CPU time spent by the process since the last event. This value is normalized by the number of CPU cores and it ranges from 0 to 100%. + metric_type: gauge + unit: percent + - name: memory + type: group + description: | + `memory` contains local memory stats. + fields: + - name: actual + type: group + description: | + Actual memory used and free. + fields: + - name: free + type: long + format: bytes + description: | + Actual free memory in bytes. It is calculated based on the OS. On Linux it consists of the free memory plus caches and buffers. On OSX it is a sum of free memory and the inactive memory. On Windows, it is equal to `system.memory.free`. + metric_type: gauge + unit: byte + - name: total + type: long + format: bytes + description: | + Total memory. + metric_type: gauge + unit: byte + - name: process + type: group + description: | + `process` contains process metadata, CPU metrics, and memory metrics. + fields: + - name: cgroup + type: group + description: Metrics and limits for the cgroup, collected by APM agents on Linux. + fields: + - name: cpu + type: group + description: CPU-specific cgroup metrics and limits. + fields: + - name: cfs + type: group + description: Completely Fair Scheduler (CFS) cgroup metrics. + fields: + - name: period.us + type: long + description: CFS period in microseconds. + metric_type: gauge + unit: micros + - name: quota.us + type: long + description: CFS quota in microseconds. + metric_type: gauge + unit: micros + - name: id + type: keyword + description: ID for the current cgroup CPU. + - name: stats.periods + type: long + description: Number of periods seen by the CPU. + metric_type: counter + - name: stats.throttled.ns + type: long + description: Nanoseconds spent throttled seen by the CPU. + metric_type: counter + unit: nanos + - name: stats.throttled.periods + type: long + description: Number of throttled periods seen by the CPU. + metric_type: counter + - name: cpuacct + type: group + description: CPU Accounting-specific cgroup metrics and limits. + fields: + - name: id + type: keyword + description: ID for the current cgroup CPU. + - name: total.ns + type: long + description: Total CPU time for the current cgroup CPU in nanoseconds. + metric_type: counter + unit: nanos + - name: memory + type: group + description: Memory-specific cgroup metrics and limits. + fields: + - name: mem.limit.bytes + type: long + format: bytes + description: Memory limit for the current cgroup slice. + metric_type: gauge + unit: byte + - name: mem.usage.bytes + type: long + format: bytes + description: Memory usage by the current cgroup slice. + metric_type: gauge + unit: byte + - name: cpu + type: group + description: | + `cpu` contains local CPU stats. + fields: + - name: total.norm.pct + type: scaled_float + format: percent + description: | + The percentage of CPU time spent by the process since the last event. This value is normalized by the number of CPU cores and it ranges from 0 to 100%. + metric_type: gauge + unit: percent + - name: memory + type: group + description: Memory-specific statistics per process. + fields: + - name: rss.bytes + type: long + format: bytes + description: | + The Resident Set Size. The amount of memory the process occupied in main memory (RAM). + metric_type: gauge + unit: byte + - name: size + type: long + format: bytes + description: | + The total virtual memory the process has. + metric_type: gauge + unit: byte +- name: timestamp + type: group + fields: + - name: us + type: long + description: | + Timestamp of the event in microseconds since Unix epoch. diff --git a/apmpackage/apm/data_stream/app_metrics/manifest.yml b/apmpackage/apm/data_stream/app_metrics/manifest.yml index 2f6fc978130..e3ad2aa7b64 100644 --- a/apmpackage/apm/data_stream/app_metrics/manifest.yml +++ b/apmpackage/apm/data_stream/app_metrics/manifest.yml @@ -3,3 +3,10 @@ type: metrics dataset: apm.app dataset_is_prefix: true ilm_policy: metrics-apm.app_metrics-default_policy +elasticsearch: + index_template: + mappings: + # Application metrics must be dynamically mapped, + # as their names are application-specific and not + # known ahead of time. + dynamic: true diff --git a/apmpackage/apm/data_stream/error_logs/fields/base-fields.yml b/apmpackage/apm/data_stream/error_logs/fields/base-fields.yml index bef973826be..bf9b70e13de 100644 --- a/apmpackage/apm/data_stream/error_logs/fields/base-fields.yml +++ b/apmpackage/apm/data_stream/error_logs/fields/base-fields.yml @@ -10,3 +10,6 @@ - name: data_stream.namespace type: constant_keyword description: Data stream namespace. +- name: ecs.version + type: keyword + description: ECS version the event conforms to. diff --git a/apmpackage/apm/data_stream/error_logs/fields/ecs.yml b/apmpackage/apm/data_stream/error_logs/fields/ecs.yml index 4e97756b7dd..e08d0951f19 100644 --- a/apmpackage/apm/data_stream/error_logs/fields/ecs.yml +++ b/apmpackage/apm/data_stream/error_logs/fields/ecs.yml @@ -1,142 +1,207 @@ -- name: agent.ephemeral_id - type: keyword - description: | - The Ephemeral ID identifies a running process. -- name: agent.name - type: keyword - description: | - Name of the agent used. -- name: agent.version - type: keyword - description: | - Version of the agent used. -- name: client.domain - type: keyword - description: | - Client domain. - ignore_above: 1024 -- name: client.ip - type: ip - description: | - IP address of the client of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. -- name: client.port - type: long - description: | - Port of the client. -- name: cloud.account.id - level: extended - type: keyword - description: Cloud account ID - ignore_above: 1024 -- name: cloud.account.name - level: extended - type: keyword - description: Cloud account name - ignore_above: 1024 -- name: cloud.availability_zone - level: extended - type: keyword - description: Cloud availability zone name - ignore_above: 1024 -- name: cloud.instance.id - level: extended - type: keyword - description: Cloud instance/machine ID - ignore_above: 1024 -- name: cloud.instance.name - level: extended - type: keyword - description: Cloud instance/machine name - ignore_above: 1024 -- name: cloud.machine.type - level: extended - type: keyword - description: Cloud instance/machine type - ignore_above: 1024 -- name: cloud.project.id - level: extended - type: keyword - description: Cloud project ID - ignore_above: 1024 -- name: cloud.project.name - level: extended - type: keyword - description: Cloud project name - ignore_above: 1024 -- name: cloud.provider - level: extended - type: keyword - description: Cloud provider name - ignore_above: 1024 -- name: cloud.region - level: extended - type: keyword - description: Cloud region name - ignore_above: 1024 -- name: cloud.service.name - level: extended - type: keyword - description: | - Cloud service name, intended to distinguish services running on different platforms within a provider. - ignore_above: 1024 -- name: container.id - type: keyword - description: | - Unique container id. -- name: destination.address - level: extended - type: keyword - description: Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is. - ignore_above: 1024 -- name: destination.ip - level: core - type: ip - description: IP addess of the destination. Can be one of multiple IPv4 or IPv6 addresses. -- name: destination.port - level: core - type: long - format: string - description: Port of the destination. -- name: error.id - type: keyword - description: | - The ID of the error. -- name: host.architecture - type: keyword - description: | - The architecture of the host the event was recorded on. -- name: host.hostname - type: keyword - description: | - The hostname of the host the event was recorded on. -- name: host.ip - type: ip - description: | - IP of the host that records the event. -- name: host.name - type: keyword - description: | - Name of the host the event was recorded on. It can contain same information as host.hostname or a name specified by the user. -- name: host.os.platform - type: keyword - description: | - The platform of the host the event was recorded on. -- name: http.request.method - type: keyword - description: | - The http method of the request leading to this event. -- name: http.request.referrer - type: keyword - description: Referrer for this HTTP request. - ignore_above: 1024 -- name: http.response.status_code - type: long - description: | - The status code of the HTTP response. -- name: http.version - type: keyword - description: | - The http version of the request leading to this event. +- name: agent + type: group + fields: + - name: ephemeral_id + type: keyword + description: | + The Ephemeral ID identifies a running process. + - name: name + type: keyword + description: | + Name of the agent used. + - name: version + type: keyword + description: | + Version of the agent used. +- name: client + type: group + fields: + - name: domain + type: keyword + description: | + Client domain. + ignore_above: 1024 + - name: ip + type: ip + description: | + IP address of the client of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. + - name: port + type: long + description: | + Port of the client. +- name: cloud + title: Cloud + type: group + description: | + Cloud metadata reported by agents + fields: + - name: account + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud account ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud account name + ignore_above: 1024 + - name: availability_zone + level: extended + type: keyword + description: Cloud availability zone name + ignore_above: 1024 + - name: instance + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud instance/machine ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud instance/machine name + ignore_above: 1024 + - name: machine + type: group + fields: + - name: type + level: extended + type: keyword + description: Cloud instance/machine type + ignore_above: 1024 + - name: project + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud project ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud project name + ignore_above: 1024 + - name: provider + level: extended + type: keyword + description: Cloud provider name + ignore_above: 1024 + - name: region + level: extended + type: keyword + description: Cloud region name + ignore_above: 1024 + - name: service + type: group + fields: + - name: name + level: extended + type: keyword + description: | + Cloud service name, intended to distinguish services running on different platforms within a provider. + ignore_above: 1024 +- name: container + title: Container + type: group + description: | + Container fields are used for meta information about the specific container that is the source of information. These fields help correlate data based containers from any runtime. + fields: + - name: id + type: keyword + description: | + Unique container id. +- name: destination + title: Destination + type: group + description: |- + Destination fields describe details about the destination of a packet/event. + Destination fields are usually populated in conjunction with source fields. + fields: + - name: address + level: extended + type: keyword + description: Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is. + ignore_above: 1024 + - name: ip + level: core + type: ip + description: IP addess of the destination. Can be one of multiple IPv4 or IPv6 addresses. + - name: port + level: core + type: long + format: string + description: Port of the destination. +- name: error + type: group + description: | + Data captured by an agent representing an event occurring in a monitored service. + fields: + - name: id + type: keyword + description: | + The ID of the error. +- name: host + type: group + description: | + Optional host fields. + fields: + - name: architecture + type: keyword + description: | + The architecture of the host the event was recorded on. + - name: hostname + type: keyword + description: | + The hostname of the host the event was recorded on. + - name: ip + type: ip + description: | + IP of the host that records the event. + - name: name + type: keyword + description: | + Name of the host the event was recorded on. It can contain same information as host.hostname or a name specified by the user. + - name: os + title: Operating System + type: group + description: | + The OS fields contain information about the operating system. + fields: + - name: platform + type: keyword + description: | + The platform of the host the event was recorded on. +- name: http + type: group + fields: + - name: request + type: group + fields: + - name: method + type: keyword + description: | + The http method of the request leading to this event. + - name: referrer + type: keyword + description: Referrer for this HTTP request. + ignore_above: 1024 + - name: response + type: group + fields: + - name: status_code + type: long + description: | + The status code of the HTTP response. + - name: version + type: keyword + description: | + The http version of the request leading to this event. - name: labels type: object description: | @@ -147,152 +212,203 @@ - object_type: boolean - object_type: scaled_float scaling_factor: 1000000 -- name: observer.hostname - type: keyword - description: | - Hostname of the APM Server. -- name: observer.type - type: keyword - description: | - The type will be set to `apm-server`. -- name: observer.version - type: keyword - description: | - APM Server version. -- name: process.args - level: extended - type: keyword - description: | - Process arguments. May be filtered to protect sensitive information. -- name: process.pid - type: long - description: | - Numeric process ID of the service process. -- name: process.ppid - type: long - description: | - Numeric ID of the service's parent process. -- name: process.title - type: keyword - description: | - Service process title. -- name: service.name - type: keyword - description: | - Immutable name of the service emitting this event. -- name: service.node.name - type: keyword - description: | - Unique meaningful name of the service node. -- name: service.version - type: keyword - description: | - Version of the service emitting this event. -- name: source.domain - type: keyword - description: | - Source domain. - ignore_above: 1024 -- name: source.ip - type: ip - description: | - IP address of the source of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. -- name: source.port - type: long - description: | - Port of the source. -- name: trace.id - type: keyword - description: | - The ID of the trace to which the event belongs to. -- name: transaction.id - type: keyword - description: | - The transaction ID. -- name: url.domain - type: keyword - description: | - The hostname of the request, e.g. "example.com". -- name: url.fragment - type: keyword - description: | - A fragment specifying a location in a web page , e.g. "top". -- name: url.full - type: keyword - description: | - The full, possibly agent-assembled URL of the request, e.g https://example.com:443/search?q=elasticsearch#top. -- name: url.path - type: keyword - description: | - The path of the request, e.g. "/search". -- name: url.port - type: long - description: | - The port of the request, e.g. 443. -- name: url.query - type: keyword - description: | - The query string of the request, e.g. "q=elasticsearch". -- name: url.scheme - type: keyword - description: | - The protocol of the request, e.g. "https:". -- name: user.domain - type: keyword - description: | - Domain of the logged in user. -- name: user.email - type: keyword - description: | - Email of the logged in user. -- name: user.id - type: keyword - description: | - Identifier of the logged in user. -- name: user.name - type: keyword - description: | - The username of the logged in user. -- name: user_agent.device.name - type: keyword - description: | - Name of the device. -- name: user_agent.name - type: keyword - description: | - Name of the user agent. -- name: user_agent.original - type: keyword - description: | - Unparsed version of the user_agent. - multi_fields: - - name: text - type: text -- name: user_agent.os.family - type: keyword - description: | - OS family (such as redhat, debian, freebsd, windows). -- name: user_agent.os.full - type: keyword - description: | - Operating system name, including the version or code name. -- name: user_agent.os.kernel - type: keyword - description: | - Operating system kernel version as a raw string. -- name: user_agent.os.name - type: keyword - description: | - Operating system name, without the version. -- name: user_agent.os.platform - type: keyword - description: | - Operating system platform (such centos, ubuntu, windows). -- name: user_agent.os.version - type: keyword - description: | - Operating system version as a raw string. -- name: user_agent.version - type: keyword - description: | - Version of the user agent. +- name: observer + type: group + fields: + - name: hostname + type: keyword + description: | + Hostname of the APM Server. + - name: type + type: keyword + description: | + The type will be set to `apm-server`. + - name: version + type: keyword + description: | + APM Server version. +- name: process + type: group + description: | + Information pertaining to the running process where the data was collected + fields: + - name: args + level: extended + type: keyword + description: | + Process arguments. May be filtered to protect sensitive information. + - name: pid + type: long + description: | + Numeric process ID of the service process. + - name: ppid + type: long + description: | + Numeric ID of the service's parent process. + - name: title + type: keyword + description: | + Service process title. +- name: service + type: group + description: | + Service fields. + fields: + - name: name + type: keyword + description: | + Immutable name of the service emitting this event. + - name: node + type: group + fields: + - name: name + type: keyword + description: | + Unique meaningful name of the service node. + - name: version + type: keyword + description: | + Version of the service emitting this event. +- name: source + type: group + fields: + - name: domain + type: keyword + description: | + Source domain. + ignore_above: 1024 + - name: ip + type: ip + description: | + IP address of the source of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. + - name: port + type: long + description: | + Port of the source. +- name: trace + type: group + fields: + - name: id + type: keyword + description: | + The ID of the trace to which the event belongs to. +- name: transaction + type: group + fields: + - name: id + type: keyword + description: | + The transaction ID. +- name: url + type: group + description: | + A complete Url, with scheme, host and path. + fields: + - name: domain + type: keyword + description: | + The hostname of the request, e.g. "example.com". + - name: fragment + type: keyword + description: | + A fragment specifying a location in a web page , e.g. "top". + - name: full + type: keyword + description: | + The full, possibly agent-assembled URL of the request, e.g https://example.com:443/search?q=elasticsearch#top. + - name: path + type: keyword + description: | + The path of the request, e.g. "/search". + - name: port + type: long + description: | + The port of the request, e.g. 443. + - name: query + type: keyword + description: | + The query string of the request, e.g. "q=elasticsearch". + - name: scheme + type: keyword + description: | + The protocol of the request, e.g. "https:". +- name: user + type: group + fields: + - name: domain + type: keyword + description: | + Domain of the logged in user. + - name: email + type: keyword + description: | + Email of the logged in user. + - name: id + type: keyword + description: | + Identifier of the logged in user. + - name: name + type: keyword + description: | + The username of the logged in user. +- name: user_agent + title: User agent + type: group + description: | + The user_agent fields normally come from a browser request. They often show up in web service logs coming from the parsed user agent string. + fields: + - name: device + title: Device + type: group + description: | + Information concerning the device. + fields: + - name: name + type: keyword + description: | + Name of the device. + - name: name + type: keyword + description: | + Name of the user agent. + - name: original + type: keyword + description: | + Unparsed version of the user_agent. + multi_fields: + - name: text + type: text + - name: os + title: Operating System + type: group + description: | + The OS fields contain information about the operating system. + fields: + - name: family + type: keyword + description: | + OS family (such as redhat, debian, freebsd, windows). + - name: full + type: keyword + description: | + Operating system name, including the version or code name. + - name: kernel + type: keyword + description: | + Operating system kernel version as a raw string. + - name: name + type: keyword + description: | + Operating system name, without the version. + - name: platform + type: keyword + description: | + Operating system platform (such centos, ubuntu, windows). + - name: version + type: keyword + description: | + Operating system version as a raw string. + - name: version + type: keyword + description: | + Version of the user agent. diff --git a/apmpackage/apm/data_stream/error_logs/fields/fields.yml b/apmpackage/apm/data_stream/error_logs/fields/fields.yml index 5c969b953c2..959cf10249c 100644 --- a/apmpackage/apm/data_stream/error_logs/fields/fields.yml +++ b/apmpackage/apm/data_stream/error_logs/fields/fields.yml @@ -1,160 +1,237 @@ -- name: error.culprit - type: keyword - description: Function call which was the primary perpetrator of this event. -- name: error.exception.code - type: keyword - description: The error code set when the error happened, e.g. database error code. -- name: error.exception.handled - type: boolean - description: Indicator whether the error was caught somewhere in the code or not. -- name: error.exception.message - type: text - description: The original error message. -- name: error.exception.module - type: keyword - description: The module namespace of the original error. -- name: error.exception.type - type: keyword - description: The type of the original error, e.g. the Java exception class name. -- name: error.grouping_key - type: keyword - description: | - Hash of select properties of the logged error for grouping purposes. -- name: error.grouping_name - type: keyword - description: | - Name to associate with an error group. Errors belonging to the same group (same grouping_key) may have differing values for grouping_name. Consumers may choose one arbitrarily. -- name: error.log.level - type: keyword - description: The severity of the record. -- name: error.log.logger_name - type: keyword - description: The name of the logger instance used. -- name: error.log.message - type: text - description: The additionally logged error message. -- name: error.log.param_message - type: keyword - description: | - A parametrized message. E.g. 'Could not connect to %s'. The property message is still required, and should be equal to the param_message, but with placeholders replaced. In some situations the param_message is used to group errors together. +- name: error + type: group + description: | + Data captured by an agent representing an event occurring in a monitored service. + fields: + - name: culprit + type: keyword + description: Function call which was the primary perpetrator of this event. + - name: exception + type: group + description: | + Information about the originally thrown error. + fields: + - name: code + type: keyword + description: The error code set when the error happened, e.g. database error code. + - name: handled + type: boolean + description: Indicator whether the error was caught somewhere in the code or not. + - name: message + type: text + description: The original error message. + - name: module + type: keyword + description: The module namespace of the original error. + - name: type + type: keyword + description: The type of the original error, e.g. the Java exception class name. + - name: grouping_key + type: keyword + description: | + Hash of select properties of the logged error for grouping purposes. + - name: grouping_name + type: keyword + description: | + Name to associate with an error group. Errors belonging to the same group (same grouping_key) may have differing values for grouping_name. Consumers may choose one arbitrarily. + - name: log + type: group + description: | + Additional information added by logging the error. + fields: + - name: level + type: keyword + description: The severity of the record. + - name: logger_name + type: keyword + description: The name of the logger instance used. + - name: message + type: text + description: The additionally logged error message. + - name: param_message + type: keyword + description: | + A parametrized message. E.g. 'Could not connect to %s'. The property message is still required, and should be equal to the param_message, but with placeholders replaced. In some situations the param_message is used to group errors together. - name: experimental type: object description: Additional experimental data sent by the agents. dynamic: true -- name: http.request.headers - type: object - description: | - The canonical headers of the monitored HTTP request. -- name: http.response.finished - type: boolean - description: | - Used by the Node agent to indicate when in the response life cycle an error has occurred. -- name: http.response.headers - type: object - description: | - The canonical headers of the monitored HTTP response. -- name: kubernetes.namespace - type: keyword - description: | - Kubernetes namespace -- name: kubernetes.node.name - type: keyword - description: | - Kubernetes node name -- name: kubernetes.pod.name - type: keyword - description: | - Kubernetes pod name -- name: kubernetes.pod.uid - type: keyword - description: | - Kubernetes Pod UID -- name: network.carrier.icc - type: keyword - description: | - ISO country code, eg. US -- name: network.carrier.mcc - type: keyword - description: | - Mobile country code -- name: network.carrier.mnc - type: keyword - description: | - Mobile network code -- name: network.carrier.name - type: keyword - description: | - Carrier name, eg. Vodafone, T-Mobile, etc. -- name: network.connection.subtype - type: keyword - description: | - Detailed network connection sub-type, e.g. "LTE", "CDMA" -- name: network.connection.type - type: keyword - description: | - Network connection type, eg. "wifi", "cell" -- name: observer.listening - type: keyword - description: | - Address the server is listening on. -- name: observer.version_major - type: byte - description: | - Major version number of the observer -- name: parent.id - type: keyword - description: | - The ID of the parent event. +- name: http + type: group + fields: + - name: request + type: group + fields: + - name: headers + type: object + description: | + The canonical headers of the monitored HTTP request. + - name: response + type: group + fields: + - name: finished + type: boolean + description: | + Used by the Node agent to indicate when in the response life cycle an error has occurred. + - name: headers + type: object + description: | + The canonical headers of the monitored HTTP response. +- name: kubernetes + title: Kubernetes + type: group + description: | + Kubernetes metadata reported by agents + fields: + - name: namespace + type: keyword + description: | + Kubernetes namespace + - name: node + type: group + fields: + - name: name + type: keyword + description: | + Kubernetes node name + - name: pod + type: group + fields: + - name: name + type: keyword + description: | + Kubernetes pod name + - name: uid + type: keyword + description: | + Kubernetes Pod UID +- name: network + type: group + description: | + Optional network fields + fields: + - name: carrier + type: group + description: | + Network operator + fields: + - name: icc + type: keyword + description: | + ISO country code, eg. US + - name: mcc + type: keyword + description: | + Mobile country code + - name: mnc + type: keyword + description: | + Mobile network code + - name: name + type: keyword + description: | + Carrier name, eg. Vodafone, T-Mobile, etc. + - name: connection + type: group + description: | + Network connection details + fields: + - name: subtype + type: keyword + description: | + Detailed network connection sub-type, e.g. "LTE", "CDMA" + - name: type + type: keyword + description: | + Network connection type, eg. "wifi", "cell" +- name: observer + type: group + fields: + - name: listening + type: keyword + description: | + Address the server is listening on. + - name: version_major + type: byte + description: | + Major version number of the observer +- name: parent + type: group + fields: + - name: id + type: keyword + description: | + The ID of the parent event. - name: processor.event type: keyword description: Processor event. - name: processor.name type: keyword description: Processor name. -- name: service.environment - type: keyword - description: | - Service environment. -- name: service.framework.name - type: keyword - description: | - Name of the framework used. -- name: service.framework.version - type: keyword - description: | - Version of the framework used. -- name: service.language.name - type: keyword - description: | - Name of the programming language used. -- name: service.language.version - type: keyword - description: | - Version of the programming language used. -- name: service.runtime.name - type: keyword - description: | - Name of the runtime used. -- name: service.runtime.version - type: keyword - description: | - Version of the runtime used. -- name: timestamp.us - type: long - description: | - Timestamp of the event in microseconds since Unix epoch. -- name: transaction.name - type: keyword - description: | - Generic designation of a transaction in the scope of a single service (eg. 'GET /users/:id'). - multi_fields: - - name: text - type: text -- name: transaction.sampled - type: boolean - description: | - Transactions that are 'sampled' will include all available information. Transactions that are not sampled will not have spans or context. -- name: transaction.type - type: keyword - description: | - Keyword of specific relevance in the service's domain (eg. 'request', 'backgroundjob', etc) +- name: service + type: group + description: | + Service fields. + fields: + - name: environment + type: keyword + description: | + Service environment. + - name: framework + type: group + fields: + - name: name + type: keyword + description: | + Name of the framework used. + - name: version + type: keyword + description: | + Version of the framework used. + - name: language + type: group + fields: + - name: name + type: keyword + description: | + Name of the programming language used. + - name: version + type: keyword + description: | + Version of the programming language used. + - name: runtime + type: group + fields: + - name: name + type: keyword + description: | + Name of the runtime used. + - name: version + type: keyword + description: | + Version of the runtime used. +- name: timestamp + type: group + fields: + - name: us + type: long + description: | + Timestamp of the event in microseconds since Unix epoch. +- name: transaction + type: group + fields: + - name: name + type: keyword + description: | + Generic designation of a transaction in the scope of a single service (eg. 'GET /users/:id'). + multi_fields: + - name: text + type: text + - name: sampled + type: boolean + description: | + Transactions that are 'sampled' will include all available information. Transactions that are not sampled will not have spans or context. + - name: type + type: keyword + description: | + Keyword of specific relevance in the service's domain (eg. 'request', 'backgroundjob', etc) diff --git a/apmpackage/apm/data_stream/error_logs/manifest.yml b/apmpackage/apm/data_stream/error_logs/manifest.yml index 8c7df729177..06d22a1a4e7 100644 --- a/apmpackage/apm/data_stream/error_logs/manifest.yml +++ b/apmpackage/apm/data_stream/error_logs/manifest.yml @@ -2,3 +2,11 @@ title: APM logs and errors type: logs dataset: apm.error ilm_policy: logs-apm.error_logs-default_policy +elasticsearch: + index_template: + mappings: + # TODO(axw) investigate setting `dynamic: runtime`, so that fields are + # runtime searchable by default. That way users can, for example, perform + # ad-hoc searches on HTTP request headers without incurring storage cost + # for users who do not need this capability. + dynamic: false diff --git a/apmpackage/apm/data_stream/internal_metrics/fields/base-fields.yml b/apmpackage/apm/data_stream/internal_metrics/fields/base-fields.yml index bef973826be..bf9b70e13de 100644 --- a/apmpackage/apm/data_stream/internal_metrics/fields/base-fields.yml +++ b/apmpackage/apm/data_stream/internal_metrics/fields/base-fields.yml @@ -10,3 +10,6 @@ - name: data_stream.namespace type: constant_keyword description: Data stream namespace. +- name: ecs.version + type: keyword + description: ECS version the event conforms to. diff --git a/apmpackage/apm/data_stream/internal_metrics/fields/ecs.yml b/apmpackage/apm/data_stream/internal_metrics/fields/ecs.yml index 313e6e23b71..181d9ce8d43 100644 --- a/apmpackage/apm/data_stream/internal_metrics/fields/ecs.yml +++ b/apmpackage/apm/data_stream/internal_metrics/fields/ecs.yml @@ -1,128 +1,182 @@ -- name: agent.ephemeral_id - type: keyword - description: | - The Ephemeral ID identifies a running process. -- name: agent.name - type: keyword - description: | - Name of the agent used. -- name: agent.version - type: keyword - description: | - Version of the agent used. -- name: client.domain - type: keyword - description: | - Client domain. - ignore_above: 1024 -- name: client.ip - type: ip - description: | - IP address of the client of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. -- name: client.port - type: long - description: | - Port of the client. -- name: cloud.account.id - level: extended - type: keyword - description: Cloud account ID - ignore_above: 1024 -- name: cloud.account.name - level: extended - type: keyword - description: Cloud account name - ignore_above: 1024 -- name: cloud.availability_zone - level: extended - type: keyword - description: Cloud availability zone name - ignore_above: 1024 -- name: cloud.instance.id - level: extended - type: keyword - description: Cloud instance/machine ID - ignore_above: 1024 -- name: cloud.instance.name - level: extended - type: keyword - description: Cloud instance/machine name - ignore_above: 1024 -- name: cloud.machine.type - level: extended - type: keyword - description: Cloud instance/machine type - ignore_above: 1024 -- name: cloud.project.id - level: extended - type: keyword - description: Cloud project ID - ignore_above: 1024 -- name: cloud.project.name - level: extended - type: keyword - description: Cloud project name - ignore_above: 1024 -- name: cloud.provider - level: extended - type: keyword - description: Cloud provider name - ignore_above: 1024 -- name: cloud.region - level: extended - type: keyword - description: Cloud region name - ignore_above: 1024 -- name: cloud.service.name - level: extended - type: keyword - description: | - Cloud service name, intended to distinguish services running on different platforms within a provider. - ignore_above: 1024 -- name: container.id - type: keyword - description: | - Unique container id. -- name: destination.address - level: extended - type: keyword - description: Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is. - ignore_above: 1024 -- name: destination.ip - level: core - type: ip - description: IP addess of the destination. Can be one of multiple IPv4 or IPv6 addresses. -- name: destination.port - level: core - type: long - format: string - description: Port of the destination. -- name: event.outcome - level: core - type: keyword - description: | - `event.outcome` simply denotes whether the event represents a success or a failure from the perspective of the entity that produced the event. - ignore_above: 1024 -- name: host.architecture - type: keyword - description: | - The architecture of the host the event was recorded on. -- name: host.hostname - type: keyword - description: | - The hostname of the host the event was recorded on. -- name: host.ip - type: ip - description: | - IP of the host that records the event. -- name: host.name - type: keyword - description: | - Name of the host the event was recorded on. It can contain same information as host.hostname or a name specified by the user. -- name: host.os.platform - type: keyword - description: | - The platform of the host the event was recorded on. +- name: agent + type: group + fields: + - name: ephemeral_id + type: keyword + description: | + The Ephemeral ID identifies a running process. + - name: name + type: keyword + description: | + Name of the agent used. + - name: version + type: keyword + description: | + Version of the agent used. +- name: client + type: group + fields: + - name: domain + type: keyword + description: | + Client domain. + ignore_above: 1024 + - name: ip + type: ip + description: | + IP address of the client of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. + - name: port + type: long + description: | + Port of the client. +- name: cloud + title: Cloud + type: group + description: | + Cloud metadata reported by agents + fields: + - name: account + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud account ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud account name + ignore_above: 1024 + - name: availability_zone + level: extended + type: keyword + description: Cloud availability zone name + ignore_above: 1024 + - name: instance + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud instance/machine ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud instance/machine name + ignore_above: 1024 + - name: machine + type: group + fields: + - name: type + level: extended + type: keyword + description: Cloud instance/machine type + ignore_above: 1024 + - name: project + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud project ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud project name + ignore_above: 1024 + - name: provider + level: extended + type: keyword + description: Cloud provider name + ignore_above: 1024 + - name: region + level: extended + type: keyword + description: Cloud region name + ignore_above: 1024 + - name: service + type: group + fields: + - name: name + level: extended + type: keyword + description: | + Cloud service name, intended to distinguish services running on different platforms within a provider. + ignore_above: 1024 +- name: container + title: Container + type: group + description: | + Container fields are used for meta information about the specific container that is the source of information. These fields help correlate data based containers from any runtime. + fields: + - name: id + type: keyword + description: | + Unique container id. +- name: destination + title: Destination + type: group + description: |- + Destination fields describe details about the destination of a packet/event. + Destination fields are usually populated in conjunction with source fields. + fields: + - name: address + level: extended + type: keyword + description: Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is. + ignore_above: 1024 + - name: ip + level: core + type: ip + description: IP addess of the destination. Can be one of multiple IPv4 or IPv6 addresses. + - name: port + level: core + type: long + format: string + description: Port of the destination. +- name: event + type: group + fields: + - name: outcome + level: core + type: keyword + description: | + `event.outcome` simply denotes whether the event represents a success or a failure from the perspective of the entity that produced the event. + ignore_above: 1024 +- name: host + type: group + description: | + Optional host fields. + fields: + - name: architecture + type: keyword + description: | + The architecture of the host the event was recorded on. + - name: hostname + type: keyword + description: | + The hostname of the host the event was recorded on. + - name: ip + type: ip + description: | + IP of the host that records the event. + - name: name + type: keyword + description: | + Name of the host the event was recorded on. It can contain same information as host.hostname or a name specified by the user. + - name: os + title: Operating System + type: group + description: | + The OS fields contain information about the operating system. + fields: + - name: platform + type: keyword + description: | + The platform of the host the event was recorded on. - name: labels type: object description: | @@ -133,116 +187,159 @@ - object_type: boolean - object_type: scaled_float scaling_factor: 1000000 -- name: observer.hostname - type: keyword - description: | - Hostname of the APM Server. -- name: observer.type - type: keyword - description: | - The type will be set to `apm-server`. -- name: observer.version - type: keyword - description: | - APM Server version. -- name: process.args - level: extended - type: keyword - description: | - Process arguments. May be filtered to protect sensitive information. -- name: process.pid - type: long - description: | - Numeric process ID of the service process. -- name: process.ppid - type: long - description: | - Numeric ID of the service's parent process. -- name: process.title - type: keyword - description: | - Service process title. -- name: service.name - type: keyword - description: | - Immutable name of the service emitting this event. -- name: service.node.name - type: keyword - description: | - Unique meaningful name of the service node. -- name: service.version - type: keyword - description: | - Version of the service emitting this event. -- name: source.domain - type: keyword - description: | - Source domain. - ignore_above: 1024 -- name: source.ip - type: ip - description: | - IP address of the source of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. -- name: source.port - type: long - description: | - Port of the source. -- name: transaction.id - type: keyword - description: | - The transaction ID. -- name: user.email - type: keyword - description: | - Email of the logged in user. -- name: user.id - type: keyword - description: | - Identifier of the logged in user. -- name: user.name - type: keyword - description: | - The username of the logged in user. -- name: user_agent.device.name - type: keyword - description: | - Name of the device. -- name: user_agent.name - type: keyword - description: | - Name of the user agent. -- name: user_agent.original - type: keyword - description: | - Unparsed version of the user_agent. - multi_fields: - - name: text - type: text -- name: user_agent.os.family - type: keyword - description: | - OS family (such as redhat, debian, freebsd, windows). -- name: user_agent.os.full - type: keyword - description: | - Operating system name, including the version or code name. -- name: user_agent.os.kernel - type: keyword - description: | - Operating system kernel version as a raw string. -- name: user_agent.os.name - type: keyword - description: | - Operating system name, without the version. -- name: user_agent.os.platform - type: keyword - description: | - Operating system platform (such centos, ubuntu, windows). -- name: user_agent.os.version - type: keyword - description: | - Operating system version as a raw string. -- name: user_agent.version - type: keyword - description: | - Version of the user agent. +- name: observer + type: group + fields: + - name: hostname + type: keyword + description: | + Hostname of the APM Server. + - name: type + type: keyword + description: | + The type will be set to `apm-server`. + - name: version + type: keyword + description: | + APM Server version. +- name: process + type: group + description: | + Information pertaining to the running process where the data was collected + fields: + - name: args + level: extended + type: keyword + description: | + Process arguments. May be filtered to protect sensitive information. + - name: pid + type: long + description: | + Numeric process ID of the service process. + - name: ppid + type: long + description: | + Numeric ID of the service's parent process. + - name: title + type: keyword + description: | + Service process title. +- name: service + type: group + description: | + Service fields. + fields: + - name: name + type: keyword + description: | + Immutable name of the service emitting this event. + - name: node + type: group + fields: + - name: name + type: keyword + description: | + Unique meaningful name of the service node. + - name: version + type: keyword + description: | + Version of the service emitting this event. +- name: source + type: group + fields: + - name: domain + type: keyword + description: | + Source domain. + ignore_above: 1024 + - name: ip + type: ip + description: | + IP address of the source of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. + - name: port + type: long + description: | + Port of the source. +- name: transaction + type: group + fields: + - name: id + type: keyword + description: | + The transaction ID. +- name: user + type: group + fields: + - name: email + type: keyword + description: | + Email of the logged in user. + - name: id + type: keyword + description: | + Identifier of the logged in user. + - name: name + type: keyword + description: | + The username of the logged in user. +- name: user_agent + title: User agent + type: group + description: | + The user_agent fields normally come from a browser request. They often show up in web service logs coming from the parsed user agent string. + fields: + - name: device + title: Device + type: group + description: | + Information concerning the device. + fields: + - name: name + type: keyword + description: | + Name of the device. + - name: name + type: keyword + description: | + Name of the user agent. + - name: original + type: keyword + description: | + Unparsed version of the user_agent. + multi_fields: + - name: text + type: text + - name: os + title: Operating System + type: group + description: | + The OS fields contain information about the operating system. + fields: + - name: family + type: keyword + description: | + OS family (such as redhat, debian, freebsd, windows). + - name: full + type: keyword + description: | + Operating system name, including the version or code name. + - name: kernel + type: keyword + description: | + Operating system kernel version as a raw string. + - name: name + type: keyword + description: | + Operating system name, without the version. + - name: platform + type: keyword + description: | + Operating system platform (such centos, ubuntu, windows). + - name: version + type: keyword + description: | + Operating system version as a raw string. + - name: version + type: keyword + description: | + Version of the user agent. diff --git a/apmpackage/apm/data_stream/internal_metrics/fields/fields.yml b/apmpackage/apm/data_stream/internal_metrics/fields/fields.yml index e2a253809e9..6ecd9aa2b01 100644 --- a/apmpackage/apm/data_stream/internal_metrics/fields/fields.yml +++ b/apmpackage/apm/data_stream/internal_metrics/fields/fields.yml @@ -4,250 +4,388 @@ dynamic: true - name: histogram type: histogram -- name: kubernetes.namespace - type: keyword - description: | - Kubernetes namespace -- name: kubernetes.node.name - type: keyword - description: | - Kubernetes node name -- name: kubernetes.pod.name - type: keyword - description: | - Kubernetes pod name -- name: kubernetes.pod.uid - type: keyword - description: | - Kubernetes Pod UID -- name: metricset.name - type: keyword - description: | - Name of the set of metrics. +- name: kubernetes + title: Kubernetes + type: group + description: | + Kubernetes metadata reported by agents + fields: + - name: namespace + type: keyword + description: | + Kubernetes namespace + - name: node + type: group + fields: + - name: name + type: keyword + description: | + Kubernetes node name + - name: pod + type: group + fields: + - name: name + type: keyword + description: | + Kubernetes pod name + - name: uid + type: keyword + description: | + Kubernetes Pod UID +- name: metricset + type: group + fields: + - name: name + type: keyword + description: | + Name of the set of metrics. - name: metricset.period type: long description: Current data collection period for this event in milliseconds. unit: ms -- name: network.carrier.icc - type: keyword - description: | - ISO country code, eg. US -- name: network.carrier.mcc - type: keyword - description: | - Mobile country code -- name: network.carrier.mnc - type: keyword - description: | - Mobile network code -- name: network.carrier.name - type: keyword - description: | - Carrier name, eg. Vodafone, T-Mobile, etc. -- name: network.connection.subtype - type: keyword - description: | - Detailed network connection sub-type, e.g. "LTE", "CDMA" -- name: network.connection.type - type: keyword - description: | - Network connection type, eg. "wifi", "cell" -- name: observer.listening - type: keyword - description: | - Address the server is listening on. -- name: observer.version_major - type: byte - description: | - Major version number of the observer +- name: network + type: group + description: | + Optional network fields + fields: + - name: carrier + type: group + description: | + Network operator + fields: + - name: icc + type: keyword + description: | + ISO country code, eg. US + - name: mcc + type: keyword + description: | + Mobile country code + - name: mnc + type: keyword + description: | + Mobile network code + - name: name + type: keyword + description: | + Carrier name, eg. Vodafone, T-Mobile, etc. + - name: connection + type: group + description: | + Network connection details + fields: + - name: subtype + type: keyword + description: | + Detailed network connection sub-type, e.g. "LTE", "CDMA" + - name: type + type: keyword + description: | + Network connection type, eg. "wifi", "cell" +- name: observer + type: group + fields: + - name: listening + type: keyword + description: | + Address the server is listening on. + - name: version_major + type: byte + description: | + Major version number of the observer - name: processor.event type: keyword description: Processor event. - name: processor.name type: keyword description: Processor name. -- name: service.environment - type: keyword - description: | - Service environment. -- name: service.framework.name - type: keyword - description: | - Name of the framework used. -- name: service.framework.version - type: keyword - description: | - Version of the framework used. -- name: service.language.name - type: keyword - description: | - Name of the programming language used. -- name: service.language.version - type: keyword - description: | - Version of the programming language used. -- name: service.runtime.name - type: keyword - description: | - Name of the runtime used. -- name: service.runtime.version - type: keyword - description: | - Version of the runtime used. -- name: span.destination.service.response_time.count - type: long - description: Number of aggregated outgoing requests. -- name: span.destination.service.response_time.sum.us - type: long - description: Aggregated duration of outgoing requests, in microseconds. - unit: micros -- name: span.self_time.count - type: long - description: Number of aggregated spans. -- name: span.self_time.sum.us - type: long - description: | - Aggregated span duration, excluding the time periods where a direct child was running, in microseconds. - unit: micros -- name: span.subtype - type: keyword - description: | - A further sub-division of the type (e.g. postgresql, elasticsearch) -- name: span.type - type: keyword - description: | - Keyword of specific relevance in the service's domain (eg: 'db.postgresql.query', 'template.erb', 'cache', etc). -- name: system.cpu.total.norm.pct - type: scaled_float - format: percent - description: | - The percentage of CPU time spent by the process since the last event. This value is normalized by the number of CPU cores and it ranges from 0 to 100%. - metric_type: gauge - unit: percent -- name: system.memory.actual.free - type: long - format: bytes - description: | - Actual free memory in bytes. It is calculated based on the OS. On Linux it consists of the free memory plus caches and buffers. On OSX it is a sum of free memory and the inactive memory. On Windows, it is equal to `system.memory.free`. - metric_type: gauge - unit: byte -- name: system.memory.total - type: long - format: bytes - description: | - Total memory. - metric_type: gauge - unit: byte -- name: system.process.cgroup.cpu.cfs.period.us - type: long - description: CFS period in microseconds. - metric_type: gauge - unit: micros -- name: system.process.cgroup.cpu.cfs.quota.us - type: long - description: CFS quota in microseconds. - metric_type: gauge - unit: micros -- name: system.process.cgroup.cpu.id - type: keyword - description: ID for the current cgroup CPU. -- name: system.process.cgroup.cpu.stats.periods - type: long - description: Number of periods seen by the CPU. - metric_type: counter -- name: system.process.cgroup.cpu.stats.throttled.ns - type: long - description: Nanoseconds spent throttled seen by the CPU. - metric_type: counter - unit: nanos -- name: system.process.cgroup.cpu.stats.throttled.periods - type: long - description: Number of throttled periods seen by the CPU. - metric_type: counter -- name: system.process.cgroup.cpuacct.id - type: keyword - description: ID for the current cgroup CPU. -- name: system.process.cgroup.cpuacct.total.ns - type: long - description: Total CPU time for the current cgroup CPU in nanoseconds. - metric_type: counter - unit: nanos -- name: system.process.cgroup.memory.mem.limit.bytes - type: long - format: bytes - description: Memory limit for the current cgroup slice. - metric_type: gauge - unit: byte -- name: system.process.cgroup.memory.mem.usage.bytes - type: long - format: bytes - description: Memory usage by the current cgroup slice. - metric_type: gauge - unit: byte -- name: system.process.cpu.total.norm.pct - type: scaled_float - format: percent - description: | - The percentage of CPU time spent by the process since the last event. This value is normalized by the number of CPU cores and it ranges from 0 to 100%. - metric_type: gauge - unit: percent -- name: system.process.memory.rss.bytes - type: long - format: bytes - description: | - The Resident Set Size. The amount of memory the process occupied in main memory (RAM). - metric_type: gauge - unit: byte -- name: system.process.memory.size - type: long - format: bytes - description: | - The total virtual memory the process has. - metric_type: gauge - unit: byte -- name: timestamp.us - type: long - description: | - Timestamp of the event in microseconds since Unix epoch. -- name: transaction.breakdown.count - type: long - description: | - Counter for collected breakdowns for the transaction -- name: transaction.duration.count - type: long - description: Number of aggregated transactions. -- name: transaction.duration.histogram - type: histogram - description: | - Pre-aggregated histogram of transaction durations. -- name: transaction.duration.sum.us - type: long - description: Aggregated transaction duration, in microseconds. - unit: micros -- name: transaction.name - type: keyword - description: | - Generic designation of a transaction in the scope of a single service (eg. 'GET /users/:id'). - multi_fields: - - name: text - type: text -- name: transaction.root - type: boolean - description: | - Identifies metrics for root transactions. This can be used for calculating metrics for traces. -- name: transaction.sampled - type: boolean - description: | - Transactions that are 'sampled' will include all available information. Transactions that are not sampled will not have spans or context. -- name: transaction.self_time.count - type: long - description: Number of aggregated transactions. -- name: transaction.self_time.sum.us - type: long - description: | - Aggregated transaction duration, excluding the time periods where a direct child was running, in microseconds. - unit: micros -- name: transaction.type - type: keyword - description: | - Keyword of specific relevance in the service's domain (eg. 'request', 'backgroundjob', etc) +- name: service + type: group + description: | + Service fields. + fields: + - name: environment + type: keyword + description: | + Service environment. + - name: framework + type: group + fields: + - name: name + type: keyword + description: | + Name of the framework used. + - name: version + type: keyword + description: | + Version of the framework used. + - name: language + type: group + fields: + - name: name + type: keyword + description: | + Name of the programming language used. + - name: version + type: keyword + description: | + Version of the programming language used. + - name: runtime + type: group + fields: + - name: name + type: keyword + description: | + Name of the runtime used. + - name: version + type: keyword + description: | + Version of the runtime used. +- name: span + type: group + fields: + - name: destination.service + type: group + fields: + - name: response_time.count + type: long + description: Number of aggregated outgoing requests. + - name: response_time.sum.us + type: long + description: Aggregated duration of outgoing requests, in microseconds. + unit: micros + - name: self_time + type: group + description: | + Portion of the span's duration where no direct child was running + fields: + - name: count + type: long + description: Number of aggregated spans. + - name: sum + type: group + fields: + - name: us + type: long + description: | + Aggregated span duration, excluding the time periods where a direct child was running, in microseconds. + unit: micros + - name: subtype + type: keyword + description: | + A further sub-division of the type (e.g. postgresql, elasticsearch) + - name: type + type: keyword + description: | + Keyword of specific relevance in the service's domain (eg: 'db.postgresql.query', 'template.erb', 'cache', etc). +- name: system + type: group + description: | + `system` contains local system metrics. + fields: + - name: cpu + type: group + description: | + `cpu` contains local CPU stats. + fields: + - name: total.norm.pct + type: scaled_float + format: percent + description: | + The percentage of CPU time spent by the process since the last event. This value is normalized by the number of CPU cores and it ranges from 0 to 100%. + metric_type: gauge + unit: percent + - name: memory + type: group + description: | + `memory` contains local memory stats. + fields: + - name: actual + type: group + description: | + Actual memory used and free. + fields: + - name: free + type: long + format: bytes + description: | + Actual free memory in bytes. It is calculated based on the OS. On Linux it consists of the free memory plus caches and buffers. On OSX it is a sum of free memory and the inactive memory. On Windows, it is equal to `system.memory.free`. + metric_type: gauge + unit: byte + - name: total + type: long + format: bytes + description: | + Total memory. + metric_type: gauge + unit: byte + - name: process + type: group + description: | + `process` contains process metadata, CPU metrics, and memory metrics. + fields: + - name: cgroup + type: group + description: Metrics and limits for the cgroup, collected by APM agents on Linux. + fields: + - name: cpu + type: group + description: CPU-specific cgroup metrics and limits. + fields: + - name: cfs + type: group + description: Completely Fair Scheduler (CFS) cgroup metrics. + fields: + - name: period.us + type: long + description: CFS period in microseconds. + metric_type: gauge + unit: micros + - name: quota.us + type: long + description: CFS quota in microseconds. + metric_type: gauge + unit: micros + - name: id + type: keyword + description: ID for the current cgroup CPU. + - name: stats.periods + type: long + description: Number of periods seen by the CPU. + metric_type: counter + - name: stats.throttled.ns + type: long + description: Nanoseconds spent throttled seen by the CPU. + metric_type: counter + unit: nanos + - name: stats.throttled.periods + type: long + description: Number of throttled periods seen by the CPU. + metric_type: counter + - name: cpuacct + type: group + description: CPU Accounting-specific cgroup metrics and limits. + fields: + - name: id + type: keyword + description: ID for the current cgroup CPU. + - name: total.ns + type: long + description: Total CPU time for the current cgroup CPU in nanoseconds. + metric_type: counter + unit: nanos + - name: memory + type: group + description: Memory-specific cgroup metrics and limits. + fields: + - name: mem.limit.bytes + type: long + format: bytes + description: Memory limit for the current cgroup slice. + metric_type: gauge + unit: byte + - name: mem.usage.bytes + type: long + format: bytes + description: Memory usage by the current cgroup slice. + metric_type: gauge + unit: byte + - name: cpu + type: group + description: | + `cpu` contains local CPU stats. + fields: + - name: total.norm.pct + type: scaled_float + format: percent + description: | + The percentage of CPU time spent by the process since the last event. This value is normalized by the number of CPU cores and it ranges from 0 to 100%. + metric_type: gauge + unit: percent + - name: memory + type: group + description: Memory-specific statistics per process. + fields: + - name: rss.bytes + type: long + format: bytes + description: | + The Resident Set Size. The amount of memory the process occupied in main memory (RAM). + metric_type: gauge + unit: byte + - name: size + type: long + format: bytes + description: | + The total virtual memory the process has. + metric_type: gauge + unit: byte +- name: timestamp + type: group + fields: + - name: us + type: long + description: | + Timestamp of the event in microseconds since Unix epoch. +- name: transaction + type: group + fields: + - name: breakdown + type: group + fields: + - name: count + type: long + description: | + Counter for collected breakdowns for the transaction + - name: duration + type: group + fields: + - name: count + type: long + description: Number of aggregated transactions. + - name: histogram + type: histogram + description: | + Pre-aggregated histogram of transaction durations. + - name: sum + type: group + fields: + - name: us + type: long + description: Aggregated transaction duration, in microseconds. + unit: micros + - name: name + type: keyword + description: | + Generic designation of a transaction in the scope of a single service (eg. 'GET /users/:id'). + multi_fields: + - name: text + type: text + - name: root + type: boolean + description: | + Identifies metrics for root transactions. This can be used for calculating metrics for traces. + - name: sampled + type: boolean + description: | + Transactions that are 'sampled' will include all available information. Transactions that are not sampled will not have spans or context. + - name: self_time + type: group + description: | + Portion of the transaction's duration where no direct child was running + fields: + - name: count + type: long + description: Number of aggregated transactions. + - name: sum + type: group + fields: + - name: us + type: long + description: | + Aggregated transaction duration, excluding the time periods where a direct child was running, in microseconds. + unit: micros + - name: type + type: keyword + description: | + Keyword of specific relevance in the service's domain (eg. 'request', 'backgroundjob', etc) diff --git a/apmpackage/apm/data_stream/internal_metrics/manifest.yml b/apmpackage/apm/data_stream/internal_metrics/manifest.yml index fcc5fd31d5d..a9041d4297e 100644 --- a/apmpackage/apm/data_stream/internal_metrics/manifest.yml +++ b/apmpackage/apm/data_stream/internal_metrics/manifest.yml @@ -2,3 +2,9 @@ title: APM internal metrics type: metrics dataset: apm.internal ilm_policy: metrics-apm.internal_metrics-default_policy +elasticsearch: + index_template: + mappings: + # Internal metrics should have all fields strictly mapped; + # we are in full control of the field names. + dynamic: strict diff --git a/apmpackage/apm/data_stream/profile_metrics/fields/base-fields.yml b/apmpackage/apm/data_stream/profile_metrics/fields/base-fields.yml index bef973826be..bf9b70e13de 100644 --- a/apmpackage/apm/data_stream/profile_metrics/fields/base-fields.yml +++ b/apmpackage/apm/data_stream/profile_metrics/fields/base-fields.yml @@ -10,3 +10,6 @@ - name: data_stream.namespace type: constant_keyword description: Data stream namespace. +- name: ecs.version + type: keyword + description: ECS version the event conforms to. diff --git a/apmpackage/apm/data_stream/profile_metrics/fields/ecs.yml b/apmpackage/apm/data_stream/profile_metrics/fields/ecs.yml index e73d8f46a16..5a95c5dc42b 100644 --- a/apmpackage/apm/data_stream/profile_metrics/fields/ecs.yml +++ b/apmpackage/apm/data_stream/profile_metrics/fields/ecs.yml @@ -1,122 +1,173 @@ -- name: agent.ephemeral_id - type: keyword - description: | - The Ephemeral ID identifies a running process. -- name: agent.name - type: keyword - description: | - Name of the agent used. -- name: agent.version - type: keyword - description: | - Version of the agent used. -- name: client.domain - type: keyword - description: | - Client domain. - ignore_above: 1024 -- name: client.ip - type: ip - description: | - IP address of the client of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. -- name: client.port - type: long - description: | - Port of the client. -- name: cloud.account.id - level: extended - type: keyword - description: Cloud account ID - ignore_above: 1024 -- name: cloud.account.name - level: extended - type: keyword - description: Cloud account name - ignore_above: 1024 -- name: cloud.availability_zone - level: extended - type: keyword - description: Cloud availability zone name - ignore_above: 1024 -- name: cloud.instance.id - level: extended - type: keyword - description: Cloud instance/machine ID - ignore_above: 1024 -- name: cloud.instance.name - level: extended - type: keyword - description: Cloud instance/machine name - ignore_above: 1024 -- name: cloud.machine.type - level: extended - type: keyword - description: Cloud instance/machine type - ignore_above: 1024 -- name: cloud.project.id - level: extended - type: keyword - description: Cloud project ID - ignore_above: 1024 -- name: cloud.project.name - level: extended - type: keyword - description: Cloud project name - ignore_above: 1024 -- name: cloud.provider - level: extended - type: keyword - description: Cloud provider name - ignore_above: 1024 -- name: cloud.region - level: extended - type: keyword - description: Cloud region name - ignore_above: 1024 -- name: cloud.service.name - level: extended - type: keyword - description: | - Cloud service name, intended to distinguish services running on different platforms within a provider. - ignore_above: 1024 -- name: container.id - type: keyword - description: | - Unique container id. -- name: destination.address - level: extended - type: keyword - description: Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is. - ignore_above: 1024 -- name: destination.ip - level: core - type: ip - description: IP addess of the destination. Can be one of multiple IPv4 or IPv6 addresses. -- name: destination.port - level: core - type: long - format: string - description: Port of the destination. -- name: host.architecture - type: keyword - description: | - The architecture of the host the event was recorded on. -- name: host.hostname - type: keyword - description: | - The hostname of the host the event was recorded on. -- name: host.ip - type: ip - description: | - IP of the host that records the event. -- name: host.name - type: keyword - description: | - Name of the host the event was recorded on. It can contain same information as host.hostname or a name specified by the user. -- name: host.os.platform - type: keyword - description: | - The platform of the host the event was recorded on. +- name: agent + type: group + fields: + - name: ephemeral_id + type: keyword + description: | + The Ephemeral ID identifies a running process. + - name: name + type: keyword + description: | + Name of the agent used. + - name: version + type: keyword + description: | + Version of the agent used. +- name: client + type: group + fields: + - name: domain + type: keyword + description: | + Client domain. + ignore_above: 1024 + - name: ip + type: ip + description: | + IP address of the client of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. + - name: port + type: long + description: | + Port of the client. +- name: cloud + title: Cloud + type: group + description: | + Cloud metadata reported by agents + fields: + - name: account + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud account ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud account name + ignore_above: 1024 + - name: availability_zone + level: extended + type: keyword + description: Cloud availability zone name + ignore_above: 1024 + - name: instance + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud instance/machine ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud instance/machine name + ignore_above: 1024 + - name: machine + type: group + fields: + - name: type + level: extended + type: keyword + description: Cloud instance/machine type + ignore_above: 1024 + - name: project + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud project ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud project name + ignore_above: 1024 + - name: provider + level: extended + type: keyword + description: Cloud provider name + ignore_above: 1024 + - name: region + level: extended + type: keyword + description: Cloud region name + ignore_above: 1024 + - name: service + type: group + fields: + - name: name + level: extended + type: keyword + description: | + Cloud service name, intended to distinguish services running on different platforms within a provider. + ignore_above: 1024 +- name: container + title: Container + type: group + description: | + Container fields are used for meta information about the specific container that is the source of information. These fields help correlate data based containers from any runtime. + fields: + - name: id + type: keyword + description: | + Unique container id. +- name: destination + title: Destination + type: group + description: |- + Destination fields describe details about the destination of a packet/event. + Destination fields are usually populated in conjunction with source fields. + fields: + - name: address + level: extended + type: keyword + description: Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is. + ignore_above: 1024 + - name: ip + level: core + type: ip + description: IP addess of the destination. Can be one of multiple IPv4 or IPv6 addresses. + - name: port + level: core + type: long + format: string + description: Port of the destination. +- name: host + type: group + description: | + Optional host fields. + fields: + - name: architecture + type: keyword + description: | + The architecture of the host the event was recorded on. + - name: hostname + type: keyword + description: | + The hostname of the host the event was recorded on. + - name: ip + type: ip + description: | + IP of the host that records the event. + - name: name + type: keyword + description: | + Name of the host the event was recorded on. It can contain same information as host.hostname or a name specified by the user. + - name: os + title: Operating System + type: group + description: | + The OS fields contain information about the operating system. + fields: + - name: platform + type: keyword + description: | + The platform of the host the event was recorded on. - name: labels type: object description: | @@ -127,112 +178,152 @@ - object_type: boolean - object_type: scaled_float scaling_factor: 1000000 -- name: observer.hostname - type: keyword - description: | - Hostname of the APM Server. -- name: observer.type - type: keyword - description: | - The type will be set to `apm-server`. -- name: observer.version - type: keyword - description: | - APM Server version. -- name: process.args - level: extended - type: keyword - description: | - Process arguments. May be filtered to protect sensitive information. -- name: process.pid - type: long - description: | - Numeric process ID of the service process. -- name: process.ppid - type: long - description: | - Numeric ID of the service's parent process. -- name: process.title - type: keyword - description: | - Service process title. -- name: service.name - type: keyword - description: | - Immutable name of the service emitting this event. -- name: service.node.name - type: keyword - description: | - Unique meaningful name of the service node. -- name: service.version - type: keyword - description: | - Version of the service emitting this event. -- name: source.domain - type: keyword - description: | - Source domain. - ignore_above: 1024 -- name: source.ip - type: ip - description: | - IP address of the source of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. -- name: source.port - type: long - description: | - Port of the source. -- name: user.email - type: keyword - description: | - Email of the logged in user. -- name: user.id - type: keyword - description: | - Identifier of the logged in user. -- name: user.name - type: keyword - description: | - The username of the logged in user. -- name: user_agent.device.name - type: keyword - description: | - Name of the device. -- name: user_agent.name - type: keyword - description: | - Name of the user agent. -- name: user_agent.original - type: keyword - description: | - Unparsed version of the user_agent. - multi_fields: - - name: text - type: text -- name: user_agent.os.family - type: keyword - description: | - OS family (such as redhat, debian, freebsd, windows). -- name: user_agent.os.full - type: keyword - description: | - Operating system name, including the version or code name. -- name: user_agent.os.kernel - type: keyword - description: | - Operating system kernel version as a raw string. -- name: user_agent.os.name - type: keyword - description: | - Operating system name, without the version. -- name: user_agent.os.platform - type: keyword - description: | - Operating system platform (such centos, ubuntu, windows). -- name: user_agent.os.version - type: keyword - description: | - Operating system version as a raw string. -- name: user_agent.version - type: keyword - description: | - Version of the user agent. +- name: observer + type: group + fields: + - name: hostname + type: keyword + description: | + Hostname of the APM Server. + - name: type + type: keyword + description: | + The type will be set to `apm-server`. + - name: version + type: keyword + description: | + APM Server version. +- name: process + type: group + description: | + Information pertaining to the running process where the data was collected + fields: + - name: args + level: extended + type: keyword + description: | + Process arguments. May be filtered to protect sensitive information. + - name: pid + type: long + description: | + Numeric process ID of the service process. + - name: ppid + type: long + description: | + Numeric ID of the service's parent process. + - name: title + type: keyword + description: | + Service process title. +- name: service + type: group + description: | + Service fields. + fields: + - name: name + type: keyword + description: | + Immutable name of the service emitting this event. + - name: node + type: group + fields: + - name: name + type: keyword + description: | + Unique meaningful name of the service node. + - name: version + type: keyword + description: | + Version of the service emitting this event. +- name: source + type: group + fields: + - name: domain + type: keyword + description: | + Source domain. + ignore_above: 1024 + - name: ip + type: ip + description: | + IP address of the source of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. + - name: port + type: long + description: | + Port of the source. +- name: user + type: group + fields: + - name: email + type: keyword + description: | + Email of the logged in user. + - name: id + type: keyword + description: | + Identifier of the logged in user. + - name: name + type: keyword + description: | + The username of the logged in user. +- name: user_agent + title: User agent + type: group + description: | + The user_agent fields normally come from a browser request. They often show up in web service logs coming from the parsed user agent string. + fields: + - name: device + title: Device + type: group + description: | + Information concerning the device. + fields: + - name: name + type: keyword + description: | + Name of the device. + - name: name + type: keyword + description: | + Name of the user agent. + - name: original + type: keyword + description: | + Unparsed version of the user_agent. + multi_fields: + - name: text + type: text + - name: os + title: Operating System + type: group + description: | + The OS fields contain information about the operating system. + fields: + - name: family + type: keyword + description: | + OS family (such as redhat, debian, freebsd, windows). + - name: full + type: keyword + description: | + Operating system name, including the version or code name. + - name: kernel + type: keyword + description: | + Operating system kernel version as a raw string. + - name: name + type: keyword + description: | + Operating system name, without the version. + - name: platform + type: keyword + description: | + Operating system platform (such centos, ubuntu, windows). + - name: version + type: keyword + description: | + Operating system version as a raw string. + - name: version + type: keyword + description: | + Version of the user agent. diff --git a/apmpackage/apm/data_stream/profile_metrics/fields/fields.yml b/apmpackage/apm/data_stream/profile_metrics/fields/fields.yml index c41b3c68f92..2432254beec 100644 --- a/apmpackage/apm/data_stream/profile_metrics/fields/fields.yml +++ b/apmpackage/apm/data_stream/profile_metrics/fields/fields.yml @@ -2,160 +2,237 @@ type: object description: Additional experimental data sent by the agents. dynamic: true -- name: kubernetes.namespace - type: keyword - description: | - Kubernetes namespace -- name: kubernetes.node.name - type: keyword - description: | - Kubernetes node name -- name: kubernetes.pod.name - type: keyword - description: | - Kubernetes pod name -- name: kubernetes.pod.uid - type: keyword - description: | - Kubernetes Pod UID -- name: network.carrier.icc - type: keyword - description: | - ISO country code, eg. US -- name: network.carrier.mcc - type: keyword - description: | - Mobile country code -- name: network.carrier.mnc - type: keyword - description: | - Mobile network code -- name: network.carrier.name - type: keyword - description: | - Carrier name, eg. Vodafone, T-Mobile, etc. -- name: network.connection.subtype - type: keyword - description: | - Detailed network connection sub-type, e.g. "LTE", "CDMA" -- name: network.connection.type - type: keyword - description: | - Network connection type, eg. "wifi", "cell" -- name: observer.listening - type: keyword - description: | - Address the server is listening on. -- name: observer.version_major - type: byte - description: | - Major version number of the observer +- name: kubernetes + title: Kubernetes + type: group + description: | + Kubernetes metadata reported by agents + fields: + - name: namespace + type: keyword + description: | + Kubernetes namespace + - name: node + type: group + fields: + - name: name + type: keyword + description: | + Kubernetes node name + - name: pod + type: group + fields: + - name: name + type: keyword + description: | + Kubernetes pod name + - name: uid + type: keyword + description: | + Kubernetes Pod UID +- name: network + type: group + description: | + Optional network fields + fields: + - name: carrier + type: group + description: | + Network operator + fields: + - name: icc + type: keyword + description: | + ISO country code, eg. US + - name: mcc + type: keyword + description: | + Mobile country code + - name: mnc + type: keyword + description: | + Mobile network code + - name: name + type: keyword + description: | + Carrier name, eg. Vodafone, T-Mobile, etc. + - name: connection + type: group + description: | + Network connection details + fields: + - name: subtype + type: keyword + description: | + Detailed network connection sub-type, e.g. "LTE", "CDMA" + - name: type + type: keyword + description: | + Network connection type, eg. "wifi", "cell" +- name: observer + type: group + fields: + - name: listening + type: keyword + description: | + Address the server is listening on. + - name: version_major + type: byte + description: | + Major version number of the observer - name: processor.event type: keyword description: Processor event. - name: processor.name type: keyword description: Processor name. -- name: profile.alloc_objects.count - type: long - description: | - Number of objects allocated since the process started. -- name: profile.alloc_space.bytes - type: long - description: | - Amount of memory allocated, in bytes, since the process started. -- name: profile.cpu.ns - type: long - description: | - Amount of CPU time profiled, in nanoseconds. - unit: nanos -- name: profile.duration - type: long - description: | - Duration of the profile, in nanoseconds. All samples within a profile will have the same duration. To aggregate durations, you should first group by the profile ID. - unit: nanos -- name: profile.id - type: keyword - description: | - Unique ID for the profile. All samples within a profile will have the same profile ID. -- name: profile.inuse_objects.count - type: long - description: | - Number of objects allocated and currently in use. -- name: profile.inuse_space.bytes - type: long - description: | - Amount of memory allocated, in bytes, and currently in use. -- name: profile.samples.count - type: long - description: | - Number of profile samples for the profiling period. -- name: profile.stack.filename - type: keyword - description: | - Source code filename for a stack frame. -- name: profile.stack.function - type: keyword - description: | - Function name for a stack frame. -- name: profile.stack.id - type: keyword - description: | - Unique ID for a stack frame in the context of its callers. -- name: profile.stack.line - type: long - description: | - Source code line number for a stack frame. -- name: profile.top.filename - type: keyword - description: | - Source code filename for the top stack frame. -- name: profile.top.function - type: keyword - description: | - Function name for the top stack frame. -- name: profile.top.id - type: keyword - description: | - Unique ID for the top stack frame in the context of its callers. -- name: profile.top.line - type: long - description: | - Source code line number for the top stack frame. -- name: profile.wall.us - type: long - description: | - Amount of wall time profiled, in microseconds. - unit: micros -- name: service.environment - type: keyword - description: | - Service environment. -- name: service.framework.name - type: keyword - description: | - Name of the framework used. -- name: service.framework.version - type: keyword - description: | - Version of the framework used. -- name: service.language.name - type: keyword - description: | - Name of the programming language used. -- name: service.language.version - type: keyword - description: | - Version of the programming language used. -- name: service.runtime.name - type: keyword - description: | - Name of the runtime used. -- name: service.runtime.version - type: keyword - description: | - Version of the runtime used. -- name: timestamp.us - type: long - description: | - Timestamp of the event in microseconds since Unix epoch. +- name: profile + type: group + fields: + - name: alloc_objects + type: group + fields: + - name: count + type: long + description: | + Number of objects allocated since the process started. + - name: alloc_space + type: group + fields: + - name: bytes + type: long + description: | + Amount of memory allocated, in bytes, since the process started. + - name: cpu + type: group + fields: + - name: ns + type: long + description: | + Amount of CPU time profiled, in nanoseconds. + unit: nanos + - name: duration + type: long + description: | + Duration of the profile, in nanoseconds. All samples within a profile will have the same duration. To aggregate durations, you should first group by the profile ID. + unit: nanos + - name: id + type: keyword + description: | + Unique ID for the profile. All samples within a profile will have the same profile ID. + - name: inuse_objects + type: group + fields: + - name: count + type: long + description: | + Number of objects allocated and currently in use. + - name: inuse_space + type: group + fields: + - name: bytes + type: long + description: | + Amount of memory allocated, in bytes, and currently in use. + - name: samples + type: group + fields: + - name: count + type: long + description: | + Number of profile samples for the profiling period. + - name: stack + type: group + fields: + - name: filename + type: keyword + description: | + Source code filename for a stack frame. + - name: function + type: keyword + description: | + Function name for a stack frame. + - name: id + type: keyword + description: | + Unique ID for a stack frame in the context of its callers. + - name: line + type: long + description: | + Source code line number for a stack frame. + - name: top + type: group + fields: + - name: filename + type: keyword + description: | + Source code filename for the top stack frame. + - name: function + type: keyword + description: | + Function name for the top stack frame. + - name: id + type: keyword + description: | + Unique ID for the top stack frame in the context of its callers. + - name: line + type: long + description: | + Source code line number for the top stack frame. + - name: wall + type: group + fields: + - name: us + type: long + description: | + Amount of wall time profiled, in microseconds. + unit: micros +- name: service + type: group + description: | + Service fields. + fields: + - name: environment + type: keyword + description: | + Service environment. + - name: framework + type: group + fields: + - name: name + type: keyword + description: | + Name of the framework used. + - name: version + type: keyword + description: | + Version of the framework used. + - name: language + type: group + fields: + - name: name + type: keyword + description: | + Name of the programming language used. + - name: version + type: keyword + description: | + Version of the programming language used. + - name: runtime + type: group + fields: + - name: name + type: keyword + description: | + Name of the runtime used. + - name: version + type: keyword + description: | + Version of the runtime used. +- name: timestamp + type: group + fields: + - name: us + type: long + description: | + Timestamp of the event in microseconds since Unix epoch. diff --git a/apmpackage/apm/data_stream/profile_metrics/manifest.yml b/apmpackage/apm/data_stream/profile_metrics/manifest.yml index b7e811bd0f7..121e328ca14 100644 --- a/apmpackage/apm/data_stream/profile_metrics/manifest.yml +++ b/apmpackage/apm/data_stream/profile_metrics/manifest.yml @@ -2,3 +2,9 @@ title: APM profiles type: metrics dataset: apm.profiling ilm_policy: metrics-apm.profile_metrics-default_policy +elasticsearch: + index_template: + mappings: + # Profile metrics currently must be dynamically + # mapped, as pprof metric names may be customised. + dynamic: true diff --git a/apmpackage/apm/data_stream/sampled_traces/fields/base-fields.yml b/apmpackage/apm/data_stream/sampled_traces/fields/base-fields.yml index bef973826be..bf9b70e13de 100644 --- a/apmpackage/apm/data_stream/sampled_traces/fields/base-fields.yml +++ b/apmpackage/apm/data_stream/sampled_traces/fields/base-fields.yml @@ -10,3 +10,6 @@ - name: data_stream.namespace type: constant_keyword description: Data stream namespace. +- name: ecs.version + type: keyword + description: ECS version the event conforms to. diff --git a/apmpackage/apm/data_stream/sampled_traces/manifest.yml b/apmpackage/apm/data_stream/sampled_traces/manifest.yml index 151c8973ea2..937472ae893 100644 --- a/apmpackage/apm/data_stream/sampled_traces/manifest.yml +++ b/apmpackage/apm/data_stream/sampled_traces/manifest.yml @@ -9,3 +9,7 @@ elasticsearch: # global checkpoints as a way of limiting search # results. number_of_shards: 1 + mappings: + # Sampled traces should have all fields strictly mapped; + # we are in full control of the field names. + dynamic: strict diff --git a/apmpackage/apm/data_stream/traces/fields/base-fields.yml b/apmpackage/apm/data_stream/traces/fields/base-fields.yml index bef973826be..bf9b70e13de 100644 --- a/apmpackage/apm/data_stream/traces/fields/base-fields.yml +++ b/apmpackage/apm/data_stream/traces/fields/base-fields.yml @@ -10,3 +10,6 @@ - name: data_stream.namespace type: constant_keyword description: Data stream namespace. +- name: ecs.version + type: keyword + description: ECS version the event conforms to. diff --git a/apmpackage/apm/data_stream/traces/fields/ecs.yml b/apmpackage/apm/data_stream/traces/fields/ecs.yml index f29d15504df..efec19378b5 100644 --- a/apmpackage/apm/data_stream/traces/fields/ecs.yml +++ b/apmpackage/apm/data_stream/traces/fields/ecs.yml @@ -1,144 +1,207 @@ -- name: agent.ephemeral_id - type: keyword - description: | - The Ephemeral ID identifies a running process. -- name: agent.name - type: keyword - description: | - Name of the agent used. -- name: agent.version - type: keyword - description: | - Version of the agent used. -- name: client.domain - type: keyword - description: | - Client domain. - ignore_above: 1024 -- name: client.ip - type: ip - description: | - IP address of the client of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. -- name: client.port - type: long - description: | - Port of the client. -- name: cloud.account.id - level: extended - type: keyword - description: Cloud account ID - ignore_above: 1024 -- name: cloud.account.name - level: extended - type: keyword - description: Cloud account name - ignore_above: 1024 -- name: cloud.availability_zone - level: extended - type: keyword - description: Cloud availability zone name - ignore_above: 1024 -- name: cloud.instance.id - level: extended - type: keyword - description: Cloud instance/machine ID - ignore_above: 1024 -- name: cloud.instance.name - level: extended - type: keyword - description: Cloud instance/machine name - ignore_above: 1024 -- name: cloud.machine.type - level: extended - type: keyword - description: Cloud instance/machine type - ignore_above: 1024 -- name: cloud.project.id - level: extended - type: keyword - description: Cloud project ID - ignore_above: 1024 -- name: cloud.project.name - level: extended - type: keyword - description: Cloud project name - ignore_above: 1024 -- name: cloud.provider - level: extended - type: keyword - description: Cloud provider name - ignore_above: 1024 -- name: cloud.region - level: extended - type: keyword - description: Cloud region name - ignore_above: 1024 -- name: cloud.service.name - level: extended - type: keyword - description: | - Cloud service name, intended to distinguish services running on different platforms within a provider. - ignore_above: 1024 -- name: container.id - type: keyword - description: | - Unique container id. -- name: destination.address - level: extended - type: keyword - description: Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is. - ignore_above: 1024 -- name: destination.ip - level: core - type: ip - description: IP addess of the destination. Can be one of multiple IPv4 or IPv6 addresses. -- name: destination.port - level: core - type: long - format: string - description: Port of the destination. -- name: event.outcome - level: core - type: keyword - description: | - `event.outcome` simply denotes whether the event represents a success or a failure from the perspective of the entity that produced the event. - ignore_above: 1024 -- name: host.architecture - type: keyword - description: | - The architecture of the host the event was recorded on. -- name: host.hostname - type: keyword - description: | - The hostname of the host the event was recorded on. -- name: host.ip - type: ip - description: | - IP of the host that records the event. -- name: host.name - type: keyword - description: | - Name of the host the event was recorded on. It can contain same information as host.hostname or a name specified by the user. -- name: host.os.platform - type: keyword - description: | - The platform of the host the event was recorded on. -- name: http.request.method - type: keyword - description: | - The http method of the request leading to this event. -- name: http.request.referrer - type: keyword - description: Referrer for this HTTP request. - ignore_above: 1024 -- name: http.response.status_code - type: long - description: | - The status code of the HTTP response. -- name: http.version - type: keyword - description: | - The http version of the request leading to this event. +- name: agent + type: group + fields: + - name: ephemeral_id + type: keyword + description: | + The Ephemeral ID identifies a running process. + - name: name + type: keyword + description: | + Name of the agent used. + - name: version + type: keyword + description: | + Version of the agent used. +- name: client + type: group + fields: + - name: domain + type: keyword + description: | + Client domain. + ignore_above: 1024 + - name: ip + type: ip + description: | + IP address of the client of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. + - name: port + type: long + description: | + Port of the client. +- name: cloud + title: Cloud + type: group + description: | + Cloud metadata reported by agents + fields: + - name: account + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud account ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud account name + ignore_above: 1024 + - name: availability_zone + level: extended + type: keyword + description: Cloud availability zone name + ignore_above: 1024 + - name: instance + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud instance/machine ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud instance/machine name + ignore_above: 1024 + - name: machine + type: group + fields: + - name: type + level: extended + type: keyword + description: Cloud instance/machine type + ignore_above: 1024 + - name: project + type: group + fields: + - name: id + level: extended + type: keyword + description: Cloud project ID + ignore_above: 1024 + - name: name + level: extended + type: keyword + description: Cloud project name + ignore_above: 1024 + - name: provider + level: extended + type: keyword + description: Cloud provider name + ignore_above: 1024 + - name: region + level: extended + type: keyword + description: Cloud region name + ignore_above: 1024 + - name: service + type: group + fields: + - name: name + level: extended + type: keyword + description: | + Cloud service name, intended to distinguish services running on different platforms within a provider. + ignore_above: 1024 +- name: container + title: Container + type: group + description: | + Container fields are used for meta information about the specific container that is the source of information. These fields help correlate data based containers from any runtime. + fields: + - name: id + type: keyword + description: | + Unique container id. +- name: destination + title: Destination + type: group + description: |- + Destination fields describe details about the destination of a packet/event. + Destination fields are usually populated in conjunction with source fields. + fields: + - name: address + level: extended + type: keyword + description: Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is. + ignore_above: 1024 + - name: ip + level: core + type: ip + description: IP addess of the destination. Can be one of multiple IPv4 or IPv6 addresses. + - name: port + level: core + type: long + format: string + description: Port of the destination. +- name: event + type: group + fields: + - name: outcome + level: core + type: keyword + description: | + `event.outcome` simply denotes whether the event represents a success or a failure from the perspective of the entity that produced the event. + ignore_above: 1024 +- name: host + type: group + description: | + Optional host fields. + fields: + - name: architecture + type: keyword + description: | + The architecture of the host the event was recorded on. + - name: hostname + type: keyword + description: | + The hostname of the host the event was recorded on. + - name: ip + type: ip + description: | + IP of the host that records the event. + - name: name + type: keyword + description: | + Name of the host the event was recorded on. It can contain same information as host.hostname or a name specified by the user. + - name: os + title: Operating System + type: group + description: | + The OS fields contain information about the operating system. + fields: + - name: platform + type: keyword + description: | + The platform of the host the event was recorded on. +- name: http + type: group + fields: + - name: request + type: group + fields: + - name: method + type: keyword + description: | + The http method of the request leading to this event. + - name: referrer + type: keyword + description: Referrer for this HTTP request. + ignore_above: 1024 + - name: response + type: group + fields: + - name: status_code + type: long + description: | + The status code of the HTTP response. + - name: version + type: keyword + description: | + The http version of the request leading to this event. - name: labels type: object description: | @@ -149,156 +212,210 @@ - object_type: boolean - object_type: scaled_float scaling_factor: 1000000 -- name: observer.hostname - type: keyword - description: | - Hostname of the APM Server. -- name: observer.type - type: keyword - description: | - The type will be set to `apm-server`. -- name: observer.version - type: keyword - description: | - APM Server version. -- name: process.args - level: extended - type: keyword - description: | - Process arguments. May be filtered to protect sensitive information. -- name: process.pid - type: long - description: | - Numeric process ID of the service process. -- name: process.ppid - type: long - description: | - Numeric ID of the service's parent process. -- name: process.title - type: keyword - description: | - Service process title. -- name: service.name - type: keyword - description: | - Immutable name of the service emitting this event. -- name: service.node.name - type: keyword - description: | - Unique meaningful name of the service node. -- name: service.version - type: keyword - description: | - Version of the service emitting this event. -- name: source.domain - type: keyword - description: | - Source domain. - ignore_above: 1024 -- name: source.ip - type: ip - description: | - IP address of the source of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. -- name: source.port - type: long - description: | - Port of the source. -- name: span.id - type: keyword - description: | - The ID of the span stored as hex encoded string. -- name: trace.id - type: keyword - description: | - The ID of the trace to which the event belongs to. -- name: transaction.id - type: keyword - description: | - The transaction ID. -- name: url.domain - type: keyword - description: | - The hostname of the request, e.g. "example.com". -- name: url.fragment - type: keyword - description: | - A fragment specifying a location in a web page , e.g. "top". -- name: url.full - type: keyword - description: | - The full, possibly agent-assembled URL of the request, e.g https://example.com:443/search?q=elasticsearch#top. -- name: url.path - type: keyword - description: | - The path of the request, e.g. "/search". -- name: url.port - type: long - description: | - The port of the request, e.g. 443. -- name: url.query - type: keyword - description: | - The query string of the request, e.g. "q=elasticsearch". -- name: url.scheme - type: keyword - description: | - The protocol of the request, e.g. "https:". -- name: user.domain - type: keyword - description: | - Domain of the logged in user. -- name: user.email - type: keyword - description: | - Email of the logged in user. -- name: user.id - type: keyword - description: | - Identifier of the logged in user. -- name: user.name - type: keyword - description: | - The username of the logged in user. -- name: user_agent.device.name - type: keyword - description: | - Name of the device. -- name: user_agent.name - type: keyword - description: | - Name of the user agent. -- name: user_agent.original - type: keyword - description: | - Unparsed version of the user_agent. - multi_fields: - - name: text - type: text -- name: user_agent.os.family - type: keyword - description: | - OS family (such as redhat, debian, freebsd, windows). -- name: user_agent.os.full - type: keyword - description: | - Operating system name, including the version or code name. -- name: user_agent.os.kernel - type: keyword - description: | - Operating system kernel version as a raw string. -- name: user_agent.os.name - type: keyword - description: | - Operating system name, without the version. -- name: user_agent.os.platform - type: keyword - description: | - Operating system platform (such centos, ubuntu, windows). -- name: user_agent.os.version - type: keyword - description: | - Operating system version as a raw string. -- name: user_agent.version - type: keyword - description: | - Version of the user agent. +- name: observer + type: group + fields: + - name: hostname + type: keyword + description: | + Hostname of the APM Server. + - name: type + type: keyword + description: | + The type will be set to `apm-server`. + - name: version + type: keyword + description: | + APM Server version. +- name: process + type: group + description: | + Information pertaining to the running process where the data was collected + fields: + - name: args + level: extended + type: keyword + description: | + Process arguments. May be filtered to protect sensitive information. + - name: pid + type: long + description: | + Numeric process ID of the service process. + - name: ppid + type: long + description: | + Numeric ID of the service's parent process. + - name: title + type: keyword + description: | + Service process title. +- name: service + type: group + description: | + Service fields. + fields: + - name: name + type: keyword + description: | + Immutable name of the service emitting this event. + - name: node + type: group + fields: + - name: name + type: keyword + description: | + Unique meaningful name of the service node. + - name: version + type: keyword + description: | + Version of the service emitting this event. +- name: source + type: group + fields: + - name: domain + type: keyword + description: | + Source domain. + ignore_above: 1024 + - name: ip + type: ip + description: | + IP address of the source of a recorded event. This is typically obtained from a request's X-Forwarded-For or the X-Real-IP header or falls back to a given configuration for remote address. + - name: port + type: long + description: | + Port of the source. +- name: span + type: group + fields: + - name: id + type: keyword + description: | + The ID of the span stored as hex encoded string. +- name: trace + type: group + fields: + - name: id + type: keyword + description: | + The ID of the trace to which the event belongs to. +- name: transaction + type: group + fields: + - name: id + type: keyword + description: | + The transaction ID. +- name: url + type: group + description: | + A complete Url, with scheme, host and path. + fields: + - name: domain + type: keyword + description: | + The hostname of the request, e.g. "example.com". + - name: fragment + type: keyword + description: | + A fragment specifying a location in a web page , e.g. "top". + - name: full + type: keyword + description: | + The full, possibly agent-assembled URL of the request, e.g https://example.com:443/search?q=elasticsearch#top. + - name: path + type: keyword + description: | + The path of the request, e.g. "/search". + - name: port + type: long + description: | + The port of the request, e.g. 443. + - name: query + type: keyword + description: | + The query string of the request, e.g. "q=elasticsearch". + - name: scheme + type: keyword + description: | + The protocol of the request, e.g. "https:". +- name: user + type: group + fields: + - name: domain + type: keyword + description: | + Domain of the logged in user. + - name: email + type: keyword + description: | + Email of the logged in user. + - name: id + type: keyword + description: | + Identifier of the logged in user. + - name: name + type: keyword + description: | + The username of the logged in user. +- name: user_agent + title: User agent + type: group + description: | + The user_agent fields normally come from a browser request. They often show up in web service logs coming from the parsed user agent string. + fields: + - name: device + title: Device + type: group + description: | + Information concerning the device. + fields: + - name: name + type: keyword + description: | + Name of the device. + - name: name + type: keyword + description: | + Name of the user agent. + - name: original + type: keyword + description: | + Unparsed version of the user_agent. + multi_fields: + - name: text + type: text + - name: os + title: Operating System + type: group + description: | + The OS fields contain information about the operating system. + fields: + - name: family + type: keyword + description: | + OS family (such as redhat, debian, freebsd, windows). + - name: full + type: keyword + description: | + Operating system name, including the version or code name. + - name: kernel + type: keyword + description: | + Operating system kernel version as a raw string. + - name: name + type: keyword + description: | + Operating system name, without the version. + - name: platform + type: keyword + description: | + Operating system platform (such centos, ubuntu, windows). + - name: version + type: keyword + description: | + Operating system version as a raw string. + - name: version + type: keyword + description: | + Version of the user agent. diff --git a/apmpackage/apm/data_stream/traces/fields/fields.yml b/apmpackage/apm/data_stream/traces/fields/fields.yml index 6a38b5aa442..95dfdbef9c9 100644 --- a/apmpackage/apm/data_stream/traces/fields/fields.yml +++ b/apmpackage/apm/data_stream/traces/fields/fields.yml @@ -1,249 +1,373 @@ -- name: child.id - type: keyword - description: | - The ID(s) of the child event(s). +- name: child + type: group + fields: + - name: id + type: keyword + description: | + The ID(s) of the child event(s). - name: experimental type: object description: Additional experimental data sent by the agents. dynamic: true -- name: http.request.headers - type: object - description: | - The canonical headers of the monitored HTTP request. -- name: http.response.finished - type: boolean - description: | - Used by the Node agent to indicate when in the response life cycle an error has occurred. -- name: http.response.headers - type: object - description: | - The canonical headers of the monitored HTTP response. -- name: kubernetes.namespace - type: keyword - description: | - Kubernetes namespace -- name: kubernetes.node.name - type: keyword - description: | - Kubernetes node name -- name: kubernetes.pod.name - type: keyword - description: | - Kubernetes pod name -- name: kubernetes.pod.uid - type: keyword - description: | - Kubernetes Pod UID -- name: network.carrier.icc - type: keyword - description: | - ISO country code, eg. US -- name: network.carrier.mcc - type: keyword - description: | - Mobile country code -- name: network.carrier.mnc - type: keyword - description: | - Mobile network code -- name: network.carrier.name - type: keyword - description: | - Carrier name, eg. Vodafone, T-Mobile, etc. -- name: network.connection.subtype - type: keyword - description: | - Detailed network connection sub-type, e.g. "LTE", "CDMA" -- name: network.connection.type - type: keyword - description: | - Network connection type, eg. "wifi", "cell" -- name: observer.listening - type: keyword - description: | - Address the server is listening on. -- name: observer.version_major - type: byte - description: | - Major version number of the observer -- name: parent.id - type: keyword - description: | - The ID of the parent event. +- name: http + type: group + fields: + - name: request + type: group + fields: + - name: headers + type: object + description: | + The canonical headers of the monitored HTTP request. + - name: response + type: group + fields: + - name: finished + type: boolean + description: | + Used by the Node agent to indicate when in the response life cycle an error has occurred. + - name: headers + type: object + description: | + The canonical headers of the monitored HTTP response. +- name: kubernetes + title: Kubernetes + type: group + description: | + Kubernetes metadata reported by agents + fields: + - name: namespace + type: keyword + description: | + Kubernetes namespace + - name: node + type: group + fields: + - name: name + type: keyword + description: | + Kubernetes node name + - name: pod + type: group + fields: + - name: name + type: keyword + description: | + Kubernetes pod name + - name: uid + type: keyword + description: | + Kubernetes Pod UID +- name: network + type: group + description: | + Optional network fields + fields: + - name: carrier + type: group + description: | + Network operator + fields: + - name: icc + type: keyword + description: | + ISO country code, eg. US + - name: mcc + type: keyword + description: | + Mobile country code + - name: mnc + type: keyword + description: | + Mobile network code + - name: name + type: keyword + description: | + Carrier name, eg. Vodafone, T-Mobile, etc. + - name: connection + type: group + description: | + Network connection details + fields: + - name: subtype + type: keyword + description: | + Detailed network connection sub-type, e.g. "LTE", "CDMA" + - name: type + type: keyword + description: | + Network connection type, eg. "wifi", "cell" +- name: observer + type: group + fields: + - name: listening + type: keyword + description: | + Address the server is listening on. + - name: version_major + type: byte + description: | + Major version number of the observer +- name: parent + type: group + fields: + - name: id + type: keyword + description: | + The ID of the parent event. - name: processor.event type: keyword description: Processor event. - name: processor.name type: keyword description: Processor name. -- name: service.environment - type: keyword - description: | - Service environment. -- name: service.framework.name - type: keyword - description: | - Name of the framework used. -- name: service.framework.version - type: keyword - description: | - Version of the framework used. -- name: service.language.name - type: keyword - description: | - Name of the programming language used. -- name: service.language.version - type: keyword - description: | - Version of the programming language used. -- name: service.runtime.name - type: keyword - description: | - Name of the runtime used. -- name: service.runtime.version - type: keyword - description: | - Version of the runtime used. -- name: session.id - type: keyword - description: | - The ID of the session to which the event belongs. - ignore_above: 1024 -- name: session.sequence - type: long - description: | - The sequence number of the event within the session to which the event belongs. -- name: span.action - type: keyword - description: | - The specific kind of event within the sub-type represented by the span (e.g. query, connect) -- name: span.composite.compression_strategy - type: keyword - description: | - The compression strategy that was used. -- name: span.composite.count - type: long - description: | - Number of compressed spans the composite span represents. -- name: span.composite.sum.us - type: long - description: | - Sum of the durations of the compressed spans, in microseconds. -- name: span.db.link - type: keyword - description: | - Database link. -- name: span.db.rows_affected - type: long - description: | - Number of rows affected by the database statement. -- name: span.destination.service.name - type: keyword - description: | - Identifier for the destination service (e.g. 'http://elastic.co', 'elasticsearch', 'rabbitmq') DEPRECATED: this field will be removed in a future release -- name: span.destination.service.resource - type: keyword - description: | - Identifier for the destination service resource being operated on (e.g. 'http://elastic.co:80', 'elasticsearch', 'rabbitmq/queue_name') -- name: span.destination.service.type - type: keyword - description: | - Type of the destination service (e.g. 'db', 'elasticsearch'). Should typically be the same as span.type. DEPRECATED: this field will be removed in a future release -- name: span.duration.us - type: long - description: | - Duration of the span, in microseconds. -- name: span.message.age.ms - type: long - description: | - Age of a message in milliseconds. -- name: span.message.queue.name - type: keyword - description: | - Name of the message queue or topic where the message is published or received. -- name: span.name - type: keyword - description: | - Generic designation of a span in the scope of a transaction. -- name: span.start.us - type: long - description: | - Offset relative to the transaction's timestamp identifying the start of the span, in microseconds. -- name: span.subtype - type: keyword - description: | - A further sub-division of the type (e.g. postgresql, elasticsearch) -- name: span.sync - type: boolean - description: | - Indicates whether the span was executed synchronously or asynchronously. -- name: span.type - type: keyword - description: | - Keyword of specific relevance in the service's domain (eg: 'db.postgresql.query', 'template.erb', 'cache', etc). -- name: timestamp.us - type: long - description: | - Timestamp of the event in microseconds since Unix epoch. -- name: transaction.duration.us - type: long - description: | - Total duration of this transaction, in microseconds. -- name: transaction.experience.cls - type: scaled_float - description: The Cumulative Layout Shift metric -- name: transaction.experience.fid - type: scaled_float - description: The First Input Delay metric -- name: transaction.experience.longtask.count - type: long - description: The total number of of longtasks -- name: transaction.experience.longtask.max - type: scaled_float - description: The max longtask duration -- name: transaction.experience.longtask.sum - type: scaled_float - description: The sum of longtask durations -- name: transaction.experience.tbt - type: scaled_float - description: The Total Blocking Time metric -- name: transaction.marks - type: object - description: | - A user-defined mapping of groups of marks in milliseconds. - dynamic: true -- name: transaction.marks.*.* - type: object - description: | - A user-defined mapping of groups of marks in milliseconds. - dynamic: true -- name: transaction.message.age.ms - type: long - description: | - Age of a message in milliseconds. -- name: transaction.message.queue.name - type: keyword - description: | - Name of the message queue or topic where the message is published or received. -- name: transaction.name - type: keyword - description: | - Generic designation of a transaction in the scope of a single service (eg. 'GET /users/:id'). - multi_fields: - - name: text - type: text -- name: transaction.result - type: keyword - description: | - The result of the transaction. HTTP status code for HTTP-related transactions. -- name: transaction.sampled - type: boolean - description: | - Transactions that are 'sampled' will include all available information. Transactions that are not sampled will not have spans or context. -- name: transaction.span_count.dropped - type: long - description: The total amount of dropped spans for this transaction. -- name: transaction.type - type: keyword - description: | - Keyword of specific relevance in the service's domain (eg. 'request', 'backgroundjob', etc) +- name: service + type: group + description: | + Service fields. + fields: + - name: environment + type: keyword + description: | + Service environment. + - name: framework + type: group + fields: + - name: name + type: keyword + description: | + Name of the framework used. + - name: version + type: keyword + description: | + Version of the framework used. + - name: language + type: group + fields: + - name: name + type: keyword + description: | + Name of the programming language used. + - name: version + type: keyword + description: | + Version of the programming language used. + - name: runtime + type: group + fields: + - name: name + type: keyword + description: | + Name of the runtime used. + - name: version + type: keyword + description: | + Version of the runtime used. +- name: session + type: group + fields: + - name: id + type: keyword + description: | + The ID of the session to which the event belongs. + ignore_above: 1024 + - name: sequence + type: long + description: | + The sequence number of the event within the session to which the event belongs. +- name: span + type: group + fields: + - name: action + type: keyword + description: | + The specific kind of event within the sub-type represented by the span (e.g. query, connect) + - name: composite + type: group + fields: + - name: compression_strategy + type: keyword + description: | + The compression strategy that was used. + - name: count + type: long + description: | + Number of compressed spans the composite span represents. + - name: sum + type: group + fields: + - name: us + type: long + description: | + Sum of the durations of the compressed spans, in microseconds. + - name: db + type: group + fields: + - name: link + type: keyword + description: | + Database link. + - name: rows_affected + type: long + description: | + Number of rows affected by the database statement. + - name: destination + type: group + fields: + - name: service + type: group + description: Destination service context + fields: + - name: name + type: keyword + description: | + Identifier for the destination service (e.g. 'http://elastic.co', 'elasticsearch', 'rabbitmq') DEPRECATED: this field will be removed in a future release + - name: resource + type: keyword + description: | + Identifier for the destination service resource being operated on (e.g. 'http://elastic.co:80', 'elasticsearch', 'rabbitmq/queue_name') + - name: type + type: keyword + description: | + Type of the destination service (e.g. 'db', 'elasticsearch'). Should typically be the same as span.type. DEPRECATED: this field will be removed in a future release + - name: duration + type: group + fields: + - name: us + type: long + description: | + Duration of the span, in microseconds. + - name: message + type: group + fields: + - name: age + type: group + fields: + - name: ms + type: long + description: | + Age of a message in milliseconds. + - name: queue + type: group + fields: + - name: name + type: keyword + description: | + Name of the message queue or topic where the message is published or received. + - name: name + type: keyword + description: | + Generic designation of a span in the scope of a transaction. + - name: start + type: group + fields: + - name: us + type: long + description: | + Offset relative to the transaction's timestamp identifying the start of the span, in microseconds. + - name: subtype + type: keyword + description: | + A further sub-division of the type (e.g. postgresql, elasticsearch) + - name: sync + type: boolean + description: | + Indicates whether the span was executed synchronously or asynchronously. + - name: type + type: keyword + description: | + Keyword of specific relevance in the service's domain (eg: 'db.postgresql.query', 'template.erb', 'cache', etc). +- name: timestamp + type: group + fields: + - name: us + type: long + description: | + Timestamp of the event in microseconds since Unix epoch. +- name: transaction + type: group + fields: + - name: duration + type: group + fields: + - name: us + type: long + description: | + Total duration of this transaction, in microseconds. + - name: experience + type: group + fields: + - name: cls + type: scaled_float + description: The Cumulative Layout Shift metric + - name: fid + type: scaled_float + description: The First Input Delay metric + - name: longtask + type: group + description: Longtask duration/count metrics + fields: + - name: count + type: long + description: The total number of of longtasks + - name: max + type: scaled_float + description: The max longtask duration + - name: sum + type: scaled_float + description: The sum of longtask durations + - name: tbt + type: scaled_float + description: The Total Blocking Time metric + - name: marks + type: object + description: | + A user-defined mapping of groups of marks in milliseconds. + dynamic: true + - name: marks.*.* + type: object + description: | + A user-defined mapping of groups of marks in milliseconds. + dynamic: true + - name: message + type: group + fields: + - name: age + type: group + fields: + - name: ms + type: long + description: | + Age of a message in milliseconds. + - name: queue + type: group + fields: + - name: name + type: keyword + description: | + Name of the message queue or topic where the message is published or received. + - name: name + type: keyword + description: | + Generic designation of a transaction in the scope of a single service (eg. 'GET /users/:id'). + multi_fields: + - name: text + type: text + - name: result + type: keyword + description: | + The result of the transaction. HTTP status code for HTTP-related transactions. + - name: sampled + type: boolean + description: | + Transactions that are 'sampled' will include all available information. Transactions that are not sampled will not have spans or context. + - name: span_count + type: group + fields: + - name: dropped + type: long + description: The total amount of dropped spans for this transaction. + - name: type + type: keyword + description: | + Keyword of specific relevance in the service's domain (eg. 'request', 'backgroundjob', etc) diff --git a/apmpackage/apm/data_stream/traces/manifest.yml b/apmpackage/apm/data_stream/traces/manifest.yml index bd7ac2b9cd4..958db83fd00 100644 --- a/apmpackage/apm/data_stream/traces/manifest.yml +++ b/apmpackage/apm/data_stream/traces/manifest.yml @@ -2,3 +2,11 @@ title: APM traces type: traces dataset: apm ilm_policy: traces-apm.traces-default_policy +elasticsearch: + index_template: + mappings: + # TODO(axw) investigate setting `dynamic: runtime`, so that fields are + # runtime searchable by default. That way users can, for example, perform + # ad-hoc searches on HTTP request headers without incurring storage cost + # for users who do not need this capability. + dynamic: false diff --git a/apmpackage/apm/docs/README.md b/apmpackage/apm/docs/README.md index 5f5c6dedfe1..dbe5e62982b 100644 --- a/apmpackage/apm/docs/README.md +++ b/apmpackage/apm/docs/README.md @@ -54,9 +54,6 @@ Traces are written to `traces-apm.*` indices. | Field | Description | Type | ECS | |---|---|---|:---:| |@timestamp|Event timestamp.|date| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | -|data\_stream.type|Data stream type.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | -|data\_stream.dataset|Data stream dataset.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | -|data\_stream.namespace|Data stream namespace.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |agent.ephemeral\_id|The Ephemeral ID identifies a running process.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |agent.name|Name of the agent used.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |agent.version|Version of the agent used.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | @@ -76,9 +73,13 @@ Traces are written to `traces-apm.*` indices. |cloud.region|Cloud region name|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |cloud.service.name|Cloud service name, intended to distinguish services running on different platforms within a provider.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |container.id|Unique container id.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|data\_stream.dataset|Data stream dataset.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|data\_stream.namespace|Data stream namespace.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|data\_stream.type|Data stream type.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |destination.address|Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the \`.address\` field. Then it should be duplicated to \`.ip\` or \`.domain\`, depending on which one it is.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |destination.ip|IP addess of the destination. Can be one of multiple IPv4 or IPv6 addresses.|ip| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |destination.port|Port of the destination.|long| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|ecs.version|ECS version the event conforms to.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |event.outcome|\`event.outcome\` simply denotes whether the event represents a success or a failure from the perspective of the entity that produced the event.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |experimental|Additional experimental data sent by the agents.|object| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |host.architecture|The architecture of the host the event was recorded on.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | @@ -426,9 +427,6 @@ Metrics are written to `metrics-apm.app.*`, `metrics-apm.internal.*`, and `metri | Field | Description | Type | ECS | |---|---|---|:---:| |@timestamp|Event timestamp.|date| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | -|data\_stream.type|Data stream type.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | -|data\_stream.dataset|Data stream dataset.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | -|data\_stream.namespace|Data stream namespace.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |agent.ephemeral\_id|The Ephemeral ID identifies a running process.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |agent.name|Name of the agent used.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |agent.version|Version of the agent used.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | @@ -447,9 +445,13 @@ Metrics are written to `metrics-apm.app.*`, `metrics-apm.internal.*`, and `metri |cloud.region|Cloud region name|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |cloud.service.name|Cloud service name, intended to distinguish services running on different platforms within a provider.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |container.id|Unique container id.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|data\_stream.dataset|Data stream dataset.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|data\_stream.namespace|Data stream namespace.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|data\_stream.type|Data stream type.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |destination.address|Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the \`.address\` field. Then it should be duplicated to \`.ip\` or \`.domain\`, depending on which one it is.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |destination.ip|IP addess of the destination. Can be one of multiple IPv4 or IPv6 addresses.|ip| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |destination.port|Port of the destination.|long| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|ecs.version|ECS version the event conforms to.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |experimental|Additional experimental data sent by the agents.|object| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |histogram||histogram| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |host.architecture|The architecture of the host the event was recorded on.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | @@ -592,9 +594,6 @@ Logs are written to `logs-apm.error.*` indices. | Field | Description | Type | ECS | |---|---|---|:---:| |@timestamp|Event timestamp.|date| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | -|data\_stream.type|Data stream type.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | -|data\_stream.dataset|Data stream dataset.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | -|data\_stream.namespace|Data stream namespace.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |agent.ephemeral\_id|The Ephemeral ID identifies a running process.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |agent.name|Name of the agent used.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |agent.version|Version of the agent used.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | @@ -613,9 +612,13 @@ Logs are written to `logs-apm.error.*` indices. |cloud.region|Cloud region name|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |cloud.service.name|Cloud service name, intended to distinguish services running on different platforms within a provider.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |container.id|Unique container id.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|data\_stream.dataset|Data stream dataset.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|data\_stream.namespace|Data stream namespace.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|data\_stream.type|Data stream type.|constant\_keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |destination.address|Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the \`.address\` field. Then it should be duplicated to \`.ip\` or \`.domain\`, depending on which one it is.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |destination.ip|IP addess of the destination. Can be one of multiple IPv4 or IPv6 addresses.|ip| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |destination.port|Port of the destination.|long| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|ecs.version|ECS version the event conforms to.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |error.culprit|Function call which was the primary perpetrator of this event.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |error.exception.code|The error code set when the error happened, e.g. database error code.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |error.exception.handled|Indicator whether the error was caught somewhere in the code or not.|boolean| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | diff --git a/apmpackage/cmd/gen-package/field.go b/apmpackage/cmd/gen-package/field.go index af1d849614e..a42f41148b1 100644 --- a/apmpackage/cmd/gen-package/field.go +++ b/apmpackage/cmd/gen-package/field.go @@ -18,16 +18,22 @@ package main type field struct { - Name string `yaml:"name,omitempty"` - Key string `yaml:"key,omitempty"` - Title string `yaml:"title,omitempty"` - Group *int `yaml:"group,omitempty"` - Level string `yaml:"level,omitempty"` - Required *bool `yaml:"required,omitempty"` - Type string `yaml:"type,omitempty"` - Format string `yaml:"format,omitempty"` - Description string `yaml:"description,omitempty"` - Dynamic bool `yaml:"dynamic,omitempty"` + Name string `yaml:"name,omitempty"` + Key string `yaml:"key,omitempty"` + Title string `yaml:"title,omitempty"` + Level string `yaml:"level,omitempty"` + Required *bool `yaml:"required,omitempty"` + Type string `yaml:"type,omitempty"` + Format string `yaml:"format,omitempty"` + Description string `yaml:"description,omitempty"` + + // Dynamic controls whether a field is dynamically mapped. + // + // Note: we intentionally omit "dynamic: false", as we set + // a default dynamic mapping value for each data stream and + // opt *in* to dynamically mapping where needed. + Dynamic bool `yaml:"dynamic,omitempty"` + ObjectTypeParams interface{} `yaml:"object_type_params,omitempty"` Release string `yaml:"release,omitempty"` Alias string `yaml:"alias,omitempty"` @@ -38,13 +44,8 @@ type field struct { Fields []field `yaml:"fields,omitempty"` MetricType string `yaml:"metric_type,omitempty"` Unit string `yaml:"unit,omitempty"` - IsECS bool `yaml:"-"` - HasECS bool `yaml:"-"` - HasNonECS bool `yaml:"-"` -} -func (f field) isNonECSLeaf() bool { - return f.Type != "group" && !f.IsECS + IsECS bool `yaml:"-"` } type multiFieldDefinition struct { @@ -53,8 +54,3 @@ type multiFieldDefinition struct { Norms *bool `yaml:"norms,omitempty"` DefaultField *bool `yaml:"default_field,omitempty"` } - -func copyFieldRoot(f field) field { - f.Fields = nil - return f -} diff --git a/apmpackage/cmd/gen-package/gendocs.go b/apmpackage/cmd/gen-package/gendocs.go index ebcb159cf2b..217ff7608a9 100644 --- a/apmpackage/cmd/gen-package/gendocs.go +++ b/apmpackage/cmd/gen-package/gendocs.go @@ -37,11 +37,12 @@ func escapeReplacer(s ...string) *strings.Replacer { var markdownReplacer = escapeReplacer("\\", "`", "*", "_") -func generateDocs(inputFields map[string][]field) { +func generateDocs(inputFields map[string]fieldMap) { + addBaseFields(inputFields, "traces", "app_metrics", "error_logs") data := docsData{ - Traces: prepareFields(inputFields, "traces"), - Metrics: prepareFields(inputFields, "app_metrics"), - Logs: prepareFields(inputFields, "error_logs"), + Traces: flattenFields(inputFields["traces"]), + Metrics: flattenFields(inputFields["app_metrics"]), + Logs: flattenFields(inputFields["error_logs"]), TransactionExample: loadExample("transactions.json"), SpanExample: loadExample("spans.json"), MetricsExample: loadExample("metricsets.json"), @@ -77,17 +78,14 @@ type docsData struct { ErrorExample string } -func prepareFields(inputFields map[string][]field, stream string) []field { - extend := func(fs []field) []field { - var baseFields []field +func addBaseFields(streamFields map[string]fieldMap, streams ...string) { + for _, stream := range streams { + fields := streamFields[stream] for _, f := range loadFieldsFile(baseFieldsFilePath(stream)) { f.IsECS = true - baseFields = append(baseFields, f) + fields[f.Name] = fieldMapItem{field: f} } - fs = append(baseFields, fs...) - return fs } - return extend(inputFields[stream]) } func loadExample(file string) string { diff --git a/apmpackage/cmd/gen-package/genfields.go b/apmpackage/cmd/gen-package/genfields.go index 012f518737f..9763a4afaad 100644 --- a/apmpackage/cmd/gen-package/genfields.go +++ b/apmpackage/cmd/gen-package/genfields.go @@ -23,113 +23,113 @@ import ( "net/http" "path/filepath" "sort" - "strings" "gopkg.in/yaml.v2" "github.com/elastic/ecs/code/go/ecs" ) -func generateFields() map[string][]field { +func generateFields() map[string]fieldMap { ecsFlatFields := loadECSFields() - inputFieldsFiles := map[string][]field{ - "error_logs": format("model/error/_meta/fields.yml"), - "internal_metrics": format("model/metricset/_meta/fields.yml", "x-pack/apm-server/fields/_meta/fields.yml"), - "profile_metrics": format("model/profile/_meta/fields.yml"), - "traces": format("model/transaction/_meta/fields.yml", "model/span/_meta/fields.yml"), + inputFieldsFiles := map[string]fieldMap{ + "error_logs": readFields("model/error/_meta/fields.yml"), + "internal_metrics": readFields("model/metricset/_meta/fields.yml", "x-pack/apm-server/fields/_meta/fields.yml"), + "profile_metrics": readFields("model/profile/_meta/fields.yml"), + "traces": readFields("model/transaction/_meta/fields.yml", "model/span/_meta/fields.yml"), } - inputFieldsFiles["app_metrics"] = filterInternalMetrics(inputFieldsFiles["internal_metrics"]) - for streamType, inputFields := range inputFieldsFiles { + appMetrics := readFields("model/metricset/_meta/fields.yml", "x-pack/apm-server/fields/_meta/fields.yml") + delete(appMetrics, "transaction") + delete(appMetrics, "span") + delete(appMetrics, "event") + inputFieldsFiles["app_metrics"] = appMetrics + + for streamType, fields := range inputFieldsFiles { log.Printf("%s", streamType) - var ecsFields []field - var nonECSFields []field - for _, fields := range populateECSInfo(ecsFlatFields, inputFields) { - ecs, nonECS := splitECSFields(fields) - if len(ecs.Fields) > 0 || ecs.IsECS { - ecsFields = append(ecsFields, ecs) - } - if len(nonECS.Fields) > 0 || ecs.isNonECSLeaf() { - nonECSFields = append(nonECSFields, nonECS) - } + populateECSInfo(ecsFlatFields, fields) + for _, field := range fields { + log.Printf(" - %s (%s)", field.Name, field.Type) } - var writeOutFields = func(fName string, data []field) { - bytes, err := yaml.Marshal(&data) - if err != nil { - panic(err) - } - err = ioutil.WriteFile(filepath.Join(fieldsPath(streamType), fName), bytes, 0644) - if err != nil { - panic(err) - } - } - if len(ecsFields) > 0 { - writeOutFields("ecs.yml", ecsFields) + ecsFields, nonECSFields := splitFields(fields) + + var topLevelECSFields, topLevelNonECSFields []field + for _, field := range ecsFields { + topLevelECSFields = append(topLevelECSFields, field.field) } - if len(nonECSFields) > 0 { - writeOutFields("fields.yml", nonECSFields) + for _, field := range nonECSFields { + topLevelNonECSFields = append(topLevelNonECSFields, field.field) } + sortFields(topLevelECSFields) + sortFields(topLevelNonECSFields) + writeFields(streamType, "ecs.yml", topLevelECSFields) + writeFields(streamType, "fields.yml", topLevelNonECSFields) } return inputFieldsFiles } -func filterInternalMetrics(fields []field) []field { - var ret []field - var isInternal = func(s string) bool { - return strings.HasPrefix(s, "transaction") || - strings.HasPrefix(s, "span") || - strings.HasPrefix(s, "event") +func writeFields(streamType, filename string, data []field) { + if len(data) == 0 { + return } - for _, f := range fields { - if !isInternal(f.Name) { - ret = append(ret, f) - } + bytes, err := yaml.Marshal(data) + if err != nil { + panic(err) + } + err = ioutil.WriteFile(filepath.Join(fieldsPath(streamType), filename), bytes, 0644) + if err != nil { + panic(err) } - return ret } -func populateECSInfo(ecsFlatFields map[string]interface{}, inputFields []field) []field { - var traverse func(string, []field) ([]field, bool, bool) - traverse = func(fName string, fs []field) ([]field, bool, bool) { - var ecsCount int - for idx, field := range fs { +// populateECSInfo sets the IsECS property of each field. Group fields +// will have IsECS set only if all sub-fields have IsECS set. +func populateECSInfo(ecsFlatFields map[string]interface{}, inputFields fieldMap) { + var traverse func(path string, fields fieldMap) (ecsOnly bool) + traverse = func(path string, fields fieldMap) bool { + ecsOnly := true + for name, field := range fields { fieldName := field.Name - if fName != "" { - fieldName = fName + "." + fieldName + if path != "" { + fieldName = path + "." + fieldName } if field.Type != "group" { - _, ok := ecsFlatFields[fieldName] - fs[idx].IsECS = ok - if ok { - ecsCount = ecsCount + 1 - } + _, field.IsECS = ecsFlatFields[fieldName] } else { - fs[idx].Fields, fs[idx].HasECS, fs[idx].HasNonECS = traverse(fieldName, field.Fields) + field.IsECS = traverse(fieldName, field.fields) } + fields[name] = field + ecsOnly = ecsOnly && field.IsECS } - // first boolean returned indicates whether there is at least an ECS field in the group - // second boolean returned indicates whether there is at least a non-ECS field in the group - return fs, ecsCount > 0, ecsCount < len(fs) + return ecsOnly } - ret, _, _ := traverse("", inputFields) - return ret + traverse("", inputFields) } -func splitECSFields(parent field) (field, field) { - ecsCopy := copyFieldRoot(parent) - nonECSCopy := copyFieldRoot(parent) - for _, field := range parent.Fields { - ecsChild, nonECSChild := splitECSFields(field) - if ecsChild.HasECS || ecsChild.IsECS { - ecsCopy.Fields = append(ecsCopy.Fields, ecsChild) +// splitFields splits fields into ECS and non-ECS fieldMaps. +func splitFields(fields fieldMap) (ecsFields, nonECSFields fieldMap) { + ecsFields = make(fieldMap) + nonECSFields = make(fieldMap) + for name, field := range fields { + if field.IsECS { + ecsFields[name] = field + continue + } else if field.Type != "group" { + nonECSFields[name] = field + continue } - if nonECSChild.HasNonECS || nonECSChild.isNonECSLeaf() { - nonECSCopy.Fields = append(nonECSCopy.Fields, nonECSChild) + subECSFields, subNonECSFields := splitFields(field.fields) + fieldCopy := field.field + fieldCopy.Fields = nil // recreated by update calls + if len(subECSFields) > 0 { + ecsFields[name] = fieldMapItem{field: fieldCopy, fields: subECSFields} + ecsFields.update(fieldCopy) } + nonECSFields[name] = fieldMapItem{field: fieldCopy, fields: subNonECSFields} + nonECSFields.update(fieldCopy) } - return ecsCopy, nonECSCopy + return ecsFields, nonECSFields } func loadECSFields() map[string]interface{} { @@ -148,77 +148,82 @@ func loadECSFields() map[string]interface{} { return ret } -func format(fileNames ...string) []field { - return order(dedup(flatten("", concatFields(fileNames...)))) -} - -func concatFields(fileNames ...string) []field { - var ret []field +// readFields reads fields from all of the specified files, +// merging them into a fieldMap. +func readFields(fileNames ...string) fieldMap { + fields := make(fieldMap) for _, fname := range fileNames { - fs := loadFieldsFile(fname) - for _, key := range fs { - ret = append(ret, key.Fields...) + for _, key := range loadFieldsFile(fname) { + for _, field := range key.Fields { + fields.update(field) + } } } - return ret + return fields } -func loadFieldsFile(path string) []field { - fields, err := ioutil.ReadFile(path) - if err != nil { - panic(err) - } - - var fs []field - err = yaml.Unmarshal(fields, &fs) - if err != nil { - panic(err) +func flattenFields(fields fieldMap) []field { + var flattened []field + var traverse func(path string, fields fieldMap) + traverse = func(path string, fields fieldMap) { + for name, field := range fields { + full := path + if full != "" { + full += "." + } + full += name + field.Name = full + if field.Type == "group" { + traverse(full, field.fields) + } else { + flattened = append(flattened, field.field) + } + } } - return overrideFieldValues(fs) + traverse("", fields) + sortFields(flattened) + return flattened } -func overrideFieldValues(fs []field) []field { - var ret []field - for _, f := range fs { - if f.Type == "" { - f.Type = "keyword" - } - f.Fields = overrideFieldValues(f.Fields) - ret = append(ret, f) - } - return ret +type fieldMap map[string]fieldMapItem + +type fieldMapItem struct { + field + fields fieldMap } -func dedup(fs []field) []field { - var m = make(map[string]field) - for _, f := range fs { - m[f.Name] = f +func (m fieldMap) update(f field) { + item := m[f.Name] + item.field = f + if item.fields == nil { + item.fields = make(fieldMap) } - var ret []field - for _, v := range m { - ret = append(ret, v) + for _, f := range f.Fields { + item.fields.update(f) } - return ret + // Update the Fields slice, in case of merges. + item.Fields = item.Fields[:0] + for _, f := range item.fields { + item.Fields = append(item.Fields, f.field) + } + sortFields(item.Fields) + m[f.Name] = item } -func order(fs []field) []field { - sort.Slice(fs, func(i, j int) bool { - return fs[i].Name < fs[j].Name - }) +func loadFieldsFile(path string) []field { + fields, err := ioutil.ReadFile(path) + if err != nil { + panic(err) + } + var fs []field + if err := yaml.Unmarshal(fields, &fs); err != nil { + panic(err) + } return fs } -func flatten(name string, fs []field) []field { - var ret []field - for _, f := range fs { - if name != "" { - f.Name = name + "." + f.Name - } - if f.Type == "group" { - ret = append(ret, flatten(f.Name, f.Fields)...) - } else { - ret = append(ret, f) - } - } - return ret +func sortFields(fields []field) { + sort.Slice(fields, func(i, j int) bool { + return fields[i].Name < fields[j].Name + }) } diff --git a/changelogs/head.asciidoc b/changelogs/head.asciidoc index 9ff42d6d070..ba50544b75c 100644 --- a/changelogs/head.asciidoc +++ b/changelogs/head.asciidoc @@ -23,6 +23,7 @@ https://github.com/elastic/apm-server/compare/7.13\...master[View commits] - `service_destination` span metrics now take into account composite spans {pull}5896[5896] - add zero-downtime config reloads via `SO_REUSEPORT` {pull}5911[5911] - experimental support for writing data streams in standalone mode {pull}5928[5928] +- Data streams now define a default `dynamic` mapping parameter, overridable in the `@custom` template {pull}5947[5947] [float] ==== Deprecated From 3708a02288342b3030765003d1360a4b8055b25a Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Wed, 18 Aug 2021 01:47:18 -0400 Subject: [PATCH 10/14] [Automation] Update elastic stack version to 8.0.0-7e122dd9 for testing (#5955) Co-authored-by: apmmachine --- docker-compose.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index c84538ad1c5..21c7e54a163 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,7 +32,7 @@ services: kibana: { condition: service_healthy } elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:8.0.0-2e89a578-SNAPSHOT + image: docker.elastic.co/elasticsearch/elasticsearch:8.0.0-7e122dd9-SNAPSHOT ports: - 9200:9200 healthcheck: @@ -61,7 +61,7 @@ services: - "./testing/docker/elasticsearch/users_roles:/usr/share/elasticsearch/config/users_roles" kibana: - image: docker.elastic.co/kibana/kibana:8.0.0-2e89a578-SNAPSHOT + image: docker.elastic.co/kibana/kibana:8.0.0-7e122dd9-SNAPSHOT ports: - 5601:5601 healthcheck: @@ -85,7 +85,7 @@ services: package-registry: { condition: service_healthy } fleet-server: - image: docker.elastic.co/beats/elastic-agent:8.0.0-2e89a578-SNAPSHOT + image: docker.elastic.co/beats/elastic-agent:8.0.0-7e122dd9-SNAPSHOT ports: - 8220:8220 healthcheck: From 9ea5e3b276dc741440230cc39c01d79db7175a3c Mon Sep 17 00:00:00 2001 From: Andrew Wilkins Date: Wed, 18 Aug 2021 17:29:32 +0800 Subject: [PATCH 11/14] model: add APMEvent.{Observer,ECSVersion} (#5958) * model: add APMEvent.{Observer,ECSVersion} Introduce Observer and ECSVersion to APMEvent, and populate them with model processors. This replaces the libbeat processors that were setting these fields. Add some missing fields to the mappings, which became evident when switching to strict mapping in the integration. * beater: update processor name --- .../data_stream/app_metrics/fields/fields.yml | 11 ++ .../data_stream/error_logs/fields/fields.yml | 8 ++ .../internal_metrics/fields/fields.yml | 26 ++++ .../profile_metrics/fields/fields.yml | 8 ++ .../apm/data_stream/traces/fields/fields.yml | 8 ++ apmpackage/apm/docs/README.md | 7 + beater/beater.go | 45 +++++- beater/processors.go | 38 +++++ beater/server_test.go | 2 +- ...TestPublishIntegrationErrors.approved.json | 5 - ...TestPublishIntegrationEvents.approved.json | 4 - ...PublishIntegrationMetricsets.approved.json | 5 - ...lishIntegrationMinimalEvents.approved.json | 7 - ...IntegrationProfileCPUProfile.approved.json | 98 ------------- ...ionProfileCPUProfileMetadata.approved.json | 98 ------------- ...ntegrationProfileHeapProfile.approved.json | 42 ------ .../TestPublishIntegrationSpans.approved.json | 7 - ...blishIntegrationTransactions.approved.json | 4 - docs/fields.asciidoc | 136 ++++++++++++++++++ include/fields.go | 2 +- model/apmevent.go | 13 +- model/apmevent_test.go | 10 +- model/batch.go | 6 +- model/error/_meta/fields.yml | 12 ++ model/host_test.go | 5 +- model/metricset/_meta/fields.yml | 37 +++++ model/metricset_test.go | 6 +- model/modeldecoder/rumv3/metadata_test.go | 2 + model/modeldecoder/v2/metadata_test.go | 9 ++ model/observer.go | 50 +++++++ model/observer_test.go | 60 ++++++++ model/profile/_meta/fields.yml | 12 ++ model/span/_meta/fields.yml | 12 ++ model/span_test.go | 6 +- model/transaction/_meta/fields.yml | 12 ++ model/transaction_test.go | 6 +- publish/pub.go | 17 +-- 37 files changed, 519 insertions(+), 317 deletions(-) create mode 100644 model/observer.go create mode 100644 model/observer_test.go diff --git a/apmpackage/apm/data_stream/app_metrics/fields/fields.yml b/apmpackage/apm/data_stream/app_metrics/fields/fields.yml index 6c51811b12c..b0a518b1301 100644 --- a/apmpackage/apm/data_stream/app_metrics/fields/fields.yml +++ b/apmpackage/apm/data_stream/app_metrics/fields/fields.yml @@ -85,6 +85,14 @@ - name: observer type: group fields: + - name: ephemeral_id + type: keyword + description: | + Ephemeral identifier of the APM Server. + - name: id + type: keyword + description: | + Unique identifier of the APM Server. - name: listening type: keyword description: | @@ -283,6 +291,9 @@ The total virtual memory the process has. metric_type: gauge unit: byte +- name: timeseries.instance + type: keyword + description: Time series instance ID - name: timestamp type: group fields: diff --git a/apmpackage/apm/data_stream/error_logs/fields/fields.yml b/apmpackage/apm/data_stream/error_logs/fields/fields.yml index 959cf10249c..474ab14caac 100644 --- a/apmpackage/apm/data_stream/error_logs/fields/fields.yml +++ b/apmpackage/apm/data_stream/error_logs/fields/fields.yml @@ -147,6 +147,14 @@ - name: observer type: group fields: + - name: ephemeral_id + type: keyword + description: | + Ephemeral identifier of the APM Server. + - name: id + type: keyword + description: | + Unique identifier of the APM Server. - name: listening type: keyword description: | diff --git a/apmpackage/apm/data_stream/internal_metrics/fields/fields.yml b/apmpackage/apm/data_stream/internal_metrics/fields/fields.yml index 6ecd9aa2b01..fbef6cd52e0 100644 --- a/apmpackage/apm/data_stream/internal_metrics/fields/fields.yml +++ b/apmpackage/apm/data_stream/internal_metrics/fields/fields.yml @@ -85,6 +85,14 @@ - name: observer type: group fields: + - name: ephemeral_id + type: keyword + description: | + Ephemeral identifier of the APM Server. + - name: id + type: keyword + description: | + Unique identifier of the APM Server. - name: listening type: keyword description: | @@ -144,6 +152,17 @@ - name: span type: group fields: + - name: destination + type: group + fields: + - name: service + type: group + description: Destination service context + fields: + - name: resource + type: keyword + description: | + Identifier for the destination service resource being operated on (e.g. 'http://elastic.co:80', 'elasticsearch', 'rabbitmq/queue_name') - name: destination.service type: group fields: @@ -320,6 +339,9 @@ The total virtual memory the process has. metric_type: gauge unit: byte +- name: timeseries.instance + type: keyword + description: Time series instance ID - name: timestamp type: group fields: @@ -361,6 +383,10 @@ multi_fields: - name: text type: text + - name: result + type: keyword + description: | + The result of the transaction. HTTP status code for HTTP-related transactions. - name: root type: boolean description: | diff --git a/apmpackage/apm/data_stream/profile_metrics/fields/fields.yml b/apmpackage/apm/data_stream/profile_metrics/fields/fields.yml index 2432254beec..c34384fbf25 100644 --- a/apmpackage/apm/data_stream/profile_metrics/fields/fields.yml +++ b/apmpackage/apm/data_stream/profile_metrics/fields/fields.yml @@ -72,6 +72,14 @@ - name: observer type: group fields: + - name: ephemeral_id + type: keyword + description: | + Ephemeral identifier of the APM Server. + - name: id + type: keyword + description: | + Unique identifier of the APM Server. - name: listening type: keyword description: | diff --git a/apmpackage/apm/data_stream/traces/fields/fields.yml b/apmpackage/apm/data_stream/traces/fields/fields.yml index 95dfdbef9c9..82111e3421f 100644 --- a/apmpackage/apm/data_stream/traces/fields/fields.yml +++ b/apmpackage/apm/data_stream/traces/fields/fields.yml @@ -100,6 +100,14 @@ - name: observer type: group fields: + - name: ephemeral_id + type: keyword + description: | + Ephemeral identifier of the APM Server. + - name: id + type: keyword + description: | + Unique identifier of the APM Server. - name: listening type: keyword description: | diff --git a/apmpackage/apm/docs/README.md b/apmpackage/apm/docs/README.md index dbe5e62982b..08e8950d74f 100644 --- a/apmpackage/apm/docs/README.md +++ b/apmpackage/apm/docs/README.md @@ -105,7 +105,9 @@ Traces are written to `traces-apm.*` indices. |network.carrier.name|Carrier name, eg. Vodafone, T-Mobile, etc.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |network.connection.subtype|Detailed network connection sub-type, e.g. "LTE", "CDMA"|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |network.connection.type|Network connection type, eg. "wifi", "cell"|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | +|observer.ephemeral\_id|Ephemeral identifier of the APM Server.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |observer.hostname|Hostname of the APM Server.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|observer.id|Unique identifier of the APM Server.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |observer.listening|Address the server is listening on.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |observer.type|The type will be set to \`apm-server\`.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |observer.version|APM Server version.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | @@ -472,7 +474,9 @@ Metrics are written to `metrics-apm.app.*`, `metrics-apm.internal.*`, and `metri |network.carrier.name|Carrier name, eg. Vodafone, T-Mobile, etc.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |network.connection.subtype|Detailed network connection sub-type, e.g. "LTE", "CDMA"|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |network.connection.type|Network connection type, eg. "wifi", "cell"|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | +|observer.ephemeral\_id|Ephemeral identifier of the APM Server.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |observer.hostname|Hostname of the APM Server.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|observer.id|Unique identifier of the APM Server.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |observer.listening|Address the server is listening on.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |observer.type|The type will be set to \`apm-server\`.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |observer.version|APM Server version.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | @@ -512,6 +516,7 @@ Metrics are written to `metrics-apm.app.*`, `metrics-apm.internal.*`, and `metri |system.process.cpu.total.norm.pct|The percentage of CPU time spent by the process since the last event. This value is normalized by the number of CPU cores and it ranges from 0 to 100%.|scaled\_float| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |system.process.memory.rss.bytes|The Resident Set Size. The amount of memory the process occupied in main memory (RAM).|long| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |system.process.memory.size|The total virtual memory the process has.|long| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | +|timeseries.instance|Time series instance ID|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |timestamp.us|Timestamp of the event in microseconds since Unix epoch.|long| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |user.email|Email of the logged in user.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |user.id|Identifier of the logged in user.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | @@ -656,7 +661,9 @@ Logs are written to `logs-apm.error.*` indices. |network.carrier.name|Carrier name, eg. Vodafone, T-Mobile, etc.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |network.connection.subtype|Detailed network connection sub-type, e.g. "LTE", "CDMA"|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |network.connection.type|Network connection type, eg. "wifi", "cell"|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | +|observer.ephemeral\_id|Ephemeral identifier of the APM Server.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |observer.hostname|Hostname of the APM Server.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | +|observer.id|Unique identifier of the APM Server.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |observer.listening|Address the server is listening on.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png) | |observer.type|The type will be set to \`apm-server\`.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | |observer.version|APM Server version.|keyword| ![](https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png) | diff --git a/beater/beater.go b/beater/beater.go index 9664738b9df..57fe7edf887 100644 --- a/beater/beater.go +++ b/beater/beater.go @@ -350,7 +350,6 @@ func (s *serverRunner) run() error { // Send config to telemetry. recordAPMServerConfig(s.config) publisherConfig := &publish.PublisherConfig{ - Info: s.beat.Info, Pipeline: s.config.Pipeline, Namespace: s.namespace, } @@ -424,8 +423,13 @@ func (s *serverRunner) run() error { // Create the runServer function. We start with newBaseRunServer, and then // wrap depending on the configuration in order to inject behaviour. + // + // The reporter is passed into newBaseRunServer for legacy event publishers + // that bypass the model processor framework, i.e. sourcemap uploads, and + // onboarding docs. Because these bypass the model processor framework, we + // must augment the reporter to set common `observer` and `ecs.version` fields. reporter := publisher.Send - runServer := newBaseRunServer(reporter) + runServer := newBaseRunServer(augmentedReporter(reporter, s.beat.Info)) if s.tracerServer != nil { runServer = runServerWithTracerServer(runServer, s.tracerServer, s.tracer) } @@ -436,7 +440,7 @@ func (s *serverRunner) run() error { } runServer = s.wrapRunServerWithPreprocessors(runServer) - var batchProcessor model.BatchProcessor = &reporterBatchProcessor{reporter} + batchProcessor := s.newFinalBatchProcessor(reporter) if !s.config.Sampling.KeepUnsampled { // The server has been configured to discard unsampled // transactions. Make sure this is done just before calling @@ -461,12 +465,19 @@ func (s *serverRunner) run() error { return publisher.Stop(s.backgroundContext) } +// newFinalBatchProcessor returns the final model.BatchProcessor that publishes events. +func (s *serverRunner) newFinalBatchProcessor(libbeatReporter publish.Reporter) model.BatchProcessor { + return &reporterBatchProcessor{libbeatReporter} +} + func (s *serverRunner) wrapRunServerWithPreprocessors(runServer RunServerFunc) RunServerFunc { processors := []model.BatchProcessor{ modelprocessor.SetHostHostname{}, modelprocessor.SetServiceNodeName{}, modelprocessor.SetMetricsetName{}, modelprocessor.SetGroupingKey{}, + newObserverBatchProcessor(s.beat.Info), + model.ProcessBatchFunc(ecsVersionBatchProcessor), } if s.config.DefaultServiceEnvironment != "" { processors = append(processors, &modelprocessor.SetDefaultServiceEnvironment{ @@ -707,3 +718,31 @@ func (p *reporterBatchProcessor) ProcessBatch(ctx context.Context, batch *model. disableTracing, _ := ctx.Value(disablePublisherTracingKey{}).(bool) return p.reporter(ctx, publish.PendingReq{Transformable: batch, Trace: !disableTracing}) } + +// augmentedReporter wraps publish.Reporter such that the events it reports have +// `observer` and `ecs.version` fields injected. +func augmentedReporter(reporter publish.Reporter, info beat.Info) publish.Reporter { + observerBatchProcessor := newObserverBatchProcessor(info) + return func(ctx context.Context, req publish.PendingReq) error { + orig := req.Transformable + req.Transformable = transformerFunc(func(ctx context.Context) []beat.Event { + // Merge common fields into each event. + events := orig.Transform(ctx) + batch := make(model.Batch, 1) + observerBatchProcessor(ctx, &batch) + ecsVersionBatchProcessor(ctx, &batch) + for _, event := range events { + event.Fields.Put("ecs.version", batch[0].ECSVersion) + event.Fields.DeepUpdate(common.MapStr{"observer": batch[0].Observer.Fields()}) + } + return events + }) + return reporter(ctx, req) + } +} + +type transformerFunc func(context.Context) []beat.Event + +func (f transformerFunc) Transform(ctx context.Context) []beat.Event { + return f(ctx) +} diff --git a/beater/processors.go b/beater/processors.go index 8b5ba8e8d28..445e04cd106 100644 --- a/beater/processors.go +++ b/beater/processors.go @@ -21,6 +21,10 @@ import ( "context" "time" + "github.com/elastic/beats/v7/libbeat/beat" + "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/ecs/code/go/ecs" + "github.com/elastic/apm-server/beater/auth" "github.com/elastic/apm-server/beater/ratelimit" "github.com/elastic/apm-server/model" @@ -57,3 +61,37 @@ func rateLimitBatchProcessor(ctx context.Context, batch *model.Batch) error { } return nil } + +// ecsVersionBatchProcessor is a model.BatchProcessor that sets the ECSVersion +// field of each event to the ECS library version. +func ecsVersionBatchProcessor(ctx context.Context, b *model.Batch) error { + for i := range *b { + event := &(*b)[i] + event.ECSVersion = ecs.Version + } + return nil +} + +// newObserverBatchProcessor returns a model.BatchProcessor that sets observer +// fields from info. +func newObserverBatchProcessor(info beat.Info) model.ProcessBatchFunc { + var versionMajor int + if version, err := common.NewVersion(info.Version); err == nil { + versionMajor = version.Major + } + return func(ctx context.Context, b *model.Batch) error { + for i := range *b { + observer := &(*b)[i].Observer + observer.EphemeralID = info.EphemeralID.String() + observer.Hostname = info.Hostname + observer.ID = info.ID.String() + if info.Name != info.Hostname { + observer.Name = info.Name + } + observer.Type = info.Beat + observer.Version = info.Version + observer.VersionMajor = versionMajor + } + return nil + } +} diff --git a/beater/server_test.go b/beater/server_test.go index 9db35191b49..b7622ab95b8 100644 --- a/beater/server_test.go +++ b/beater/server_test.go @@ -645,7 +645,7 @@ func dummyPipeline(cfg *common.Config, info beat.Info, clients ...outputs.Client if cfg == nil { cfg = common.NewConfig() } - processors, err := processing.MakeDefaultObserverSupport(false)(info, logp.NewLogger("testbeat"), cfg) + processors, err := processing.MakeDefaultSupport(false)(info, logp.NewLogger("testbeat"), cfg) if err != nil { panic(err) } diff --git a/beater/test_approved_es_documents/TestPublishIntegrationErrors.approved.json b/beater/test_approved_es_documents/TestPublishIntegrationErrors.approved.json index 02357c387cb..cac7eec2948 100644 --- a/beater/test_approved_es_documents/TestPublishIntegrationErrors.approved.json +++ b/beater/test_approved_es_documents/TestPublishIntegrationErrors.approved.json @@ -289,7 +289,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -423,7 +422,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -538,7 +536,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -653,7 +650,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -773,7 +769,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", diff --git a/beater/test_approved_es_documents/TestPublishIntegrationEvents.approved.json b/beater/test_approved_es_documents/TestPublishIntegrationEvents.approved.json index f56f3d5872d..7650e772100 100644 --- a/beater/test_approved_es_documents/TestPublishIntegrationEvents.approved.json +++ b/beater/test_approved_es_documents/TestPublishIntegrationEvents.approved.json @@ -216,7 +216,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -337,7 +336,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -551,7 +549,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -694,7 +691,6 @@ "negative.d.o.t.t.e.d": -1022, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", diff --git a/beater/test_approved_es_documents/TestPublishIntegrationMetricsets.approved.json b/beater/test_approved_es_documents/TestPublishIntegrationMetricsets.approved.json index dc73e64e92f..d5d9eff9389 100644 --- a/beater/test_approved_es_documents/TestPublishIntegrationMetricsets.approved.json +++ b/beater/test_approved_es_documents/TestPublishIntegrationMetricsets.approved.json @@ -29,7 +29,6 @@ "negative.d.o.t.t.e.d": -1022, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -93,7 +92,6 @@ "metricset.name": "app", "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -140,7 +138,6 @@ "metricset.name": "app", "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -189,7 +186,6 @@ "metricset.name": "app", "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -262,7 +258,6 @@ "metricset.name": "app", "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", diff --git a/beater/test_approved_es_documents/TestPublishIntegrationMinimalEvents.approved.json b/beater/test_approved_es_documents/TestPublishIntegrationMinimalEvents.approved.json index c6733268a0a..5ac5340f5c9 100644 --- a/beater/test_approved_es_documents/TestPublishIntegrationMinimalEvents.approved.json +++ b/beater/test_approved_es_documents/TestPublishIntegrationMinimalEvents.approved.json @@ -21,7 +21,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -61,7 +60,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -101,7 +99,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -135,7 +132,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -186,7 +182,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -237,7 +232,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -284,7 +278,6 @@ "metricset.name": "app", "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", diff --git a/beater/test_approved_es_documents/TestPublishIntegrationProfileCPUProfile.approved.json b/beater/test_approved_es_documents/TestPublishIntegrationProfileCPUProfile.approved.json index c490284421e..dad5e968b73 100644 --- a/beater/test_approved_es_documents/TestPublishIntegrationProfileCPUProfile.approved.json +++ b/beater/test_approved_es_documents/TestPublishIntegrationProfileCPUProfile.approved.json @@ -10,7 +10,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -147,7 +146,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -230,7 +228,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -385,7 +382,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -468,7 +464,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -533,7 +528,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -634,7 +628,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -729,7 +722,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -818,7 +810,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -925,7 +916,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1050,7 +1040,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1109,7 +1098,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1180,7 +1168,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1287,7 +1274,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1424,7 +1410,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1489,7 +1474,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1608,7 +1592,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1715,7 +1698,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1810,7 +1792,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1905,7 +1886,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2030,7 +2010,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2089,7 +2068,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2178,7 +2156,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2243,7 +2220,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2314,7 +2290,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2445,7 +2420,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2528,7 +2502,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2587,7 +2560,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2634,7 +2606,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2717,7 +2688,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2842,7 +2812,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2955,7 +2924,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3068,7 +3036,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3145,7 +3112,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3264,7 +3230,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3329,7 +3294,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3412,7 +3376,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3483,7 +3446,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3608,7 +3570,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3781,7 +3742,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3864,7 +3824,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3965,7 +3924,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4132,7 +4090,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4191,7 +4148,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4322,7 +4278,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4441,7 +4396,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4506,7 +4460,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4595,7 +4548,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4648,7 +4600,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4725,7 +4676,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4784,7 +4734,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4915,7 +4864,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4974,7 +4922,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5021,7 +4968,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5104,7 +5050,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5217,7 +5162,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5312,7 +5256,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5389,7 +5332,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5496,7 +5438,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5603,7 +5544,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5686,7 +5626,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5811,7 +5750,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5900,7 +5838,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5995,7 +5932,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6084,7 +6020,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6161,7 +6096,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6220,7 +6154,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6333,7 +6266,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6470,7 +6402,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6619,7 +6550,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6708,7 +6638,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6767,7 +6696,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6862,7 +6790,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7017,7 +6944,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7154,7 +7080,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7279,7 +7204,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7344,7 +7268,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7415,7 +7338,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7522,7 +7444,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7563,7 +7484,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7616,7 +7536,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7687,7 +7606,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7764,7 +7682,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7841,7 +7758,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7930,7 +7846,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8043,7 +7958,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8114,7 +8028,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8191,7 +8104,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8310,7 +8222,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8381,7 +8292,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8494,7 +8404,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8589,7 +8498,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8684,7 +8592,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8737,7 +8644,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8844,7 +8750,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8921,7 +8826,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8974,7 +8878,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -9111,7 +9014,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", diff --git a/beater/test_approved_es_documents/TestPublishIntegrationProfileCPUProfileMetadata.approved.json b/beater/test_approved_es_documents/TestPublishIntegrationProfileCPUProfileMetadata.approved.json index ae4bb869569..4b165dc6902 100644 --- a/beater/test_approved_es_documents/TestPublishIntegrationProfileCPUProfileMetadata.approved.json +++ b/beater/test_approved_es_documents/TestPublishIntegrationProfileCPUProfileMetadata.approved.json @@ -14,7 +14,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -158,7 +157,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -248,7 +246,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -410,7 +407,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -500,7 +496,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -572,7 +567,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -680,7 +674,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -782,7 +775,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -878,7 +870,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -992,7 +983,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1124,7 +1114,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1190,7 +1179,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1268,7 +1256,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1382,7 +1369,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1526,7 +1512,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1598,7 +1583,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1724,7 +1708,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1838,7 +1821,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1940,7 +1922,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2042,7 +2023,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2174,7 +2154,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2240,7 +2219,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2336,7 +2314,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2408,7 +2385,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2486,7 +2462,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2624,7 +2599,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2714,7 +2688,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2780,7 +2753,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2834,7 +2806,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2924,7 +2895,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3056,7 +3026,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3176,7 +3145,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3296,7 +3264,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3380,7 +3347,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3506,7 +3472,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3578,7 +3543,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3668,7 +3632,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3746,7 +3709,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3878,7 +3840,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4058,7 +4019,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4148,7 +4108,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4256,7 +4215,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4430,7 +4388,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4496,7 +4453,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4634,7 +4590,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4760,7 +4715,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4832,7 +4786,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4928,7 +4881,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4988,7 +4940,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5072,7 +5023,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5138,7 +5088,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5276,7 +5225,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5342,7 +5290,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5396,7 +5343,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5486,7 +5432,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5606,7 +5551,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5708,7 +5652,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5792,7 +5735,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -5906,7 +5848,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6020,7 +5961,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6110,7 +6050,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6242,7 +6181,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6338,7 +6276,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6440,7 +6377,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6536,7 +6472,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6620,7 +6555,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6686,7 +6620,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6806,7 +6739,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -6950,7 +6882,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7106,7 +7037,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7202,7 +7132,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7268,7 +7197,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7370,7 +7298,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7532,7 +7459,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7676,7 +7602,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7808,7 +7733,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7880,7 +7804,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -7958,7 +7881,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8072,7 +7994,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8120,7 +8041,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8180,7 +8100,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8258,7 +8177,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8342,7 +8260,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8426,7 +8343,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8522,7 +8438,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8642,7 +8557,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8720,7 +8634,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8804,7 +8717,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -8930,7 +8842,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -9008,7 +8919,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -9128,7 +9038,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -9230,7 +9139,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -9332,7 +9240,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -9392,7 +9299,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -9506,7 +9412,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -9590,7 +9495,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -9650,7 +9554,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -9794,7 +9697,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", diff --git a/beater/test_approved_es_documents/TestPublishIntegrationProfileHeapProfile.approved.json b/beater/test_approved_es_documents/TestPublishIntegrationProfileHeapProfile.approved.json index 71e9b121e0a..f40b8f43363 100644 --- a/beater/test_approved_es_documents/TestPublishIntegrationProfileHeapProfile.approved.json +++ b/beater/test_approved_es_documents/TestPublishIntegrationProfileHeapProfile.approved.json @@ -10,7 +10,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -82,7 +81,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -196,7 +194,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -298,7 +295,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -400,7 +396,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -448,7 +443,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -544,7 +538,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -592,7 +585,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -664,7 +656,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -730,7 +721,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -850,7 +840,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -934,7 +923,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1048,7 +1036,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1132,7 +1119,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1204,7 +1190,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1252,7 +1237,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1300,7 +1284,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1378,7 +1361,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1426,7 +1408,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1642,7 +1623,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1696,7 +1676,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1762,7 +1741,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1900,7 +1878,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -1954,7 +1931,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2086,7 +2062,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2128,7 +2103,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2194,7 +2168,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2266,7 +2239,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2422,7 +2394,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2584,7 +2555,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2794,7 +2764,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -2914,7 +2883,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3004,7 +2972,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3142,7 +3109,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3268,7 +3234,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3376,7 +3341,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3574,7 +3538,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3694,7 +3657,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3814,7 +3776,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3898,7 +3859,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -3982,7 +3942,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -4090,7 +4049,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", diff --git a/beater/test_approved_es_documents/TestPublishIntegrationSpans.approved.json b/beater/test_approved_es_documents/TestPublishIntegrationSpans.approved.json index b53ac3653a3..7ad789912a2 100644 --- a/beater/test_approved_es_documents/TestPublishIntegrationSpans.approved.json +++ b/beater/test_approved_es_documents/TestPublishIntegrationSpans.approved.json @@ -67,7 +67,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -197,7 +196,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -331,7 +329,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -463,7 +460,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -608,7 +604,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -822,7 +817,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -960,7 +954,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", diff --git a/beater/test_approved_es_documents/TestPublishIntegrationTransactions.approved.json b/beater/test_approved_es_documents/TestPublishIntegrationTransactions.approved.json index 70463ff4615..5552d3c573a 100644 --- a/beater/test_approved_es_documents/TestPublishIntegrationTransactions.approved.json +++ b/beater/test_approved_es_documents/TestPublishIntegrationTransactions.approved.json @@ -64,7 +64,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -258,7 +257,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -422,7 +420,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", @@ -569,7 +566,6 @@ }, "observer": { "ephemeral_id": "00000000-0000-0000-0000-000000000000", - "hostname": "", "id": "fbba762a-14dd-412c-b7e9-b79f903eb492", "type": "test-apm-server", "version": "1.2.3", diff --git a/docs/fields.asciidoc b/docs/fields.asciidoc index cf2f17d51b3..01f84915a43 100644 --- a/docs/fields.asciidoc +++ b/docs/fields.asciidoc @@ -829,6 +829,26 @@ type: keyword -- +*`observer.id`*:: ++ +-- +Unique identifier of the APM Server. + + +type: keyword + +-- + +*`observer.ephemeral_id`*:: ++ +-- +Ephemeral identifier of the APM Server. + + +type: keyword + +-- + *`user.name`*:: + @@ -1994,6 +2014,26 @@ type: keyword -- +*`observer.id`*:: ++ +-- +Unique identifier of the APM Server. + + +type: keyword + +-- + +*`observer.ephemeral_id`*:: ++ +-- +Ephemeral identifier of the APM Server. + + +type: keyword + +-- + *`user.name`*:: + @@ -3301,6 +3341,26 @@ type: keyword -- +*`observer.id`*:: ++ +-- +Unique identifier of the APM Server. + + +type: keyword + +-- + +*`observer.ephemeral_id`*:: ++ +-- +Ephemeral identifier of the APM Server. + + +type: keyword + +-- + *`user.name`*:: + @@ -4938,6 +4998,26 @@ type: keyword -- +*`observer.id`*:: ++ +-- +Unique identifier of the APM Server. + + +type: keyword + +-- + +*`observer.ephemeral_id`*:: ++ +-- +Ephemeral identifier of the APM Server. + + +type: keyword + +-- + *`user.domain`*:: + @@ -5463,6 +5543,15 @@ type: keyword -- +*`timeseries.instance`*:: ++ +-- +Time series instance ID + +type: keyword + +-- + *`timestamp.us`*:: + @@ -5734,6 +5823,16 @@ type: boolean -- +*`transaction.result`*:: ++ +-- +The result of the transaction. HTTP status code for HTTP-related transactions. + + +type: keyword + +-- + *`span.type`*:: + @@ -5783,6 +5882,23 @@ type: long -- +[float] +=== service + +Destination service context + + +*`span.destination.service.resource`*:: ++ +-- +Identifier for the destination service resource being operated on (e.g. 'http://elastic.co:80', 'elasticsearch', 'rabbitmq/queue_name') + + +type: keyword + +-- + + *`agent.name`*:: + -- @@ -6154,6 +6270,26 @@ type: keyword -- +*`observer.id`*:: ++ +-- +Unique identifier of the APM Server. + + +type: keyword + +-- + +*`observer.ephemeral_id`*:: ++ +-- +Ephemeral identifier of the APM Server. + + +type: keyword + +-- + *`user.name`*:: + diff --git a/include/fields.go b/include/fields.go index b7793fd6df3..de7e1bad69c 100644 --- a/include/fields.go +++ b/include/fields.go @@ -32,5 +32,5 @@ func init() { // AssetBuildFieldsFieldsYml returns asset data. // This is the base64 encoded zlib format compressed contents of build/fields/fields.yml. func AssetBuildFieldsFieldsYml() string { - return "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" + return "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" } diff --git a/model/apmevent.go b/model/apmevent.go index 940d816bb70..013a6c62dcc 100644 --- a/model/apmevent.go +++ b/model/apmevent.go @@ -36,8 +36,10 @@ type APMEvent struct { // in standalone mode. DataStream DataStream + ECSVersion string Event Event Agent Agent + Observer Observer Container Container Kubernetes Kubernetes Service Service @@ -65,7 +67,8 @@ type APMEvent struct { ProfileSample *ProfileSample } -func (e *APMEvent) appendBeatEvent(ctx context.Context, out []beat.Event) []beat.Event { +// BeatEvent converts e to a beat.Event. +func (e *APMEvent) BeatEvent(ctx context.Context) beat.Event { event := beat.Event{Timestamp: e.Timestamp} switch { case e.Transaction != nil: @@ -79,7 +82,7 @@ func (e *APMEvent) appendBeatEvent(ctx context.Context, out []beat.Event) []beat case e.ProfileSample != nil: event.Fields = e.ProfileSample.fields() default: - return out + event.Fields = make(common.MapStr) } // Set high resolution timestamp. @@ -93,8 +96,12 @@ func (e *APMEvent) appendBeatEvent(ctx context.Context, out []beat.Event) []beat fields := (*mapStr)(&event.Fields) event.Timestamp = e.Timestamp e.DataStream.setFields(fields) + if e.ECSVersion != "" { + fields.set("ecs", common.MapStr{"version": e.ECSVersion}) + } fields.maybeSetMapStr("service", e.Service.Fields()) fields.maybeSetMapStr("agent", e.Agent.fields()) + fields.maybeSetMapStr("observer", e.Observer.Fields()) fields.maybeSetMapStr("host", e.Host.fields()) fields.maybeSetMapStr("process", e.Process.fields()) fields.maybeSetMapStr("user", e.User.fields()) @@ -116,5 +123,5 @@ func (e *APMEvent) appendBeatEvent(ctx context.Context, out []beat.Event) []beat fields.maybeSetMapStr("event", e.Event.fields()) fields.maybeSetMapStr("url", e.URL.fields()) fields.maybeSetMapStr("session", e.Session.fields()) - return append(out, event) + return event } diff --git a/model/apmevent_test.go b/model/apmevent_test.go index 56aa6429984..9c74dbd7e4a 100644 --- a/model/apmevent_test.go +++ b/model/apmevent_test.go @@ -23,7 +23,6 @@ import ( "time" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/elastic/beats/v7/libbeat/common" ) @@ -48,10 +47,12 @@ func TestAPMEventFields(t *testing.T) { }{ { input: APMEvent{ + ECSVersion: "1.0.0", Agent: Agent{ Name: agentName, Version: agentVersion, }, + Observer: Observer{Type: "apm-server"}, Container: Container{ID: containerID}, Service: Service{ Name: serviceName, @@ -74,7 +75,9 @@ func TestAPMEventFields(t *testing.T) { }, output: common.MapStr{ // common fields + "ecs": common.MapStr{"version": "1.0.0"}, "agent": common.MapStr{"version": "1.0.0", "name": "elastic-node"}, + "observer": common.MapStr{"type": "apm-server"}, "container": common.MapStr{"id": containerID}, "host": common.MapStr{"hostname": hostname, "name": host}, "process": common.MapStr{"pid": pid}, @@ -113,8 +116,7 @@ func TestAPMEventFields(t *testing.T) { }, }, } { - events := test.input.appendBeatEvent(context.Background(), nil) - require.Len(t, events, 1) - assert.Equal(t, test.output, events[0].Fields) + event := test.input.BeatEvent(context.Background()) + assert.Equal(t, test.output, event.Fields) } } diff --git a/model/batch.go b/model/batch.go index 45d14e383ea..1f8b2583a0c 100644 --- a/model/batch.go +++ b/model/batch.go @@ -46,9 +46,9 @@ type Batch []APMEvent // Transform transforms all events in the batch, in sequence. func (b *Batch) Transform(ctx context.Context) []beat.Event { - out := make([]beat.Event, 0, len(*b)) - for _, event := range *b { - out = event.appendBeatEvent(ctx, out) + out := make([]beat.Event, len(*b)) + for i, event := range *b { + out[i] = event.BeatEvent(ctx) } return out } diff --git a/model/error/_meta/fields.yml b/model/error/_meta/fields.yml index eb1ab01114b..1e2d7d144dd 100644 --- a/model/error/_meta/fields.yml +++ b/model/error/_meta/fields.yml @@ -515,6 +515,18 @@ description: > The type will be set to `apm-server`. + - name: id + type: keyword + overwrite: true + description: > + Unique identifier of the APM Server. + + - name: ephemeral_id + type: keyword + overwrite: true + description: > + Ephemeral identifier of the APM Server. + - name: user type: group dynamic: false diff --git a/model/host_test.go b/model/host_test.go index 9ac34ce6132..5dbe9d98fb0 100644 --- a/model/host_test.go +++ b/model/host_test.go @@ -52,10 +52,9 @@ func TestSystemTransformation(t *testing.T) { } { t.Run(name, func(t *testing.T) { event := &APMEvent{Host: host, Transaction: &Transaction{}} - beatEvents := event.appendBeatEvent(context.Background(), nil) - require.Len(t, beatEvents, 1) + beatEvent := event.BeatEvent(context.Background()) - resultJSON, err := json.Marshal(beatEvents[0].Fields["host"]) + resultJSON, err := json.Marshal(beatEvent.Fields["host"]) require.NoError(t, err) name := filepath.Join("test_approved", "host", strings.ReplaceAll(name, " ", "_")) approvaltest.ApproveJSON(t, name, resultJSON) diff --git a/model/metricset/_meta/fields.yml b/model/metricset/_meta/fields.yml index 382a39e5375..32501bc848e 100644 --- a/model/metricset/_meta/fields.yml +++ b/model/metricset/_meta/fields.yml @@ -24,6 +24,11 @@ description: Processor event. overwrite: true + - name: timeseries.instance + type: keyword + description: Time series instance ID + overwrite: true + - name: timestamp type: group fields: @@ -214,6 +219,10 @@ description: > Identifies metrics for root transactions. This can be used for calculating metrics for traces. + - name: result + type: keyword + description: > + The result of the transaction. HTTP status code for HTTP-related transactions. - name: span type: group @@ -253,6 +262,22 @@ Aggregated span duration, excluding the time periods where a direct child was running, in microseconds. + - name: destination + type: group + dynamic: false + fields: + + - name: service + type: group + dynamic: false + description: Destination service context + fields: + + - name: resource + type: keyword + description: > + Identifier for the destination service resource being operated on (e.g. 'http://elastic.co:80', 'elasticsearch', 'rabbitmq/queue_name') + - name: agent type: group dynamic: false @@ -498,6 +523,18 @@ description: > The type will be set to `apm-server`. + - name: id + type: keyword + overwrite: true + description: > + Unique identifier of the APM Server. + + - name: ephemeral_id + type: keyword + overwrite: true + description: > + Ephemeral identifier of the APM Server. + - name: user type: group dynamic: false diff --git a/model/metricset_test.go b/model/metricset_test.go index e72736dc86b..28ceb2dcbeb 100644 --- a/model/metricset_test.go +++ b/model/metricset_test.go @@ -23,7 +23,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/elastic/beats/v7/libbeat/common" ) @@ -200,8 +199,7 @@ func TestMetricset(t *testing.T) { for idx, test := range tests { event := APMEvent{Metricset: test.Metricset} - outputEvents := event.appendBeatEvent(context.Background(), nil) - require.Len(t, outputEvents, 1) - assert.Equal(t, test.Output, outputEvents[0].Fields, fmt.Sprintf("Failed at idx %v; %s", idx, test.Msg)) + outputEvent := event.BeatEvent(context.Background()) + assert.Equal(t, test.Output, outputEvent.Fields, fmt.Sprintf("Failed at idx %v; %s", idx, test.Msg)) } } diff --git a/model/modeldecoder/rumv3/metadata_test.go b/model/modeldecoder/rumv3/metadata_test.go index ba3419bea23..1212450f520 100644 --- a/model/modeldecoder/rumv3/metadata_test.go +++ b/model/modeldecoder/rumv3/metadata_test.go @@ -54,8 +54,10 @@ func metadataExceptions(keys ...string) func(key string) bool { "Container", "DataStream", "Destination", + "ECSVersion", "Kubernetes", "Network", + "Observer", "Process", "Service.Node", "Service.Agent.EphemeralID", diff --git a/model/modeldecoder/v2/metadata_test.go b/model/modeldecoder/v2/metadata_test.go index c4680282183..5f868c2063b 100644 --- a/model/modeldecoder/v2/metadata_test.go +++ b/model/modeldecoder/v2/metadata_test.go @@ -54,6 +54,7 @@ func isUnmappedMetadataField(key string) bool { "Destination.Address", "Destination.IP", "Destination.Port", + "ECSVersion", "Network", "Network.Connection", "Network.Connection.Subtype", @@ -62,6 +63,14 @@ func isUnmappedMetadataField(key string) bool { "Network.Carrier.MCC", "Network.Carrier.MNC", "Network.Carrier.ICC", + "Observer", + "Observer.EphemeralID", + "Observer.Hostname", + "Observer.ID", + "Observer.Name", + "Observer.Type", + "Observer.Version", + "Observer.VersionMajor", "Process.CommandLine", "Process.Executable", "Host.OS.Full", diff --git a/model/observer.go b/model/observer.go new file mode 100644 index 00000000000..85a2bf010ec --- /dev/null +++ b/model/observer.go @@ -0,0 +1,50 @@ +// 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 model + +import ( + "github.com/elastic/beats/v7/libbeat/common" +) + +// Observer describes a special network, security, or application device used to detect, +// observe, or create network, security, or application-related events and metrics. +// +// https://www.elastic.co/guide/en/ecs/current/ecs-observer.html +type Observer struct { + EphemeralID string + Hostname string + ID string + Name string + Type string + Version string + VersionMajor int +} + +func (o *Observer) Fields() common.MapStr { + var fields mapStr + fields.maybeSetString("ephemeral_id", o.EphemeralID) + fields.maybeSetString("hostname", o.Hostname) + fields.maybeSetString("id", o.ID) + fields.maybeSetString("name", o.Name) + fields.maybeSetString("type", o.Type) + fields.maybeSetString("version", o.Version) + if o.VersionMajor > 0 { + fields.set("version_major", o.VersionMajor) + } + return common.MapStr(fields) +} diff --git a/model/observer_test.go b/model/observer_test.go new file mode 100644 index 00000000000..d76c9a30f97 --- /dev/null +++ b/model/observer_test.go @@ -0,0 +1,60 @@ +// 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 model + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/v7/libbeat/common" +) + +func TestObserverFields(t *testing.T) { + tests := []struct { + Observer Observer + Fields common.MapStr + }{ + { + Observer: Observer{}, + Fields: nil, + }, + { + Observer: Observer{ + EphemeralID: "observer_ephemeral_id", + Hostname: "observer_hostname", + ID: "observer_id", + Name: "observer_name", + Type: "observer_type", + Version: "observer_version", + }, + Fields: common.MapStr{ + "ephemeral_id": "observer_ephemeral_id", + "hostname": "observer_hostname", + "id": "observer_id", + "name": "observer_name", + "type": "observer_type", + "version": "observer_version", + }, + }, + } + + for _, test := range tests { + assert.Equal(t, test.Fields, test.Observer.Fields()) + } +} diff --git a/model/profile/_meta/fields.yml b/model/profile/_meta/fields.yml index f451063235a..e89ca706670 100644 --- a/model/profile/_meta/fields.yml +++ b/model/profile/_meta/fields.yml @@ -360,6 +360,18 @@ description: > The type will be set to `apm-server`. + - name: id + type: keyword + overwrite: true + description: > + Unique identifier of the APM Server. + + - name: ephemeral_id + type: keyword + overwrite: true + description: > + Ephemeral identifier of the APM Server. + - name: user type: group dynamic: false diff --git a/model/span/_meta/fields.yml b/model/span/_meta/fields.yml index 794f1bb6ea8..42c4b92e0f6 100644 --- a/model/span/_meta/fields.yml +++ b/model/span/_meta/fields.yml @@ -408,6 +408,18 @@ description: > The type will be set to `apm-server`. + - name: id + type: keyword + overwrite: true + description: > + Unique identifier of the APM Server. + + - name: ephemeral_id + type: keyword + overwrite: true + description: > + Ephemeral identifier of the APM Server. + - name: user type: group dynamic: false diff --git a/model/span_test.go b/model/span_test.go index 84119960118..85a3feaf336 100644 --- a/model/span_test.go +++ b/model/span_test.go @@ -23,7 +23,6 @@ import ( "time" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/elastic/beats/v7/libbeat/common" ) @@ -155,8 +154,7 @@ func TestSpanTransform(t *testing.T) { Timestamp: timestamp, URL: URL{Original: url}, } - output := event.appendBeatEvent(context.Background(), nil) - require.Len(t, output, 1) - assert.Equal(t, test.Output, output[0].Fields, test.Msg) + output := event.BeatEvent(context.Background()) + assert.Equal(t, test.Output, output.Fields, test.Msg) } } diff --git a/model/transaction/_meta/fields.yml b/model/transaction/_meta/fields.yml index f24d8f4f1ab..67b85d0eb3a 100644 --- a/model/transaction/_meta/fields.yml +++ b/model/transaction/_meta/fields.yml @@ -526,6 +526,18 @@ description: > The type will be set to `apm-server`. + - name: id + type: keyword + overwrite: true + description: > + Unique identifier of the APM Server. + + - name: ephemeral_id + type: keyword + overwrite: true + description: > + Ephemeral identifier of the APM Server. + - name: user type: group dynamic: false diff --git a/model/transaction_test.go b/model/transaction_test.go index da966bc64db..4a8eea22e09 100644 --- a/model/transaction_test.go +++ b/model/transaction_test.go @@ -24,7 +24,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/elastic/beats/v7/libbeat/common" ) @@ -159,10 +158,7 @@ func TestEventsTransformWithMetadata(t *testing.T) { }, } - events := txWithContext.appendBeatEvent(context.Background(), nil) - require.Len(t, events, 1) - event := events[0] - + event := txWithContext.BeatEvent(context.Background()) assert.Equal(t, common.MapStr{ "user": common.MapStr{"id": "123", "name": "jane"}, "client": common.MapStr{"ip": ip}, diff --git a/publish/pub.go b/publish/pub.go index a7e72d92a04..5d0c84de203 100644 --- a/publish/pub.go +++ b/publish/pub.go @@ -27,7 +27,6 @@ import ( "go.elastic.co/apm" "github.com/elastic/beats/v7/libbeat/beat" - "github.com/elastic/beats/v7/libbeat/common" ) type Reporter func(context.Context, PendingReq) error @@ -87,21 +86,7 @@ func NewPublisher(pipeline beat.Pipeline, tracer *apm.Tracer, cfg *PublisherConf return nil, errors.Wrap(err, "invalid config") } - observerFields := common.MapStr{ - "type": cfg.Info.Beat, - "hostname": cfg.Info.Hostname, - "version": cfg.Info.Version, - "id": cfg.Info.ID.String(), - "ephemeral_id": cfg.Info.EphemeralID.String(), - } - if version, err := common.NewVersion(cfg.Info.Version); err == nil { - observerFields["version_major"] = version.Major - } - - processingCfg := beat.ProcessingConfig{ - Fields: common.MapStr{"observer": observerFields}, - Processor: cfg.Processor, - } + processingCfg := beat.ProcessingConfig{Processor: cfg.Processor} if cfg.Pipeline != "" { processingCfg.Meta = map[string]interface{}{"pipeline": cfg.Pipeline} } From 2c65c70cda74aa3eb4633c022417548ef52d89c7 Mon Sep 17 00:00:00 2001 From: Andrew Wilkins Date: Wed, 18 Aug 2021 17:52:08 +0800 Subject: [PATCH 12/14] Update tail sampling to require data streams (#5952) * Update tail sampling to require data streams Tail-sampling now requires data streams to be enabled, and apm-server will error if tail-sampling is enabled and data streams are not. The code for creating a sampled traces data stream when running in standalone has been removed. The data stream is now expected to be created by installing the integration package. Rename the sampled traces data stream from `traces-sampled-*` to `traces-apm.sampled-*`, to maintain a common "apm" prefix for all datasets. The Elasticsearch role used by apm-server in tests has been updated with access to `traces-apm*`, `metrics-apm*`, and `logs-apm*`. * systemtest: fix TestTailSamplingUnlicensed * Update changelog --- .../data_stream/sampled_traces/manifest.yml | 2 +- beater/config/config.go | 2 +- beater/config/config_test.go | 11 +- beater/config/sampling.go | 5 +- beater/config/sampling_test.go | 12 ++ beater/waitintegration.go | 2 +- changelogs/head.asciidoc | 2 + systemtest/apmservertest/config.go | 3 +- systemtest/fleettest/client.go | 11 ++ systemtest/sampling_test.go | 30 ++++- testing/docker/elasticsearch/roles.yml | 2 +- x-pack/apm-server/main.go | 37 ++---- x-pack/apm-server/main_test.go | 1 + .../apm-server/sampling/pubsub/datastream.go | 114 ------------------ 14 files changed, 81 insertions(+), 153 deletions(-) delete mode 100644 x-pack/apm-server/sampling/pubsub/datastream.go diff --git a/apmpackage/apm/data_stream/sampled_traces/manifest.yml b/apmpackage/apm/data_stream/sampled_traces/manifest.yml index 937472ae893..27d9752c8a5 100644 --- a/apmpackage/apm/data_stream/sampled_traces/manifest.yml +++ b/apmpackage/apm/data_stream/sampled_traces/manifest.yml @@ -1,6 +1,6 @@ title: APM tail-sampled traces type: traces -dataset: sampled +dataset: apm.sampled ilm_policy: traces-apm.sampled-default_policy elasticsearch: index_template: diff --git a/beater/config/config.go b/beater/config/config.go index a65f0c3ca11..a94481030ac 100644 --- a/beater/config/config.go +++ b/beater/config/config.go @@ -118,7 +118,7 @@ func NewConfig(ucfg *common.Config, outputESCfg *common.Config) (*Config, error) return nil, err } - if err := c.Sampling.Tail.setup(logger, outputESCfg); err != nil { + if err := c.Sampling.Tail.setup(logger, c.DataStreams.Enabled, outputESCfg); err != nil { return nil, err } diff --git a/beater/config/config_test.go b/beater/config/config_test.go index c095d3ae617..cbbfdac656b 100644 --- a/beater/config/config_test.go +++ b/beater/config/config_test.go @@ -342,7 +342,7 @@ func TestUnpackConfig(t *testing.T) { "aggregation.service_destinations.enabled": false, "sampling.keep_unsampled": false, "sampling.tail": map[string]interface{}{ - "enabled": true, + "enabled": false, "policies": []map[string]interface{}{{"sample_rate": 0.5}}, "interval": "2m", "ingest_rate_decay": 1.0, @@ -468,7 +468,7 @@ func TestUnpackConfig(t *testing.T) { Sampling: SamplingConfig{ KeepUnsampled: false, Tail: TailSamplingConfig{ - Enabled: true, + Enabled: false, Policies: []TailSamplingPolicy{{SampleRate: 0.5}}, ESConfig: elasticsearch.DefaultConfig(), Interval: 2 * time.Minute, @@ -653,7 +653,12 @@ func TestAgentConfigs(t *testing.T) { } func TestNewConfig_ESConfig(t *testing.T) { - ucfg, err := common.NewConfigFrom(`{"rum.enabled":true,"api_key.enabled":true,"sampling.tail.policies":[{"sample_rate": 0.5}]}`) + ucfg, err := common.NewConfigFrom(`{ + "rum.enabled":true, + "api_key.enabled":true, + "data_streams.enabled":true, + "sampling.tail.policies":[{"sample_rate": 0.5}], + }`) require.NoError(t, err) // no es config given diff --git a/beater/config/sampling.go b/beater/config/sampling.go index 22661c9f27e..f236de738af 100644 --- a/beater/config/sampling.go +++ b/beater/config/sampling.go @@ -108,10 +108,13 @@ func (c *TailSamplingConfig) Validate() error { return nil } -func (c *TailSamplingConfig) setup(log *logp.Logger, outputESCfg *common.Config) error { +func (c *TailSamplingConfig) setup(log *logp.Logger, dataStreamsEnabled bool, outputESCfg *common.Config) error { if !c.Enabled { return nil } + if !dataStreamsEnabled { + return errors.New("tail-sampling requires data streams to be enabled") + } if !c.esConfigured && outputESCfg != nil { log.Info("Falling back to elasticsearch output for tail-sampling") if err := outputESCfg.Unpack(&c.ESConfig); err != nil { diff --git a/beater/config/sampling_test.go b/beater/config/sampling_test.go index e2de09e66f1..0b22ae10c81 100644 --- a/beater/config/sampling_test.go +++ b/beater/config/sampling_test.go @@ -28,6 +28,7 @@ import ( func TestSamplingPoliciesValidation(t *testing.T) { t.Run("MinimallyValid", func(t *testing.T) { _, err := NewConfig(common.MustNewConfigFrom(map[string]interface{}{ + "data_streams.enabled": true, "sampling.tail.policies": []map[string]interface{}{{ "sample_rate": 0.5, }}, @@ -36,12 +37,14 @@ func TestSamplingPoliciesValidation(t *testing.T) { }) t.Run("NoPolicies", func(t *testing.T) { _, err := NewConfig(common.MustNewConfigFrom(map[string]interface{}{ + "data_streams.enabled": true, "sampling.tail.enabled": true, }), nil) assert.EqualError(t, err, "Error processing configuration: invalid tail sampling config: no policies specified accessing 'sampling.tail'") }) t.Run("NoDefaultPolicies", func(t *testing.T) { _, err := NewConfig(common.MustNewConfigFrom(map[string]interface{}{ + "data_streams.enabled": true, "sampling.tail.policies": []map[string]interface{}{{ "service.name": "foo", "sample_rate": 0.5, @@ -49,4 +52,13 @@ func TestSamplingPoliciesValidation(t *testing.T) { }), nil) assert.EqualError(t, err, "Error processing configuration: invalid tail sampling config: no default (empty criteria) policy specified accessing 'sampling.tail'") }) + t.Run("DataStreamsDisabled", func(t *testing.T) { + _, err := NewConfig(common.MustNewConfigFrom(map[string]interface{}{ + "sampling.tail.enabled": true, + "sampling.tail.policies": []map[string]interface{}{{ + "sample_rate": 0.5, + }}, + }), nil) + assert.EqualError(t, err, "tail-sampling requires data streams to be enabled") + }) } diff --git a/beater/waitintegration.go b/beater/waitintegration.go index 95f1899350e..40a791158fb 100644 --- a/beater/waitintegration.go +++ b/beater/waitintegration.go @@ -119,7 +119,7 @@ func checkIntegrationInstalledElasticsearch(ctx context.Context, esClient elasti // TODO(axw) generate the list of expected index templates. templates := []string{ "traces-apm", - "traces-sampled", + "traces-apm.sampled", "metrics-apm.app", "metrics-apm.internal", "logs-apm.error", diff --git a/changelogs/head.asciidoc b/changelogs/head.asciidoc index ba50544b75c..cbc3b0f40ce 100644 --- a/changelogs/head.asciidoc +++ b/changelogs/head.asciidoc @@ -7,6 +7,8 @@ https://github.com/elastic/apm-server/compare/7.13\...master[View commits] ==== Breaking Changes - `network.connection_type` is now `network.connection.type` {pull}5671[5671] - `transaction.page` and `error.page` no longer recorded {pull}5872[5872] +- experimental:["This breaking change applies to the experimental tail-based sampling feature."] `apm-server.sampling.tail` now requires `apm-server.data_streams.enabled` {pull}5952[5952] +- beta:["This breaking change applies to the beta <>."] The `traces-sampled-*` data stream is now `traces-apm.sampled-*` {pull}5952[5952] [float] ==== Bug fixes diff --git a/systemtest/apmservertest/config.go b/systemtest/apmservertest/config.go index 1264bae1d8b..8e8d5170efb 100644 --- a/systemtest/apmservertest/config.go +++ b/systemtest/apmservertest/config.go @@ -198,7 +198,8 @@ type RUMSourcemapCacheConfig struct { // DataStreamsConfig holds APM Server data streams configuration. type DataStreamsConfig struct { - Enabled bool `json:"enabled"` + Enabled bool `json:"enabled"` + WaitForIntegration *bool `json:"wait_for_integration,omitempty"` } // APIKeyConfig holds agent auth configuration. diff --git a/systemtest/fleettest/client.go b/systemtest/fleettest/client.go index 0f93351f2dd..830cbefcb56 100644 --- a/systemtest/fleettest/client.go +++ b/systemtest/fleettest/client.go @@ -239,6 +239,17 @@ func (c *Client) Package(name, version string) (*Package, error) { return &result.Response, nil } +// InstallPackage installs the package with the given name. +func (c *Client) InstallPackage(name, version string) error { + req := c.newFleetRequest("POST", "/epm/packages/"+name+"-"+version, nil) + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + return consumeResponse(resp, nil) +} + // DeletePackage deletes (uninstalls) the package with the given name and version. func (c *Client) DeletePackage(name, version string) error { req := c.newFleetRequest("DELETE", "/epm/packages/"+name+"-"+version, nil) diff --git a/systemtest/sampling_test.go b/systemtest/sampling_test.go index 848cc86bb0a..3b25213f758 100644 --- a/systemtest/sampling_test.go +++ b/systemtest/sampling_test.go @@ -92,8 +92,13 @@ func TestKeepUnsampledWarning(t *testing.T) { func TestTailSampling(t *testing.T) { systemtest.CleanupElasticsearch(t) + cleanupFleet(t, systemtest.Fleet) + integrationPackage := getAPMIntegrationPackage(t, systemtest.Fleet) + err := systemtest.Fleet.InstallPackage(integrationPackage.Name, integrationPackage.Version) + require.NoError(t, err) srv1 := apmservertest.NewUnstartedServer(t) + srv1.Config.DataStreams = &apmservertest.DataStreamsConfig{Enabled: true} srv1.Config.Sampling = &apmservertest.SamplingConfig{ Tail: &apmservertest.TailSamplingConfig{ Enabled: true, @@ -105,6 +110,7 @@ func TestTailSampling(t *testing.T) { require.NoError(t, srv1.Start()) srv2 := apmservertest.NewUnstartedServer(t) + srv2.Config.DataStreams = &apmservertest.DataStreamsConfig{Enabled: true} srv2.Config.Sampling = srv1.Config.Sampling require.NoError(t, srv2.Start()) @@ -128,12 +134,12 @@ func TestTailSampling(t *testing.T) { // Flush the data stream while the test is running, as we have no // control over the settings for the sampled traces index template. - refreshPeriodically(t, 250*time.Millisecond, "apm-sampled-traces") + refreshPeriodically(t, 250*time.Millisecond, "traces-apm.sampled-*") for _, transactionType := range []string{"parent", "child"} { var result estest.SearchResult t.Logf("waiting for %d %q transactions", expected, transactionType) - _, err := systemtest.Elasticsearch.Search("apm-*").WithQuery(estest.TermQuery{ + _, err := systemtest.Elasticsearch.Search("traces-*").WithQuery(estest.TermQuery{ Field: "transaction.type", Value: transactionType, }).WithSize(total).Do(context.Background(), &result, @@ -172,8 +178,17 @@ func TestTailSamplingUnlicensed(t *testing.T) { require.NoError(t, es.Start()) defer es.Close() + // Data streams are required for tail-based sampling, but since we're using + // an ephemeral Elasticsearch container it's not straightforward to install + // the integration package. We won't be indexing anything, so just don't wait + // for the integration package to be installed in this test. + waitForIntegration := false srv := apmservertest.NewUnstartedServer(t) srv.Config.Output.Elasticsearch.Hosts = []string{es.Addr} + srv.Config.DataStreams = &apmservertest.DataStreamsConfig{ + Enabled: true, + WaitForIntegration: &waitForIntegration, + } srv.Config.Sampling = &apmservertest.SamplingConfig{ Tail: &apmservertest.TailSamplingConfig{ Enabled: true, @@ -183,6 +198,15 @@ func TestTailSamplingUnlicensed(t *testing.T) { } require.NoError(t, srv.Start()) + // Send some transactions to trigger an indexing attempt. + tracer := srv.Tracer() + for i := 0; i < 100; i++ { + tx := tracer.StartTransaction("GET /", "parent") + tx.Duration = time.Second * time.Duration(i+1) + tx.End() + } + tracer.Flush(nil) + timeout := time.After(time.Minute) logs := srv.Logs.Iterator() for { @@ -198,7 +222,7 @@ func TestTailSamplingUnlicensed(t *testing.T) { // Due to the failing license check, APM Server will refuse to index anything. var result estest.SearchResult - _, err = es.Client.Search("apm-*").Do(context.Background(), &result) + _, err = es.Client.Search("traces-apm*").Do(context.Background(), &result) assert.NoError(t, err) assert.Empty(t, result.Hits.Hits) } diff --git a/testing/docker/elasticsearch/roles.yml b/testing/docker/elasticsearch/roles.yml index 38df16e9982..72f8fbbbe69 100644 --- a/testing/docker/elasticsearch/roles.yml +++ b/testing/docker/elasticsearch/roles.yml @@ -1,7 +1,7 @@ apm_server: cluster: ['manage_ilm','manage_security','manage_api_key'] indices: - - names: ['apm-*'] + - names: ['apm-*', 'traces-apm*', 'logs-apm*', 'metrics-apm*'] privileges: ['write','create_index','manage','manage_ilm'] applications: - application: 'apm' diff --git a/x-pack/apm-server/main.go b/x-pack/apm-server/main.go index f50ef4e79aa..ae6bce79049 100644 --- a/x-pack/apm-server/main.go +++ b/x-pack/apm-server/main.go @@ -26,7 +26,6 @@ import ( "github.com/elastic/apm-server/x-pack/apm-server/aggregation/txmetrics" "github.com/elastic/apm-server/x-pack/apm-server/cmd" "github.com/elastic/apm-server/x-pack/apm-server/sampling" - "github.com/elastic/apm-server/x-pack/apm-server/sampling/pubsub" ) var ( @@ -118,6 +117,10 @@ func licensePlatinumCovered(client *eslegclient.Connection) error { } func newTailSamplingProcessor(args beater.ServerParams) (*sampling.Processor, error) { + if !args.Config.DataStreams.Enabled { + return nil, errors.New("tail-based sampling requires data streams") + } + // Tail-based sampling is a Platinum-licensed feature. // // FIXME(axw) each time libes.RegisterGlobalCallback is called an additional global @@ -132,30 +135,6 @@ func newTailSamplingProcessor(args beater.ServerParams) (*sampling.Processor, er return nil, errors.Wrap(err, "failed to create Elasticsearch client for tail-sampling") } - var sampledTracesDataStream sampling.DataStreamConfig - if args.Managed { - // Data stream and ILM policy are managed by Fleet. - sampledTracesDataStream = sampling.DataStreamConfig{ - Type: "traces", - Dataset: "sampled", - Namespace: args.Namespace, - } - } else { - sampledTracesDataStream = sampling.DataStreamConfig{ - Type: "apm", - Dataset: "sampled", - Namespace: "traces", - } - if err := pubsub.SetupDataStream(context.Background(), es, - "apm-sampled-traces", // Index template - "apm-sampled-traces", // ILM policy - "apm-sampled-traces", // Index pattern - ); err != nil { - return nil, errors.Wrap(err, "failed to create data stream for tail-sampling") - } - args.Logger.Infof("Created tail-sampling data stream index template") - } - policies := make([]sampling.Policy, len(tailSamplingConfig.Policies)) for i, in := range tailSamplingConfig.Policies { policies[i] = sampling.Policy{ @@ -178,8 +157,12 @@ func newTailSamplingProcessor(args beater.ServerParams) (*sampling.Processor, er IngestRateDecayFactor: tailSamplingConfig.IngestRateDecayFactor, }, RemoteSamplingConfig: sampling.RemoteSamplingConfig{ - Elasticsearch: es, - SampledTracesDataStream: sampledTracesDataStream, + Elasticsearch: es, + SampledTracesDataStream: sampling.DataStreamConfig{ + Type: "traces", + Dataset: "apm.sampled", + Namespace: args.Namespace, + }, }, StorageConfig: sampling.StorageConfig{ StorageDir: paths.Resolve(paths.Data, tailSamplingConfig.StorageDir), diff --git a/x-pack/apm-server/main_test.go b/x-pack/apm-server/main_test.go index 261ece10ca6..937e717b64d 100644 --- a/x-pack/apm-server/main_test.go +++ b/x-pack/apm-server/main_test.go @@ -63,6 +63,7 @@ func TestMonitoring(t *testing.T) { require.NoError(t, err) cfg := config.DefaultConfig() + cfg.DataStreams.Enabled = true cfg.Aggregation.Transactions.Enabled = true cfg.Sampling.Tail.Enabled = true cfg.Sampling.Tail.Policies = []config.TailSamplingPolicy{{SampleRate: 0.1}} diff --git a/x-pack/apm-server/sampling/pubsub/datastream.go b/x-pack/apm-server/sampling/pubsub/datastream.go deleted file mode 100644 index 96fe8da7a41..00000000000 --- a/x-pack/apm-server/sampling/pubsub/datastream.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package pubsub - -import ( - "context" - "fmt" - "io/ioutil" - "strings" - - "github.com/elastic/apm-server/elasticsearch" - - "github.com/elastic/go-elasticsearch/v7/esapi" -) - -// SetupDataStream ensures that the sampled traces data stream index template -// exists with the given name, creating it and its associated ILM policy if it -// does not. -// -// This should only be called when not running under Fleet. -func SetupDataStream( - ctx context.Context, - client elasticsearch.Client, - indexTemplateName string, - ilmPolicyName string, - indexPattern string, -) error { - // Create/replace ILM policy. - resp, err := esapi.ILMPutLifecycleRequest{ - Policy: ilmPolicyName, - Body: strings.NewReader(ilmPolicy), - }.Do(ctx, client) - if err != nil { - return err - } - defer resp.Body.Close() - if resp.IsError() { - body, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("failed to create ILM policy (%d): %s", resp.StatusCode, body) - } - - // Create/replace index template. - dataStreamIndexTemplate := fmt.Sprintf(dataStreamIndexTemplate, indexPattern, ilmPolicyName) - resp, err = esapi.IndicesPutIndexTemplateRequest{ - Name: indexTemplateName, - Body: strings.NewReader(dataStreamIndexTemplate), - }.Do(ctx, client) - if err != nil { - return err - } - defer resp.Body.Close() - if resp.IsError() { - body, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("failed to create index template (%d): %s", resp.StatusCode, body) - } - return nil -} - -// NOTE(axw) these replicate the index template and ILM policy created by Fleet, -// and should be kept in sync with apmpackage/apm/.../data_stream/sampled_traces. - -const ilmPolicy = `{ - "policy": { - "phases": { - "hot": { - "actions": { - "rollover": { - "max_age": "1h" - } - } - }, - "delete": { - "min_age": "1h", - "actions": { - "delete": {} - } - } - } - } -}` - -const dataStreamIndexTemplate = `{ - "index_patterns": [%q], - "priority": 1, - "data_stream": {}, - "template": { - "settings": { - "index.lifecycle.name": %q, - "index.number_of_shards": 1 - }, - "mappings": { - "properties": { - "@timestamp": {"type": "date"}, - "event": { - "properties": { - "ingested": {"type": "date"} - } - }, - "observer": { - "properties": { - "id": {"type": "keyword"} - } - }, - "trace": { - "properties": { - "id": {"type": "keyword"} - } - } - } - } - } -}` From 993bf331ca950423541389d11ab88b9701f4837e Mon Sep 17 00:00:00 2001 From: apmmachine <58790750+apmmachine@users.noreply.github.com> Date: Thu, 19 Aug 2021 01:46:22 -0400 Subject: [PATCH 13/14] [Automation] Update elastic stack version to 8.0.0-fa246295 for testing (#5969) Co-authored-by: apmmachine --- docker-compose.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 21c7e54a163..9d40286ceb8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,7 +32,7 @@ services: kibana: { condition: service_healthy } elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:8.0.0-7e122dd9-SNAPSHOT + image: docker.elastic.co/elasticsearch/elasticsearch:8.0.0-fa246295-SNAPSHOT ports: - 9200:9200 healthcheck: @@ -61,7 +61,7 @@ services: - "./testing/docker/elasticsearch/users_roles:/usr/share/elasticsearch/config/users_roles" kibana: - image: docker.elastic.co/kibana/kibana:8.0.0-7e122dd9-SNAPSHOT + image: docker.elastic.co/kibana/kibana:8.0.0-fa246295-SNAPSHOT ports: - 5601:5601 healthcheck: @@ -85,7 +85,7 @@ services: package-registry: { condition: service_healthy } fleet-server: - image: docker.elastic.co/beats/elastic-agent:8.0.0-7e122dd9-SNAPSHOT + image: docker.elastic.co/beats/elastic-agent:8.0.0-fa246295-SNAPSHOT ports: - 8220:8220 healthcheck: From 0ded23def7f8df139dad2803db1a51a3378aee72 Mon Sep 17 00:00:00 2001 From: Silvia Mitter Date: Thu, 19 Aug 2021 13:24:28 +0200 Subject: [PATCH 14/14] Update mergify to 7.15 (#5972) --- .mergify.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.mergify.yml b/.mergify.yml index 47d4f83f81c..d2bc4b19bc2 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -25,6 +25,18 @@ pull_request_rules: branches: - "7.x" title: "[{{ destination_branch }}] {{ title }} (backport #{{ number }})" + - name: backport patches to 7.15 branch + conditions: + - merged + - base=master + - label=backport-7.15 + actions: + backport: + assignees: + - "{{ author }}" + branches: + - "7.15" + title: "[{{ destination_branch }}] {{ title }} (backport #{{ number }})" - name: backport patches to 7.14 branch conditions: - merged