initial commit
This commit is contained in:
96
internal/collector/process.go
Normal file
96
internal/collector/process.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.sinav-lab.com/sinav/keenetic-exporter-v2/internal/device"
|
||||
"gitea.sinav-lab.com/sinav/keenetic-exporter-v2/internal/keenetic"
|
||||
"gitea.sinav-lab.com/sinav/keenetic-exporter-v2/internal/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
type ProcessCollector struct {
|
||||
cpuDesc *prometheus.Desc
|
||||
vmSizeDesc *prometheus.Desc
|
||||
vmRSSDesc *prometheus.Desc
|
||||
threadsDesc *prometheus.Desc
|
||||
fdsDesc *prometheus.Desc
|
||||
}
|
||||
|
||||
func NewProcessCollector() *ProcessCollector {
|
||||
labels := []string{"device", "comm", "pid"}
|
||||
return &ProcessCollector{
|
||||
cpuDesc: prometheus.NewDesc("keenetic_process_cpu_seconds", "CPU usage of the process", labels, nil),
|
||||
vmSizeDesc: prometheus.NewDesc("keenetic_process_memory_virtual_bytes", "Virtual memory size in bytes", labels, nil),
|
||||
vmRSSDesc: prometheus.NewDesc("keenetic_process_memory_resident_bytes", "Resident memory size in bytes", labels, nil),
|
||||
threadsDesc: prometheus.NewDesc("keenetic_process_threads", "Number of threads", labels, nil),
|
||||
fdsDesc: prometheus.NewDesc("keenetic_process_fds", "Number of open file descriptors", labels, nil),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ProcessCollector) Name() string {
|
||||
return "process"
|
||||
}
|
||||
|
||||
func (c *ProcessCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- c.cpuDesc
|
||||
ch <- c.vmSizeDesc
|
||||
ch <- c.vmRSSDesc
|
||||
ch <- c.threadsDesc
|
||||
ch <- c.fdsDesc
|
||||
}
|
||||
|
||||
func (c *ProcessCollector) Collect(dev *device.Device, ch chan<- prometheus.Metric) error {
|
||||
var processInfo any
|
||||
var ok bool
|
||||
|
||||
hostname := dev.Name
|
||||
client := dev.Client
|
||||
|
||||
dev.CacheMutex.RLock()
|
||||
processInfo, ok = dev.Cache["process"]
|
||||
valid := time.Since(dev.LastUpdate) < dev.CacheTTL
|
||||
dev.CacheMutex.RUnlock()
|
||||
|
||||
if !ok || !valid {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
fresh, err := client.GetProcessInfo(ctx)
|
||||
cancel()
|
||||
if err != nil {
|
||||
log.Printf("failed to get process info from %s: %v", hostname, err)
|
||||
return err
|
||||
}
|
||||
processInfo = fresh
|
||||
dev.CacheMutex.Lock()
|
||||
dev.Cache["process"] = fresh
|
||||
dev.LastUpdate = time.Now()
|
||||
dev.CacheMutex.Unlock()
|
||||
}
|
||||
|
||||
procs, ok := processInfo.([]*keenetic.ProcessInfo)
|
||||
if !ok {
|
||||
log.Printf("invalid cache data type for process info on %s", hostname)
|
||||
return fmt.Errorf("invalid cache data type for process info")
|
||||
}
|
||||
|
||||
for _, p := range procs {
|
||||
labels := []string{hostname, p.Comm, p.Pid}
|
||||
|
||||
vmSize := utils.ParseKB(p.VMSize) * 1024
|
||||
vmRSS := utils.ParseKB(p.VMRSS) * 1024
|
||||
threads, _ := strconv.Atoi(strings.TrimSpace(p.Threads))
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(c.cpuDesc, prometheus.CounterValue, p.Statistics.CPU.Cur, labels...)
|
||||
ch <- prometheus.MustNewConstMetric(c.vmSizeDesc, prometheus.GaugeValue, vmSize, labels...)
|
||||
ch <- prometheus.MustNewConstMetric(c.vmRSSDesc, prometheus.GaugeValue, vmRSS, labels...)
|
||||
ch <- prometheus.MustNewConstMetric(c.threadsDesc, prometheus.GaugeValue, float64(threads), labels...)
|
||||
ch <- prometheus.MustNewConstMetric(c.fdsDesc, prometheus.GaugeValue, p.Fds, labels...)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user