diff --git a/libbeat/cmd/instance/beat.go b/libbeat/cmd/instance/beat.go index fec526d14e2..3a7a47cbe41 100644 --- a/libbeat/cmd/instance/beat.go +++ b/libbeat/cmd/instance/beat.go @@ -401,6 +401,14 @@ func (b *Beat) launch(settings Settings, bt beat.Creator) error { return err } defer reporter.Stop() + + // Expose monitoring.cluster_uuid in state API + if reporterSettings.ClusterUUID != "" { + stateRegistry := monitoring.GetNamespace("state").GetRegistry() + monitoringRegistry := stateRegistry.NewRegistry("monitoring") + clusterUUIDRegVar := monitoring.NewString(monitoringRegistry, "cluster_uuid") + clusterUUIDRegVar.Set(reporterSettings.ClusterUUID) + } } if b.Config.MetricLogging == nil || b.Config.MetricLogging.Enabled() { diff --git a/metricbeat/module/beat/beat.go b/metricbeat/module/beat/beat.go index 1539d83c71a..941885e6e92 100644 --- a/metricbeat/module/beat/beat.go +++ b/metricbeat/module/beat/beat.go @@ -93,6 +93,9 @@ type Info struct { // State construct contains the relevant data from the Beat's /state endpoint type State struct { + Monitoring struct { + ClusterUUID string `json:"cluster_uuid"` + } `json:"monitoring"` Output struct { Name string `json:"name"` } `json:"output"` diff --git a/metricbeat/module/beat/state/data_xpack.go b/metricbeat/module/beat/state/data_xpack.go index 3b66f0fc006..e92bdd924d9 100644 --- a/metricbeat/module/beat/state/data_xpack.go +++ b/metricbeat/module/beat/state/data_xpack.go @@ -54,14 +54,16 @@ func eventMappingXPack(r mb.ReporterV2, m *MetricSet, info b.Info, content []byt "timestamp": now, } - var clusterUUID string - if isOutputES(state) { - clusterUUID = getClusterUUID(state) - if clusterUUID == "" { - // Output is ES but cluster UUID could not be determined. No point sending monitoring - // data with empty cluster UUID since it will not be associated with the correct ES - // production cluster. Log error instead. - return errors.Wrap(b.ErrClusterUUID, "could not determine cluster UUID") + clusterUUID := getMonitoringClusterUUID(state) + if clusterUUID == "" { + if isOutputES(state) { + clusterUUID = getClusterUUID(state) + if clusterUUID == "" { + // Output is ES but cluster UUID could not be determined. No point sending monitoring + // data with empty cluster UUID since it will not be associated with the correct ES + // production cluster. Log error instead. + return errors.Wrap(b.ErrClusterUUID, "could not determine cluster UUID") + } } } @@ -141,3 +143,27 @@ func isOutputES(state map[string]interface{}) bool { return name == "elasticsearch" } + +func getMonitoringClusterUUID(state map[string]interface{}) string { + m, exists := state["monitoring"] + if !exists { + return "" + } + + monitoring, ok := m.(map[string]interface{}) + if !ok { + return "" + } + + c, exists := monitoring["cluster_uuid"] + if !exists { + return "" + } + + clusterUUID, ok := c.(string) + if !ok { + return "" + } + + return clusterUUID +} diff --git a/metricbeat/module/beat/stats/data_xpack.go b/metricbeat/module/beat/stats/data_xpack.go index e9d4fd00f1c..8b0da8a84e6 100644 --- a/metricbeat/module/beat/stats/data_xpack.go +++ b/metricbeat/module/beat/stats/data_xpack.go @@ -83,11 +83,16 @@ func (m *MetricSet) getClusterUUID() (string, error) { return "", errors.Wrap(err, "could not get state information") } + clusterUUID := state.Monitoring.ClusterUUID + if clusterUUID != "" { + return clusterUUID, nil + } + if state.Output.Name != "elasticsearch" { return "", nil } - clusterUUID := state.Outputs.Elasticsearch.ClusterUUID + clusterUUID = state.Outputs.Elasticsearch.ClusterUUID if clusterUUID == "" { // Output is ES but cluster UUID could not be determined. No point sending monitoring // data with empty cluster UUID since it will not be associated with the correct ES