HealthCheckAPI/healthchecker.go

84 lines
1.6 KiB
Go

package main
import (
"encoding/json"
"log"
"net/http"
"sync"
"time"
)
var services = []string{
"https://git.aaronic.cc",
"https://portainer.aaronic.cc",
"https://jellyfin.aaronic.cc",
"https://dnd.aaronic.cc",
}
type HealthChecker struct {
status map[string]ServiceStatus
mu sync.RWMutex
client *http.Client
sse *SSEBroker
}
func NewHealthChecker() *HealthChecker {
return &HealthChecker{
status: make(map[string]ServiceStatus),
client: &http.Client{
Timeout: 5 * time.Second,
},
sse: NewSSEBroker(),
}
}
func (hc *HealthChecker) CheckAll() {
for _, service := range services {
go hc.checkService(service)
}
}
func (hc *HealthChecker) checkService(url string) {
resp, err := hc.client.Get(url)
status := ServiceStatus{
URL: url,
CheckedAt: time.Now(),
}
if err != nil {
log.Printf("Error checking %s: %s", url, err)
status.IsUp = false
} else {
defer resp.Body.Close()
status.StatusCode = resp.StatusCode
status.IsUp = resp.StatusCode >= 200 && resp.StatusCode < 300
log.Printf("%s: %d", url, resp.StatusCode)
}
hc.mu.Lock()
hc.status[url] = status
hc.mu.Unlock()
data, _ := json.Marshal(status)
hc.sse.Broadcast(string(data))
}
func (hc *HealthChecker) GetStatuses() []ServiceStatus {
hc.mu.RLock()
defer hc.mu.RUnlock()
results := make([]ServiceStatus, 0, len(hc.status))
for _, status := range hc.status {
results = append(results, status)
}
return results
}
func (hc *HealthChecker) GetStatus(url string) (ServiceStatus, bool) {
hc.mu.RLock()
defer hc.mu.RUnlock()
status, ok := hc.status[url]
return status, ok
}