forked from cloudfoundry/gosigar
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpdh_windows.go
154 lines (135 loc) · 4.63 KB
/
pdh_windows.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package sigar
/* These are convenience methods for extracting metrics from the Windows
Performance Data Helper (PDH) library */
import (
"fmt"
"github.com/scalingdata/win"
)
// An error encountered calling PDH
type PdhError struct {
errno uint32
method string
}
func (self *PdhError) Error() string {
return fmt.Sprintf("Error calling %v (%v): %v", self.method, self.errno, win.PdhFormatError(self.errno))
}
func NewPdhError(method string, errno uint32) *PdhError {
return &PdhError{
errno: errno,
method: method,
}
}
// An error encountered working with a specific PDH counter
type PdhCounterError struct {
errno uint32
method string
query string
}
func NewPdhCounterError(method, query string, errno uint32) *PdhCounterError {
return &PdhCounterError{
errno: errno,
method: method,
query: query,
}
}
func (self *PdhCounterError) Error() string {
return fmt.Sprintf("Error calling %v on counter %v (%v): %v", self.method, self.query, self.errno, win.PdhFormatError(self.errno))
}
/* Run the set of provided queries once and report back the raw counter values for each.
Queries must have a wildcard, like `\Processor(*)\% idle time`. Returns a map of
wildcard values to arrays of results. The indices in the array match up with the
index of the query in `queries`. */
func runRawPdhArrayQueries(queries []string) (map[string][]uint64, error) {
var query win.PDH_HQUERY
counters := make([]win.PDH_HCOUNTER, len(queries))
results := make(map[string][]uint64, len(queries))
// Open a new query
err := win.PdhOpenQuery(0, 0, &query)
if err != 0 {
return nil, NewPdhError("PdhOpenQuery", err)
}
// Add all of the counters. If any fail, give up.
for i := 0; i < len(queries); i++ {
err = win.PdhAddEnglishCounter(query, queries[i], 0, &counters[i])
if err != 0 {
win.PdhCloseQuery(query)
return nil, NewPdhCounterError("PdhAddEnglishCounter", queries[i], err)
}
}
// Collect query data only once. For raw counters this will give us a value at a point in time
err = win.PdhCollectQueryData(query)
if err != 0 {
win.PdhCloseQuery(query)
return nil, NewPdhError("PdhCollectQueryData", err)
}
// For each query PDH will hand back an array of key-value pairs
for i := 0; i < len(queries); i++ {
bufSize := uint32(0)
items := uint32(0)
// Get the size for the raw data buffer
err = win.PdhGetRawCounterArray(counters[i], &bufSize, &items, nil)
if err != win.PDH_MORE_DATA {
win.PdhCloseQuery(query)
return nil, NewPdhCounterError("PdhGetRawCounterArray", queries[i], err)
}
buffer := make([]byte, bufSize)
err = win.PdhGetRawCounterArray(counters[i], &bufSize, &items, &buffer[0])
if err != 0 {
win.PdhCloseQuery(query)
return nil, NewPdhCounterError("PdhGetRawCounterArray", queries[i], err)
}
counters := win.PdhConvertRawCounterArray(items, buffer)
for _, item := range counters {
keyString := win.UTF16PtrToString(item.SzName)
results[keyString] = append(results[keyString], uint64(item.RawValue.FirstValue))
}
}
err = win.PdhCloseQuery(query)
if err != 0 {
return nil, NewPdhError("PdhCloseQuery", err)
}
return results, nil
}
/* Run the set of provided queries once and report back the raw counter values for each.
Queries cannot have a wildcard. Returns an array of results, where the indices in the array
match up with the index of the query in `queries`. */
func runRawPdhQueries(queries []string) ([]uint64, error) {
var query win.PDH_HQUERY
counters := make([]win.PDH_HCOUNTER, len(queries))
results := make([]uint64, 0)
// Open a new query
err := win.PdhOpenQuery(0, 0, &query)
if err != 0 {
return nil, NewPdhError("PdhOpenQuery", err)
}
// Add all the counters, give up if any fail
for i := 0; i < len(queries); i++ {
err = win.PdhAddEnglishCounter(query, queries[i], 0, &counters[i])
if err != 0 {
win.PdhCloseQuery(query)
return nil, NewPdhCounterError("PdhAddEnglishCounter", queries[i], err)
}
}
// Collect query data at a single point in time. This is sufficient for raw counters.
err = win.PdhCollectQueryData(query)
if err != 0 {
win.PdhCloseQuery(query)
return nil, NewPdhError("PdhCollectQueryData", err)
}
// Each query should return a single struct with a 64-bit int value
for i := 0; i < len(queries); i++ {
counterType := uint32(0)
var counter win.PDH_RAW_COUNTER
err = win.PdhGetRawCounterValue(counters[i], &counterType, &counter)
if err != 0 {
win.PdhCloseQuery(query)
return nil, NewPdhCounterError("PdhGetRawCounterValue", queries[i], err)
}
results = append(results, uint64(counter.FirstValue))
}
err = win.PdhCloseQuery(query)
if err != 0 {
return nil, NewPdhError("PdhCloseQuery", err)
}
return results, nil
}