github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/daemon/top_windows.go (about)

     1  package daemon // import "github.com/docker/docker/daemon"
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"time"
     8  
     9  	containertypes "github.com/docker/docker/api/types/container"
    10  	units "github.com/docker/go-units"
    11  )
    12  
    13  // ContainerTop handles `docker top` client requests.
    14  //
    15  // Future considerations:
    16  //   - Windows users are far more familiar with CPU% total.
    17  //     Further, users on Windows rarely see user/kernel CPU stats split.
    18  //     The kernel returns everything in terms of 100ns. To obtain
    19  //     CPU%, we could do something like docker stats does which takes two
    20  //     samples, subtract the difference and do the maths. Unfortunately this
    21  //     would slow the stat call down and require two kernel calls. So instead,
    22  //     we do something similar to linux and display the CPU as combined HH:MM:SS.mmm.
    23  //   - Perhaps we could add an argument to display "raw" stats
    24  //   - "Memory" is an extremely overloaded term in Windows. Hence we do what
    25  //     task manager does and use the private working set as the memory counter.
    26  //     We could return more info for those who really understand how memory
    27  //     management works in Windows if we introduced a "raw" stats (above).
    28  func (daemon *Daemon) ContainerTop(name string, psArgs string) (*containertypes.ContainerTopOKBody, error) {
    29  	// It's not at all an equivalent to linux 'ps' on Windows
    30  	if psArgs != "" {
    31  		return nil, errors.New("Windows does not support arguments to top")
    32  	}
    33  
    34  	container, err := daemon.GetContainer(name)
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  
    39  	if !container.IsRunning() {
    40  		return nil, errNotRunning(container.ID)
    41  	}
    42  
    43  	if container.IsRestarting() {
    44  		return nil, errContainerIsRestarting(container.ID)
    45  	}
    46  
    47  	s, err := daemon.containerd.Summary(context.Background(), container.ID)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	procList := &containertypes.ContainerTopOKBody{}
    52  	procList.Titles = []string{"Name", "PID", "CPU", "Private Working Set"}
    53  
    54  	for _, j := range s {
    55  		d := time.Duration((j.KernelTime_100Ns + j.UserTime_100Ns) * 100) // Combined time in nanoseconds
    56  		procList.Processes = append(procList.Processes, []string{
    57  			j.ImageName,
    58  			fmt.Sprint(j.ProcessID),
    59  			fmt.Sprintf("%02d:%02d:%02d.%03d", int(d.Hours()), int(d.Minutes())%60, int(d.Seconds())%60, int(d.Nanoseconds()/1000000)%1000),
    60  			units.HumanSize(float64(j.MemoryWorkingSetPrivateBytes))})
    61  	}
    62  
    63  	return procList, nil
    64  }