mirror of
https://github.com/henrygd/beszel.git
synced 2026-04-21 04:01:50 +02:00
feat(hub): add network probe API, sync, result collection, and aggregation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -168,6 +168,9 @@ func (sys *System) update() error {
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch and save network probe results
|
||||
go sys.fetchAndSaveProbeResults()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/henrygd/beszel/internal/hub/ws"
|
||||
|
||||
"github.com/henrygd/beszel/internal/entities/probe"
|
||||
"github.com/henrygd/beszel/internal/entities/system"
|
||||
"github.com/henrygd/beszel/internal/hub/expirymap"
|
||||
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
"github.com/henrygd/beszel"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"github.com/pocketbase/pocketbase/tools/store"
|
||||
"golang.org/x/crypto/ssh"
|
||||
@@ -317,6 +319,17 @@ func (sm *SystemManager) AddWebSocketSystem(systemId string, agentVersion semver
|
||||
if err := sm.AddRecord(systemRecord, system); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Sync network probes to the newly connected agent
|
||||
go func() {
|
||||
configs := sm.GetProbeConfigsForSystem(systemId)
|
||||
if len(configs) > 0 {
|
||||
if err := system.SyncNetworkProbes(configs); err != nil {
|
||||
sm.hub.Logger().Warn("failed to sync probes on connect", "system", systemId, "err", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -329,6 +342,31 @@ func (sm *SystemManager) resetFailedSmartFetchState(systemID string) {
|
||||
}
|
||||
}
|
||||
|
||||
// GetProbeConfigsForSystem returns all enabled probe configs for a system.
|
||||
func (sm *SystemManager) GetProbeConfigsForSystem(systemID string) []probe.Config {
|
||||
records, err := sm.hub.FindRecordsByFilter(
|
||||
"network_probes",
|
||||
"system = {:system} && enabled = true",
|
||||
"",
|
||||
0, 0,
|
||||
dbx.Params{"system": systemID},
|
||||
)
|
||||
if err != nil || len(records) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
configs := make([]probe.Config, 0, len(records))
|
||||
for _, r := range records {
|
||||
configs = append(configs, probe.Config{
|
||||
Target: r.GetString("target"),
|
||||
Protocol: r.GetString("protocol"),
|
||||
Port: uint16(r.GetInt("port")),
|
||||
Interval: uint16(r.GetInt("interval")),
|
||||
})
|
||||
}
|
||||
return configs
|
||||
}
|
||||
|
||||
// createSSHClientConfig initializes the SSH client configuration for connecting to an agent's server
|
||||
func (sm *SystemManager) createSSHClientConfig() error {
|
||||
privateKey, err := sm.hub.GetSSHKey("")
|
||||
|
||||
59
internal/hub/systems/system_probes.go
Normal file
59
internal/hub/systems/system_probes.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package systems
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/henrygd/beszel/internal/common"
|
||||
"github.com/henrygd/beszel/internal/entities/probe"
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
// SyncNetworkProbes sends probe configurations to the agent.
|
||||
func (sys *System) SyncNetworkProbes(configs []probe.Config) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
var result string
|
||||
return sys.request(ctx, common.SyncNetworkProbes, configs, &result)
|
||||
}
|
||||
|
||||
// FetchNetworkProbeResults fetches probe results from the agent.
|
||||
func (sys *System) FetchNetworkProbeResults() (map[string]probe.Result, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
var results map[string]probe.Result
|
||||
err := sys.request(ctx, common.GetNetworkProbeResults, nil, &results)
|
||||
return results, err
|
||||
}
|
||||
|
||||
// fetchAndSaveProbeResults fetches probe results and saves them to the database.
|
||||
func (sys *System) fetchAndSaveProbeResults() {
|
||||
hub := sys.manager.hub
|
||||
|
||||
// Check if this system has any probes
|
||||
count, err := hub.CountRecords("network_probes",
|
||||
dbx.NewExp("system = {:system} AND enabled = true", dbx.Params{"system": sys.Id}))
|
||||
if err != nil || count == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
results, err := sys.FetchNetworkProbeResults()
|
||||
if err != nil || len(results) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
collection, err := hub.FindCachedCollectionByNameOrId("network_probe_stats")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
record := core.NewRecord(collection)
|
||||
record.Set("system", sys.Id)
|
||||
record.Set("stats", results)
|
||||
record.Set("type", "1m")
|
||||
|
||||
if err := hub.SaveNoValidate(record); err != nil {
|
||||
hub.Logger().Warn("failed to save probe stats", "system", sys.Id, "err", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user