winstats.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // +build windows
  2. /*
  3. Copyright 2017 The Kubernetes Authors.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. */
  14. // Package winstats provides a client to get node and pod level stats on windows
  15. package winstats
  16. import (
  17. "syscall"
  18. "time"
  19. "unsafe"
  20. cadvisorapi "github.com/google/cadvisor/info/v1"
  21. cadvisorapiv2 "github.com/google/cadvisor/info/v2"
  22. )
  23. var (
  24. procGetDiskFreeSpaceEx = modkernel32.NewProc("GetDiskFreeSpaceExW")
  25. )
  26. // Client is an interface that is used to get stats information.
  27. type Client interface {
  28. WinContainerInfos() (map[string]cadvisorapiv2.ContainerInfo, error)
  29. WinMachineInfo() (*cadvisorapi.MachineInfo, error)
  30. WinVersionInfo() (*cadvisorapi.VersionInfo, error)
  31. GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error)
  32. }
  33. // StatsClient is a client that implements the Client interface
  34. type StatsClient struct {
  35. client winNodeStatsClient
  36. }
  37. type winNodeStatsClient interface {
  38. startMonitoring() error
  39. getNodeMetrics() (nodeMetrics, error)
  40. getNodeInfo() nodeInfo
  41. getMachineInfo() (*cadvisorapi.MachineInfo, error)
  42. getVersionInfo() (*cadvisorapi.VersionInfo, error)
  43. }
  44. type nodeMetrics struct {
  45. cpuUsageCoreNanoSeconds uint64
  46. cpuUsageNanoCores uint64
  47. memoryPrivWorkingSetBytes uint64
  48. memoryCommittedBytes uint64
  49. timeStamp time.Time
  50. interfaceStats []cadvisorapi.InterfaceStats
  51. }
  52. type nodeInfo struct {
  53. memoryPhysicalCapacityBytes uint64
  54. kernelVersion string
  55. osImageVersion string
  56. // startTime is the time when the node was started
  57. startTime time.Time
  58. }
  59. type cpuUsageCoreNanoSecondsCache struct {
  60. latestValue uint64
  61. previousValue uint64
  62. }
  63. // newClient constructs a Client.
  64. func newClient(statsNodeClient winNodeStatsClient) (Client, error) {
  65. statsClient := new(StatsClient)
  66. statsClient.client = statsNodeClient
  67. err := statsClient.client.startMonitoring()
  68. if err != nil {
  69. return nil, err
  70. }
  71. return statsClient, nil
  72. }
  73. // WinContainerInfos returns a map of container infos. The map contains node and
  74. // pod level stats. Analogous to cadvisor GetContainerInfoV2 method.
  75. func (c *StatsClient) WinContainerInfos() (map[string]cadvisorapiv2.ContainerInfo, error) {
  76. infos := make(map[string]cadvisorapiv2.ContainerInfo)
  77. rootContainerInfo, err := c.createRootContainerInfo()
  78. if err != nil {
  79. return nil, err
  80. }
  81. infos["/"] = *rootContainerInfo
  82. return infos, nil
  83. }
  84. // WinMachineInfo returns a cadvisorapi.MachineInfo with details about the
  85. // node machine. Analogous to cadvisor MachineInfo method.
  86. func (c *StatsClient) WinMachineInfo() (*cadvisorapi.MachineInfo, error) {
  87. return c.client.getMachineInfo()
  88. }
  89. // WinVersionInfo returns a cadvisorapi.VersionInfo with version info of
  90. // the kernel and docker runtime. Analogous to cadvisor VersionInfo method.
  91. func (c *StatsClient) WinVersionInfo() (*cadvisorapi.VersionInfo, error) {
  92. return c.client.getVersionInfo()
  93. }
  94. func (c *StatsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, error) {
  95. nodeMetrics, err := c.client.getNodeMetrics()
  96. if err != nil {
  97. return nil, err
  98. }
  99. var stats []*cadvisorapiv2.ContainerStats
  100. stats = append(stats, &cadvisorapiv2.ContainerStats{
  101. Timestamp: nodeMetrics.timeStamp,
  102. Cpu: &cadvisorapi.CpuStats{
  103. Usage: cadvisorapi.CpuUsage{
  104. Total: nodeMetrics.cpuUsageCoreNanoSeconds,
  105. },
  106. },
  107. CpuInst: &cadvisorapiv2.CpuInstStats{
  108. Usage: cadvisorapiv2.CpuInstUsage{
  109. Total: nodeMetrics.cpuUsageNanoCores,
  110. },
  111. },
  112. Memory: &cadvisorapi.MemoryStats{
  113. WorkingSet: nodeMetrics.memoryPrivWorkingSetBytes,
  114. Usage: nodeMetrics.memoryCommittedBytes,
  115. },
  116. Network: &cadvisorapiv2.NetworkStats{
  117. Interfaces: nodeMetrics.interfaceStats,
  118. },
  119. })
  120. nodeInfo := c.client.getNodeInfo()
  121. rootInfo := cadvisorapiv2.ContainerInfo{
  122. Spec: cadvisorapiv2.ContainerSpec{
  123. CreationTime: nodeInfo.startTime,
  124. HasCpu: true,
  125. HasMemory: true,
  126. HasNetwork: true,
  127. Memory: cadvisorapiv2.MemorySpec{
  128. Limit: nodeInfo.memoryPhysicalCapacityBytes,
  129. },
  130. },
  131. Stats: stats,
  132. }
  133. return &rootInfo, nil
  134. }
  135. // GetDirFsInfo returns filesystem capacity and usage information.
  136. func (c *StatsClient) GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error) {
  137. var freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes int64
  138. var err error
  139. ret, _, err := syscall.Syscall6(
  140. procGetDiskFreeSpaceEx.Addr(),
  141. 4,
  142. uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
  143. uintptr(unsafe.Pointer(&freeBytesAvailable)),
  144. uintptr(unsafe.Pointer(&totalNumberOfBytes)),
  145. uintptr(unsafe.Pointer(&totalNumberOfFreeBytes)),
  146. 0,
  147. 0,
  148. )
  149. if ret == 0 {
  150. return cadvisorapiv2.FsInfo{}, err
  151. }
  152. return cadvisorapiv2.FsInfo{
  153. Timestamp: time.Now(),
  154. Capacity: uint64(totalNumberOfBytes),
  155. Available: uint64(freeBytesAvailable),
  156. Usage: uint64(totalNumberOfBytes - freeBytesAvailable),
  157. }, nil
  158. }