blob: e0b935d1fef70c1ebb1d7438bce222e404a1ef8f [file] [log] [blame]
khenaidooab1f7bd2019-11-14 14:00:27 -05001// Copyright 2019 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
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
14package prometheus
15
16import (
17 "syscall"
18 "unsafe"
19
20 "golang.org/x/sys/windows"
21)
22
23func canCollectProcess() bool {
24 return true
25}
26
27var (
28 modpsapi = syscall.NewLazyDLL("psapi.dll")
29 modkernel32 = syscall.NewLazyDLL("kernel32.dll")
30
31 procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
32 procGetProcessHandleCount = modkernel32.NewProc("GetProcessHandleCount")
33)
34
35type processMemoryCounters struct {
36 // https://docs.microsoft.com/en-us/windows/desktop/api/psapi/ns-psapi-_process_memory_counters_ex
37 _ uint32
38 PageFaultCount uint32
39 PeakWorkingSetSize uint64
40 WorkingSetSize uint64
41 QuotaPeakPagedPoolUsage uint64
42 QuotaPagedPoolUsage uint64
43 QuotaPeakNonPagedPoolUsage uint64
44 QuotaNonPagedPoolUsage uint64
45 PagefileUsage uint64
46 PeakPagefileUsage uint64
47 PrivateUsage uint64
48}
49
50func getProcessMemoryInfo(handle windows.Handle) (processMemoryCounters, error) {
51 mem := processMemoryCounters{}
52 r1, _, err := procGetProcessMemoryInfo.Call(
53 uintptr(handle),
54 uintptr(unsafe.Pointer(&mem)),
55 uintptr(unsafe.Sizeof(mem)),
56 )
57 if r1 != 1 {
58 return mem, err
59 } else {
60 return mem, nil
61 }
62}
63
64func getProcessHandleCount(handle windows.Handle) (uint32, error) {
65 var count uint32
66 r1, _, err := procGetProcessHandleCount.Call(
67 uintptr(handle),
68 uintptr(unsafe.Pointer(&count)),
69 )
70 if r1 != 1 {
71 return 0, err
72 } else {
73 return count, nil
74 }
75}
76
77func (c *processCollector) processCollect(ch chan<- Metric) {
78 h, err := windows.GetCurrentProcess()
79 if err != nil {
80 c.reportError(ch, nil, err)
81 return
82 }
83
84 var startTime, exitTime, kernelTime, userTime windows.Filetime
85 err = windows.GetProcessTimes(h, &startTime, &exitTime, &kernelTime, &userTime)
86 if err != nil {
87 c.reportError(ch, nil, err)
88 return
89 }
90 ch <- MustNewConstMetric(c.startTime, GaugeValue, float64(startTime.Nanoseconds()/1e9))
91 ch <- MustNewConstMetric(c.cpuTotal, CounterValue, fileTimeToSeconds(kernelTime)+fileTimeToSeconds(userTime))
92
93 mem, err := getProcessMemoryInfo(h)
94 if err != nil {
95 c.reportError(ch, nil, err)
96 return
97 }
98 ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(mem.PrivateUsage))
99 ch <- MustNewConstMetric(c.rss, GaugeValue, float64(mem.WorkingSetSize))
100
101 handles, err := getProcessHandleCount(h)
102 if err != nil {
103 c.reportError(ch, nil, err)
104 return
105 }
106 ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(handles))
107 ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(16*1024*1024)) // Windows has a hard-coded max limit, not per-process.
108}
109
110func fileTimeToSeconds(ft windows.Filetime) float64 {
111 return float64(uint64(ft.HighDateTime)<<32+uint64(ft.LowDateTime)) / 1e7
112}