mirror of
https://github.com/fankes/beszel.git
synced 2025-10-20 10:19:27 +08:00
rename variables for clarity
This commit is contained in:
@@ -27,30 +27,30 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Agent struct {
|
type Agent struct {
|
||||||
addr string // Adress that the ssh server listens on
|
addr string // Adress that the ssh server listens on
|
||||||
pubKey []byte // Public key for ssh server
|
pubKey []byte // Public key for ssh server
|
||||||
sem chan struct{} // Semaphore to limit concurrent access to docker api
|
sem chan struct{} // Semaphore to limit concurrent access to docker api
|
||||||
containerStatsMap map[string]*container.PrevContainerStats // Keeps track of container stats
|
fsNames []string // List of filesystem device names being monitored
|
||||||
containerStatsMutex *sync.Mutex // Mutex to prevent concurrent access to containerStatsMap
|
fsStats map[string]*system.FsStats // Keeps track of disk stats for each filesystem
|
||||||
fsNames []string // List of filesystem device names being monitored
|
netInterfaces map[string]struct{} // Stores all valid network interfaces
|
||||||
fsStats map[string]*system.FsStats // Keeps track of disk stats for each filesystem
|
netIoStats *system.NetIoStats // Keeps track of bandwidth usage
|
||||||
netInterfaces map[string]struct{} // Stores all valid network interfaces
|
prevContainerStatsMap map[string]*container.PrevContainerStats // Keeps track of container stats
|
||||||
netIoStats *system.NetIoStats // Keeps track of bandwidth usage
|
prevContainerStatsMutex *sync.Mutex // Mutex to prevent concurrent access to prevContainerStatsMap
|
||||||
dockerClient *http.Client // HTTP client to query docker api
|
dockerClient *http.Client // HTTP client to query docker api
|
||||||
sensorsContext context.Context // Sensors context to override sys location
|
sensorsContext context.Context // Sensors context to override sys location
|
||||||
debug bool // true if LOG_LEVEL is set to debug
|
debug bool // true if LOG_LEVEL is set to debug
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAgent(pubKey []byte, addr string) *Agent {
|
func NewAgent(pubKey []byte, addr string) *Agent {
|
||||||
return &Agent{
|
return &Agent{
|
||||||
addr: addr,
|
addr: addr,
|
||||||
pubKey: pubKey,
|
pubKey: pubKey,
|
||||||
sem: make(chan struct{}, 15),
|
sem: make(chan struct{}, 15),
|
||||||
containerStatsMap: make(map[string]*container.PrevContainerStats),
|
prevContainerStatsMap: make(map[string]*container.PrevContainerStats),
|
||||||
containerStatsMutex: &sync.Mutex{},
|
prevContainerStatsMutex: &sync.Mutex{},
|
||||||
netIoStats: &system.NetIoStats{},
|
netIoStats: &system.NetIoStats{},
|
||||||
dockerClient: newDockerClient(),
|
dockerClient: newDockerClient(),
|
||||||
sensorsContext: context.Background(),
|
sensorsContext: context.Background(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,21 +223,22 @@ func (a *Agent) getDockerStats() ([]container.Stats, error) {
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var containers []container.ApiInfo
|
// docker host container list response
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&containers); err != nil {
|
var res []container.ApiInfo
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {
|
||||||
slog.Error("Error decoding containers", "err", err)
|
slog.Error("Error decoding containers", "err", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
containerStats := make([]container.Stats, 0, len(containers))
|
containerStats := make([]container.Stats, 0, len(res))
|
||||||
containerStatsMutex := sync.Mutex{}
|
containerStatsMutex := sync.Mutex{}
|
||||||
|
|
||||||
// store valid ids to clean up old container ids from map
|
// store valid ids to clean up old container ids from map
|
||||||
validIds := make(map[string]struct{}, len(containers))
|
validIds := make(map[string]struct{}, len(res))
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
for _, ctr := range containers {
|
for _, ctr := range res {
|
||||||
ctr.IdShort = ctr.Id[:12]
|
ctr.IdShort = ctr.Id[:12]
|
||||||
validIds[ctr.IdShort] = struct{}{}
|
validIds[ctr.IdShort] = struct{}{}
|
||||||
// check if container is less than 1 minute old (possible restart)
|
// check if container is less than 1 minute old (possible restart)
|
||||||
@@ -275,9 +276,9 @@ func (a *Agent) getDockerStats() ([]container.Stats, error) {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
// remove old / invalid container stats
|
// remove old / invalid container stats
|
||||||
for id := range a.containerStatsMap {
|
for id := range a.prevContainerStatsMap {
|
||||||
if _, exists := validIds[id]; !exists {
|
if _, exists := validIds[id]; !exists {
|
||||||
delete(a.containerStatsMap, id)
|
delete(a.prevContainerStatsMap, id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,77 +286,77 @@ func (a *Agent) getDockerStats() ([]container.Stats, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) getContainerStats(ctr container.ApiInfo) (container.Stats, error) {
|
func (a *Agent) getContainerStats(ctr container.ApiInfo) (container.Stats, error) {
|
||||||
cStats := container.Stats{}
|
curStats := container.Stats{}
|
||||||
|
|
||||||
resp, err := a.dockerClient.Get("http://localhost/containers/" + ctr.IdShort + "/stats?stream=0&one-shot=1")
|
resp, err := a.dockerClient.Get("http://localhost/containers/" + ctr.IdShort + "/stats?stream=0&one-shot=1")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cStats, err
|
return curStats, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
// decode the json data from the response body
|
// docker host container stats response
|
||||||
var statsJson container.ApiStats
|
var res container.ApiStats
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&statsJson); err != nil {
|
if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {
|
||||||
return cStats, err
|
return curStats, err
|
||||||
}
|
}
|
||||||
|
|
||||||
name := ctr.Names[0][1:]
|
name := ctr.Names[0][1:]
|
||||||
|
|
||||||
// check if container has valid data, otherwise may be in restart loop (#103)
|
// check if container has valid data, otherwise may be in restart loop (#103)
|
||||||
if statsJson.MemoryStats.Usage == 0 {
|
if res.MemoryStats.Usage == 0 {
|
||||||
return cStats, fmt.Errorf("%s - no memory stats - see https://github.com/henrygd/beszel/issues/144", name)
|
return curStats, fmt.Errorf("%s - no memory stats - see https://github.com/henrygd/beszel/issues/144", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// memory (https://docs.docker.com/reference/cli/docker/container/stats/)
|
// memory (https://docs.docker.com/reference/cli/docker/container/stats/)
|
||||||
memCache := statsJson.MemoryStats.Stats["inactive_file"]
|
memCache := res.MemoryStats.Stats["inactive_file"]
|
||||||
if memCache == 0 {
|
if memCache == 0 {
|
||||||
memCache = statsJson.MemoryStats.Stats["cache"]
|
memCache = res.MemoryStats.Stats["cache"]
|
||||||
}
|
}
|
||||||
usedMemory := statsJson.MemoryStats.Usage - memCache
|
usedMemory := res.MemoryStats.Usage - memCache
|
||||||
|
|
||||||
a.containerStatsMutex.Lock()
|
a.prevContainerStatsMutex.Lock()
|
||||||
defer a.containerStatsMutex.Unlock()
|
defer a.prevContainerStatsMutex.Unlock()
|
||||||
|
|
||||||
// add empty values if they doesn't exist in map
|
// add empty values if they doesn't exist in map
|
||||||
stats, initialized := a.containerStatsMap[ctr.IdShort]
|
prevStats, initialized := a.prevContainerStatsMap[ctr.IdShort]
|
||||||
if !initialized {
|
if !initialized {
|
||||||
stats = &container.PrevContainerStats{}
|
prevStats = &container.PrevContainerStats{}
|
||||||
a.containerStatsMap[ctr.IdShort] = stats
|
a.prevContainerStatsMap[ctr.IdShort] = prevStats
|
||||||
}
|
}
|
||||||
|
|
||||||
// cpu
|
// cpu
|
||||||
cpuDelta := statsJson.CPUStats.CPUUsage.TotalUsage - stats.Cpu[0]
|
cpuDelta := res.CPUStats.CPUUsage.TotalUsage - prevStats.Cpu[0]
|
||||||
systemDelta := statsJson.CPUStats.SystemUsage - stats.Cpu[1]
|
systemDelta := res.CPUStats.SystemUsage - prevStats.Cpu[1]
|
||||||
cpuPct := float64(cpuDelta) / float64(systemDelta) * 100
|
cpuPct := float64(cpuDelta) / float64(systemDelta) * 100
|
||||||
if cpuPct > 100 {
|
if cpuPct > 100 {
|
||||||
return cStats, fmt.Errorf("%s cpu pct greater than 100: %+v", name, cpuPct)
|
return curStats, fmt.Errorf("%s cpu pct greater than 100: %+v", name, cpuPct)
|
||||||
}
|
}
|
||||||
stats.Cpu = [2]uint64{statsJson.CPUStats.CPUUsage.TotalUsage, statsJson.CPUStats.SystemUsage}
|
prevStats.Cpu = [2]uint64{res.CPUStats.CPUUsage.TotalUsage, res.CPUStats.SystemUsage}
|
||||||
|
|
||||||
// network
|
// network
|
||||||
var total_sent, total_recv uint64
|
var total_sent, total_recv uint64
|
||||||
for _, v := range statsJson.Networks {
|
for _, v := range res.Networks {
|
||||||
total_sent += v.TxBytes
|
total_sent += v.TxBytes
|
||||||
total_recv += v.RxBytes
|
total_recv += v.RxBytes
|
||||||
}
|
}
|
||||||
var sent_delta, recv_delta float64
|
var sent_delta, recv_delta float64
|
||||||
// prevent first run from sending all prev sent/recv bytes
|
// prevent first run from sending all prev sent/recv bytes
|
||||||
if initialized {
|
if initialized {
|
||||||
secondsElapsed := time.Since(stats.Net.Time).Seconds()
|
secondsElapsed := time.Since(prevStats.Net.Time).Seconds()
|
||||||
sent_delta = float64(total_sent-stats.Net.Sent) / secondsElapsed
|
sent_delta = float64(total_sent-prevStats.Net.Sent) / secondsElapsed
|
||||||
recv_delta = float64(total_recv-stats.Net.Recv) / secondsElapsed
|
recv_delta = float64(total_recv-prevStats.Net.Recv) / secondsElapsed
|
||||||
}
|
}
|
||||||
stats.Net.Sent = total_sent
|
prevStats.Net.Sent = total_sent
|
||||||
stats.Net.Recv = total_recv
|
prevStats.Net.Recv = total_recv
|
||||||
stats.Net.Time = time.Now()
|
prevStats.Net.Time = time.Now()
|
||||||
|
|
||||||
cStats.Name = name
|
curStats.Name = name
|
||||||
cStats.Cpu = twoDecimals(cpuPct)
|
curStats.Cpu = twoDecimals(cpuPct)
|
||||||
cStats.Mem = bytesToMegabytes(float64(usedMemory))
|
curStats.Mem = bytesToMegabytes(float64(usedMemory))
|
||||||
cStats.NetworkSent = bytesToMegabytes(sent_delta)
|
curStats.NetworkSent = bytesToMegabytes(sent_delta)
|
||||||
cStats.NetworkRecv = bytesToMegabytes(recv_delta)
|
curStats.NetworkRecv = bytesToMegabytes(recv_delta)
|
||||||
|
|
||||||
return cStats, nil
|
return curStats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) gatherStats() system.CombinedData {
|
func (a *Agent) gatherStats() system.CombinedData {
|
||||||
|
@@ -12,9 +12,9 @@ func (a *Agent) releaseSemaphore() {
|
|||||||
|
|
||||||
// delete container stats from map using mutex
|
// delete container stats from map using mutex
|
||||||
func (a *Agent) deleteContainerStatsSync(id string) {
|
func (a *Agent) deleteContainerStatsSync(id string) {
|
||||||
a.containerStatsMutex.Lock()
|
a.prevContainerStatsMutex.Lock()
|
||||||
defer a.containerStatsMutex.Unlock()
|
defer a.prevContainerStatsMutex.Unlock()
|
||||||
delete(a.containerStatsMap, id)
|
delete(a.prevContainerStatsMap, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func bytesToMegabytes(b float64) float64 {
|
func bytesToMegabytes(b float64) float64 {
|
||||||
|
Reference in New Issue
Block a user