af1dd14933
Second-pass logging cleanup: consistent [LEVEL] [module] format across all 41 files. Remove stale prefixes ([CF], [SYNC], [SCHED], [API], [STORAGE], [HEALTH], [ROLLBACK]). Remove 5 duplicate log lines. Gate ungated DEBUG lines. Fix wrong log levels (restore start WARN→INFO). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
121 lines
2.7 KiB
Go
121 lines
2.7 KiB
Go
package monitor
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-controller/internal/config"
|
|
)
|
|
|
|
// Pinger sends health check pings to a Healthchecks.io-compatible server.
|
|
type Pinger struct {
|
|
baseURL string
|
|
httpClient *http.Client
|
|
logger *log.Logger
|
|
enabled bool
|
|
debug bool
|
|
}
|
|
|
|
// NewPinger creates a new Pinger from monitoring config.
|
|
func NewPinger(cfg *config.MonitoringConfig, logger *log.Logger) *Pinger {
|
|
return &Pinger{
|
|
baseURL: strings.TrimRight(cfg.HealthchecksBase, "/"),
|
|
httpClient: &http.Client{
|
|
Timeout: 10 * time.Second,
|
|
},
|
|
logger: logger,
|
|
enabled: cfg.Enabled,
|
|
}
|
|
}
|
|
|
|
// SetDebug enables or disables debug logging for the pinger.
|
|
func (p *Pinger) SetDebug(debug bool) {
|
|
p.debug = debug
|
|
}
|
|
|
|
// Ping sends a success signal with optional diagnostic body.
|
|
func (p *Pinger) Ping(uuid string, body string) error {
|
|
if p.debug {
|
|
p.logger.Printf("[DEBUG] [pinger] Ping uuid=%s body_len=%d", uuid, len(body))
|
|
}
|
|
return p.send(uuid, "", body)
|
|
}
|
|
|
|
// Fail sends a failure signal with diagnostic body.
|
|
func (p *Pinger) Fail(uuid string, body string) error {
|
|
if p.debug {
|
|
p.logger.Printf("[DEBUG] [pinger] Fail uuid=%s body=%q", uuid, body)
|
|
}
|
|
return p.send(uuid, "/fail", body)
|
|
}
|
|
|
|
// Start sends a "job started" signal (for duration tracking).
|
|
func (p *Pinger) Start(uuid string) error {
|
|
if p.debug {
|
|
p.logger.Printf("[DEBUG] [pinger] Start uuid=%s", uuid)
|
|
}
|
|
return p.send(uuid, "/start", "")
|
|
}
|
|
|
|
func (p *Pinger) send(uuid, suffix, body string) error {
|
|
if !p.enabled {
|
|
return nil
|
|
}
|
|
|
|
if uuid == "" || strings.HasPrefix(uuid, "CHANGEME") {
|
|
return nil
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/ping/%s%s", p.baseURL, uuid, suffix)
|
|
if p.debug {
|
|
p.logger.Printf("[DEBUG] [pinger] send url=%s", url)
|
|
}
|
|
|
|
var lastErr error
|
|
for attempt := 0; attempt < 3; attempt++ {
|
|
if attempt > 0 {
|
|
if p.debug {
|
|
p.logger.Printf("[DEBUG] [pinger] retry attempt=%d uuid=%s", attempt+1, uuid)
|
|
}
|
|
time.Sleep(2 * time.Second)
|
|
}
|
|
|
|
var bodyReader io.Reader
|
|
if body != "" {
|
|
bodyReader = strings.NewReader(body)
|
|
}
|
|
|
|
req, err := http.NewRequest(http.MethodPost, url, bodyReader)
|
|
if err != nil {
|
|
lastErr = err
|
|
continue
|
|
}
|
|
|
|
resp, err := p.httpClient.Do(req)
|
|
if err != nil {
|
|
lastErr = err
|
|
continue
|
|
}
|
|
resp.Body.Close()
|
|
|
|
if p.debug {
|
|
p.logger.Printf("[DEBUG] [pinger] response status=%d uuid=%s", resp.StatusCode, uuid)
|
|
}
|
|
|
|
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
|
if p.debug {
|
|
p.logger.Printf("[DEBUG] [pinger] success uuid=%s", uuid)
|
|
}
|
|
return nil
|
|
}
|
|
lastErr = fmt.Errorf("HTTP %d", resp.StatusCode)
|
|
}
|
|
|
|
p.logger.Printf("[WARN] [monitor] Health ping failed after 3 attempts (%s): %v", uuid, lastErr)
|
|
return nil // Never let ping failures affect the caller
|
|
}
|