func (f *CPUFingerprint) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) { if err := stats.Init(); err != nil { return false, fmt.Errorf("Unable to obtain CPU information: %v", err) } modelName := stats.CPUModelName() if modelName != "" { node.Attributes["cpu.modelname"] = modelName } mhz := stats.CPUMHzPerCore() node.Attributes["cpu.frequency"] = fmt.Sprintf("%.0f", mhz) f.logger.Printf("[DEBUG] fingerprint.cpu: frequency: %.0f MHz", mhz) numCores := stats.CPUNumCores() node.Attributes["cpu.numcores"] = fmt.Sprintf("%d", numCores) f.logger.Printf("[DEBUG] fingerprint.cpu: core count: %d", numCores) tt := stats.TotalTicksAvailable() node.Attributes["cpu.totalcompute"] = fmt.Sprintf("%.0f", tt) if node.Resources == nil { node.Resources = &structs.Resources{} } node.Resources.CPU = int(tt) return true, nil }
// Collect collects stats related to resource usage of a host func (h *HostStatsCollector) Collect() (*HostStats, error) { hs := &HostStats{Timestamp: time.Now().UTC().UnixNano()} if memStats, err := mem.VirtualMemory(); err == nil { ms := &MemoryStats{ Total: memStats.Total, Available: memStats.Available, Used: memStats.Used, Free: memStats.Free, } hs.Memory = ms } ticksConsumed := 0.0 if cpuStats, err := cpu.Times(true); err == nil { cs := make([]*CPUStats, len(cpuStats)) for idx, cpuStat := range cpuStats { percentCalculator, ok := h.statsCalculator[cpuStat.CPU] if !ok { percentCalculator = NewHostCpuStatsCalculator() h.statsCalculator[cpuStat.CPU] = percentCalculator } idle, user, system, total := percentCalculator.Calculate(cpuStat) cs[idx] = &CPUStats{ CPU: cpuStat.CPU, User: user, System: system, Idle: idle, Total: total, } ticksConsumed += (total / 100) * (shelpers.TotalTicksAvailable() / float64(len(cpuStats))) } hs.CPU = cs hs.CPUTicksConsumed = ticksConsumed } if partitions, err := disk.Partitions(false); err == nil { var diskStats []*DiskStats for _, partition := range partitions { if usage, err := disk.Usage(partition.Mountpoint); err == nil { ds := DiskStats{ Device: partition.Device, Mountpoint: partition.Mountpoint, Size: usage.Total, Used: usage.Used, Available: usage.Free, UsedPercent: usage.UsedPercent, InodesUsedPercent: usage.InodesUsedPercent, } diskStats = append(diskStats, &ds) } } hs.DiskStats = diskStats } if uptime, err := host.Uptime(); err == nil { hs.Uptime = uptime } return hs, nil }
// collectStats starts collecting resource usage stats of a docker container func (h *DockerHandle) collectStats() { statsCh := make(chan *docker.Stats) statsOpts := docker.StatsOptions{ID: h.containerID, Done: h.doneCh, Stats: statsCh, Stream: true} go func() { //TODO handle Stats error if err := h.waitClient.Stats(statsOpts); err != nil { h.logger.Printf("[DEBUG] driver.docker: error collecting stats from container %s: %v", h.containerID, err) } }() numCores := runtime.NumCPU() for { select { case s := <-statsCh: if s != nil { ms := &cstructs.MemoryStats{ RSS: s.MemoryStats.Stats.Rss, Cache: s.MemoryStats.Stats.Cache, Swap: s.MemoryStats.Stats.Swap, MaxUsage: s.MemoryStats.MaxUsage, Measured: DockerMeasuredMemStats, } cs := &cstructs.CpuStats{ ThrottledPeriods: s.CPUStats.ThrottlingData.ThrottledPeriods, ThrottledTime: s.CPUStats.ThrottlingData.ThrottledTime, Measured: DockerMeasuredCpuStats, } // Calculate percentage cores := len(s.CPUStats.CPUUsage.PercpuUsage) cs.Percent = calculatePercent( s.CPUStats.CPUUsage.TotalUsage, s.PreCPUStats.CPUUsage.TotalUsage, s.CPUStats.SystemCPUUsage, s.PreCPUStats.SystemCPUUsage, cores) cs.SystemMode = calculatePercent( s.CPUStats.CPUUsage.UsageInKernelmode, s.PreCPUStats.CPUUsage.UsageInKernelmode, s.CPUStats.CPUUsage.TotalUsage, s.PreCPUStats.CPUUsage.TotalUsage, cores) cs.UserMode = calculatePercent( s.CPUStats.CPUUsage.UsageInUsermode, s.PreCPUStats.CPUUsage.UsageInUsermode, s.CPUStats.CPUUsage.TotalUsage, s.PreCPUStats.CPUUsage.TotalUsage, cores) cs.TotalTicks = (cs.Percent / 100) * shelpers.TotalTicksAvailable() / float64(numCores) h.resourceUsageLock.Lock() h.resourceUsage = &cstructs.TaskResourceUsage{ ResourceUsage: &cstructs.ResourceUsage{ MemoryStats: ms, CpuStats: cs, }, Timestamp: s.Read.UTC().UnixNano(), } h.resourceUsageLock.Unlock() } case <-h.doneCh: return } } }
// TicksConsumed calculates the total ticks consumes by the process across all // cpu cores func (c *CpuStats) TicksConsumed(percent float64) float64 { return (percent / 100) * shelpers.TotalTicksAvailable() / float64(c.totalCpus) }
// Collect collects stats related to resource usage of a host func (h *HostStatsCollector) Collect() (*HostStats, error) { hs := &HostStats{Timestamp: time.Now().UTC().UnixNano()} memStats, err := mem.VirtualMemory() if err != nil { return nil, err } hs.Memory = &MemoryStats{ Total: memStats.Total, Available: memStats.Available, Used: memStats.Used, Free: memStats.Free, } ticksConsumed := 0.0 cpuStats, err := cpu.Times(true) if err != nil { return nil, err } cs := make([]*CPUStats, len(cpuStats)) for idx, cpuStat := range cpuStats { percentCalculator, ok := h.statsCalculator[cpuStat.CPU] if !ok { percentCalculator = NewHostCpuStatsCalculator() h.statsCalculator[cpuStat.CPU] = percentCalculator } idle, user, system, total := percentCalculator.Calculate(cpuStat) cs[idx] = &CPUStats{ CPU: cpuStat.CPU, User: user, System: system, Idle: idle, Total: total, } ticksConsumed += (total / 100) * (shelpers.TotalTicksAvailable() / float64(len(cpuStats))) } hs.CPU = cs hs.CPUTicksConsumed = ticksConsumed partitions, err := disk.Partitions(false) if err != nil { return nil, err } var diskStats []*DiskStats for _, partition := range partitions { usage, err := disk.Usage(partition.Mountpoint) if err != nil { h.logger.Printf("[WARN] client: error fetching host disk usage stats for %v: %v", partition.Mountpoint, err) continue } ds := DiskStats{ Device: partition.Device, Mountpoint: partition.Mountpoint, Size: usage.Total, Used: usage.Used, Available: usage.Free, UsedPercent: usage.UsedPercent, InodesUsedPercent: usage.InodesUsedPercent, } if math.IsNaN(ds.UsedPercent) { ds.UsedPercent = 0.0 } if math.IsNaN(ds.InodesUsedPercent) { ds.InodesUsedPercent = 0.0 } diskStats = append(diskStats, &ds) } hs.DiskStats = diskStats uptime, err := host.Uptime() if err != nil { return nil, err } hs.Uptime = uptime return hs, nil }