1
2
3
4
19
20
21 package winstats
22
23 import (
24 "syscall"
25 "time"
26 "unsafe"
27
28 cadvisorapi "github.com/google/cadvisor/info/v1"
29 cadvisorapiv2 "github.com/google/cadvisor/info/v2"
30 )
31
32 var (
33 procGetDiskFreeSpaceEx = modkernel32.NewProc("GetDiskFreeSpaceExW")
34 )
35
36
37 type Client interface {
38 WinContainerInfos() (map[string]cadvisorapiv2.ContainerInfo, error)
39 WinMachineInfo() (*cadvisorapi.MachineInfo, error)
40 WinVersionInfo() (*cadvisorapi.VersionInfo, error)
41 GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error)
42 }
43
44
45 type StatsClient struct {
46 client winNodeStatsClient
47 }
48
49 type winNodeStatsClient interface {
50 startMonitoring() error
51 getNodeMetrics() (nodeMetrics, error)
52 getNodeInfo() nodeInfo
53 getMachineInfo() (*cadvisorapi.MachineInfo, error)
54 getVersionInfo() (*cadvisorapi.VersionInfo, error)
55 }
56
57 type nodeMetrics struct {
58 cpuUsageCoreNanoSeconds uint64
59 cpuUsageNanoCores uint64
60 memoryPrivWorkingSetBytes uint64
61 memoryCommittedBytes uint64
62 timeStamp time.Time
63 interfaceStats []cadvisorapi.InterfaceStats
64 }
65
66 type nodeInfo struct {
67 memoryPhysicalCapacityBytes uint64
68 kernelVersion string
69 osImageVersion string
70
71 startTime time.Time
72 }
73
74 type cpuUsageCoreNanoSecondsCache struct {
75 latestValue uint64
76 previousValue uint64
77 }
78
79
80 func newClient(statsNodeClient winNodeStatsClient) (Client, error) {
81 statsClient := new(StatsClient)
82 statsClient.client = statsNodeClient
83
84 err := statsClient.client.startMonitoring()
85 if err != nil {
86 return nil, err
87 }
88
89 return statsClient, nil
90 }
91
92
93
94 func (c *StatsClient) WinContainerInfos() (map[string]cadvisorapiv2.ContainerInfo, error) {
95 infos := make(map[string]cadvisorapiv2.ContainerInfo)
96 rootContainerInfo, err := c.createRootContainerInfo()
97 if err != nil {
98 return nil, err
99 }
100
101 infos["/"] = *rootContainerInfo
102
103 return infos, nil
104 }
105
106
107
108 func (c *StatsClient) WinMachineInfo() (*cadvisorapi.MachineInfo, error) {
109 return c.client.getMachineInfo()
110 }
111
112
113
114 func (c *StatsClient) WinVersionInfo() (*cadvisorapi.VersionInfo, error) {
115 return c.client.getVersionInfo()
116 }
117
118 func (c *StatsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, error) {
119 nodeMetrics, err := c.client.getNodeMetrics()
120 if err != nil {
121 return nil, err
122 }
123
124 var stats []*cadvisorapiv2.ContainerStats
125 stats = append(stats, &cadvisorapiv2.ContainerStats{
126 Timestamp: nodeMetrics.timeStamp,
127 Cpu: &cadvisorapi.CpuStats{
128 Usage: cadvisorapi.CpuUsage{
129 Total: nodeMetrics.cpuUsageCoreNanoSeconds,
130 },
131 },
132 CpuInst: &cadvisorapiv2.CpuInstStats{
133 Usage: cadvisorapiv2.CpuInstUsage{
134 Total: nodeMetrics.cpuUsageNanoCores,
135 },
136 },
137 Memory: &cadvisorapi.MemoryStats{
138 WorkingSet: nodeMetrics.memoryPrivWorkingSetBytes,
139 Usage: nodeMetrics.memoryCommittedBytes,
140 },
141 Network: &cadvisorapiv2.NetworkStats{
142 Interfaces: nodeMetrics.interfaceStats,
143 },
144 })
145
146 nodeInfo := c.client.getNodeInfo()
147 rootInfo := cadvisorapiv2.ContainerInfo{
148 Spec: cadvisorapiv2.ContainerSpec{
149 CreationTime: nodeInfo.startTime,
150 HasCpu: true,
151 HasMemory: true,
152 HasNetwork: true,
153 Memory: cadvisorapiv2.MemorySpec{
154 Limit: nodeInfo.memoryPhysicalCapacityBytes,
155 },
156 },
157 Stats: stats,
158 }
159
160 return &rootInfo, nil
161 }
162
163
164 func (c *StatsClient) GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error) {
165 var freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes int64
166 var err error
167
168 ret, _, err := syscall.Syscall6(
169 procGetDiskFreeSpaceEx.Addr(),
170 4,
171 uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
172 uintptr(unsafe.Pointer(&freeBytesAvailable)),
173 uintptr(unsafe.Pointer(&totalNumberOfBytes)),
174 uintptr(unsafe.Pointer(&totalNumberOfFreeBytes)),
175 0,
176 0,
177 )
178 if ret == 0 {
179 return cadvisorapiv2.FsInfo{}, err
180 }
181
182 return cadvisorapiv2.FsInfo{
183 Timestamp: time.Now(),
184 Capacity: uint64(totalNumberOfBytes),
185 Available: uint64(freeBytesAvailable),
186 Usage: uint64(totalNumberOfBytes - freeBytesAvailable),
187 }, nil
188 }
189
View as plain text