| 
									
										
										
										
											2015-09-26 08:36:40 -07:00
										 |  |  | // Copyright 2015 The Prometheus Authors
 | 
					
						
							|  |  |  | // Licensed 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.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-03 04:35:24 -07:00
										 |  |  | //go:build !nonetdev
 | 
					
						
							| 
									
										
										
										
											2015-05-12 04:06:41 -07:00
										 |  |  | // +build !nonetdev
 | 
					
						
							| 
									
										
										
										
											2014-06-04 04:12:34 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | package collector | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2022-10-24 01:30:32 -07:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	"log/slog" | 
					
						
							| 
									
										
										
										
											2022-10-24 01:30:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-07 00:25:05 -08:00
										 |  |  | 	"github.com/alecthomas/kingpin/v2" | 
					
						
							| 
									
										
										
										
											2024-09-20 10:23:06 -07:00
										 |  |  | 	"github.com/jsimonetti/rtnetlink/v2" | 
					
						
							| 
									
										
										
										
											2022-10-24 01:30:32 -07:00
										 |  |  | 	"github.com/prometheus/procfs" | 
					
						
							| 
									
										
										
										
											2024-09-11 00:26:34 -07:00
										 |  |  | 	"github.com/prometheus/procfs/sysfs" | 
					
						
							| 
									
										
										
										
											2022-10-24 01:30:32 -07:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							| 
									
										
										
										
											2024-09-11 00:26:34 -07:00
										 |  |  | 	netDevNetlink      = kingpin.Flag("collector.netdev.netlink", "Use netlink to gather stats instead of /proc/net/dev.").Default("true").Bool() | 
					
						
							|  |  |  | 	netdevLabelIfAlias = kingpin.Flag("collector.netdev.label-ifalias", "Add ifAlias label").Default("false").Bool() | 
					
						
							| 
									
										
										
										
											2015-05-20 15:34:24 -07:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | func getNetDevStats(filter *deviceFilter, logger *slog.Logger) (netDevStats, error) { | 
					
						
							| 
									
										
										
										
											2022-10-24 01:30:32 -07:00
										 |  |  | 	if *netDevNetlink { | 
					
						
							|  |  |  | 		return netlinkStats(filter, logger) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return procNetDevStats(filter, logger) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | func netlinkStats(filter *deviceFilter, logger *slog.Logger) (netDevStats, error) { | 
					
						
							| 
									
										
										
										
											2021-07-07 02:05:06 -07:00
										 |  |  | 	conn, err := rtnetlink.Dial(nil) | 
					
						
							| 
									
										
										
										
											2014-06-04 04:12:34 -07:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-11-24 15:30:07 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-24 01:30:32 -07:00
										 |  |  | 	defer conn.Close() | 
					
						
							| 
									
										
										
										
											2021-07-07 02:05:06 -07:00
										 |  |  | 	links, err := conn.Link.List() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2014-06-04 04:12:34 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-09-15 08:31:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-24 01:30:32 -07:00
										 |  |  | 	return parseNetlinkStats(links, filter, logger), nil | 
					
						
							| 
									
										
										
										
											2021-07-07 02:05:06 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-04-16 05:34:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | func parseNetlinkStats(links []rtnetlink.LinkMessage, filter *deviceFilter, logger *slog.Logger) netDevStats { | 
					
						
							| 
									
										
										
										
											2021-07-07 02:05:06 -07:00
										 |  |  | 	metrics := netDevStats{} | 
					
						
							| 
									
										
										
										
											2018-04-16 05:34:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-07 02:05:06 -07:00
										 |  |  | 	for _, msg := range links { | 
					
						
							| 
									
										
										
										
											2023-08-01 06:58:53 -07:00
										 |  |  | 		if msg.Attributes == nil { | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 			logger.Debug("No netlink attributes, skipping") | 
					
						
							| 
									
										
										
										
											2023-08-01 06:58:53 -07:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-07-07 02:05:06 -07:00
										 |  |  | 		name := msg.Attributes.Name | 
					
						
							|  |  |  | 		stats := msg.Attributes.Stats64 | 
					
						
							| 
									
										
										
										
											2023-08-01 06:58:53 -07:00
										 |  |  | 		if stats32 := msg.Attributes.Stats; stats == nil && stats32 != nil { | 
					
						
							|  |  |  | 			stats = &rtnetlink.LinkStats64{ | 
					
						
							|  |  |  | 				RXPackets:          uint64(stats32.RXPackets), | 
					
						
							|  |  |  | 				TXPackets:          uint64(stats32.TXPackets), | 
					
						
							|  |  |  | 				RXBytes:            uint64(stats32.RXBytes), | 
					
						
							|  |  |  | 				TXBytes:            uint64(stats32.TXBytes), | 
					
						
							|  |  |  | 				RXErrors:           uint64(stats32.RXErrors), | 
					
						
							|  |  |  | 				TXErrors:           uint64(stats32.TXErrors), | 
					
						
							|  |  |  | 				RXDropped:          uint64(stats32.RXDropped), | 
					
						
							|  |  |  | 				TXDropped:          uint64(stats32.TXDropped), | 
					
						
							|  |  |  | 				Multicast:          uint64(stats32.Multicast), | 
					
						
							|  |  |  | 				Collisions:         uint64(stats32.Collisions), | 
					
						
							|  |  |  | 				RXLengthErrors:     uint64(stats32.RXLengthErrors), | 
					
						
							|  |  |  | 				RXOverErrors:       uint64(stats32.RXOverErrors), | 
					
						
							|  |  |  | 				RXCRCErrors:        uint64(stats32.RXCRCErrors), | 
					
						
							|  |  |  | 				RXFrameErrors:      uint64(stats32.RXFrameErrors), | 
					
						
							|  |  |  | 				RXFIFOErrors:       uint64(stats32.RXFIFOErrors), | 
					
						
							|  |  |  | 				RXMissedErrors:     uint64(stats32.RXMissedErrors), | 
					
						
							|  |  |  | 				TXAbortedErrors:    uint64(stats32.TXAbortedErrors), | 
					
						
							|  |  |  | 				TXCarrierErrors:    uint64(stats32.TXCarrierErrors), | 
					
						
							|  |  |  | 				TXFIFOErrors:       uint64(stats32.TXFIFOErrors), | 
					
						
							|  |  |  | 				TXHeartbeatErrors:  uint64(stats32.TXHeartbeatErrors), | 
					
						
							|  |  |  | 				TXWindowErrors:     uint64(stats32.TXWindowErrors), | 
					
						
							|  |  |  | 				RXCompressed:       uint64(stats32.RXCompressed), | 
					
						
							|  |  |  | 				TXCompressed:       uint64(stats32.TXCompressed), | 
					
						
							|  |  |  | 				RXNoHandler:        uint64(stats32.RXNoHandler), | 
					
						
							|  |  |  | 				RXOtherhostDropped: 0, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-08-24 08:43:27 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-07 02:05:06 -07:00
										 |  |  | 		if filter.ignored(name) { | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 			logger.Debug("Ignoring device", "device", name) | 
					
						
							| 
									
										
										
										
											2021-07-07 02:05:06 -07:00
										 |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2018-04-14 06:02:20 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-04-14 04:58:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-01 06:58:53 -07:00
										 |  |  | 		// Make sure we don't panic when accessing `stats` attributes below.
 | 
					
						
							|  |  |  | 		if stats == nil { | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 			logger.Debug("No netlink stats, skipping") | 
					
						
							| 
									
										
										
										
											2023-08-01 06:58:53 -07:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-07 02:05:06 -07:00
										 |  |  | 		// https://github.com/torvalds/linux/blob/master/include/uapi/linux/if_link.h#L42-L246
 | 
					
						
							|  |  |  | 		metrics[name] = map[string]uint64{ | 
					
						
							| 
									
										
										
										
											2021-07-09 02:44:03 -07:00
										 |  |  | 			"receive_packets":  stats.RXPackets, | 
					
						
							|  |  |  | 			"transmit_packets": stats.TXPackets, | 
					
						
							|  |  |  | 			"receive_bytes":    stats.RXBytes, | 
					
						
							|  |  |  | 			"transmit_bytes":   stats.TXBytes, | 
					
						
							|  |  |  | 			"receive_errors":   stats.RXErrors, | 
					
						
							|  |  |  | 			"transmit_errors":  stats.TXErrors, | 
					
						
							|  |  |  | 			"receive_dropped":  stats.RXDropped, | 
					
						
							|  |  |  | 			"transmit_dropped": stats.TXDropped, | 
					
						
							|  |  |  | 			"multicast":        stats.Multicast, | 
					
						
							|  |  |  | 			"collisions":       stats.Collisions, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// detailed rx_errors
 | 
					
						
							|  |  |  | 			"receive_length_errors": stats.RXLengthErrors, | 
					
						
							|  |  |  | 			"receive_over_errors":   stats.RXOverErrors, | 
					
						
							|  |  |  | 			"receive_crc_errors":    stats.RXCRCErrors, | 
					
						
							|  |  |  | 			"receive_frame_errors":  stats.RXFrameErrors, | 
					
						
							|  |  |  | 			"receive_fifo_errors":   stats.RXFIFOErrors, | 
					
						
							|  |  |  | 			"receive_missed_errors": stats.RXMissedErrors, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// detailed tx_errors
 | 
					
						
							|  |  |  | 			"transmit_aborted_errors":   stats.TXAbortedErrors, | 
					
						
							|  |  |  | 			"transmit_carrier_errors":   stats.TXCarrierErrors, | 
					
						
							|  |  |  | 			"transmit_fifo_errors":      stats.TXFIFOErrors, | 
					
						
							|  |  |  | 			"transmit_heartbeat_errors": stats.TXHeartbeatErrors, | 
					
						
							|  |  |  | 			"transmit_window_errors":    stats.TXWindowErrors, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// for cslip etc
 | 
					
						
							| 
									
										
										
										
											2021-07-07 02:05:06 -07:00
										 |  |  | 			"receive_compressed":  stats.RXCompressed, | 
					
						
							|  |  |  | 			"transmit_compressed": stats.TXCompressed, | 
					
						
							| 
									
										
										
										
											2021-07-09 02:44:03 -07:00
										 |  |  | 			"receive_nohandler":   stats.RXNoHandler, | 
					
						
							| 
									
										
										
										
											2018-04-14 06:02:20 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-06-04 04:12:34 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-07-07 02:05:06 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return metrics | 
					
						
							| 
									
										
										
										
											2014-06-04 04:12:34 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-10-24 01:30:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | func procNetDevStats(filter *deviceFilter, logger *slog.Logger) (netDevStats, error) { | 
					
						
							| 
									
										
										
										
											2022-10-24 01:30:32 -07:00
										 |  |  | 	metrics := netDevStats{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fs, err := procfs.NewFS(*procPath) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return metrics, fmt.Errorf("failed to open procfs: %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	netDev, err := fs.NetDev() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return metrics, fmt.Errorf("failed to parse /proc/net/dev: %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, stats := range netDev { | 
					
						
							|  |  |  | 		name := stats.Name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if filter.ignored(name) { | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 			logger.Debug("Ignoring device", "device", name) | 
					
						
							| 
									
										
										
										
											2022-10-24 01:30:32 -07:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		metrics[name] = map[string]uint64{ | 
					
						
							|  |  |  | 			"receive_bytes":       stats.RxBytes, | 
					
						
							|  |  |  | 			"receive_packets":     stats.RxPackets, | 
					
						
							|  |  |  | 			"receive_errors":      stats.RxErrors, | 
					
						
							|  |  |  | 			"receive_dropped":     stats.RxDropped, | 
					
						
							|  |  |  | 			"receive_fifo":        stats.RxFIFO, | 
					
						
							|  |  |  | 			"receive_frame":       stats.RxFrame, | 
					
						
							|  |  |  | 			"receive_compressed":  stats.RxCompressed, | 
					
						
							|  |  |  | 			"receive_multicast":   stats.RxMulticast, | 
					
						
							|  |  |  | 			"transmit_bytes":      stats.TxBytes, | 
					
						
							|  |  |  | 			"transmit_packets":    stats.TxPackets, | 
					
						
							|  |  |  | 			"transmit_errors":     stats.TxErrors, | 
					
						
							|  |  |  | 			"transmit_dropped":    stats.TxDropped, | 
					
						
							|  |  |  | 			"transmit_fifo":       stats.TxFIFO, | 
					
						
							|  |  |  | 			"transmit_colls":      stats.TxCollisions, | 
					
						
							|  |  |  | 			"transmit_carrier":    stats.TxCarrier, | 
					
						
							|  |  |  | 			"transmit_compressed": stats.TxCompressed, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return metrics, nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-09-11 00:26:34 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | func getNetDevLabels() (map[string]map[string]string, error) { | 
					
						
							|  |  |  | 	if !*netdevLabelIfAlias { | 
					
						
							|  |  |  | 		return nil, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fs, err := sysfs.NewFS(*sysPath) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	interfaces, err := fs.NetClass() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	labels := make(map[string]map[string]string) | 
					
						
							|  |  |  | 	for iface, params := range interfaces { | 
					
						
							|  |  |  | 		labels[iface] = map[string]string{"ifalias": params.IfAlias} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return labels, nil | 
					
						
							|  |  |  | } |