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