Commit 1220025e authored by Pengfei Ni's avatar Pengfei Ni

Add network stats for node interfaces

parent 84a7f48c
...@@ -101,8 +101,13 @@ func (p *perfCounterNodeStatsClient) startMonitoring() error { ...@@ -101,8 +101,13 @@ func (p *perfCounterNodeStatsClient) startMonitoring() error {
return err return err
} }
networkAdapterCounter, err := newNetworkCounters()
if err != nil {
return err
}
go wait.Forever(func() { go wait.Forever(func() {
p.collectMetricsData(cpuCounter, memWorkingSetCounter, memCommittedBytesCounter) p.collectMetricsData(cpuCounter, memWorkingSetCounter, memCommittedBytesCounter, networkAdapterCounter)
}, perfCounterUpdatePeriod) }, perfCounterUpdatePeriod)
return nil return nil
...@@ -138,7 +143,7 @@ func (p *perfCounterNodeStatsClient) getNodeInfo() nodeInfo { ...@@ -138,7 +143,7 @@ func (p *perfCounterNodeStatsClient) getNodeInfo() nodeInfo {
return p.nodeInfo return p.nodeInfo
} }
func (p *perfCounterNodeStatsClient) collectMetricsData(cpuCounter, memWorkingSetCounter, memCommittedBytesCounter *perfCounter) { func (p *perfCounterNodeStatsClient) collectMetricsData(cpuCounter, memWorkingSetCounter, memCommittedBytesCounter *perfCounter, networkAdapterCounter *networkCounter) {
cpuValue, err := cpuCounter.getData() cpuValue, err := cpuCounter.getData()
if err != nil { if err != nil {
klog.Errorf("Unable to get cpu perf counter data; err: %v", err) klog.Errorf("Unable to get cpu perf counter data; err: %v", err)
...@@ -157,12 +162,19 @@ func (p *perfCounterNodeStatsClient) collectMetricsData(cpuCounter, memWorkingSe ...@@ -157,12 +162,19 @@ func (p *perfCounterNodeStatsClient) collectMetricsData(cpuCounter, memWorkingSe
return return
} }
networkAdapterStats, err := networkAdapterCounter.getData()
if err != nil {
klog.Errorf("Unable to get network adapter perf counter data; err: %v", err)
return
}
p.mu.Lock() p.mu.Lock()
defer p.mu.Unlock() defer p.mu.Unlock()
p.nodeMetrics = nodeMetrics{ p.nodeMetrics = nodeMetrics{
cpuUsageCoreNanoSeconds: p.convertCPUValue(cpuValue), cpuUsageCoreNanoSeconds: p.convertCPUValue(cpuValue),
memoryPrivWorkingSetBytes: memWorkingSetValue, memoryPrivWorkingSetBytes: memWorkingSetValue,
memoryCommittedBytes: memCommittedBytesValue, memoryCommittedBytes: memCommittedBytesValue,
interfaceStats: networkAdapterStats,
timeStamp: time.Now(), timeStamp: time.Now(),
} }
} }
......
...@@ -71,6 +71,7 @@ func newPerfCounter(counter string) (*perfCounter, error) { ...@@ -71,6 +71,7 @@ func newPerfCounter(counter string) (*perfCounter, error) {
}, nil }, nil
} }
// getData is used for getting data without * in counter name.
func (p *perfCounter) getData() (uint64, error) { func (p *perfCounter) getData() (uint64, error) {
ret := win_pdh.PdhCollectQueryData(p.queryHandle) ret := win_pdh.PdhCollectQueryData(p.queryHandle)
if ret != win_pdh.ERROR_SUCCESS { if ret != win_pdh.ERROR_SUCCESS {
...@@ -100,3 +101,36 @@ func (p *perfCounter) getData() (uint64, error) { ...@@ -100,3 +101,36 @@ func (p *perfCounter) getData() (uint64, error) {
return data, nil return data, nil
} }
// getData is used for getting data with * in counter name.
func (p *perfCounter) getDataList() (map[string]uint64, error) {
ret := win_pdh.PdhCollectQueryData(p.queryHandle)
if ret != win_pdh.ERROR_SUCCESS {
return nil, fmt.Errorf("unable to collect data from counter. Error code is %x", ret)
}
var bufSize, bufCount uint32
var size = uint32(unsafe.Sizeof(win_pdh.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE{}))
var emptyBuf [1]win_pdh.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE // need at least 1 addressable null ptr.
data := map[string]uint64{}
ret = win_pdh.PdhGetFormattedCounterArrayDouble(p.counterHandle, &bufSize, &bufCount, &emptyBuf[0])
if ret != win_pdh.PDH_MORE_DATA {
return nil, fmt.Errorf("unable to collect data from counter. Error code is %x", ret)
}
filledBuf := make([]win_pdh.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE, bufCount*size)
ret = win_pdh.PdhGetFormattedCounterArrayDouble(p.counterHandle, &bufSize, &bufCount, &filledBuf[0])
if ret != win_pdh.ERROR_SUCCESS {
return nil, fmt.Errorf("unable to collect data from counter. Error code is %x", ret)
}
for i := 0; i < int(bufCount); i++ {
c := filledBuf[i]
value := uint64(c.FmtValue.DoubleValue)
name := win_pdh.UTF16PtrToString(c.SzName)
data[name] = value
}
return data, nil
}
...@@ -58,6 +58,7 @@ type nodeMetrics struct { ...@@ -58,6 +58,7 @@ type nodeMetrics struct {
memoryPrivWorkingSetBytes uint64 memoryPrivWorkingSetBytes uint64
memoryCommittedBytes uint64 memoryCommittedBytes uint64
timeStamp time.Time timeStamp time.Time
interfaceStats []cadvisorapi.InterfaceStats
} }
type nodeInfo struct { type nodeInfo struct {
...@@ -109,12 +110,11 @@ func (c *StatsClient) WinVersionInfo() (*cadvisorapi.VersionInfo, error) { ...@@ -109,12 +110,11 @@ func (c *StatsClient) WinVersionInfo() (*cadvisorapi.VersionInfo, error) {
func (c *StatsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, error) { func (c *StatsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, error) {
nodeMetrics, err := c.client.getNodeMetrics() nodeMetrics, err := c.client.getNodeMetrics()
if err != nil { if err != nil {
return nil, err return nil, err
} }
var stats []*cadvisorapiv2.ContainerStats
var stats []*cadvisorapiv2.ContainerStats
stats = append(stats, &cadvisorapiv2.ContainerStats{ stats = append(stats, &cadvisorapiv2.ContainerStats{
Timestamp: nodeMetrics.timeStamp, Timestamp: nodeMetrics.timeStamp,
Cpu: &cadvisorapi.CpuStats{ Cpu: &cadvisorapi.CpuStats{
...@@ -126,6 +126,9 @@ func (c *StatsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, e ...@@ -126,6 +126,9 @@ func (c *StatsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, e
WorkingSet: nodeMetrics.memoryPrivWorkingSetBytes, WorkingSet: nodeMetrics.memoryPrivWorkingSetBytes,
Usage: nodeMetrics.memoryCommittedBytes, Usage: nodeMetrics.memoryCommittedBytes,
}, },
Network: &cadvisorapiv2.NetworkStats{
Interfaces: nodeMetrics.interfaceStats,
},
}) })
nodeInfo := c.client.getNodeInfo() nodeInfo := c.client.getNodeInfo()
...@@ -134,6 +137,7 @@ func (c *StatsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, e ...@@ -134,6 +137,7 @@ func (c *StatsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, e
CreationTime: nodeInfo.startTime, CreationTime: nodeInfo.startTime,
HasCpu: true, HasCpu: true,
HasMemory: true, HasMemory: true,
HasNetwork: true,
Memory: cadvisorapiv2.MemorySpec{ Memory: cadvisorapiv2.MemorySpec{
Limit: nodeInfo.memoryPhysicalCapacityBytes, Limit: nodeInfo.memoryPhysicalCapacityBytes,
}, },
......
...@@ -86,8 +86,9 @@ func TestWinContainerInfos(t *testing.T) { ...@@ -86,8 +86,9 @@ func TestWinContainerInfos(t *testing.T) {
infos := make(map[string]cadvisorapiv2.ContainerInfo) infos := make(map[string]cadvisorapiv2.ContainerInfo)
infos["/"] = cadvisorapiv2.ContainerInfo{ infos["/"] = cadvisorapiv2.ContainerInfo{
Spec: cadvisorapiv2.ContainerSpec{ Spec: cadvisorapiv2.ContainerSpec{
HasCpu: true, HasCpu: true,
HasMemory: true, HasMemory: true,
HasNetwork: true,
Memory: cadvisorapiv2.MemorySpec{ Memory: cadvisorapiv2.MemorySpec{
Limit: 1.6e+10, Limit: 1.6e+10,
}, },
...@@ -95,7 +96,11 @@ func TestWinContainerInfos(t *testing.T) { ...@@ -95,7 +96,11 @@ func TestWinContainerInfos(t *testing.T) {
Stats: stats, Stats: stats,
} }
assert.Equal(t, actualRootInfos, infos) assert.Equal(t, len(actualRootInfos), len(infos))
assert.Equal(t, actualRootInfos["/"].Spec, infos["/"].Spec)
assert.Equal(t, len(actualRootInfos["/"].Stats), len(infos["/"].Stats))
assert.Equal(t, actualRootInfos["/"].Stats[0].Cpu, infos["/"].Stats[0].Cpu)
assert.Equal(t, actualRootInfos["/"].Stats[0].Memory, infos["/"].Stats[0].Memory)
} }
func TestWinMachineInfo(t *testing.T) { func TestWinMachineInfo(t *testing.T) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment