81 lines
2.2 KiB
Go
81 lines
2.2 KiB
Go
package health
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
agentpb "git.ipao.vip/rogee/go-sip/gen/agent"
|
|
"github.com/shirou/gopsutil/v4/cpu"
|
|
"github.com/shirou/gopsutil/v4/disk"
|
|
"github.com/shirou/gopsutil/v4/mem"
|
|
"github.com/shirou/gopsutil/v4/process"
|
|
)
|
|
|
|
// Sampler uses gopsutil for host/process observations. Unsupported or
|
|
// unconfigured dimensions stay explicitly unknown instead of being reported as
|
|
// zero capacity.
|
|
type Sampler struct {
|
|
Now func() time.Time
|
|
}
|
|
|
|
func (s Sampler) Sample(ctx context.Context, spoolRoot string) *agentpb.ResourceSample {
|
|
now := time.Now
|
|
if s.Now != nil {
|
|
now = s.Now
|
|
}
|
|
sample := &agentpb.ResourceSample{
|
|
ObservedAtUnixMs: now().UnixMilli(),
|
|
SampleFresh: true,
|
|
}
|
|
var missing []string
|
|
|
|
if values, err := cpu.PercentWithContext(ctx, 0, false); err != nil || len(values) == 0 {
|
|
missing = append(missing, "cpu")
|
|
} else {
|
|
sample.CpuUsedRatio = values[0] / 100
|
|
}
|
|
if value, err := mem.VirtualMemoryWithContext(ctx); err != nil {
|
|
missing = append(missing, "memory")
|
|
} else {
|
|
sample.MemoryAvailableBytes = int64(value.Available)
|
|
}
|
|
if spoolRoot == "" {
|
|
missing = append(missing, "spool")
|
|
} else if value, err := disk.UsageWithContext(ctx, spoolRoot); err != nil {
|
|
missing = append(missing, "spool")
|
|
} else {
|
|
sample.SpoolUsedBytes = int64(value.Used)
|
|
sample.SpoolCapacityBytes = int64(value.Total)
|
|
}
|
|
proc, err := process.NewProcess(int32(os.Getpid()))
|
|
if err != nil {
|
|
missing = append(missing, "fd")
|
|
} else if limits, limitErr := proc.RlimitUsageWithContext(ctx, true); limitErr != nil {
|
|
missing = append(missing, "fd")
|
|
} else {
|
|
found := false
|
|
for _, limit := range limits {
|
|
if limit.Resource == process.RLIMIT_NOFILE {
|
|
sample.FdUsed = int64(limit.Used)
|
|
sample.FdLimit = int64(limit.Soft)
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
missing = append(missing, "fd")
|
|
}
|
|
}
|
|
|
|
// Media-port and AI-provider quotas are owned by the Cell/Dispatcher, not
|
|
// this host sampler. Keep them unknown until those sources are connected.
|
|
missing = append(missing, "media_ports", "ai_quota")
|
|
if len(missing) != 0 {
|
|
sample.SampleFresh = false
|
|
sample.MissingReason = strings.Join(missing, ",")
|
|
}
|
|
return sample
|
|
}
|