mirror of
https://github.com/crocofied/CoreControl.git
synced 2025-12-18 07:56:57 +00:00
131 lines
3.6 KiB
Go
131 lines
3.6 KiB
Go
|
|
package app
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"crypto/x509"
|
||
|
|
"database/sql"
|
||
|
|
"errors"
|
||
|
|
"fmt"
|
||
|
|
"net"
|
||
|
|
"net/http"
|
||
|
|
"net/url"
|
||
|
|
"strings"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/corecontrol/agent/internal/models"
|
||
|
|
"github.com/corecontrol/agent/internal/notifications"
|
||
|
|
)
|
||
|
|
|
||
|
|
// MonitorApplications checks and updates the status of all applications
|
||
|
|
func MonitorApplications(db *sql.DB, client *http.Client, apps []models.Application, notifSender *notifications.NotificationSender) {
|
||
|
|
var notificationTemplate string
|
||
|
|
err := db.QueryRow("SELECT notification_text_application FROM settings LIMIT 1").Scan(¬ificationTemplate)
|
||
|
|
if err != nil || notificationTemplate == "" {
|
||
|
|
notificationTemplate = "The application !name (!url) went !status!"
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, app := range apps {
|
||
|
|
logPrefix := fmt.Sprintf("[App %s (%s)]", app.Name, app.PublicURL)
|
||
|
|
fmt.Printf("%s Checking...\n", logPrefix)
|
||
|
|
|
||
|
|
// Determine which URL to use for monitoring
|
||
|
|
checkURL := app.PublicURL
|
||
|
|
if app.UptimeCheckURL != "" {
|
||
|
|
checkURL = app.UptimeCheckURL
|
||
|
|
fmt.Printf("%s Using custom uptime check URL: %s\n", logPrefix, checkURL)
|
||
|
|
}
|
||
|
|
|
||
|
|
parsedURL, parseErr := url.Parse(checkURL)
|
||
|
|
if parseErr != nil {
|
||
|
|
fmt.Printf("%s Invalid URL: %v\n", logPrefix, parseErr)
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
|
||
|
|
hostIsIP := isIPAddress(parsedURL.Hostname())
|
||
|
|
var isOnline bool
|
||
|
|
|
||
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||
|
|
defer cancel()
|
||
|
|
|
||
|
|
req, err := http.NewRequestWithContext(ctx, "GET", checkURL, nil)
|
||
|
|
if err != nil {
|
||
|
|
fmt.Printf("%s Request creation failed: %v\n", logPrefix, err)
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
|
||
|
|
resp, err := client.Do(req)
|
||
|
|
if err == nil {
|
||
|
|
defer resp.Body.Close()
|
||
|
|
isOnline = resp.StatusCode >= 200 && resp.StatusCode < 400
|
||
|
|
fmt.Printf("%s Response status: %d\n", logPrefix, resp.StatusCode)
|
||
|
|
} else {
|
||
|
|
fmt.Printf("%s Connection error: %v\n", logPrefix, err)
|
||
|
|
|
||
|
|
if hostIsIP {
|
||
|
|
var urlErr *url.Error
|
||
|
|
if errors.As(err, &urlErr) {
|
||
|
|
var certErr x509.HostnameError
|
||
|
|
var unknownAuthErr x509.UnknownAuthorityError
|
||
|
|
if errors.As(urlErr.Err, &certErr) || errors.As(urlErr.Err, &unknownAuthErr) {
|
||
|
|
fmt.Printf("%s Ignoring TLS error for IP, marking as online\n", logPrefix)
|
||
|
|
isOnline = true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if isOnline != app.Online {
|
||
|
|
status := "offline"
|
||
|
|
if isOnline {
|
||
|
|
status = "online"
|
||
|
|
}
|
||
|
|
|
||
|
|
message := strings.ReplaceAll(notificationTemplate, "!name", app.Name)
|
||
|
|
message = strings.ReplaceAll(message, "!url", app.PublicURL)
|
||
|
|
message = strings.ReplaceAll(message, "!status", status)
|
||
|
|
|
||
|
|
notifSender.SendNotifications(message)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Update application status in database
|
||
|
|
updateApplicationStatus(db, app.ID, isOnline)
|
||
|
|
|
||
|
|
// Add entry to uptime history
|
||
|
|
addUptimeHistoryEntry(db, app.ID, isOnline)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Helper function to update application status
|
||
|
|
func updateApplicationStatus(db *sql.DB, appID int, online bool) {
|
||
|
|
dbCtx, dbCancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||
|
|
defer dbCancel()
|
||
|
|
|
||
|
|
_, err := db.ExecContext(dbCtx,
|
||
|
|
`UPDATE application SET online = $1 WHERE id = $2`,
|
||
|
|
online, appID,
|
||
|
|
)
|
||
|
|
if err != nil {
|
||
|
|
fmt.Printf("DB update failed for app ID %d: %v\n", appID, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Helper function to add uptime history entry
|
||
|
|
func addUptimeHistoryEntry(db *sql.DB, appID int, online bool) {
|
||
|
|
dbCtx, dbCancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||
|
|
defer dbCancel()
|
||
|
|
|
||
|
|
_, err := db.ExecContext(dbCtx,
|
||
|
|
`INSERT INTO uptime_history("applicationId", online, "createdAt") VALUES ($1, $2, now())`,
|
||
|
|
appID, online,
|
||
|
|
)
|
||
|
|
if err != nil {
|
||
|
|
fmt.Printf("History insert failed for app ID %d: %v\n", appID, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Helper function to check if a host is an IP address
|
||
|
|
func isIPAddress(host string) bool {
|
||
|
|
ip := net.ParseIP(host)
|
||
|
|
return ip != nil
|
||
|
|
}
|