Files
uptime/internal/monitor/monitor.go
2026-03-22 11:30:31 -05:00

60 lines
1.7 KiB
Go

package monitor
import (
"fmt"
"time"
"arclineit/arcline-uptime/internal/config"
)
// Result is returned by every Checker after a single probe.
type Result struct {
MonitorName string
Up bool
StatusCode int // HTTP only; 0 for TCP/TLS/DNS
ResponseTime time.Duration
Error string // empty when Up == true
CheckedAt time.Time
}
// Checker probes one endpoint.
type Checker interface {
Name() string
Check() Result
Interval() time.Duration // per-monitor interval; 0 means use the global default
}
// BuildCheckers constructs one Checker per MonitorConfig entry.
// globalTimeout is the fallback when a monitor's own Timeout is 0.
func BuildCheckers(monitors []config.MonitorConfig, globalTimeout time.Duration) ([]Checker, error) {
checkers := make([]Checker, 0, len(monitors))
for _, m := range monitors {
timeout := globalTimeout
if m.Timeout > 0 {
timeout = time.Duration(m.Timeout) * time.Second
}
switch m.Type {
case "http":
checkers = append(checkers, NewHTTPChecker(m, timeout))
case "tcp":
checkers = append(checkers, NewTCPChecker(m, timeout))
case "tls":
checkers = append(checkers, NewTLSChecker(m, timeout))
case "dns":
checkers = append(checkers, NewDNSChecker(m, timeout))
default:
return nil, fmt.Errorf("unknown monitor type %q for %q", m.Type, m.Name)
}
}
return checkers, nil
}
// applyThreshold marks a successful result as failed if response time exceeds max.
func applyThreshold(r *Result, maxResponseMS int64) {
if maxResponseMS > 0 && r.Up && r.ResponseTime.Milliseconds() > maxResponseMS {
r.Up = false
r.Error = fmt.Sprintf("response time %dms exceeded threshold %dms",
r.ResponseTime.Milliseconds(), maxResponseMS)
}
}