From 8ab2c9f13f8e1bb676eccfae93ff3c52a64cc706 Mon Sep 17 00:00:00 2001 From: arbulu89 Date: Wed, 27 Nov 2024 14:03:23 +0100 Subject: [PATCH] Implement node exporter target auto-detection --- internal/agent/agent.go | 3 +- internal/core/hosts/discovered_host.go | 21 +++++----- internal/discovery/host.go | 55 ++++++++++++++++++++++---- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/internal/agent/agent.go b/internal/agent/agent.go index 73c25f19..a5987850 100644 --- a/internal/agent/agent.go +++ b/internal/agent/agent.go @@ -36,6 +36,7 @@ type Config struct { DiscoveriesConfig *discovery.DiscoveriesConfig FactsServiceURL string PluginsFolder string + PrometheusTargets discovery.PrometheusTargets } // NewAgent returns a new instance of Agent with the given configuration @@ -48,7 +49,7 @@ func NewAgent(config *Config) (*Agent, error) { discovery.NewSAPSystemsDiscovery(collectorClient, *config.DiscoveriesConfig), discovery.NewCloudDiscovery(collectorClient, *config.DiscoveriesConfig), discovery.NewSubscriptionDiscovery(collectorClient, config.InstanceName, *config.DiscoveriesConfig), - discovery.NewHostDiscovery(collectorClient, config.InstanceName, *config.DiscoveriesConfig), + discovery.NewHostDiscovery(collectorClient, config.InstanceName, config.PrometheusTargets, *config.DiscoveriesConfig), discovery.NewSaptuneDiscovery(collectorClient, *config.DiscoveriesConfig), } diff --git a/internal/core/hosts/discovered_host.go b/internal/core/hosts/discovered_host.go index 723312b7..49378852 100644 --- a/internal/core/hosts/discovered_host.go +++ b/internal/core/hosts/discovered_host.go @@ -1,14 +1,15 @@ package hosts type DiscoveredHost struct { - OSVersion string `json:"os_version"` - HostIPAddresses []string `json:"ip_addresses"` - Netmasks []int `json:"netmasks"` - HostName string `json:"hostname"` - CPUCount int `json:"cpu_count"` - SocketCount int `json:"socket_count"` - TotalMemoryMB int `json:"total_memory_mb"` - AgentVersion string `json:"agent_version"` - InstallationSource string `json:"installation_source"` - FullyQualifiedDomainName *string `json:"fully_qualified_domain_name,omitempty"` + OSVersion string `json:"os_version"` + HostIPAddresses []string `json:"ip_addresses"` + Netmasks []int `json:"netmasks"` + HostName string `json:"hostname"` + CPUCount int `json:"cpu_count"` + SocketCount int `json:"socket_count"` + TotalMemoryMB int `json:"total_memory_mb"` + AgentVersion string `json:"agent_version"` + InstallationSource string `json:"installation_source"` + FullyQualifiedDomainName *string `json:"fully_qualified_domain_name,omitempty"` + PrometheusTargets map[string]string `json:"prometheus_targets"` } diff --git a/internal/discovery/host.go b/internal/discovery/host.go index 12f8bffd..1feb9aca 100644 --- a/internal/discovery/host.go +++ b/internal/discovery/host.go @@ -1,9 +1,11 @@ package discovery import ( + "bytes" "context" "fmt" "net" + "sort" "strconv" "time" @@ -20,23 +22,31 @@ import ( const HostDiscoveryID string = "host_discovery" const HostDiscoveryMinPeriod time.Duration = 1 * time.Second +const NodeExporterName string = "node_exporter" +const NodeExporterPort int = 9100 + +type PrometheusTargets map[string]string + type HostDiscovery struct { - id string - collectorClient collector.Client - host string - interval time.Duration + id string + collectorClient collector.Client + host string + prometheusTargets PrometheusTargets + interval time.Duration } func NewHostDiscovery( collectorClient collector.Client, hostname string, + prometheusTargets PrometheusTargets, config DiscoveriesConfig, ) Discovery { return HostDiscovery{ - id: HostDiscoveryID, - collectorClient: collectorClient, - host: hostname, - interval: config.DiscoveriesPeriodsConfig.Host, + id: HostDiscoveryID, + collectorClient: collectorClient, + host: hostname, + prometheusTargets: prometheusTargets, + interval: config.DiscoveriesPeriodsConfig.Host, } } @@ -55,6 +65,8 @@ func (d HostDiscovery) Discover(ctx context.Context) (string, error) { return "", err } + updatedPrometheusTargets := updatePrometheusTargets(d.prometheusTargets, ipAddresses) + host := hosts.DiscoveredHost{ OSVersion: getOSVersion(), HostIPAddresses: ipAddresses, @@ -66,6 +78,7 @@ func (d HostDiscovery) Discover(ctx context.Context) (string, error) { AgentVersion: version.Version, InstallationSource: version.InstallationSource, FullyQualifiedDomainName: getHostFQDN(), + PrometheusTargets: updatedPrometheusTargets, } err = d.collectorClient.Publish(ctx, d.id, host) @@ -107,6 +120,32 @@ func getNetworksData() ([]string, []int, error) { return ipAddrList, netmasks, nil } +func updatePrometheusTargets(targets PrometheusTargets, ipAddresses []string) PrometheusTargets { + // Get lowest IP address value to replace empty exporter targets + ips := make([]net.IP, 0, len(ipAddresses)) + for _, ip := range ipAddresses { + parsedIp := net.ParseIP(ip) + if parsedIp.To4() != nil && !parsedIp.IsLoopback() { + ips = append(ips, parsedIp) + } + + } + + sort.Slice(ips, func(i, j int) bool { + return bytes.Compare(ips[i], ips[j]) < 0 + }) + + // Replace exporter values if they are not given by the user + nodeExporterTarget, ok := targets[NodeExporterName] + if !ok || nodeExporterTarget == "" { + nodeExporterTarget = fmt.Sprintf("%s:%d", ips[0], NodeExporterPort) + } + + return PrometheusTargets{ + NodeExporterName: nodeExporterTarget, + } +} + func getHostFQDN() *string { fqdn, err := fqdn.FqdnHostname()