mirror of
				https://github.com/ClusterCockpit/cc-metric-collector.git
				synced 2025-11-04 10:45:06 +01:00 
			
		
		
		
	* Add cpu_used (all-cpu_idle) to CpustatCollector * Update cc-metric-collector.init * Allow selection of timestamp precision in HttpSink * Add comment about precision requirement for cc-metric-store * Fix for API changes in gofish@v0.15.0 * Update requirements to latest version * Read sensors through redfish * Update golang toolchain to 1.21 * Remove stray error check * Update main config in configuration.md * Update Release action to use golang 1.22 stable release, no golang RPMs anymore * Update runonce action to use golang 1.22 stable release, no golang RPMs anymore * Update README.md Use right JSON type in configuration * Update sink's README * Test whether ipmitool or ipmi-sensors can be executed without errors * Little fixes to the prometheus sink (#115) * Add uint64 to float64 cast option * Add prometheus sink to the list of available sinks * Add aggregated counters by gpu for nvlink errors --------- Co-authored-by: Michael Schwarz <schwarz@uni-paderborn.de> * Ccmessage migration (#119) * Add cpu_used (all-cpu_idle) to CpustatCollector * Update cc-metric-collector.init * Allow selection of timestamp precision in HttpSink * Add comment about precision requirement for cc-metric-store * Fix for API changes in gofish@v0.15.0 * Update requirements to latest version * Read sensors through redfish * Update golang toolchain to 1.21 * Remove stray error check * Update main config in configuration.md * Update Release action to use golang 1.22 stable release, no golang RPMs anymore * Update runonce action to use golang 1.22 stable release, no golang RPMs anymore * Switch to CCMessage for all files. --------- Co-authored-by: Holger Obermaier <Holger.Obermaier@kit.edu> Co-authored-by: Holger Obermaier <40787752+ho-ob@users.noreply.github.com> * Switch to ccmessage also for latest additions in nvidiaMetric * New Message processor (#118) * Add cpu_used (all-cpu_idle) to CpustatCollector * Update cc-metric-collector.init * Allow selection of timestamp precision in HttpSink * Add comment about precision requirement for cc-metric-store * Fix for API changes in gofish@v0.15.0 * Update requirements to latest version * Read sensors through redfish * Update golang toolchain to 1.21 * Remove stray error check * Update main config in configuration.md * Update Release action to use golang 1.22 stable release, no golang RPMs anymore * Update runonce action to use golang 1.22 stable release, no golang RPMs anymore * New message processor to check whether a message should be dropped or manipulate it in flight * Create a copy of message before manipulation --------- Co-authored-by: Holger Obermaier <Holger.Obermaier@kit.edu> Co-authored-by: Holger Obermaier <40787752+ho-ob@users.noreply.github.com> * Update collector's Makefile and go.mod/sum files * Use message processor in router, all sinks and all receivers * Add support for credential file (NKEY) to NATS sink and receiver * Fix JSON keys in message processor configuration * Update docs for message processor, router and the default router config file * Add link to expr syntax and fix regex matching docs * Update sample collectors * Minor style change in collector manager * Some helpers for ccTopology * LIKWID collector: write log owner change only once * Fix for metrics without units and reduce debugging messages for messageProcessor * Use shorted hostname for hostname added by router * Define default port for NATS * CPUstat collector: only add unit for applicable metrics * Add precision option to all sinks using Influx's encoder * Add message processor to all sink documentation * Add units to documentation of cpustat collector --------- Co-authored-by: Holger Obermaier <Holger.Obermaier@kit.edu> Co-authored-by: Holger Obermaier <40787752+ho-ob@users.noreply.github.com> Co-authored-by: oscarminus <me@oscarminus.de> Co-authored-by: Michael Schwarz <schwarz@uni-paderborn.de>
		
			
				
	
	
		
			176 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package collectors
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/json"
 | 
						|
	"fmt"
 | 
						|
	"log"
 | 
						|
 | 
						|
	//	"os"
 | 
						|
	"os/exec"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
	"time"
 | 
						|
 | 
						|
	lp "github.com/ClusterCockpit/cc-energy-manager/pkg/cc-message"
 | 
						|
)
 | 
						|
 | 
						|
// First part contains the code for the general NfsCollector.
 | 
						|
// Later, the general NfsCollector is more limited to Nfs3- and Nfs4Collector.
 | 
						|
 | 
						|
const NFSSTAT_EXEC = `nfsstat`
 | 
						|
 | 
						|
type NfsCollectorData struct {
 | 
						|
	current int64
 | 
						|
	last    int64
 | 
						|
}
 | 
						|
 | 
						|
type nfsCollector struct {
 | 
						|
	metricCollector
 | 
						|
	tags    map[string]string
 | 
						|
	version string
 | 
						|
	config  struct {
 | 
						|
		Nfsstats       string   `json:"nfsstat"`
 | 
						|
		ExcludeMetrics []string `json:"exclude_metrics,omitempty"`
 | 
						|
	}
 | 
						|
	data map[string]NfsCollectorData
 | 
						|
}
 | 
						|
 | 
						|
