func()

in container/libcontainer/handler.go [75:192]


func (h *Handler) GetStats() (*info.ContainerStats, error) {
	ignoreStatsError := false
	if cgroups.IsCgroup2UnifiedMode() {
		// On cgroup v2 the root cgroup stats have been introduced in recent kernel versions,
		// so not all kernel versions have all the data. This means that stat fetching can fail
		// due to lacking cgroup stat files, but that some data is provided.
		if h.cgroupManager.Path("") == fs2.UnifiedMountpoint {
			ignoreStatsError = true
		}
	}

	cgroupStats, err := h.cgroupManager.GetStats()
	if err != nil {
		if !ignoreStatsError {
			return nil, err
		}
		klog.V(4).Infof("Ignoring errors when gathering stats for root cgroup since some controllers don't have stats on the root cgroup: %v", err)
	}
	libcontainerStats := &libcontainer.Stats{
		CgroupStats: cgroupStats,
	}
	stats := newContainerStats(libcontainerStats, h.includedMetrics)

	if h.includedMetrics.Has(container.ProcessSchedulerMetrics) {
		stats.Cpu.Schedstat, err = h.schedulerStatsFromProcs()
		if err != nil {
			klog.V(4).Infof("Unable to get Process Scheduler Stats: %v", err)
		}
	}

	if h.includedMetrics.Has(container.ReferencedMemoryMetrics) {
		h.cycles++
		pids, err := h.cgroupManager.GetPids()
		if err != nil {
			klog.V(4).Infof("Could not get PIDs for container %d: %v", h.pid, err)
		} else {
			stats.ReferencedMemory, err = referencedBytesStat(pids, h.cycles, *referencedResetInterval)
			if err != nil {
				klog.V(4).Infof("Unable to get referenced bytes: %v", err)
			}
		}
	}

	// If we know the pid then get network stats from /proc/<pid>/net/dev
	if h.pid > 0 {
		if h.includedMetrics.Has(container.NetworkUsageMetrics) {
			netStats, err := networkStatsFromProc(h.rootFs, h.pid)
			if err != nil {
				klog.V(4).Infof("Unable to get network stats from pid %d: %v", h.pid, err)
			} else {
				stats.Network.Interfaces = append(stats.Network.Interfaces, netStats...)
			}
		}
		if h.includedMetrics.Has(container.NetworkTcpUsageMetrics) {
			t, err := tcpStatsFromProc(h.rootFs, h.pid, "net/tcp")
			if err != nil {
				klog.V(4).Infof("Unable to get tcp stats from pid %d: %v", h.pid, err)
			} else {
				stats.Network.Tcp = t
			}

			t6, err := tcpStatsFromProc(h.rootFs, h.pid, "net/tcp6")
			if err != nil {
				klog.V(4).Infof("Unable to get tcp6 stats from pid %d: %v", h.pid, err)
			} else {
				stats.Network.Tcp6 = t6
			}

		}
		if h.includedMetrics.Has(container.NetworkAdvancedTcpUsageMetrics) {
			ta, err := advancedTCPStatsFromProc(h.rootFs, h.pid, "net/netstat", "net/snmp")
			if err != nil {
				klog.V(4).Infof("Unable to get advanced tcp stats from pid %d: %v", h.pid, err)
			} else {
				stats.Network.TcpAdvanced = ta
			}
		}
		if h.includedMetrics.Has(container.NetworkUdpUsageMetrics) {
			u, err := udpStatsFromProc(h.rootFs, h.pid, "net/udp")
			if err != nil {
				klog.V(4).Infof("Unable to get udp stats from pid %d: %v", h.pid, err)
			} else {
				stats.Network.Udp = u
			}

			u6, err := udpStatsFromProc(h.rootFs, h.pid, "net/udp6")
			if err != nil {
				klog.V(4).Infof("Unable to get udp6 stats from pid %d: %v", h.pid, err)
			} else {
				stats.Network.Udp6 = u6
			}
		}
	}
	// some process metrics are per container ( number of processes, number of
	// file descriptors etc.) and not required a proper container's
	// root PID (systemd services don't have the root PID atm)
	if h.includedMetrics.Has(container.ProcessMetrics) {
		path, ok := common.GetControllerPath(h.cgroupManager.GetPaths(), "cpu", cgroups.IsCgroup2UnifiedMode())
		if !ok {
			klog.V(4).Infof("Could not find cgroups CPU for container %d", h.pid)
		} else {
			stats.Processes, err = processStatsFromProcs(h.rootFs, path, h.pid)
			if err != nil {
				klog.V(4).Infof("Unable to get Process Stats: %v", err)
			}
		}

		// if include processes metrics, just set threads metrics if exist, and has no relationship with cpu path
		setThreadsStats(cgroupStats, stats)
	}

	// For backwards compatibility.
	if len(stats.Network.Interfaces) > 0 {
		stats.Network.InterfaceStats = stats.Network.Interfaces[0]
	}

	return stats, nil
}