예제 #1
0
// Collect reads cpu.stat for cgroups and per process cpu.stat
// entries for all processes in the cgroup
func (s *PerCgroupStat) Collect() {
	file, err := os.Open(s.path + "/" + "cpu.stat")
	defer file.Close()
	if err != nil {
		return
	}

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		f := regexp.MustCompile("\\s+").Split(scanner.Text(), 2)

		if f[0] == "nr_periods" {
			s.NrPeriods.Set(misc.ParseUint(f[1]))
		}

		if f[0] == "nr_throttled" {
			s.NrThrottled.Set(misc.ParseUint(f[1]))
		}

		if f[0] == "throttled_time" {
			s.ThrottledTime.Set(misc.ParseUint(f[1]))
		}
	}

	s.CfsPeriodUs.Set(
		float64(misc.ReadUintFromFile(
			s.path + "/" + "cpu.cfs_period_us")))
	// negative values of quota indicate no quota.
	// it is not possible for this variable to be zero
	s.CfsQuotaUs.Set(
		float64(misc.ReadUintFromFile(
			s.path + "/" + "cpu.cfs_quota_us")))

	// Calculate approximate cumulative CPU usage for all
	// processes within this cgroup by calculating difference
	// between sum number of ticks.
	// We reset between loops because PIDs within cgroup can
	// change and sum-counter from previous run can be
	// unreliable
	s.getCgroupCPUTimes()
	time.Sleep(time.Millisecond * 1000)
	s.getCgroupCPUTimes()
	// Expose summary metrics for easy json access
	s.UsageCount.Set(s.usage())
	s.UserspaceCount.Set(s.userspace())
	s.KernelCount.Set(s.kernel())
	s.TotalCount.Set(s.Quota())
	s.ThrottleCount.Set(s.Throttle())
	// Reset counters
	s.Utime.Reset()
	s.Stime.Reset()
}
예제 #2
0
// Collect reads memory.stat and uses reflection to populate PerCgroupStat
func (s *PerCgroupStat) Collect() {
	file, err := os.Open(s.path + "/" + "memory.stat")
	if err != nil {
		fmt.Println(err)
		return
	}

	d := map[string]*metrics.Gauge{}
	// Get all fields we care about
	r := reflect.ValueOf(s).Elem()
	typeOfT := r.Type()
	for i := 0; i < r.NumField(); i++ {
		f := r.Field(i)
		if f.Kind().String() == "ptr" && f.Type().Elem() == reflect.TypeOf(metrics.Gauge{}) {
			d[strings.ToLower(typeOfT.Field(i).Name)] =
				f.Interface().(*metrics.Gauge)
		}
	}

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		f := regexp.MustCompile("[\\s]+").Split(scanner.Text(), 2)
		g, ok := d[strings.ToLower(f[0])]
		if ok {
			parseCgroupMemLine(g, f)
		}
	}

	s.Soft_Limit_In_Bytes.Set(
		float64(misc.ReadUintFromFile(
			s.path + "/" + "memory.soft_limit_in_bytes")))

	s.UsageInBytes.Set(s.Usage())
}
예제 #3
0
// Collect reads /proc/net/dev to gather statistics for interfaces.
// Collect reads /sysfs to figure out interface capabilities.
// Collect is generally called directly when the package is initialized.
func (s *InterfaceStat) Collect() {
	file, err := os.Open(root + "proc/net/dev")
	defer file.Close()
	if err != nil {
		return
	}

	var rx [8]uint64
	var tx [8]uint64

	scanner := bufio.NewScanner(file)
	scanner.Scan()
	for scanner.Scan() {
		f := strings.Split(scanner.Text(), ":")
		if len(f) < 2 {
			continue
		}
		dev := strings.TrimSpace(f[0])
		rest := f[1]
		fmt.Sscanf(rest,
			"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
			&rx[0], &rx[1], &rx[2], &rx[3], &rx[4], &rx[5], &rx[6], &rx[7],
			&tx[0], &tx[1], &tx[2], &tx[3], &tx[4], &tx[5], &tx[6], &tx[7])

		o, ok := s.Interfaces[dev]
		if !ok {
			o = NewPerInterfaceStat(s.m, dev)
			s.Interfaces[dev] = o
		}

		d := o.Metrics
		d.RXbytes.Set(rx[0])
		d.RXpackets.Set(rx[1])
		d.RXerrs.Set(rx[2])
		d.RXdrop.Set(rx[3])
		d.RXfifo.Set(rx[4])
		d.RXframe.Set(rx[5])
		d.RXcompressed.Set(rx[6])
		d.RXmulticast.Set(rx[7])
		d.TXbytes.Set(tx[0])
		d.TXpackets.Set(tx[1])
		d.TXerrs.Set(tx[2])
		d.TXdrop.Set(tx[3])
		d.TXfifo.Set(tx[4])
		d.TXframe.Set(tx[5])
		d.TXcompressed.Set(tx[6])
		d.TXmulticast.Set(tx[7])
		speed := misc.ReadUintFromFile(root + "sys/class/net/" + dev + "/speed")
		if speed > 0 {
			d.Speed.Set(float64(speed))
		}
	}
}
예제 #4
0
// Collect walks through /proc/diskstats and updates relevant metrics
func (s *DiskStat) Collect() {
	file, err := os.Open(root + "proc/diskstats")
	defer file.Close()
	if err != nil {
		return
	}
	var blkdev string
	var major, minor uint64
	var f [11]uint64
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		fmt.Sscanf(scanner.Text(),
			"%d %d %s %d %d %d %d %d %d %d %d %d %d %d",
			&major, &minor, &blkdev, &f[0], &f[1], &f[2], &f[3],
			&f[4], &f[5], &f[6], &f[7], &f[8], &f[9], &f[10])
		// skip loop/ram/dm drives
		if major == 1 || major == 7 || major == 253 {
			continue
		}
		// skip collecting for individual partitions
		_, ok := s.blkdevs[blkdev]
		if !ok {
			continue
		}
		o, ok := s.Disks[blkdev]
		if !ok {
			o = NewPerDiskStat(s.m, blkdev)
			s.Disks[blkdev] = o
		}
		sectorSize := misc.ReadUintFromFile(root + "sys/block/" + blkdev + "/queue/hw_sector_size")
		o.ReadCompleted.Set(f[0])
		o.ReadMerged.Set(f[1])
		o.ReadSectors.Set(f[2])
		o.ReadSpentMsecs.Set(f[3])
		o.WriteCompleted.Set(f[4])
		o.WriteMerged.Set(f[5])
		o.WriteSectors.Set(f[6])
		o.WriteSpentMsecs.Set(f[7])
		o.IOInProgress.Set(float64(f[8]))
		o.IOSpentMsecs.Set(f[9])
		o.WeightedIOSpentMsecs.Set(f[10])
		o.SectorSize.Set(float64(sectorSize))
	}
}