Merge pull request #13597 from Luap99/stats
podman stats: calc CPU percentage correctly
This commit is contained in:
		
						commit
						7371306280
					
				| 
						 | 
				
			
			@ -138,7 +138,6 @@ type ContainerStats struct {
 | 
			
		|||
	CPU           float64
 | 
			
		||||
	CPUNano       uint64
 | 
			
		||||
	CPUSystemNano uint64
 | 
			
		||||
	DataPoints    int64
 | 
			
		||||
	SystemNano    uint64
 | 
			
		||||
	MemUsage      uint64
 | 
			
		||||
	MemLimit      uint64
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -422,10 +422,6 @@ type PodContainerStats struct {
 | 
			
		|||
 | 
			
		||||
// GetPodStats returns the stats for each of its containers
 | 
			
		||||
func (p *Pod) GetPodStats(previousContainerStats map[string]*define.ContainerStats) (map[string]*define.ContainerStats, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		ok       bool
 | 
			
		||||
		prevStat *define.ContainerStats
 | 
			
		||||
	)
 | 
			
		||||
	p.lock.Lock()
 | 
			
		||||
	defer p.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -438,10 +434,7 @@ func (p *Pod) GetPodStats(previousContainerStats map[string]*define.ContainerSta
 | 
			
		|||
	}
 | 
			
		||||
	newContainerStats := make(map[string]*define.ContainerStats)
 | 
			
		||||
	for _, c := range containers {
 | 
			
		||||
		if prevStat, ok = previousContainerStats[c.ID()]; !ok {
 | 
			
		||||
			prevStat = &define.ContainerStats{}
 | 
			
		||||
		}
 | 
			
		||||
		newStats, err := c.GetContainerStats(prevStat)
 | 
			
		||||
		newStats, err := c.GetContainerStats(previousContainerStats[c.ID()])
 | 
			
		||||
		// If the container wasn't running, don't include it
 | 
			
		||||
		// but also suppress the error
 | 
			
		||||
		if err != nil && errors.Cause(err) != define.ErrCtrStateInvalid {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,9 @@ import (
 | 
			
		|||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetContainerStats gets the running stats for a given container
 | 
			
		||||
// GetContainerStats gets the running stats for a given container.
 | 
			
		||||
// The previousStats is used to correctly calculate cpu percentages. You
 | 
			
		||||
// should pass nil if there is no previous stat for this container.
 | 
			
		||||
func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*define.ContainerStats, error) {
 | 
			
		||||
	stats := new(define.ContainerStats)
 | 
			
		||||
	stats.ContainerID = c.ID()
 | 
			
		||||
| 
						 | 
				
			
			@ -36,6 +38,14 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de
 | 
			
		|||
		return stats, define.ErrCtrStateInvalid
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if previousStats == nil {
 | 
			
		||||
		previousStats = &define.ContainerStats{
 | 
			
		||||
			// if we have no prev stats use the container start time as prev time
 | 
			
		||||
			// otherwise we cannot correctly calculate the CPU percentage
 | 
			
		||||
			SystemNano: uint64(c.state.StartedTime.UnixNano()),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cgroupPath, err := c.cGroupPath()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
| 
						 | 
				
			
			@ -67,8 +77,8 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de
 | 
			
		|||
	stats.Duration = cgroupStats.CPU.Usage.Total
 | 
			
		||||
	stats.UpTime = time.Duration(stats.Duration)
 | 
			
		||||
	stats.CPU = calculateCPUPercent(cgroupStats, previousCPU, now, previousStats.SystemNano)
 | 
			
		||||
	stats.AvgCPU = calculateAvgCPU(stats.CPU, previousStats.AvgCPU, previousStats.DataPoints)
 | 
			
		||||
	stats.DataPoints = previousStats.DataPoints + 1
 | 
			
		||||
	// calc the average cpu usage for the time the container is running
 | 
			
		||||
	stats.AvgCPU = calculateCPUPercent(cgroupStats, 0, now, uint64(c.state.StartedTime.UnixNano()))
 | 
			
		||||
	stats.MemUsage = cgroupStats.Memory.Usage.Usage
 | 
			
		||||
	stats.MemLimit = c.getMemLimit()
 | 
			
		||||
	stats.MemPerc = (float64(stats.MemUsage) / float64(stats.MemLimit)) * 100
 | 
			
		||||
| 
						 | 
				
			
			@ -146,9 +156,3 @@ func calculateBlockIO(stats *cgroups.Metrics) (read uint64, write uint64) {
 | 
			
		|||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// calculateAvgCPU calculates the avg CPU percentage given the previous average and the number of data points.
 | 
			
		||||
func calculateAvgCPU(statsCPU float64, prevAvg float64, prevData int64) float64 {
 | 
			
		||||
	avgPer := ((prevAvg * float64(prevData)) + statsCPU) / (float64(prevData) + 1)
 | 
			
		||||
	return avgPer
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
 | 
			
		|||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	stats, err := ctnr.GetContainerStats(&define.ContainerStats{})
 | 
			
		||||
	stats, err := ctnr.GetContainerStats(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		utils.InternalServerError(w, errors.Wrapf(err, "failed to obtain Container %s stats", name))
 | 
			
		||||
		return
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1431,12 +1431,7 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri
 | 
			
		|||
 | 
			
		||||
			reportStats := []define.ContainerStats{}
 | 
			
		||||
			for _, ctr := range containers {
 | 
			
		||||
				prev, ok := containerStats[ctr.ID()]
 | 
			
		||||
				if !ok {
 | 
			
		||||
					prev = &define.ContainerStats{}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				stats, err := ctr.GetContainerStats(prev)
 | 
			
		||||
				stats, err := ctr.GetContainerStats(containerStats[ctr.ID()])
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					cause := errors.Cause(err)
 | 
			
		||||
					if queryAll && (cause == define.ErrCtrRemoved || cause == define.ErrNoSuchCtr || cause == define.ErrCtrStateInvalid) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue