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  }