mirror of
				https://github.com/ClusterCockpit/cc-metric-collector.git
				synced 2025-10-31 00:55:06 +01:00 
			
		
		
		
	Add optional interface alias in netstat (#130)
* Check creation of CCMessage in NATS receiver * add optional interface aliases for netstatMetric * small fix --------- Co-authored-by: Thomas Roehl <thomas.roehl@fau.de> Co-authored-by: exterr2f <Robert.Externbrink@rub.de> Co-authored-by: Thomas Gruber <Thomas.Roehl@googlemail.com>
This commit is contained in:
		| @@ -10,15 +10,16 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	cclog "github.com/ClusterCockpit/cc-metric-collector/pkg/ccLogger" | ||||
| 	lp "github.com/ClusterCockpit/cc-energy-manager/pkg/cc-message" | ||||
| 	lp "github.com/ClusterCockpit/cc-lib/ccMessage" | ||||
| ) | ||||
|  | ||||
| const NETSTATFILE = "/proc/net/dev" | ||||
|  | ||||
| type NetstatCollectorConfig struct { | ||||
| 	IncludeDevices     []string `json:"include_devices"` | ||||
| 	SendAbsoluteValues bool     `json:"send_abs_values"` | ||||
| 	SendDerivedValues  bool     `json:"send_derived_values"` | ||||
| 	IncludeDevices     []string              `json:"include_devices"` | ||||
| 	SendAbsoluteValues bool                  `json:"send_abs_values"` | ||||
| 	SendDerivedValues  bool                  `json:"send_derived_values"` | ||||
| 	InterfaceAliases   map[string][]string   `json:"interface_aliases,omitempty"` | ||||
| } | ||||
|  | ||||
| type NetstatCollectorMetric struct { | ||||
| @@ -32,9 +33,26 @@ type NetstatCollectorMetric struct { | ||||
|  | ||||
| type NetstatCollector struct { | ||||
| 	metricCollector | ||||
| 	config        NetstatCollectorConfig | ||||
| 	matches       map[string][]NetstatCollectorMetric | ||||
| 	lastTimestamp time.Time | ||||
| 	config           NetstatCollectorConfig | ||||
| 	aliasToCanonical map[string]string | ||||
| 	matches          map[string][]NetstatCollectorMetric | ||||
| 	lastTimestamp    time.Time | ||||
| } | ||||
|  | ||||
| func (m *NetstatCollector) buildAliasMapping() { | ||||
| 	m.aliasToCanonical = make(map[string]string) | ||||
| 	for canon, aliases := range m.config.InterfaceAliases { | ||||
| 		for _, alias := range aliases { | ||||
| 			m.aliasToCanonical[alias] = canon | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func getCanonicalName(raw string, aliasToCanonical map[string]string) string { | ||||
| 	if canon, ok := aliasToCanonical[raw]; ok { | ||||
| 		return canon | ||||
| 	} | ||||
| 	return raw | ||||
| } | ||||
|  | ||||
| func (m *NetstatCollector) Init(config json.RawMessage) error { | ||||
| @@ -77,6 +95,8 @@ func (m *NetstatCollector) Init(config json.RawMessage) error { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	m.buildAliasMapping() | ||||
|  | ||||
| 	// Check access to net statistic file | ||||
| 	file, err := os.Open(NETSTATFILE) | ||||
| 	if err != nil { | ||||
| @@ -97,18 +117,20 @@ func (m *NetstatCollector) Init(config json.RawMessage) error { | ||||
| 		// Split line into fields | ||||
| 		f := strings.Fields(l) | ||||
|  | ||||
| 		// Get net device entry | ||||
| 		dev := strings.Trim(f[0], ": ") | ||||
| 		// Get raw and canonical names | ||||
| 		raw := strings.Trim(f[0], ": ") | ||||
| 		canonical := getCanonicalName(raw, m.aliasToCanonical) | ||||
|  | ||||
| 		// Check if device is a included device | ||||
| 		if _, ok := stringArrayContains(m.config.IncludeDevices, dev); ok { | ||||
| 			tags := map[string]string{"stype": "network", "stype-id": dev, "type": "node"} | ||||
| 		if _, ok := stringArrayContains(m.config.IncludeDevices, canonical); ok { | ||||
| 			// Tag will contain original device name (raw). | ||||
| 			tags := map[string]string{"stype": "network", "stype-id": raw, "type": "node"} | ||||
| 			meta_unit_byte := map[string]string{"source": m.name, "group": "Network", "unit": "bytes"} | ||||
| 			meta_unit_byte_per_sec := map[string]string{"source": m.name, "group": "Network", "unit": "bytes/sec"} | ||||
| 			meta_unit_pkts := map[string]string{"source": m.name, "group": "Network", "unit": "packets"} | ||||
| 			meta_unit_pkts_per_sec := map[string]string{"source": m.name, "group": "Network", "unit": "packets/sec"} | ||||
|  | ||||
| 			m.matches[dev] = []NetstatCollectorMetric{ | ||||
| 			m.matches[canonical] = []NetstatCollectorMetric{ | ||||
| 				{ | ||||
| 					name:       "net_bytes_in", | ||||
| 					index:      fieldReceiveBytes, | ||||
| @@ -143,7 +165,6 @@ func (m *NetstatCollector) Init(config json.RawMessage) error { | ||||
| 				}, | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	if len(m.matches) == 0 { | ||||
| @@ -164,7 +185,7 @@ func (m *NetstatCollector) Read(interval time.Duration, output chan lp.CCMessage | ||||
| 	// Save current timestamp | ||||
| 	m.lastTimestamp = now | ||||
|  | ||||
| 	file, err := os.Open(string(NETSTATFILE)) | ||||
| 	file, err := os.Open(NETSTATFILE) | ||||
| 	if err != nil { | ||||
| 		cclog.ComponentError(m.name, err.Error()) | ||||
| 		return | ||||
| @@ -183,11 +204,12 @@ func (m *NetstatCollector) Read(interval time.Duration, output chan lp.CCMessage | ||||
| 		// Split line into fields | ||||
| 		f := strings.Fields(l) | ||||
|  | ||||
| 		// Get net device entry | ||||
| 		dev := strings.Trim(f[0], ":") | ||||
| 		// Get raw and canonical names | ||||
| 		raw := strings.Trim(f[0], ":") | ||||
| 		canonical := getCanonicalName(raw, m.aliasToCanonical) | ||||
|  | ||||
| 		// Check if device is a included device | ||||
| 		if devmetrics, ok := m.matches[dev]; ok { | ||||
| 		if devmetrics, ok := m.matches[canonical]; ok { | ||||
| 			for i := range devmetrics { | ||||
| 				metric := &devmetrics[i] | ||||
|  | ||||
|   | ||||
| @@ -4,14 +4,19 @@ | ||||
| ```json | ||||
|   "netstat": { | ||||
|     "include_devices": [ | ||||
|       "eth0" | ||||
|       "eth0", | ||||
|       "eno1" | ||||
|     ], | ||||
|     "send_abs_values" : true, | ||||
|     "send_derived_values" : true | ||||
|     "send_abs_values": true, | ||||
|     "send_derived_values": true, | ||||
|     "interface_aliases": { | ||||
|       "eno1": ["eno1np0", "eno1_alt"], | ||||
|       "eth0": ["eth0_alias"] | ||||
|     } | ||||
|   } | ||||
| ``` | ||||
|  | ||||
| The `netstat` collector reads data from `/proc/net/dev` and outputs a handful **node** metrics. With the `include_devices` list you can specify which network devices should be measured. **Note**: Most other collectors use an _exclude_ list instead of an include list. | ||||
| The `netstat` collector reads data from `/proc/net/dev` and outputs a handful **node** metrics. With the `include_devices` list you can specify which network devices should be measured. **Note**: Most other collectors use an _exclude_ list instead of an include list. Optionally, you can define an interface_aliases mapping. For each canonical device (as listed in include_devices), you may provide an array of aliases that may be reported by the system. When an alias is detected, it is preferred for matching, while the output tag stype-id always shows the actual system-reported name. | ||||
|  | ||||
| Metrics: | ||||
| * `net_bytes_in` (`unit=bytes`) | ||||
| @@ -23,5 +28,4 @@ Metrics: | ||||
| * `net_pkts_in_bw` (`unit=packets/sec` if `send_derived_values == true`) | ||||
| * `net_pkts_out_bw` (`unit=packets/sec` if `send_derived_values == true`) | ||||
|  | ||||
| The device name is added as tag `stype=network,stype-id=<device>`. | ||||
|  | ||||
| The device name is added as tag `stype=network,stype-id=<device>`. | ||||
		Reference in New Issue
	
	Block a user