github.com/nginxinc/kubernetes-ingress@v1.12.5/internal/metrics/collectors/processes.go (about) 1 package collectors 2 3 import ( 4 "bytes" 5 "fmt" 6 "io/ioutil" 7 "strconv" 8 9 "github.com/golang/glog" 10 "github.com/prometheus/client_golang/prometheus" 11 ) 12 13 // NginxProcessesMetricsCollector implements prometheus.Collector interface 14 type NginxProcessesMetricsCollector struct { 15 workerProcessTotal *prometheus.GaugeVec 16 } 17 18 // NewNginxProcessesMetricsCollector creates a new NginxProcessMetricsCollector 19 func NewNginxProcessesMetricsCollector(constLabels map[string]string) *NginxProcessesMetricsCollector { 20 return &NginxProcessesMetricsCollector{ 21 workerProcessTotal: prometheus.NewGaugeVec( 22 prometheus.GaugeOpts{ 23 Name: "nginx_worker_processes_total", 24 Namespace: metricsNamespace, 25 Help: "Number of NGINX worker processes", 26 ConstLabels: constLabels, 27 }, 28 []string{"generation"}, 29 ), 30 } 31 } 32 33 // updateWorkerProcessCount sets the number of NGINX worker processes 34 func (pc *NginxProcessesMetricsCollector) updateWorkerProcessCount() { 35 currWorkerProcesses, prevWorkerPrcesses, err := getWorkerProcesses() 36 if err != nil { 37 glog.Errorf("unable to collect process metrics : %v", err) 38 return 39 } 40 pc.workerProcessTotal.WithLabelValues("current").Set(float64(currWorkerProcesses)) 41 pc.workerProcessTotal.WithLabelValues("old").Set(float64(prevWorkerPrcesses)) 42 } 43 44 func getWorkerProcesses() (int, int, error) { 45 var workerProcesses int 46 var prevWorkerProcesses int 47 48 procFolders, err := ioutil.ReadDir("/proc") 49 if err != nil { 50 return 0, 0, fmt.Errorf("unable to read directory /proc : %w", err) 51 } 52 53 for _, folder := range procFolders { 54 _, err := strconv.Atoi(folder.Name()) 55 if err != nil { 56 continue 57 } 58 59 cmdlineFile := fmt.Sprintf("/proc/%v/cmdline", folder.Name()) 60 content, err := ioutil.ReadFile(cmdlineFile) 61 if err != nil { 62 return 0, 0, fmt.Errorf("unable to read file %v: %w", cmdlineFile, err) 63 } 64 65 text := string(bytes.TrimRight(content, "\x00")) 66 if text == "nginx: worker process" { 67 workerProcesses++ 68 } else if text == "nginx: worker process is shutting down" { 69 prevWorkerProcesses++ 70 } 71 } 72 return workerProcesses, prevWorkerProcesses, nil 73 } 74 75 // Collect implements the prometheus.Collector interface Collect method 76 func (pc *NginxProcessesMetricsCollector) Collect(ch chan<- prometheus.Metric) { 77 pc.updateWorkerProcessCount() 78 pc.workerProcessTotal.Collect(ch) 79 } 80 81 // Describe implements prometheus.Collector interface Describe method 82 func (pc *NginxProcessesMetricsCollector) Describe(ch chan<- *prometheus.Desc) { 83 pc.workerProcessTotal.Describe(ch) 84 } 85 86 // Register registers all the metrics of the collector 87 func (pc *NginxProcessesMetricsCollector) Register(registry *prometheus.Registry) error { 88 return registry.Register(pc) 89 }