-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
334 lines (278 loc) · 8.88 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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"strconv"
"syscall"
"time"
"github.com/joho/godotenv"
"github.com/shirou/gopsutil/cpu"
)
// Define the Pushbullet API endpoint and your API token here.
var checkIntervalDuration time.Duration
var logger *log.Logger
var apiKey string
var apiURL string
var threshold float64
var averageLen int
var enableConsole bool
var enableTestNotif bool
var timespanAverage float64
var checkInterval float64
var notifInterval int
var thresholdDuration int
// var enableConsole = true
// var checkInterval = 1.0
// var timespanAverage = 1.0
// var enableTestNotif = true
// var threshold = 80.0
// var apiURL = "https://api.pushbullet.com/v2/pushes"
// apiURL := "ht#tps://api.pushbullet.com/v2/pushes"
// threshold := "80.0"
// averag#eLen := "1"
// enableConsole
// enableTestNotif
func checkCPULoad() float64 {
percent, _ := cpu.Percent(time.Second, false)
return percent[0]
}
func pushAlert(cpuLoad float64) {
// Create a data structure for your Pushbullet request.
timeString := time.Now().Format("2006-01-02 15:04:05")
data := map[string]interface{}{
"type": "note",
"title": "CPU Alert",
"body": fmt.Sprintf("%s \nHigh CPU load detected: %.2f%%", timeString, cpuLoad), //"This is a test message sent via Pushbullet API.",
}
// Convert the data to JSON.
jsonData, err := json.Marshal(data)
if err != nil {
fmt.Println("Error encoding JSON:", err)
return
}
// Create an HTTP request.
req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(jsonData))
if err != nil {
fmt.Println("Error creating request:", err)
return
}
// Set the request headers, including your API key.
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Access-Token", apiKey)
// Create an HTTP client and send the request.
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending request:", err)
return
}
defer resp.Body.Close()
// Check the response status.
if resp.StatusCode == http.StatusOK {
fmt.Println("Message sent successfully!")
} else {
fmt.Println("Error sending message. Status code:", resp.Status)
}
}
func setEnvs() {
var err error
apiURLStr := os.Getenv("PUSHBULLET_ENDPOINT_URL")
if apiURLStr != "" {
apiURL = apiURLStr
}
apiKey = os.Getenv("PUSHBULLET_API_KEY")
if apiKey == "" {
fmt.Println("NO PUSHBULLET_API_KEY given!")
log.Fatalf("NO PUSHBULLET_API_KEY given!")
os.Exit(1)
} else if apiKey == "SKIP" {
fmt.Println("NO PUSHBULLET_API_KEY given!")
logger.Println("NO PUSHBULLET_API_KEY given!")
fmt.Println("PUSHBULLET API SKIPPED")
logger.Println("PUSHBULLET API SKIPPED")
apiURL = "https://api.pushbullet.com/v2/pushes"
threshold = 80.0
averageLen = 1.0
enableConsole = true
enableTestNotif = true
}
thresholdStr := os.Getenv("CPU_AVERAGE_MAX_THRESHOLD")
if thresholdStr != "" {
// Convert the string to an integer
threshold, err = strconv.ParseFloat(thresholdStr, 64)
if err != nil {
log.Fatalf("Error converting CPU_AVERAGE_MAX_THRESHOLD to float: %v", err)
}
}
checkIntervalStr := os.Getenv("CHECK_INTERVAL_SECONDS")
if checkIntervalStr != "" {
// Convert the string to an integer
checkInterval, err = strconv.ParseFloat(checkIntervalStr, 64)
if err != nil {
log.Fatalf("Error converting CHECK_INTERVAL_SECONDS to float: %v", err)
}
}
timespanAvStr := os.Getenv("TIMESPAN_AVERAGE_MINUTES")
if timespanAvStr != "" {
// Convert the string to an integer
timespanAverage, err = strconv.ParseFloat(timespanAvStr, 64)
if err != nil {
log.Fatalf("Error converting TIMESPAN_AVERAGE_MINUTES to float: %v", err)
}
}
// Read the ENABLE_CONSOLE_OUTPUT variable from the environment
enableConsoleOutputStr := os.Getenv("ENABLE_CONSOLE_OUTPUT")
if enableConsoleOutputStr != "" {
// Convert the string to a boolean
enableConsole, err = strconv.ParseBool(enableConsoleOutputStr)
if err != nil {
log.Fatalf("Error parsing ENABLE_CONSOLE_OUTPUT: %v", err)
}
}
checkIntervalDuration = time.Second * time.Duration(checkInterval) //checkInterval//time.Minute
// Calculate the amount of measured points needed for the given time settings
avergageValsFloat := timespanAverage / checkInterval * 60
averageLen = int(avergageValsFloat)
// Read the SEND_TEST_NOTIFICATION_ON_LAUNCH variable from the environment
enableTestNotifStr := os.Getenv("SEND_TEST_NOTIFICATION_ON_LAUNCH")
if enableTestNotifStr != "" {
// Convert the string to a boolean
enableTestNotif, err = strconv.ParseBool(enableTestNotifStr)
if err != nil {
log.Fatalf("Error parsing SEND_TEST_NOTIFICATION_ON_LAUNCH: %v", err)
}
}
notifIntervalStr := os.Getenv("NOTIFICATION_INTERVAL_MINUTES")
if notifIntervalStr != "" {
notifInterval, err = strconv.Atoi(notifIntervalStr)
if err != nil {
log.Fatalf("Error parsing NOTIFICATION_INTERVAL_MINUTES: %v", err)
}
}
thresholdDurationStr := os.Getenv("THRESHOLD_DURATION_ALARM_MINUTES")
if thresholdDurationStr != "" {
thresholdDuration, err = strconv.Atoi(thresholdDurationStr)
if err != nil {
log.Fatalf("Error parsing THRESHOLD_DURATION_ALARM_MINUTES: %v", err)
}
}
if enableTestNotif {
pushAlert(420.69)
}
}
func pushArray(item float64, arr []float64) []float64 {
if len(arr) < averageLen {
return append([]float64{item}, arr...)
} else {
return append([]float64{item}, arr[:len(arr)-1]...)
}
}
func averageArray(arr []float64) float64 {
var sum float64 = 0
for _, i := range arr {
sum += i
}
return sum / float64(len(arr))
}
// func timestamp() string {
// t := time.Now()
// formatted := fmt.Sprintf("%d-%02d-%02d %02d:%02d:%02d : ",
// t.Year(), t.Month(), t.Day(),
// t.Hour(), t.Minute(), t.Second())
// return formatted
// }
func main() {
// Open the file for appending or create it if it doesn't exist
logFile, err := os.OpenFile("application.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal("Error opening log file:", err)
}
defer func() {
logger.Println("Closing Application")
logFile.Close() // Close the file when done
}()
// Create a logger using the opened file
logger = log.New(logFile, "CPU: ", log.Ldate|log.Ltime)
// Capture Ctrl+C signal
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
go func() {
<-sigCh
logger.Println("Closing Application")
logFile.Close()
os.Exit(0)
}()
// Print the formatted time
logger.Println("CPU watcher launched.")
if os.Getenv("DISABLE_ENV_FILE") != "true" && os.Getenv("DISABLE_ENV_FILE") == "" {
fmt.Println("Reading Environment variables from file .env")
logger.Println("Reading Environment variables from file .env")
if err := godotenv.Load(".env"); err != nil {
fmt.Printf("Error loading .env file: %v", err)
log.Fatalf("Error loading .env file: %v", err)
}
}
setEnvs()
logger.Println("Environment variables loaded.")
array := []float64{0}
// array := make([]float64, 25)
var averageCPU float64
now := time.Now()
lastAlertT := now.Add(-time.Duration(notifInterval) * time.Minute)
//timestamp := now.Add(-time.Duration(notifInterval))
thresholdCounter := 0
thresholdCheckedT := time.Now()
thresholdMax := int(thresholdDuration)
// fmt.Println(time.Duration(notifInterval) * time.Minute)
// fmt.Println(time.Now().After(lastAlertT.Add(time.Duration(notifInterval) * time.Minute)))
for {
cpuLoad := checkCPULoad()
array = pushArray(cpuLoad, array)
averageCPU = averageArray(array)
// fmt.Println(thresholdCounter)
// fmt.Printf("Current CPU load: %.2f%%\n", averageCPU)
if enableConsole {
fmt.Printf("Average CPU load: %.2f%% - momentary %.2f%%\n", averageCPU, cpuLoad)
}
if time.Now().After(thresholdCheckedT.Add(time.Minute)) {
thresholdCheckedT = time.Now()
if averageCPU > threshold {
if enableConsole {
fmt.Println(time.Now().Format("2006-02-13 15:04:05"))
fmt.Printf("Warning! CPU load: %.2f%% - momentary %.2f%%\n", averageCPU, cpuLoad)
}
if thresholdCounter == thresholdMax {
// fmt.Println("Max reached")
if time.Now().After(lastAlertT.Add(time.Duration(notifInterval) * time.Minute)) {
lastAlertT = time.Now()
pushAlert(averageCPU)
logger.Println("Pushed Notification")
}
} else {
thresholdCounter += 1
}
} else {
if thresholdCounter > 0 {
thresholdCounter -= 1
}
}
}
// if averageCPU > threshold {
// logger.Printf("WARNING average CPU load: %.2f%% - momentary %.2f%%\n", averageCPU, cpuLoad)
// timestamp := time.Now().Add(- time.Minute * time.Duration(thresholdDuration))
// if time.Now().After(timestamp.Add(time.Duration(notifInterval) * time.Minute)) { // timestamp.Add + time.Duration(notifInterval).Minutes() {
// pushAlert(averageCPU)
// fmt.Println("A:", time.Now().Second())
// fmt.Println("B:", timestamp.Add(time.Duration(notifInterval)).Second())
// timestamp = time.Now()
// fmt.Println("T:", timestamp)
// }
// }
time.Sleep(checkIntervalDuration)
}
}