diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index e97fd625570c..963587ec045f 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -2061,6 +2061,12 @@ https://github.com/elastic/beats/compare/v7.15.2...v7.16.0[View commits] - Override `Host()` on statsd MetricSet {pull}29103[29103] - Add Linux pressure metricset {pull}27355[27355] - Add User-Agent header to HTTP requests. {issue}18160[18160] {pull}27509[27509] +- Add a `/inputs/` route to the HTTP monitoring endpoint that exposes metrics for each metricset instance. + +*Auditbeat* + +- Add a `/inputs/` route to the HTTP monitoring endpoint that exposes metrics for each dataset instance. + *Functionbeat* diff --git a/metricbeat/beater/metricbeat.go b/metricbeat/beater/metricbeat.go index cbc44f88bf57..acd4aa02b1e3 100644 --- a/metricbeat/beater/metricbeat.go +++ b/metricbeat/beater/metricbeat.go @@ -26,6 +26,7 @@ import ( "github.com/elastic/beats/v7/libbeat/cfgfile" "github.com/elastic/beats/v7/libbeat/common/reload" "github.com/elastic/beats/v7/libbeat/management" + "github.com/elastic/beats/v7/libbeat/monitoring/inputmon" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/metricbeat/mb/module" conf "github.com/elastic/elastic-agent-libs/config" @@ -155,6 +156,24 @@ func newMetricbeat(b *beat.Beat, c *conf.C, options ...Option) (*Metricbeat, err return metricbeat, nil } + if b.API != nil { + if err := inputmon.AttachHandler(b.API.Router()); err != nil { + return nil, fmt.Errorf("failed attach inputs api to monitoring endpoint server: %w", err) + } + } + + if b.Manager != nil { + b.Manager.RegisterDiagnosticHook("input_metrics", "Metrics from active inputs.", + "input_metrics.json", "application/json", func() []byte { + data, err := inputmon.MetricSnapshotJSON() + if err != nil { + logp.L().Warnw("Failed to collect input metric snapshot for Agent diagnostics.", "error", err) + return []byte(err.Error()) + } + return data + }) + } + moduleOptions := append( []module.Option{module.WithMaxStartDelay(config.MaxStartDelay)}, metricbeat.moduleOptions...) diff --git a/metricbeat/mb/builders.go b/metricbeat/mb/builders.go index 269c194063cb..54c1cc94b90b 100644 --- a/metricbeat/mb/builders.go +++ b/metricbeat/mb/builders.go @@ -184,18 +184,31 @@ func newBaseMetricSets(r *Register, m Module) ([]BaseMetricSet, error) { metrics := monitoring.NewRegistry() monitoring.NewString(metrics, "module").Set(m.Name()) monitoring.NewString(metrics, "metricset").Set(name) + monitoring.NewString(metrics, "input").Set(m.Name() + "/" + name) if host != "" { monitoring.NewString(metrics, "host").Set(host) } - monitoring.NewString(metrics, "id").Set(msID) + monitoring.NewString(metrics, "ephemeral_id").Set(msID) + if configuredID := m.Config().ID; configuredID != "" { + // If a module ID was configured, then use that as the ID within metrics. + // The ID is user controlled and is not guaranteed to be unique, so the + // ephemeral_id (a random UUID) will be used as the registry key. + monitoring.NewString(metrics, "id").Set(configuredID) + } else { + monitoring.NewString(metrics, "id").Set(msID) + } + logger := logp.NewLogger(m.Name() + "." + name) + if m.Config().ID != "" { + logger = logger.With("id", m.Config().ID) + } metricsets = append(metricsets, BaseMetricSet{ id: msID, name: name, module: m, host: host, metrics: metrics, - logger: logp.NewLogger(m.Name() + "." + name), + logger: logger, }) } } diff --git a/metricbeat/mb/mb.go b/metricbeat/mb/mb.go index 06b85662838c..7e18dc9029d2 100644 --- a/metricbeat/mb/mb.go +++ b/metricbeat/mb/mb.go @@ -362,6 +362,7 @@ func (b *BaseMetricSet) Registration() MetricSetRegistration { // the metricset fetches not only the predefined fields but add alls raw data under // the raw namespace to the event. type ModuleConfig struct { + ID string `config:"id"` // Optional ID (not guaranteed to be unique). Hosts []string `config:"hosts"` Period time.Duration `config:"period" validate:"positive"` Timeout time.Duration `config:"timeout" validate:"positive"` @@ -375,8 +376,8 @@ type ModuleConfig struct { func (c ModuleConfig) String() string { return fmt.Sprintf(`{Module:"%v", MetricSets:%v, Enabled:%v, `+ - `Hosts:[%v hosts], Period:"%v", Timeout:"%v", Raw:%v, Query:%v}`, - c.Module, c.MetricSets, c.Enabled, len(c.Hosts), c.Period, c.Timeout, + `ID:"%s", Hosts:[%v hosts], Period:"%v", Timeout:"%v", Raw:%v, Query:%v}`, + c.Module, c.MetricSets, c.Enabled, c.ID, len(c.Hosts), c.Period, c.Timeout, c.Raw, c.Query) }