Skip to content

Commit 1763579

Browse files
committed
check_pdh: move windows specifics into separate file
so we can generate the docs on linux as well
1 parent 0f6acd4 commit 1763579

File tree

9 files changed

+215
-198
lines changed

9 files changed

+215
-198
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,7 @@ DOC_COMMANDS=\
698698
check_os_updates \
699699
check_pagefile \
700700
check_ping \
701+
check_pdh \
701702
check_process \
702703
check_snclient_version \
703704
check_tasksched \

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ Further details are covered in the [documentation](https://omd.consol.de/docs/sn
7878
| **check_os_version** | X | X | X | X |
7979
| **check_pagefile** | X | | | |
8080
| **check_ping** | X | X | X | X |
81+
| **check_pdh** | X | | | |
8182
| **check_process** | X | X | X | X |
8283
| **check_service** | X | X | | |
8384
| **check_snclient_version** | X | X | X | X |

docs/checks/commands/check_pdh.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,21 @@ Naemon Config
4545
| Argument | Default Value |
4646
| ------------- | ------------------------------------------------------------------------ |
4747
| empty-state | 3 (UNKNOWN) |
48-
| empty-syntax | No Counter Found |
49-
| top-syntax | %(status) - %(problem_count)/%(count) Counter (%(count)) %(problem_list) |
50-
| ok-syntax | %(status) - All %(count) Counter Values are ok |
48+
| empty-syntax | %(status) - No counter found |
49+
| top-syntax | %(status) - %(problem_count)/%(count) counter (%(count)) %(problem_list) |
50+
| ok-syntax | %(status) - All %(count) counter values are ok |
5151
| detail-syntax | %(name) |
5252

5353
## Check Specific Arguments
5454

5555
| Argument | Description |
5656
| ------------ | ------------------------------------------------------------------------------------------------------ |
57-
| counter | The fully qualified Counter Name |
58-
| english | Using English Names Regardless of system Language requires Windows Vista or higher |
59-
| expand-index | Should Indices be translated? |
60-
| host | The Name Of the Host Mashine in Network where the Counter should be searched, defults to local mashine |
61-
| instances | Expand WildCards And Fethch all instances |
62-
| type | this can be large or float depending what you expect, defualt is large |
57+
| counter | The fully qualified counter name |
58+
| english | Using English names regardless of system language. Requires Windows Vista or higher |
59+
| expand-index | Should indices be translated? |
60+
| host | The name of the host machine in network where the counter should be searched, defaults to local machine |
61+
| instances | Expand wildcards and fetch all instances |
62+
| type | This can be large or float depending what you expect, default is large |
6363

6464
## Attributes
6565

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ require (
1212
github.com/kdar/factorlog v0.0.0-20211012144011-6ea75a169038
1313
github.com/mackerelio/checkers v0.2.0
1414
github.com/miekg/dns v1.1.64
15-
github.com/niemp100/win v0.0.0-20250330143617-fe9e49037e74
1615
github.com/otiai10/copy v1.14.1
1716
github.com/prometheus/client_golang v1.21.1
1817
github.com/reeflective/readline v1.1.2

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@ github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ=
5656
github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck=
5757
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
5858
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
59-
github.com/niemp100/win v0.0.0-20250330143617-fe9e49037e74 h1:vJGm+t1uT0KbAWPTedWHymBMdVUgyRlvDX2iBW2D0aU=
60-
github.com/niemp100/win v0.0.0-20250330143617-fe9e49037e74/go.mod h1:goAZDFEKsvGFZz/cJSXkJKsP0EYkFMHzVFakd4Osi2c=
6159
github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8=
6260
github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I=
6361
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=

pkg/pdh/pdh.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,6 @@ returns the localized Counter Path String
568568
contains the same wildcards as before
569569
*/
570570
func PdhGetCounterInfo(hConuter PDH_HCOUNTER, retrieveExplainText bool) (string, error) {
571-
572571
zz := uint32(0)
573572
tr := uint8(1)
574573
if res, _, _ := pdh_PdhGetCounterInfoW.Call(

pkg/snclient/check_pdh.go

Lines changed: 11 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,7 @@
1-
//go:build windows
2-
// +build windows
3-
41
package snclient
52

63
import (
74
"context"
8-
"fmt"
9-
"regexp"
10-
"strconv"
11-
"strings"
12-
"syscall"
13-
"time"
14-
"unsafe"
15-
16-
"github.com/consol-monitoring/snclient/pkg/pdh"
175
)
186

197
func init() {
@@ -41,17 +29,17 @@ func (c *CheckPDH) Build() *CheckData {
4129
name: "check_pdh",
4230
description: "Checks pdh paths Handles WildCard Expansion",
4331
detailSyntax: "%(name)",
44-
okSyntax: "%(status) - All %(count) Counter Values are ok",
45-
topSyntax: "%(status) - %(problem_count)/%(count) Counter (%(count)) %(problem_list)",
46-
emptySyntax: "No Counter Found",
32+
okSyntax: "%(status) - All %(count) counter values are ok",
33+
topSyntax: "%(status) - %(problem_count)/%(count) counter (%(count)) %(problem_list)",
34+
emptySyntax: "%(status) - No counter found",
4735
emptyState: CheckExitUnknown,
4836
args: map[string]CheckArgument{
49-
"counter": {value: &c.CounterPath, description: "The fully qualified Counter Name"},
50-
"host": {value: &c.HostName, description: "The Name Of the Host Mashine in Network where the Counter should be searched, defults to local mashine"},
51-
"expand-index": {value: &c.ExpandIndex, description: "Should Indices be translated?"},
52-
"instances": {value: &c.Instances, description: "Expand WildCards And Fethch all instances"},
53-
"type": {value: &c.Type, description: "this can be large or float depending what you expect, default is large "},
54-
"english": {value: &c.EnglishFallBackNames, description: "Using English Names Regardless of system Language requires Windows Vista or higher"},
37+
"counter": {value: &c.CounterPath, description: "The fully qualified counter name"},
38+
"host": {value: &c.HostName, description: "The name of the host machine in network where the counter should be searched, defaults to local machine"},
39+
"expand-index": {value: &c.ExpandIndex, description: "Should indices be translated?"},
40+
"instances": {value: &c.Instances, description: "Expand wildcards and fetch all instances"},
41+
"type": {value: &c.Type, description: "This can be large or float depending what you expect, default is large"},
42+
"english": {value: &c.EnglishFallBackNames, description: "Using English names regardless of system language. Requires Windows Vista or higher"},
5543
},
5644
result: &CheckResult{
5745
State: CheckExitOK,
@@ -70,168 +58,6 @@ func (c *CheckPDH) Build() *CheckData {
7058
}
7159

7260
// Check implements CheckHandler.
73-
func (c *CheckPDH) Check(_ context.Context, _ *Agent, check *CheckData, _ []Argument) (*CheckResult, error) {
74-
var possiblePaths []string
75-
var hQuery pdh.PDH_HQUERY
76-
// Open Query - Data Source = 0 => Real Time Datasource
77-
ret := pdh.PdhOpenQuery(uintptr(0), uintptr(0), &hQuery)
78-
defer pdh.PdhCloseQuery(hQuery)
79-
80-
if ret != pdh.ERROR_SUCCESS {
81-
return nil, fmt.Errorf("could not open query, something is wrong with the countername")
82-
}
83-
84-
tmpPath := c.CounterPath
85-
if c.EnglishFallBackNames {
86-
var hCounter pdh.PDH_HCOUNTER
87-
ret = pdh.PdhAddEnglishCounter(hQuery, tmpPath, 0, &hCounter)
88-
if ret != pdh.ERROR_SUCCESS {
89-
return nil, fmt.Errorf("cannot use provided counter path as english fallback path, api response: %d", ret)
90-
}
91-
tpm, err := pdh.PdhGetCounterInfo(hCounter, false)
92-
if err != nil {
93-
return nil, fmt.Errorf("cannot use provided counter path as english fallback path, error: %s", err.Error())
94-
}
95-
tmpPath = tpm
96-
}
97-
98-
// If HostName is set it needs to be part of the counter path
99-
if c.HostName != "" {
100-
tmpPath = `\\` + c.HostName + `\` + c.CounterPath
101-
}
102-
103-
// Find Indices and replace with Performance Name
104-
r := regexp.MustCompile(`\\d+`)
105-
matches := r.FindAllString(c.CounterPath, -1)
106-
for _, match := range matches {
107-
index, err := strconv.Atoi(strings.ReplaceAll(match, `\`, ""))
108-
if err != nil {
109-
return nil, fmt.Errorf("could not convert index. error was %s", err.Error())
110-
}
111-
res, path := pdh.PdhLookupPerfNameByIndex(uint32(index)) //nolint:gosec // Index is small and needs to be uint32 for system call
112-
if res != pdh.ERROR_SUCCESS {
113-
return nil, fmt.Errorf("could not find given index: %d response code: %d", index, res)
114-
}
115-
tmpPath = strings.Replace(tmpPath, match, "\\"+path, 1)
116-
}
117-
118-
// Expand Counter Path That Ends with WildCard *
119-
if c.Instances && strings.HasSuffix(tmpPath, "*") {
120-
res, paths := pdh.PdhExpandCounterPath("", tmpPath, 0)
121-
if res != pdh.ERROR_SUCCESS {
122-
return nil, fmt.Errorf("something went wrong when expanding the counter path api call returned %d", res)
123-
}
124-
possiblePaths = append(possiblePaths, paths...)
125-
} else {
126-
possiblePaths = append(possiblePaths, tmpPath)
127-
}
128-
129-
counters, err := c.addAllPathToCounter(hQuery, possiblePaths)
130-
if err != nil {
131-
return nil, fmt.Errorf("could not add all counter path to query, error: %s", err.Error())
132-
}
133-
134-
// Collect Values For All Counters and save values in check.listData
135-
err = collectValuesForAllCounters(hQuery, counters, check)
136-
if err != nil {
137-
return nil, fmt.Errorf("could not get values for all counter path, error: %s", err.Error())
138-
}
139-
140-
return check.Finalize()
141-
}
142-
143-
func collectValuesForAllCounters(hQuery pdh.PDH_HQUERY, counters map[string]pdh.PDH_HCOUNTER, check *CheckData) error {
144-
for counterPath, hCounter := range counters {
145-
var resArr [1]pdh.PDH_FMT_COUNTERVALUE_ITEM_LARGE // Need at least one nil pointer
146-
147-
largeArr, ret := collectLargeValuesArray(hCounter, hQuery, resArr)
148-
if ret != pdh.ERROR_SUCCESS && ret != pdh.PDH_MORE_DATA && ret != pdh.PDH_NO_MORE_DATA {
149-
return fmt.Errorf("could not collect formatted value %v", ret)
150-
}
151-
152-
entry := map[string]string{}
153-
for _, fmtValue := range largeArr {
154-
entry["name"] = strings.Replace(counterPath, "*", utf16PtrToString(fmtValue.SzName), 1)
155-
entry["value"] = fmt.Sprintf("%d", fmtValue.FmtValue.LargeValue)
156-
if check.showAll {
157-
check.result.Metrics = append(check.result.Metrics,
158-
&CheckMetric{
159-
Name: strings.Replace(counterPath, "*", utf16PtrToString(fmtValue.SzName), 1),
160-
ThresholdName: "value",
161-
Value: fmtValue.FmtValue.LargeValue,
162-
Warning: check.warnThreshold,
163-
Critical: check.critThreshold,
164-
Min: &Zero,
165-
})
166-
}
167-
if check.MatchMapCondition(check.filter, entry, true) {
168-
check.listData = append(check.listData, entry)
169-
}
170-
}
171-
}
172-
173-
return nil
174-
}
175-
176-
func (c *CheckPDH) addAllPathToCounter(hQuery pdh.PDH_HQUERY, possiblePaths []string) (map[string]pdh.PDH_HCOUNTER, error) {
177-
counters := map[string]pdh.PDH_HCOUNTER{}
178-
179-
for _, path := range possiblePaths {
180-
var hCounter pdh.PDH_HCOUNTER
181-
ret := pdh.PdhAddCounter(hQuery, path, 0, &hCounter)
182-
if ret != pdh.ERROR_SUCCESS {
183-
return nil, fmt.Errorf("could not add one of the possible paths to the query: %s, api response code: %d", path, ret)
184-
}
185-
counters[path] = hCounter
186-
}
187-
188-
return counters, nil
189-
}
190-
191-
func collectQueryData(hQuery *pdh.PDH_HQUERY) uint32 {
192-
ret := pdh.PdhCollectQueryData(*hQuery)
193-
if ret != pdh.PDH_MORE_DATA && ret != pdh.ERROR_SUCCESS {
194-
return ret
195-
}
196-
// PDH requires a double collection with a second wait between the calls See MSDN
197-
time.Sleep(time.Duration(1))
198-
ret = pdh.PdhCollectQueryData(*hQuery)
199-
200-
return ret
201-
}
202-
203-
/*
204-
- Collect Data
205-
- Collect formatted with size = 0 to get actual size
206-
- if More Data -> Create Actual Array and fill
207-
*/
208-
func collectLargeValuesArray(hCounter pdh.PDH_HCOUNTER, hQuery pdh.PDH_HQUERY, resArr [1]pdh.PDH_FMT_COUNTERVALUE_ITEM_LARGE) (values []pdh.PDH_FMT_COUNTERVALUE_ITEM_LARGE, apiResponseCode uint32) {
209-
var ret uint32
210-
var filledBuf []pdh.PDH_FMT_COUNTERVALUE_ITEM_LARGE
211-
size := uint32(0)
212-
bufferCount := uint32(0)
213-
if res := collectQueryData(&hQuery); res != pdh.ERROR_SUCCESS {
214-
return nil, res
215-
}
216-
if ret = pdh.PdhGetFormattedCounterArrayLarge(hCounter, &size, &bufferCount, &resArr[0]); ret == pdh.PDH_MORE_DATA {
217-
// create array of size = bufferCount * sizeOf(pdh.PDH_FMT_COUNTERVALUE_ITEM_LARGE)
218-
filledBuf = make([]pdh.PDH_FMT_COUNTERVALUE_ITEM_LARGE, bufferCount)
219-
ret = pdh.PdhGetFormattedCounterArrayLarge(hCounter, &size, &bufferCount, &filledBuf[0])
220-
}
221-
222-
return filledBuf, ret
223-
}
224-
225-
func utf16PtrToString(ptr *uint16) string {
226-
if ptr == nil {
227-
return ""
228-
}
229-
end := unsafe.Pointer(ptr)
230-
charCounter := 0
231-
for *(*uint16)(end) != 0 {
232-
end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*ptr))
233-
charCounter++
234-
}
235-
236-
return syscall.UTF16ToString(unsafe.Slice(ptr, charCounter))
61+
func (c *CheckPDH) Check(ctx context.Context, snc *Agent, check *CheckData, args []Argument) (*CheckResult, error) {
62+
return c.check(ctx, snc, check, args)
23763
}

pkg/snclient/check_pdh_other.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//go:build !windows
2+
3+
package snclient
4+
5+
import (
6+
"context"
7+
"fmt"
8+
)
9+
10+
func (c *CheckPDH) check(_ context.Context, _ *Agent, _ *CheckData, _ []Argument) (*CheckResult, error) {
11+
return nil, fmt.Errorf("check_pdh is a windows only check")
12+
}

0 commit comments

Comments
 (0)