func (m *nfsCollector) initStats() error {
 | 
						|
	cmd := exec.Command(m.config.Nfsstats, `-l`, `--all`)
 | 
						|
	cmd.Wait()
 | 
						|
	buffer, err := cmd.Output()
 | 
						|
	if err == nil {
 | 
						|
		for _, line := range strings.Split(string(buffer), "\n") {
 | 
						|
			lf := strings.Fields(line)
 | 
						|
			if len(lf) != 5 {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			if lf[1] == m.version {
 | 
						|
				name := strings.Trim(lf[3], ":")
 | 
						|
				if _, exist := m.data[name]; !exist {
 | 
						|
					value, err := strconv.ParseInt(lf[4], 0, 64)
 | 
						|
					if err == nil {
 | 
						|
						x := m.data[name]
 | 
						|
						x.current = value
 | 
						|
						x.last = value
 | 
						|
						m.data[name] = x
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return err
 | 
						|
}
 | 
						|
 | 
						|
func (m *nfsCollector) updateStats() error {
 | 
						|
	cmd := exec.Command(m.config.Nfsstats, `-l`, `--all`)
 | 
						|
	cmd.Wait()
 | 
						|
	buffer, err := cmd.Output()
 | 
						|
	if err == nil {
 | 
						|
		for _, line := range strings.Split(string(buffer), "\n") {
 | 
						|
			lf := strings.Fields(line)
 | 
						|
			if len(lf) != 5 {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			if lf[1] == m.version {
 | 
						|
				name := strings.Trim(lf[3], ":")
 | 
						|
				if _, exist := m.data[name]; exist {
 | 
						|
					value, err := strconv.ParseInt(lf[4], 0, 64)
 | 
						|
					if err == nil {
 | 
						|
						x := m.data[name]
 | 
						|
						x.last = x.current
 | 
						|
						x.current = value
 | 
						|
						m.data[name] = x
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return err
 | 
						|
}
 | 
						|
 | 
						|
func (m *nfsCollector) MainInit(config json.RawMessage) error {
 | 
						|
	m.config.Nfsstats = string(NFSSTAT_EXEC)
 | 
						|
	// Read JSON configuration
 | 
						|
	if len(config) > 0 {
 | 
						|
		err := json.Unmarshal(config, &m.config)
 | 
						|
		if err != nil {
 | 
						|
			log.Print(err.Error())
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	m.meta = map[string]string{
 | 
						|
		"source": m.name,
 | 
						|
		"group":  "NFS",
 | 
						|
	}
 | 
						|
	m.tags = map[string]string{
 | 
						|
		"type": "node",
 | 
						|
	}
 | 
						|
	// Check if nfsstat is in executable search path
 | 
						|
	_, err := exec.LookPath(m.config.Nfsstats)
 | 
						|
	if err != nil {
 | 
						|
		return fmt.Errorf("NfsCollector.Init(): Failed to find nfsstat binary '%s': %v", m.config.Nfsstats, err)
 | 
						|
	}
 | 
						|
	m.data = make(map[string]NfsCollectorData)
 | 
						|
	m.initStats()
 | 
						|
	m.init = true
 | 
						|
	m.parallel = true
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (m *nfsCollector) Read(interval time.Duration, output chan lp.CCMessage) {
 | 
						|
	if !m.init {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	timestamp := time.Now()
 | 
						|
 | 
						|
	m.updateStats()
 | 
						|
	prefix := ""
 | 
						|
	switch m.version {
 | 
						|
	case "v3":
 | 
						|
		prefix = "nfs3"
 | 
						|
	case "v4":
 | 
						|
		prefix = "nfs4"
 | 
						|
	default:
 | 
						|
		prefix = "nfs"
 | 
						|
	}
 | 
						|
 | 
						|
	for name, data := range m.data {
 | 
						|
		if _, skip := stringArrayContains(m.config.ExcludeMetrics, name); skip {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		value := data.current - data.last
 | 
						|
		y, err := lp.NewMessage(fmt.Sprintf("%s_%s", prefix, name), m.tags, m.meta, map[string]interface{}{"value": value}, timestamp)
 | 
						|
		if err == nil {
 | 
						|
			y.AddMeta("version", m.version)
 | 
						|
			output <- y
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (m *nfsCollector) Close() {
 | 
						|
	m.init = false
 | 
						|
}
 | 
						|
 | 
						|
type Nfs3Collector struct {
 | 
						|
	nfsCollector
 | 
						|
}
 | 
						|
 | 
						|
type Nfs4Collector struct {
 | 
						|
	nfsCollector
 | 
						|
}
 | 
						|
 | 
						|
func (m *Nfs3Collector) Init(config json.RawMessage) error {
 | 
						|
	m.name = "Nfs3Collector"
 | 
						|
	m.version = `v3`
 | 
						|
	m.setup()
 | 
						|
	return m.MainInit(config)
 | 
						|
}
 | 
						|
 | 
						|
func (m *Nfs4Collector) Init(config json.RawMessage) error {
 | 
						|
	m.name = "Nfs4Collector"
 | 
						|
	m.version = `v4`
 | 
						|
	m.setup()
 | 
						|
	return m.MainInit(config)
 | 
						|
}
 |