This repository has been archived on 2024-10-27. You can view files and clone it, but cannot push or open issues or pull requests.
cpuwatch/main.go
2023-11-08 08:48:42 +01:00

101 lines
2.4 KiB
Go

package main
import (
"flag"
"fmt"
"os"
"regexp"
"time"
"github.com/TheCreeper/go-notify"
"github.com/shirou/gopsutil/process"
)
var (
processRegex string
threshold float64
interval int
gracePeriod int
lastNotified time.Time
prevCPUTimes = make(map[int32]float64)
currentCPUTimes = make(map[int32]float64)
)
func init() {
flag.StringVar(&processRegex, "regex", "", "Regular expression to match process name")
flag.Float64Var(&threshold, "threshold", 66, "CPU usage threshold")
flag.IntVar(&interval, "interval", 30, "Interval in seconds to check the processes")
flag.IntVar(&gracePeriod, "grace", 300, "Grace period in seconds after a notification is sent")
flag.Parse()
}
func main() {
if processRegex == "" {
fmt.Fprintln(os.Stderr, "Error: regex is required")
return
}
re, err := regexp.Compile(processRegex)
if err != nil {
fmt.Fprintln(os.Stderr, "Error compiling regex:", err)
return
}
for {
processes, err := process.Processes()
if err != nil {
fmt.Fprintln(os.Stderr, "Error fetching processes:", err)
return
}
for _, p := range processes {
pid := p.Pid
name, err := p.Name()
if err != nil {
continue
}
if re.MatchString(name) {
cpuTime, err := p.Times()
if err != nil {
continue
}
currentTotalTime := cpuTime.User + cpuTime.System
if prevTime, exists := prevCPUTimes[pid]; exists {
cpuPercent := (currentTotalTime - prevTime) / float64(interval) * 100.0
if cpuPercent > threshold && time.Since(lastNotified) > time.Duration(gracePeriod)*time.Second {
sendNotification(name, int(pid), cpuPercent)
lastNotified = time.Now()
}
}
currentCPUTimes[pid] = currentTotalTime
}
}
// Swap maps and clear the old currentCPUTimes
prevCPUTimes, currentCPUTimes = currentCPUTimes, prevCPUTimes
for k := range currentCPUTimes {
delete(currentCPUTimes, k)
}
time.Sleep(time.Duration(interval) * time.Second)
}
}
func sendNotification(processName string, pid int, cpuUsage float64) {
title := "High CPU Usage"
message := fmt.Sprintf("Process with PID %d (%s) is using %.2f%% CPU.", pid, processName, cpuUsage)
fmt.Fprintf(os.Stderr, "%s\n", message)
notification := notify.Notification{
Summary: title,
Body: message,
}
_, err := notification.Show()
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to send notification:", err)
}
}