| 
									
										
										
										
											2015-12-19 16:57:52 -08: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 !noconntrack
 | 
					
						
							| 
									
										
										
										
											2015-12-19 16:57:52 -08:00
										 |  |  | // +build !noconntrack
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package collector | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2020-08-26 05:35:39 -07:00
										 |  |  | 	"errors" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	"log/slog" | 
					
						
							| 
									
										
										
										
											2020-08-26 05:35:39 -07:00
										 |  |  | 	"os" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-19 16:57:52 -08:00
										 |  |  | 	"github.com/prometheus/client_golang/prometheus" | 
					
						
							| 
									
										
										
										
											2021-06-23 02:52:43 -07:00
										 |  |  | 	"github.com/prometheus/procfs" | 
					
						
							| 
									
										
										
										
											2015-12-19 16:57:52 -08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type conntrackCollector struct { | 
					
						
							| 
									
										
										
										
											2021-06-23 02:52:43 -07:00
										 |  |  | 	current       *prometheus.Desc | 
					
						
							|  |  |  | 	limit         *prometheus.Desc | 
					
						
							|  |  |  | 	found         *prometheus.Desc | 
					
						
							|  |  |  | 	invalid       *prometheus.Desc | 
					
						
							|  |  |  | 	ignore        *prometheus.Desc | 
					
						
							|  |  |  | 	insert        *prometheus.Desc | 
					
						
							|  |  |  | 	insertFailed  *prometheus.Desc | 
					
						
							|  |  |  | 	drop          *prometheus.Desc | 
					
						
							|  |  |  | 	earlyDrop     *prometheus.Desc | 
					
						
							|  |  |  | 	searchRestart *prometheus.Desc | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	logger        *slog.Logger | 
					
						
							| 
									
										
										
										
											2021-06-23 02:52:43 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type conntrackStatistics struct { | 
					
						
							|  |  |  | 	found         uint64 // Number of searched entries which were successful
 | 
					
						
							|  |  |  | 	invalid       uint64 // Number of packets seen which can not be tracked
 | 
					
						
							|  |  |  | 	ignore        uint64 // Number of packets seen which are already connected to a conntrack entry
 | 
					
						
							|  |  |  | 	insert        uint64 // Number of entries inserted into the list
 | 
					
						
							|  |  |  | 	insertFailed  uint64 // Number of entries for which list insertion was attempted but failed (happens if the same entry is already present)
 | 
					
						
							|  |  |  | 	drop          uint64 // Number of packets dropped due to conntrack failure. Either new conntrack entry allocation failed, or protocol helper dropped the packet
 | 
					
						
							|  |  |  | 	earlyDrop     uint64 // Number of dropped conntrack entries to make room for new ones, if maximum table size was reached
 | 
					
						
							|  |  |  | 	searchRestart uint64 // Number of conntrack table lookups which had to be restarted due to hashtable resizes
 | 
					
						
							| 
									
										
										
										
											2015-12-19 16:57:52 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							| 
									
										
										
										
											2017-09-28 06:06:26 -07:00
										 |  |  | 	registerCollector("conntrack", defaultEnabled, NewConntrackCollector) | 
					
						
							| 
									
										
										
										
											2015-12-19 16:57:52 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-28 08:44:53 -08:00
										 |  |  | // NewConntrackCollector returns a new Collector exposing conntrack stats.
 | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | func NewConntrackCollector(logger *slog.Logger) (Collector, error) { | 
					
						
							| 
									
										
										
										
											2015-12-19 16:57:52 -08:00
										 |  |  | 	return &conntrackCollector{ | 
					
						
							|  |  |  | 		current: prometheus.NewDesc( | 
					
						
							| 
									
										
										
										
											2017-09-28 06:06:26 -07:00
										 |  |  | 			prometheus.BuildFQName(namespace, "", "nf_conntrack_entries"), | 
					
						
							| 
									
										
										
										
											2015-12-19 16:57:52 -08:00
										 |  |  | 			"Number of currently allocated flow entries for connection tracking.", | 
					
						
							|  |  |  | 			nil, nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		limit: prometheus.NewDesc( | 
					
						
							| 
									
										
										
										
											2017-09-28 06:06:26 -07:00
										 |  |  | 			prometheus.BuildFQName(namespace, "", "nf_conntrack_entries_limit"), | 
					
						
							| 
									
										
										
										
											2015-12-19 16:57:52 -08:00
										 |  |  | 			"Maximum size of connection tracking table.", | 
					
						
							|  |  |  | 			nil, nil, | 
					
						
							|  |  |  | 		), | 
					
						
							| 
									
										
										
										
											2021-06-23 02:52:43 -07:00
										 |  |  | 		found: prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName(namespace, "", "nf_conntrack_stat_found"), | 
					
						
							|  |  |  | 			"Number of searched entries which were successful.", | 
					
						
							|  |  |  | 			nil, nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		invalid: prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName(namespace, "", "nf_conntrack_stat_invalid"), | 
					
						
							|  |  |  | 			"Number of packets seen which can not be tracked.", | 
					
						
							|  |  |  | 			nil, nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		ignore: prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName(namespace, "", "nf_conntrack_stat_ignore"), | 
					
						
							|  |  |  | 			"Number of packets seen which are already connected to a conntrack entry.", | 
					
						
							|  |  |  | 			nil, nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		insert: prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName(namespace, "", "nf_conntrack_stat_insert"), | 
					
						
							|  |  |  | 			"Number of entries inserted into the list.", | 
					
						
							|  |  |  | 			nil, nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		insertFailed: prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName(namespace, "", "nf_conntrack_stat_insert_failed"), | 
					
						
							|  |  |  | 			"Number of entries for which list insertion was attempted but failed.", | 
					
						
							|  |  |  | 			nil, nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		drop: prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName(namespace, "", "nf_conntrack_stat_drop"), | 
					
						
							|  |  |  | 			"Number of packets dropped due to conntrack failure.", | 
					
						
							|  |  |  | 			nil, nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		earlyDrop: prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName(namespace, "", "nf_conntrack_stat_early_drop"), | 
					
						
							|  |  |  | 			"Number of dropped conntrack entries to make room for new ones, if maximum table size was reached.", | 
					
						
							|  |  |  | 			nil, nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		searchRestart: prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName(namespace, "", "nf_conntrack_stat_search_restart"), | 
					
						
							|  |  |  | 			"Number of conntrack table lookups which had to be restarted due to hashtable resizes.", | 
					
						
							|  |  |  | 			nil, nil, | 
					
						
							|  |  |  | 		), | 
					
						
							| 
									
										
										
										
											2019-12-31 08:19:37 -08:00
										 |  |  | 		logger: logger, | 
					
						
							| 
									
										
										
										
											2015-12-19 16:57:52 -08:00
										 |  |  | 	}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-28 10:47:20 -08:00
										 |  |  | func (c *conntrackCollector) Update(ch chan<- prometheus.Metric) error { | 
					
						
							| 
									
										
										
										
											2015-12-19 16:57:52 -08:00
										 |  |  | 	value, err := readUintFromFile(procFilePath("sys/net/netfilter/nf_conntrack_count")) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-08-26 05:35:39 -07:00
										 |  |  | 		return c.handleErr(err) | 
					
						
							| 
									
										
										
										
											2015-12-19 16:57:52 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		c.current, prometheus.GaugeValue, float64(value)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	value, err = readUintFromFile(procFilePath("sys/net/netfilter/nf_conntrack_max")) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-08-26 05:35:39 -07:00
										 |  |  | 		return c.handleErr(err) | 
					
						
							| 
									
										
										
										
											2015-12-19 16:57:52 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		c.limit, prometheus.GaugeValue, float64(value)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-23 02:52:43 -07:00
										 |  |  | 	conntrackStats, err := getConntrackStatistics() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2021-07-15 04:45:07 -07:00
										 |  |  | 		return c.handleErr(err) | 
					
						
							| 
									
										
										
										
											2021-06-23 02:52:43 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		c.found, prometheus.GaugeValue, float64(conntrackStats.found)) | 
					
						
							|  |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		c.invalid, prometheus.GaugeValue, float64(conntrackStats.invalid)) | 
					
						
							|  |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		c.ignore, prometheus.GaugeValue, float64(conntrackStats.ignore)) | 
					
						
							|  |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		c.insert, prometheus.GaugeValue, float64(conntrackStats.insert)) | 
					
						
							|  |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		c.insertFailed, prometheus.GaugeValue, float64(conntrackStats.insertFailed)) | 
					
						
							|  |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		c.drop, prometheus.GaugeValue, float64(conntrackStats.drop)) | 
					
						
							|  |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		c.earlyDrop, prometheus.GaugeValue, float64(conntrackStats.earlyDrop)) | 
					
						
							|  |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		c.searchRestart, prometheus.GaugeValue, float64(conntrackStats.searchRestart)) | 
					
						
							| 
									
										
										
										
											2015-12-19 16:57:52 -08:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-08-26 05:35:39 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (c *conntrackCollector) handleErr(err error) error { | 
					
						
							|  |  |  | 	if errors.Is(err, os.ErrNotExist) { | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 		c.logger.Debug("conntrack probably not loaded") | 
					
						
							| 
									
										
										
										
											2020-08-26 05:35:39 -07:00
										 |  |  | 		return ErrNoData | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fmt.Errorf("failed to retrieve conntrack stats: %w", err) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-06-23 02:52:43 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | func getConntrackStatistics() (*conntrackStatistics, error) { | 
					
						
							|  |  |  | 	c := conntrackStatistics{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fs, err := procfs.NewFS(*procPath) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("failed to open procfs: %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	connStats, err := fs.ConntrackStat() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, connStat := range connStats { | 
					
						
							|  |  |  | 		c.found += connStat.Found | 
					
						
							|  |  |  | 		c.invalid += connStat.Invalid | 
					
						
							|  |  |  | 		c.ignore += connStat.Ignore | 
					
						
							|  |  |  | 		c.insert += connStat.Insert | 
					
						
							|  |  |  | 		c.insertFailed += connStat.InsertFailed | 
					
						
							|  |  |  | 		c.drop += connStat.Drop | 
					
						
							|  |  |  | 		c.earlyDrop += connStat.EarlyDrop | 
					
						
							|  |  |  | 		c.searchRestart += connStat.SearchRestart | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return &c, nil | 
					
						
							| 
									
										
										
										
											2021-06-23 02:53:57 -07:00
										 |  |  | } |