mirror of
				https://github.com/ClusterCockpit/cc-metric-collector.git
				synced 2025-10-31 00:55:06 +01:00 
			
		
		
		
	* InfiniBandCollector: Scale raw readings from octets to bytes * Fix clock frequency coming from LikwidCollector and update docs * Build DEB package for Ubuntu 20.04 for releases * Fix memstat collector with numa_stats option * Remove useless prints from MemstatCollector * Replace ioutils with os and io (#87) * Use lower case for error strings in RocmSmiCollector * move maybe-usable-by-other-cc-components to pkg. Fix all files to use the new paths (#88) * Add collector for monitoring the execution of cc-metric-collector itself (#81) * Add collector to monitor execution of cc-metric-collector itself * Register SelfCollector * Fix import paths for moved packages
		
			
				
	
	
		
			129 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			129 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package collectors
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| 
 | |
| 	cclog "github.com/ClusterCockpit/cc-metric-collector/pkg/ccLogger"
 | |
| 	lp "github.com/ClusterCockpit/cc-metric-collector/pkg/ccMetric"
 | |
| )
 | |
| 
 | |
| //
 | |
| // LoadavgCollector collects:
 | |
| // * load average of last 1, 5 & 15 minutes
 | |
| // * number of processes currently runnable
 | |
| // * total number of processes in system
 | |
| //
 | |
| // See: https://www.kernel.org/doc/html/latest/filesystems/proc.html
 | |
| //
 | |
| const LOADAVGFILE = "/proc/loadavg"
 | |
| 
 | |
| type LoadavgCollector struct {
 | |
| 	metricCollector
 | |
| 	tags         map[string]string
 | |
| 	load_matches []string
 | |
| 	load_skips   []bool
 | |
| 	proc_matches []string
 | |
| 	proc_skips   []bool
 | |
| 	config       struct {
 | |
| 		ExcludeMetrics []string `json:"exclude_metrics,omitempty"`
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (m *LoadavgCollector) Init(config json.RawMessage) error {
 | |
| 	m.name = "LoadavgCollector"
 | |
| 	m.parallel = true
 | |
| 	m.setup()
 | |
| 	if len(config) > 0 {
 | |
| 		err := json.Unmarshal(config, &m.config)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 	m.meta = map[string]string{
 | |
| 		"source": m.name,
 | |
| 		"group":  "LOAD"}
 | |
| 	m.tags = map[string]string{"type": "node"}
 | |
| 	m.load_matches = []string{
 | |
| 		"load_one",
 | |
| 		"load_five",
 | |
| 		"load_fifteen"}
 | |
| 	m.load_skips = make([]bool, len(m.load_matches))
 | |
| 	m.proc_matches = []string{
 | |
| 		"proc_run",
 | |
| 		"proc_total"}
 | |
| 	m.proc_skips = make([]bool, len(m.proc_matches))
 | |
| 
 | |
| 	for i, name := range m.load_matches {
 | |
| 		_, m.load_skips[i] = stringArrayContains(m.config.ExcludeMetrics, name)
 | |
| 	}
 | |
| 	for i, name := range m.proc_matches {
 | |
| 		_, m.proc_skips[i] = stringArrayContains(m.config.ExcludeMetrics, name)
 | |
| 	}
 | |
| 	m.init = true
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *LoadavgCollector) Read(interval time.Duration, output chan lp.CCMetric) {
 | |
| 	if !m.init {
 | |
| 		return
 | |
| 	}
 | |
| 	buffer, err := os.ReadFile(LOADAVGFILE)
 | |
| 	if err != nil {
 | |
| 		if err != nil {
 | |
| 			cclog.ComponentError(
 | |
| 				m.name,
 | |
| 				fmt.Sprintf("Read(): Failed to read file '%s': %v", LOADAVGFILE, err))
 | |
| 		}
 | |
| 		return
 | |
| 	}
 | |
| 	now := time.Now()
 | |
| 
 | |
| 	// Load metrics
 | |
| 	ls := strings.Split(string(buffer), ` `)
 | |
| 	for i, name := range m.load_matches {
 | |
| 		x, err := strconv.ParseFloat(ls[i], 64)
 | |
| 		if err != nil {
 | |
| 			cclog.ComponentError(
 | |
| 				m.name,
 | |
| 				fmt.Sprintf("Read(): Failed to convert '%s' to float64: %v", ls[i], err))
 | |
| 			continue
 | |
| 		}
 | |
| 		if m.load_skips[i] {
 | |
| 			continue
 | |
| 		}
 | |
| 		y, err := lp.New(name, m.tags, m.meta, map[string]interface{}{"value": x}, now)
 | |
| 		if err == nil {
 | |
| 			output <- y
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Process metrics
 | |
| 	lv := strings.Split(ls[3], `/`)
 | |
| 	for i, name := range m.proc_matches {
 | |
| 		x, err := strconv.ParseInt(lv[i], 10, 64)
 | |
| 		if err != nil {
 | |
| 			cclog.ComponentError(
 | |
| 				m.name,
 | |
| 				fmt.Sprintf("Read(): Failed to convert '%s' to float64: %v", lv[i], err))
 | |
| 			continue
 | |
| 		}
 | |
| 		if m.proc_skips[i] {
 | |
| 			continue
 | |
| 		}
 | |
| 		y, err := lp.New(name, m.tags, m.meta, map[string]interface{}{"value": x}, now)
 | |
| 		if err == nil {
 | |
| 			output <- y
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (m *LoadavgCollector) Close() {
 | |
| 	m.init = false
 | |
| }
 |