101 lines
2.1 KiB
Go
101 lines
2.1 KiB
Go
package agent
|
|
|
|
import (
|
|
"log"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/shirou/gopsutil/v3/cpu"
|
|
"github.com/shirou/gopsutil/v3/mem"
|
|
"github.com/shirou/gopsutil/v3/net"
|
|
)
|
|
|
|
type Metrics struct {
|
|
CPU float64
|
|
Memory float64
|
|
Bandwidth float64
|
|
NetworkIn float64
|
|
NetworkOut float64
|
|
ActiveConns int
|
|
HlsReaders int
|
|
ViewerCount int
|
|
FrameDrops int
|
|
PacketLoss int
|
|
MediaAvailable bool
|
|
}
|
|
|
|
type Monitor struct {
|
|
mu sync.RWMutex
|
|
current Metrics
|
|
prevNetIn uint64
|
|
prevNetOut uint64
|
|
prevNetTime time.Time
|
|
}
|
|
|
|
func NewMonitor() *Monitor {
|
|
return &Monitor{}
|
|
}
|
|
|
|
func (m *Monitor) Tick() {
|
|
metrics := Metrics{}
|
|
|
|
if pct, err := cpu.Percent(0, false); err == nil && len(pct) > 0 {
|
|
metrics.CPU = pct[0]
|
|
}
|
|
|
|
if v, err := mem.VirtualMemory(); err == nil {
|
|
metrics.Memory = v.UsedPercent
|
|
}
|
|
|
|
ioCounters, err := net.IOCounters(false)
|
|
if err == nil && len(ioCounters) > 0 {
|
|
now := time.Now()
|
|
curIn := ioCounters[0].BytesRecv
|
|
curOut := ioCounters[0].BytesSent
|
|
|
|
if m.prevNetTime.IsZero() {
|
|
m.prevNetIn = curIn
|
|
m.prevNetOut = curOut
|
|
m.prevNetTime = now
|
|
} else {
|
|
elapsed := now.Sub(m.prevNetTime).Seconds()
|
|
if elapsed > 0 {
|
|
metrics.NetworkIn = float64(curIn-m.prevNetIn) * 8 / elapsed / 1e6
|
|
metrics.NetworkOut = float64(curOut-m.prevNetOut) * 8 / elapsed / 1e6
|
|
metrics.Bandwidth = metrics.NetworkIn + metrics.NetworkOut
|
|
}
|
|
m.prevNetIn = curIn
|
|
m.prevNetOut = curOut
|
|
m.prevNetTime = now
|
|
}
|
|
}
|
|
|
|
conns, _ := net.Connections("tcp")
|
|
metrics.ActiveConns = len(conns)
|
|
|
|
metrics.HlsReaders = 0
|
|
|
|
m.mu.Lock()
|
|
m.current = metrics
|
|
m.mu.Unlock()
|
|
|
|
log.Printf("Metrics: CPU=%.1f%% MEM=%.1f%% BW=%.1fMbps CONN=%d",
|
|
metrics.CPU, metrics.Memory, metrics.Bandwidth, metrics.ActiveConns)
|
|
}
|
|
|
|
func (m *Monitor) Snapshot() Metrics {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
return m.current
|
|
}
|
|
|
|
func (m *Monitor) SetMediaMetrics(media MediaMetrics) {
|
|
m.mu.Lock()
|
|
m.current.ViewerCount = media.ViewerCount
|
|
m.current.HlsReaders = media.ViewerCount
|
|
m.current.FrameDrops = media.FrameDrops
|
|
m.current.PacketLoss = media.PacketLoss
|
|
m.current.MediaAvailable = media.Available
|
|
m.mu.Unlock()
|
|
}
|