-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
main.go
145 lines (119 loc) · 2.89 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package main
//Import the packages we need
import (
"fmt"
"io"
"os"
"strconv"
"strings"
"github.com/sensu/sensu-go/types"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/load"
"github.com/spf13/cobra"
)
//Set up some variables. Most notably, warning and critical as load 1/5/15 values
var (
warning, critical string
stdin *os.File
)
//Start our main function
func main() {
rootCmd := configureRootCommand()
if err := rootCmd.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
}
//Set up our flags for the command. Note that we have load defaults for warning & critical
func configureRootCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "sensu-go-load-check",
Short: "The Sensu Go check for system Load",
RunE: run,
}
cmd.Flags().StringVarP(&warning,
"warning",
"w",
"2.75, 2.5, 2.0",
"Load WARNING threshold, 1/5/15 min average")
cmd.Flags().StringVarP(&critical,
"critical",
"c",
"3.5, 3.25, 3.0",
"Load CRITICAL threshold, 1/5/15 min average")
return cmd
}
func parseArg(arg string) []float64 {
var list []float64
for _, x := range strings.Split(arg, ",") {
w, err := strconv.ParseFloat(strings.TrimSpace(x), 64)
if err != nil {
msg := fmt.Sprintf("Failed to parse %s", err.Error())
io.WriteString(os.Stdout, msg)
os.Exit(3)
}
list = append(list, w)
}
return list
}
func run(cmd *cobra.Command, args []string) error {
if len(args) != 0 {
_ = cmd.Help()
return fmt.Errorf("invalid argument(s) received")
}
if stdin == nil {
stdin = os.Stdin
}
event := &types.Event{}
return checkLoad(event)
}
//Here we start the meat of what we do.
func checkLoad(event *types.Event) error {
const checkName = "CheckLoad"
const metricName = "core_load"
warn := parseArg(warning)
crit := parseArg(critical)
cpuLoad, err := load.Avg()
if err != nil {
msg := fmt.Sprintf("Failed to obtain load info %s", err.Error())
io.WriteString(os.Stdout, msg)
os.Exit(3)
}
cpuCount, err := cpu.Counts(false)
if err != nil {
msg := fmt.Sprintf("Failed to obtain CPU counts %s", err.Error())
io.WriteString(os.Stdout, msg)
os.Exit(3)
}
cpuLoadList := []float64{cpuLoad.Load1, cpuLoad.Load5, cpuLoad.Load15}
// Calculate load per core
for i, x := range cpuLoadList {
cpuLoadList[i] = x / float64(cpuCount)
}
// Detect total level
// 0=ok, 1=warn, 2=crit
var level int = 0
for i, v := range cpuLoadList {
if v > crit[i] {
if 2 > level {
level = 2
}
} else if v >= warn[i] && v <= crit[i] {
if 1 > level {
level = 1
}
}
}
levelStrings := []string{"OK", "WARNING", "CRITICAL"}
msg := fmt.Sprintf(
"%[1]s %[2]s - value = %.2[4]f, %.2[5]f, %.2[6]f | %[3]s_1=%.2[4]f, %[3]s_5=%.2[5]f, %[3]s_15=%.2[6]f\n",
checkName,
levelStrings[level],
metricName,
cpuLoadList[0],
cpuLoadList[1],
cpuLoadList[2])
io.WriteString(os.Stdout, msg)
os.Exit(level)
return nil
}