mirror of
https://github.com/henrygd/beszel.git
synced 2026-09-21 08:57:48 +02:00
feat: add network monitors (ICMP/TCP/HTTP/DNS) (#2266)
Co-authored-by: xiaomiku01 <xiaomiku01@outlook.com> Co-authored-by: henrygd <hank@henrygd.me>
This commit is contained in:
102
internal/entities/monitor/monitor.go
Normal file
102
internal/entities/monitor/monitor.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package monitor
|
||||
|
||||
import "time"
|
||||
|
||||
// MaxProbeTimeout is the longest agent probe timeout (currently HTTP).
|
||||
// Hub requests that run a probe must allow this time in addition to transport overhead.
|
||||
const MaxProbeTimeout = 10 * time.Second
|
||||
|
||||
type SyncAction uint8
|
||||
|
||||
const (
|
||||
// SyncActionReplace indicates a full sync where the provided configs should replace all existing monitors for the system.
|
||||
SyncActionReplace SyncAction = iota
|
||||
// SyncActionUpsert indicates an incremental sync where the provided config should be added or updated.
|
||||
SyncActionUpsert
|
||||
// SyncActionDelete indicates an incremental sync where the provided config should be removed.
|
||||
SyncActionDelete
|
||||
)
|
||||
|
||||
// Config defines a network monitor task sent from hub to agent.
|
||||
type Config struct {
|
||||
// ID is the stable network_monitors record ID generated by the hub.
|
||||
ID string `cbor:"0,keyasint"`
|
||||
Target string `cbor:"1,keyasint"`
|
||||
Protocol string `cbor:"2,keyasint"` // "icmp", "tcp", "http", or "dns"
|
||||
Port uint16 `cbor:"3,keyasint,omitempty"`
|
||||
Interval uint16 `cbor:"4,keyasint"` // seconds
|
||||
}
|
||||
|
||||
// SyncRequest defines an incremental or full monitor sync request sent to the agent.
|
||||
type SyncRequest struct {
|
||||
Action SyncAction `cbor:"0,keyasint"`
|
||||
Config Config `cbor:"1,keyasint,omitempty"`
|
||||
Configs []Config `cbor:"2,keyasint,omitempty"`
|
||||
RunNow bool `cbor:"3,keyasint,omitempty"`
|
||||
}
|
||||
|
||||
// SyncResponse returns the immediate result for an upsert when requested.
|
||||
type SyncResponse struct {
|
||||
Result Result `cbor:"0,keyasint,omitempty"`
|
||||
}
|
||||
|
||||
// Result holds aggregated monitor results for a single target.
|
||||
//
|
||||
// 0: avg response in microseconds
|
||||
//
|
||||
// 1: 1h average response in microseconds
|
||||
//
|
||||
// 2: min response in microseconds
|
||||
//
|
||||
// 3: 1h min response in microseconds
|
||||
//
|
||||
// 4: max response in microseconds
|
||||
//
|
||||
// 5: 1h max response in microseconds
|
||||
//
|
||||
// 6: packet loss percentage (0-100)
|
||||
//
|
||||
// 7: 1h packet loss percentage (0-100)
|
||||
type Result struct {
|
||||
AvgResponse int64 `cbor:"0,keyasint,omitempty"`
|
||||
AvgResponse1h int64 `cbor:"1,keyasint,omitempty"`
|
||||
MinResponse int64 `cbor:"2,keyasint,omitempty"`
|
||||
MinResponse1h int64 `cbor:"3,keyasint,omitempty"`
|
||||
MaxResponse int64 `cbor:"4,keyasint,omitempty"`
|
||||
MaxResponse1h int64 `cbor:"5,keyasint,omitempty"`
|
||||
PacketLoss float64 `cbor:"6,keyasint,omitempty"`
|
||||
PacketLoss1h float64 `cbor:"7,keyasint,omitempty"`
|
||||
// LastProbeAt is the latest completed probe's Unix timestamp in milliseconds.
|
||||
LastProbeAt int64 `cbor:"8,keyasint"`
|
||||
// SampleCount includes all completed probes since this monitor started.
|
||||
// Used for alert warm-up even when the interval is longer than 20 minutes.
|
||||
SampleCount int64 `cbor:"9,keyasint,omitempty"`
|
||||
// Counts and sum cover the current response window (or latest-sample
|
||||
// fallback), not the hourly window or lifetime SampleCount.
|
||||
TotalCount int64 `cbor:"10,keyasint"`
|
||||
SuccessCount int64 `cbor:"11,keyasint"`
|
||||
ResponseSum int64 `cbor:"12,keyasint"`
|
||||
}
|
||||
|
||||
// Stats holds response times in microseconds and packet loss percentage (0-100).
|
||||
type Stats struct {
|
||||
ResAvg float64 `json:"res_avg" db:"-"` // Derived for display; not stored.
|
||||
ResMin float64 `json:"res_min" db:"res_min"`
|
||||
ResMax float64 `json:"res_max" db:"res_max"`
|
||||
Loss float64 `json:"loss" db:"-"` // Derived for display; not stored.
|
||||
TotalCount int64 `json:"-" db:"total_count"`
|
||||
SuccessCount int64 `json:"-" db:"success_count"`
|
||||
ResponseSum int64 `json:"-" db:"res_sum"`
|
||||
}
|
||||
|
||||
func (s Stats) FromResult(result Result) Stats {
|
||||
return Stats{
|
||||
ResAvg: float64(result.AvgResponse),
|
||||
ResMin: float64(result.MinResponse),
|
||||
ResMax: float64(result.MaxResponse),
|
||||
Loss: result.PacketLoss,
|
||||
TotalCount: result.TotalCount,
|
||||
SuccessCount: result.SuccessCount,
|
||||
ResponseSum: result.ResponseSum,
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/henrygd/beszel/internal/entities/container"
|
||||
"github.com/henrygd/beszel/internal/entities/monitor"
|
||||
"github.com/henrygd/beszel/internal/entities/systemd"
|
||||
)
|
||||
|
||||
@@ -210,5 +211,6 @@ type CombinedData struct {
|
||||
Details *Details `cbor:"4,keyasint,omitempty"`
|
||||
// SystemdServicesUpdated distinguishes a fresh empty snapshot from a response
|
||||
// that omitted systemd data (for example, a short-cache dashboard request).
|
||||
SystemdServicesUpdated bool `json:"systemdUpdated,omitempty" cbor:"5,keyasint,omitempty"`
|
||||
SystemdServicesUpdated bool `json:"systemdUpdated,omitempty" cbor:"5,keyasint,omitempty"`
|
||||
Monitors map[string]monitor.Result `cbor:"6,keyasint"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user