Compare commits

...

77 Commits

Author SHA1 Message Date
vbeausoleil
44c39405c7 Added flag to filter services (like the one for processes). Added example for said flag in README.md (#109) 2017-08-11 00:31:39 +02:00
Martin Lindhe
96faedf481 process,iis: fix log call 2017-08-10 03:50:21 +02:00
Martin Lindhe
3cfc11c6d2 ad: fix log call 2017-08-10 03:36:28 +02:00
Martin Lindhe
80f1cf0546 README: update build instructions (#106) 2017-08-10 02:14:06 +02:00
Calle Pettersson
691b672a1e Add DisplayName and Description to Windows service (#100) 2017-08-10 02:13:32 +02:00
Martin Lindhe
2e0842573d Makefile: add build command 2017-08-10 01:32:54 +02:00
Calle Pettersson
7537c9896e Add hint in usage about quoting flags in powershell (#95) 2017-07-18 13:18:36 +02:00
Calle Pettersson
88271ddf14 Merge pull request #86 from martinlindhe/iis-wp-and-cache
Implement IIS worker process and server cache classes
2017-07-18 12:52:09 +02:00
Calle Pettersson
b0f1e1843b First implementation of AD collector (#93) 2017-07-16 12:19:40 +02:00
Calle Pettersson
00f57c183d Merge pull request #79 from andrewmostello/master
Add Win32_PerfRawData_PerfProc_Process collector
2017-07-16 10:54:23 +02:00
Calle Pettersson
dc76c4227d Remove process index from name label, add README 2017-07-16 09:49:42 +01:00
Calle Pettersson
f4195aa435 Conditional query for wmi fields added in IIS 8 2017-07-15 13:59:33 +01:00
Calle Pettersson
1ebee26c30 Change scrape_duration_seconds to gauge (#90)
* Change and rename scrape_duration metric to gauge collector_duration, split out collector_success

* Change to const metrics
2017-07-05 13:12:42 +02:00
Martin Lindhe
1db60e22b9 add a Makefile with a 'fmt' target 2017-06-30 22:50:48 +02:00
Calle Pettersson
e8cfeef26c Implement IIS worker process and server cache classes 2017-06-30 20:55:45 +01:00
Calle Pettersson
0c4c15c4ce Update WiX download url (#84)
WiX is now on GitHub, which means stable download urls. Yay!
2017-06-27 14:10:38 +02:00
Calle Pettersson
175c54acf1 Fix memory leak by updating go-ole and adding wbem initialization (#82) 2017-06-26 21:03:17 +02:00
Calle Pettersson
22a9c96ffd Add Vmware collector (#81) 2017-06-10 13:59:40 +02:00
Andrew Mostello
95b04ec0a1 Add flag to specify "where" in process WMI query
This flag can be used to limit the Win32_PerfRawData_PerfProc_Process
response and pull metrics for only the desired processes.
2017-05-28 22:04:31 -04:00
Andrew Mostello
2c84c5ad8a Add Win32_PerfRawData_PerfProc_Process collector
Collector to scrape per process data metrics from WMI. Collector not
enabled by default.
2017-05-28 10:16:40 -04:00
Martin Lindhe
d163a30e15 README: add link to releases, fix #76 2017-05-22 19:17:31 +02:00
Calle Pettersson
ec6b786608 Update WiX url. Again. 2017-05-02 14:41:15 +02:00
Martin Lindhe
781ab7ca20 update vendoring (#72) 2017-05-01 17:06:33 +02:00
Jürgen Hötzel
6bb522b6c3 Use the new prometheus http API (#71)
* Use the new prometheus http API

The new recommended way of using the prometheus http handler is through
the promhttp package:

https://github.com/prometheus/client_golang/releases/tag/v0.8.0 (Separated
HTTP exposition, allowing custom HTTP handlers (package promhttp))

* ListenAndServe always returns a non-nil error

* updated vendored dependencies
2017-05-01 00:12:05 +02:00
Simon Willcock
9d515255a6 Add App Pool metrics to IIS module (#70)
* Initial attempt at app pool collector

* Rename and tweak

* Attempt to convert uptime to unix timestamp

* Merge app pool metrics with existing IIS modules

* Update comments to reference new class

* Add state label to CurrentApplicationPoolState metric

* Return 0 value metrics for all non-active app states

Return 1 for active state

* Remove unnecessary float cast

* Add calculation for uptime

* Convert iis uptimes to unix timestamps and alter help msg

* Rename application pool uptime to start_time
2017-04-26 15:19:33 +02:00
Martin Lindhe
012e143601 Merge pull request #68 from martinlindhe/ignore-firewall-on-w2k3-installer
Ignore failures to setup the firewall exception during installation
2017-04-10 16:00:06 +02:00
Calle Pettersson
880ad4d07c Ignore failures to setup the firewall exception during installation. This happens on Win2003 and WinXP 2017-04-10 15:13:56 +02:00
Martin Lindhe
b6d5367093 Merge pull request #67 from atezs82/master
Added local_time metric with time_zone label to OS collector
2017-04-03 11:52:11 +02:00
Attila Tóth
4895e707ef Added metrics to OS collector
"time" for the Unix time
"timezone" for the name of the timezone
2017-04-03 10:50:16 +02:00
有张纸
0616dd6690 Update cpu.go (#65)
fix typo
2017-03-22 17:33:05 +01:00
有张纸
53048a42fd Update system.go (#66)
fix typo
2017-03-22 17:32:57 +01:00
Calle Pettersson
a41b9de37c Fix WiX download url 2017-03-17 19:23:03 +01:00
jimliming
745f0a6f61 updating Win32_PerfRawData_Tcpip_NetworkInterface to uint64 (#61) 2017-03-17 19:12:47 +01:00
Martin Lindhe
8ca60af43a Merge pull request #59 from martinlindhe/additional-collectors
Add [defaults] placeholder support to collectors.enabled
2017-03-04 12:56:10 +01:00
Calle Pettersson
a66f0b5475 Add [defaults] placeholder support to collectors.enabled 2017-03-04 12:44:47 +01:00
Martin Lindhe
25b8dba6df Merge pull request #58 from martinlindhe/expose-all-service-states
Always expose all possible service states/start modes
2017-03-04 11:12:31 +01:00
Calle Pettersson
f5365c96f6 Always expose all possible service states/start modes 2017-03-04 10:38:40 +01:00
Martin Lindhe
a05febe069 install.ps1: fix wix download url 2017-03-04 09:13:38 +01:00
Martin Lindhe
47dc455dc2 Merge pull request #56 from martinlindhe/service-collector
Add Win32_Service collector
2017-03-03 17:01:13 +01:00
Calle Pettersson
9ea0c95ca5 Add support for generating collectors from remote systems 2017-03-03 14:55:11 +01:00
Calle Pettersson
91374a75f2 Add Win32_Service collector 2017-03-03 14:51:24 +01:00
Calle Pettersson
b4ca3412dd Fix arch name typo 2016-12-25 07:55:42 +01:00
Martin Lindhe
7fdbdad140 Merge pull request #48 from martinlindhe/x86-builds 2016-12-24 17:48:01 +01:00
Calle Pettersson
e65b785995 Remove rdp-debug 2016-12-22 07:45:09 +01:00
Calle Pettersson
8482814343 Add arch-specific go-bin directory to path 2016-12-22 06:54:46 +01:00
Calle Pettersson
8df4ea3f51 Debug x86 build failure 2016-12-22 06:45:58 +01:00
Calle Pettersson
f60211aba3 Compile for both x86 and amd64 2016-12-20 18:51:56 +01:00
Martin Lindhe
2808da68d8 Merge pull request #41 from martinlindhe/fix_system_uptime
system: fix uptime calculation
2016-11-16 08:38:21 +01:00
Martin Lindhe
a3f44f60c5 system: fix uptime calculation, fixes #40 2016-11-15 09:07:04 +01:00
Martin Lindhe
5925816a9a Merge pull request #42 from martinlindhe/dns-server-collector
Add DNS server collector
2016-11-15 08:44:38 +01:00
Calle Pettersson
0beff465c0 Add DNS server collector 2016-11-15 06:37:52 +01:00
Martin Lindhe
b40d60b8a4 fix comments 2016-11-14 08:55:51 +01:00
Martin Lindhe
a1910c3963 Merge pull request #39 from martinlindhe/setup-gitversion
Setup GitVersion
2016-10-18 20:13:13 +02:00
Calle Pettersson
4c39660624 Setup GitVersion 2016-10-18 16:37:30 +02:00
Martin Lindhe
2fce1541d8 README: for roadmap, link to issues rather than TODO wiki 2016-10-14 14:32:11 +02:00
Martin Lindhe
66b6145835 README: remove experimental banner 2016-10-14 14:31:03 +02:00
Martin Lindhe
e0b6bf5b4f bumped govendor (#34) 2016-10-14 12:50:14 +02:00
Martin Lindhe
56eef24660 Merge pull request #37 from martinlindhe/update-default-collectors
Set default collectors and update documentation
2016-10-14 10:36:59 +02:00
Calle Pettersson
fab166f70a Set default collectors and update documentation 2016-10-14 10:24:08 +02:00
Martin Lindhe
5dd08db8c4 Merge pull request #36 from martinlindhe/rename-system-factory-from-perfos
Fix missing rename from perfos->system
2016-10-14 10:17:00 +02:00
Calle Pettersson
a973ce9bca Fix missing rename from perfos->system 2016-10-14 10:14:32 +02:00
Martin Lindhe
8974d840d0 Merge pull request #35 from martinlindhe/promu-appveyor
appveyor: build using promu to embed branch and revision info into binary
2016-10-14 09:58:39 +02:00
Martin Lindhe
c5d7bb8375 appveyor: build using promu to embed branch and revision info into binary 2016-10-13 09:07:41 +02:00
Martin Lindhe
2fa997dc7e Merge pull request #32 from martinlindhe/version-info
add boilerplate for promu
2016-10-13 09:03:44 +02:00
Martin Lindhe
5aba27bfe3 add boilerplate for promu 2016-09-30 08:31:19 +02:00
Martin Lindhe
ef04d2c51c Merge pull request #29 from martinlindhe/network
add network collector
2016-09-28 08:23:36 +02:00
Martin Lindhe
2ff652ed86 simplify appveyor (#31) 2016-09-27 19:59:29 +02:00
Martin Lindhe
6a5ae712d6 add network collector 2016-09-27 16:17:03 +02:00
Martin Lindhe
2544995940 Merge pull request #30 from martinlindhe/health
exporter: add /health endpoint. fixes #25
2016-09-27 14:51:24 +02:00
Martin Lindhe
88863c1107 exporter: add /health endpoint. fixes #25 2016-09-27 14:37:12 +02:00
Martin Lindhe
141b28a656 Merge pull request #26 from martinlindhe/cpu-collector
Cpu collector
2016-09-25 08:33:26 +02:00
Martin Lindhe
497ee6563f Merge pull request #28 from martinlindhe/generator-tool
Add a collector generator script
2016-09-25 08:32:51 +02:00
Calle Pettersson
c0b133d157 Add a collector generator script 2016-09-24 20:55:40 +02:00
Calle Pettersson
92b762f6a1 Initial cpu collector implementation 2016-09-24 20:52:56 +02:00
Martin Lindhe
c98a0c16b2 Merge pull request #20 from martinlindhe/improve-os
os: expose Win32_ComputerSystem and Win32_PerfRawData_PerfOS_System
2016-09-21 08:04:55 +02:00
Martin Lindhe
15036bbed3 AUTHORS.md 2016-09-19 09:06:26 +02:00
Martin Lindhe
52592bb097 os: expose Win32_ComputerSystem and Win32_PerfRawData_PerfOS_System 2016-09-19 09:02:05 +02:00
118 changed files with 10829 additions and 3339 deletions

3
.gitignore vendored
View File

@@ -1 +1,2 @@
/wmi_exporter.exe
*.exe
VERSION

12
.promu.yml Normal file
View File

@@ -0,0 +1,12 @@
repository:
path: github.com/martinlindhe/wmi_exporter
build:
ldflags: |
-X {{repoPath}}/vendor/github.com/prometheus/common/version.Version={{.Version}}
-X {{repoPath}}/vendor/github.com/prometheus/common/version.Revision={{.Revision}}
-X {{repoPath}}/vendor/github.com/prometheus/common/version.Branch={{.Branch}}
-X {{repoPath}}/vendor/github.com/prometheus/common/version.BuildUser={{user}}@{{host}}
-X {{repoPath}}/vendor/github.com/prometheus/common/version.BuildDate={{date "20060102-15:04:05"}}
tarball:
files:
- LICENSE

4
AUTHORS.md Normal file
View File

@@ -0,0 +1,4 @@
Contributors in alphabetical order
* [Martin Lindhe](https://github.com/martinlindhe)
* [Calle Pettersson](https://github.com/carlpett)

5
Makefile Normal file
View File

@@ -0,0 +1,5 @@
fmt:
gofmt -l -w -s .
build:
promu build -v .

View File

@@ -4,20 +4,29 @@
Prometheus exporter for Windows machines, using the WMI (Windows Management Instrumentation).
**EXPERIMENTAL, use at your own risk!**
## Collectors
Name | Description
---------|-------------
os | [Win32_OperatingSystem](https://msdn.microsoft.com/en-us/library/aa394239) metrics (memory, processes, users)
logical_disk | [Win32_PerfRawData_PerfDisk_LogicalDisk](https://msdn.microsoft.com/en-us/windows/hardware/aa394307(v=vs.71)) metrics (disk I/O)
iis | [Win32_PerfRawData_W3SVC_WebService](https://msdn.microsoft.com/en-us/library/aa394345) IIS metrics
Name | Description | Enabled by default
---------|-------------|--------------------
ad | [Win32_PerfRawData_DirectoryServices_DirectoryServices](https://msdn.microsoft.com/en-us/library/ms803980.aspx) Active Directory |
cpu | [Win32_PerfRawData_PerfOS_Processor](https://msdn.microsoft.com/en-us/library/aa394317(v=vs.90).aspx) metrics (cpu usage) | ✓
cs | [Win32_ComputerSystem](https://msdn.microsoft.com/en-us/library/aa394102) metrics (system properties, num cpus/total memory) | ✓
dns | [Win32_PerfRawData_DNS_DNS](https://technet.microsoft.com/en-us/library/cc977686.aspx) metrics (DNS Server) |
iis | [Win32_PerfRawData_W3SVC_WebService](https://msdn.microsoft.com/en-us/library/aa394345) IIS metrics |
logical_disk | [Win32_PerfRawData_PerfDisk_LogicalDisk](https://msdn.microsoft.com/en-us/windows/hardware/aa394307(v=vs.71)) metrics (disk I/O) | ✓
net | [Win32_PerfRawData_Tcpip_NetworkInterface](https://technet.microsoft.com/en-us/security/aa394340(v=vs.80)) metrics (network interface I/O) | ✓
os | [Win32_OperatingSystem](https://msdn.microsoft.com/en-us/library/aa394239) metrics (memory, processes, users) | ✓
process | [Win32_PerfRawData_PerfProc_Process](https://msdn.microsoft.com/en-us/library/aa394323(v=vs.85).aspx) metrics (per-process stats) |
service | [Win32_Service](https://msdn.microsoft.com/en-us/library/aa394418(v=vs.85).aspx) metrics (service states) | ✓
system | Win32_PerfRawData_PerfOS_System metrics (system calls) | ✓
vmware | Performance counters installed by the Vmware Guest agent |
The HELP texts shows the WMI data source, please see MSDN documentation for details.
## Installation
The latest release can be downloaded from the [releases page](https://github.com/martinlindhe/wmi_exporter/releases).
Each release provides a .msi installer. The installer will setup the WMI Exporter as a Windows service, as well as create an exception in the Windows Firewall.
If the installer is run without any parameters, the exporter will run with default settings for enabled collectors, ports, etc. The following parameters are available:
@@ -37,19 +46,28 @@ msiexec /i <path-to-msi-file> ENABLED_COLLECTORS=os,iis LISTEN_PORT=5000
## Roadmap
See [Wiki](https://github.com/martinlindhe/wmi_exporter/wiki/TODO)
See [open issues](https://github.com/martinlindhe/wmi_exporter/issues)
## Usage
go get -u github.com/kardianos/govendor
go get -u github.com/prometheus/promu
go get -u github.com/martinlindhe/wmi_exporter
cd $env:GOPATH/src/github.com/martinlindhe/wmi_exporter
govendor build +local
promu build -v .
.\wmi_exporter.exe
The prometheus metrics will be exposed on [localhost:9182](http://localhost:9182)
## Examples
Please note: The quotes in the parameter names are required because of how Powershell parses command line arguments.
### Enable only service collector and specify a custom query
.\wmi_exporter.exe "-collectors.enabled" "service" "-collector.service.services-where" "Name='wmi_exporter'"
## License

View File

@@ -4,35 +4,41 @@ os: Windows Server 2012 R2
environment:
GOPATH: c:\gopath
GOVERSION: 1.7
matrix:
- MSI_ARCH: amd64
GOARCH: amd64
- MSI_ARCH: 386
GOARCH: 386
clone_folder: c:\gopath\src\github.com\martinlindhe\wmi_exporter
install:
- go version
- set PATH=%GOPATH%\bin;c:\go\bin;%PATH%
- rmdir c:\go /s /q
- appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.zip
- 7z x go%GOVERSION%.windows-amd64.zip -y -oC:\ > NUL
- go version
- go env
- set PATH=%GOPATH%\bin;c:\go\bin;%GOPATH%\bin\windows_%GOARCH%;%PATH%
- go get -u github.com/kardianos/govendor
- go get -u github.com/prometheus/promu
- choco install gitversion.portable -y
build_script:
- govendor build -v +p
- ps: gitversion /output json /showvariable FullSemVer | Set-Content VERSION -PassThru
- govendor test -v +local
- promu build -v .
- ps: |
$ErrorActionPreference = "Stop"
if($env:APPVEYOR_REPO_TAG -eq "True") {
# The MSI version is not semver compliant, so just take the numerical parts
$Version = $env:APPVEYOR_REPO_TAG_NAME -replace '^v?([0-9\.]+).*$','$1'
Write-Verbose "Setting msi version to $Version"
.\installer\build.ps1 -PathToExecutable .\wmi_exporter.exe -Version $Version -Arch "amd64"
Push-AppveyorArtifact installer\Output\wmi_exporter-$Version-amd64.msi -DeploymentName Installer
.\installer\build.ps1 -PathToExecutable .\wmi_exporter.exe -Version $Version -Arch "$env:MSI_ARCH"
Push-AppveyorArtifact installer\Output\wmi_exporter-$Version-$env:MSI_ARCH.msi -DeploymentName Installer
}
after_build:
- 7z a wmi_exporter-%MSI_ARCH%.zip wmi_exporter.exe
artifacts:
- name: Executable
path: wmi_exporter.exe
path: 'wmi_exporter-*.zip'
deploy:
- provider: GitHub

1308
collector/ad.go Normal file

File diff suppressed because it is too large Load Diff

211
collector/cpu.go Normal file
View File

@@ -0,0 +1,211 @@
// returns data points from Win32_PerfRawData_PerfOS_Processor
// https://msdn.microsoft.com/en-us/library/aa394317(v=vs.90).aspx - Win32_PerfRawData_PerfOS_Processor class
package collector
import (
"log"
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
Factories["cpu"] = NewCPUCollector
}
// A CPUCollector is a Prometheus collector for WMI Win32_PerfRawData_PerfOS_Processor metrics
type CPUCollector struct {
CStateSecondsTotal *prometheus.Desc
TimeTotal *prometheus.Desc
InterruptsTotal *prometheus.Desc
DPCsTotal *prometheus.Desc
}
func NewCPUCollector() (Collector, error) {
const subsystem = "cpu"
return &CPUCollector{
CStateSecondsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "cstate_seconds_total"),
"Time spent in low-power idle state",
[]string{"core", "state"},
nil,
),
TimeTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "time_total"),
"Time that processor spent in different modes (idle, user, system, ...)",
[]string{"core", "mode"},
nil,
),
InterruptsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "interrupts_total"),
"Total number of received and serviced hardware interrupts",
[]string{"core"},
nil,
),
DPCsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "dpcs_total"),
"Total number of received and serviced deferred procedure calls (DPCs)",
[]string{"core"},
nil,
),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *CPUCollector) Collect(ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Println("[ERROR] failed collecting cpu metrics:", desc, err)
return err
}
return nil
}
type Win32_PerfRawData_PerfOS_Processor struct {
Name string
C1TransitionsPersec uint64
C2TransitionsPersec uint64
C3TransitionsPersec uint64
DPCRate uint32
DPCsQueuedPersec uint32
InterruptsPersec uint32
PercentC1Time uint64
PercentC2Time uint64
PercentC3Time uint64
PercentDPCTime uint64
PercentIdleTime uint64
PercentInterruptTime uint64
PercentPrivilegedTime uint64
PercentProcessorTime uint64
PercentUserTime uint64
}
/* NOTE: This is an alternative class, but it is not as widely available. Decide which to use
type Win32_PerfRawData_Counters_ProcessorInformation struct {
Name string
AverageIdleTime uint64
C1TransitionsPersec uint64
C2TransitionsPersec uint64
C3TransitionsPersec uint64
ClockInterruptsPersec uint64
DPCRate uint64
DPCsQueuedPersec uint64
IdleBreakEventsPersec uint64
InterruptsPersec uint64
ParkingStatus uint64
PercentC1Time uint64
PercentC2Time uint64
PercentC3Time uint64
PercentDPCTime uint64
PercentIdleTime uint64
PercentInterruptTime uint64
PercentofMaximumFrequency uint64
PercentPerformanceLimit uint64
PercentPriorityTime uint64
PercentPrivilegedTime uint64
PercentPrivilegedUtility uint64
PercentProcessorPerformance uint64
PercentProcessorTime uint64
PercentProcessorUtility uint64
PercentUserTime uint64
PerformanceLimitFlags uint64
ProcessorFrequency uint64
ProcessorStateFlags uint64
}*/
func (c *CPUCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_PerfOS_Processor
q := wmi.CreateQuery(&dst, "")
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
for _, data := range dst {
if strings.Contains(data.Name, "_Total") {
continue
}
core := data.Name
// These are only available from Win32_PerfRawData_Counters_ProcessorInformation, which is only available from Win2008R2+
/*ch <- prometheus.MustNewConstMetric(
c.ProcessorFrequency,
prometheus.GaugeValue,
float64(data.ProcessorFrequency),
socket, core,
)
ch <- prometheus.MustNewConstMetric(
c.MaximumFrequency,
prometheus.GaugeValue,
float64(data.PercentofMaximumFrequency)/100*float64(data.ProcessorFrequency),
socket, core,
)*/
ch <- prometheus.MustNewConstMetric(
c.CStateSecondsTotal,
prometheus.GaugeValue,
float64(data.PercentC1Time)*ticksToSecondsScaleFactor,
core, "c1",
)
ch <- prometheus.MustNewConstMetric(
c.CStateSecondsTotal,
prometheus.GaugeValue,
float64(data.PercentC2Time)*ticksToSecondsScaleFactor,
core, "c2",
)
ch <- prometheus.MustNewConstMetric(
c.CStateSecondsTotal,
prometheus.GaugeValue,
float64(data.PercentC3Time)*ticksToSecondsScaleFactor,
core, "c3",
)
ch <- prometheus.MustNewConstMetric(
c.TimeTotal,
prometheus.GaugeValue,
float64(data.PercentIdleTime)*ticksToSecondsScaleFactor,
core, "idle",
)
ch <- prometheus.MustNewConstMetric(
c.TimeTotal,
prometheus.GaugeValue,
float64(data.PercentInterruptTime)*ticksToSecondsScaleFactor,
core, "interrupt",
)
ch <- prometheus.MustNewConstMetric(
c.TimeTotal,
prometheus.GaugeValue,
float64(data.PercentDPCTime)*ticksToSecondsScaleFactor,
core, "dpc",
)
ch <- prometheus.MustNewConstMetric(
c.TimeTotal,
prometheus.GaugeValue,
float64(data.PercentPrivilegedTime)*ticksToSecondsScaleFactor,
core, "privileged",
)
ch <- prometheus.MustNewConstMetric(
c.TimeTotal,
prometheus.GaugeValue,
float64(data.PercentUserTime)*ticksToSecondsScaleFactor,
core, "user",
)
ch <- prometheus.MustNewConstMetric(
c.InterruptsTotal,
prometheus.CounterValue,
float64(data.InterruptsPersec),
core,
)
ch <- prometheus.MustNewConstMetric(
c.DPCsTotal,
prometheus.CounterValue,
float64(data.DPCsQueuedPersec),
core,
)
}
return nil, nil
}

77
collector/cs.go Normal file
View File

@@ -0,0 +1,77 @@
// returns data points from Win32_ComputerSystem
// https://msdn.microsoft.com/en-us/library/aa394102 - Win32_ComputerSystem class
package collector
import (
"log"
"github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
Factories["cs"] = NewCSCollector
}
// A CSCollector is a Prometheus collector for WMI metrics
type CSCollector struct {
PhysicalMemoryBytes *prometheus.Desc
LogicalProcessors *prometheus.Desc
}
// NewCSCollector ...
func NewCSCollector() (Collector, error) {
const subsystem = "cs"
return &CSCollector{
LogicalProcessors: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "logical_processors"),
"ComputerSystem.NumberOfLogicalProcessors",
nil,
nil,
),
PhysicalMemoryBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "physical_memory_bytes"),
"ComputerSystem.TotalPhysicalMemory",
nil,
nil,
),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *CSCollector) Collect(ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Println("[ERROR] failed collecting cs metrics:", desc, err)
return err
}
return nil
}
type Win32_ComputerSystem struct {
NumberOfLogicalProcessors uint32
TotalPhysicalMemory uint64
}
func (c *CSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_ComputerSystem
if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil {
return nil, err
}
ch <- prometheus.MustNewConstMetric(
c.LogicalProcessors,
prometheus.GaugeValue,
float64(dst[0].NumberOfLogicalProcessors),
)
ch <- prometheus.MustNewConstMetric(
c.PhysicalMemoryBytes,
prometheus.GaugeValue,
float64(dst[0].TotalPhysicalMemory),
)
return nil, nil
}

492
collector/dns.go Normal file
View File

@@ -0,0 +1,492 @@
// returns data points from Win32_PerfRawData_DNS_DNS
// https://msdn.microsoft.com/en-us/library/ms803992.aspx?f=255&MSPPError=-2147217396
// https://technet.microsoft.com/en-us/library/cc977686.aspx
package collector
import (
"log"
"github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
Factories["dns"] = NewDNSCollector
}
// A DNSCollector is a Prometheus collector for WMI Win32_PerfRawData_DNS_DNS metrics
type DNSCollector struct {
ZoneTransferRequestsReceived *prometheus.Desc
ZoneTransferRequestsSent *prometheus.Desc
ZoneTransferResponsesReceived *prometheus.Desc
ZoneTransferSuccessReceived *prometheus.Desc
ZoneTransferSuccessSent *prometheus.Desc
ZoneTransferFailures *prometheus.Desc
MemoryUsedBytes *prometheus.Desc
DynamicUpdatesQueued *prometheus.Desc
DynamicUpdatesReceived *prometheus.Desc
DynamicUpdatesFailures *prometheus.Desc
NotifyReceived *prometheus.Desc
NotifySent *prometheus.Desc
SecureUpdateFailures *prometheus.Desc
SecureUpdateReceived *prometheus.Desc
Queries *prometheus.Desc
Responses *prometheus.Desc
RecursiveQueries *prometheus.Desc
RecursiveQueryFailures *prometheus.Desc
RecursiveQuerySendTimeouts *prometheus.Desc
WinsQueries *prometheus.Desc
WinsResponses *prometheus.Desc
UnmatchedResponsesReceived *prometheus.Desc
}
// NewDNSCollector ...
func NewDNSCollector() (Collector, error) {
const subsystem = "dns"
return &DNSCollector{
ZoneTransferRequestsReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_requests_received_total"),
"Number of zone transfer requests (AXFR/IXFR) received by the master DNS server",
[]string{"qtype"},
nil,
),
ZoneTransferRequestsSent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_requests_sent_total"),
"Number of zone transfer requests (AXFR/IXFR) sent by the secondary DNS server",
[]string{"qtype"},
nil,
),
ZoneTransferResponsesReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_response_received_total"),
"Number of zone transfer responses (AXFR/IXFR) received by the secondary DNS server",
[]string{"qtype"},
nil,
),
ZoneTransferSuccessReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_success_received_total"),
"Number of successful zone transfers (AXFR/IXFR) received by the secondary DNS server",
[]string{"qtype", "protocol"},
nil,
),
ZoneTransferSuccessSent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_success_sent_total"),
"Number of successful zone transfers (AXFR/IXFR) of the master DNS server",
[]string{"qtype"},
nil,
),
ZoneTransferFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_failures_total"),
"Number of failed zone transfers of the master DNS server",
nil,
nil,
),
MemoryUsedBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "memory_used_bytes_total"),
"Total memory used by DNS server",
[]string{"area"},
nil,
),
DynamicUpdatesQueued: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "dynamic_updates_queued"),
"Number of dynamic updates queued by the DNS server",
nil,
nil,
),
DynamicUpdatesReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "dynamic_updates_received_total"),
"Number of secure update requests received by the DNS server",
[]string{"operation"},
nil,
),
DynamicUpdatesFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "dynamic_updates_failures_total"),
"Number of dynamic updates which timed out or were rejected by the DNS server",
[]string{"reason"},
nil,
),
NotifyReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "notify_received_total"),
"Number of notifies received by the secondary DNS server",
nil,
nil,
),
NotifySent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "notify_sent_total"),
"Number of notifies sent by the master DNS server",
nil,
nil,
),
SecureUpdateFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "secure_update_failures_total"),
"Number of secure updates that failed on the DNS server",
nil,
nil,
),
SecureUpdateReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "secure_update_received_total"),
"Number of secure update requests received by the DNS server",
nil,
nil,
),
Queries: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "queries_total"),
"Number of queries received by DNS server",
[]string{"protocol"},
nil,
),
Responses: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "responses_total"),
"Number of reponses sent by DNS server",
[]string{"protocol"},
nil,
),
RecursiveQueries: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "recursive_queries_total"),
"Number of recursive queries received by DNS server",
nil,
nil,
),
RecursiveQueryFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "recursive_query_failures_total"),
"Number of recursive query failures",
nil,
nil,
),
RecursiveQuerySendTimeouts: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "recursive_query_send_timeouts_total"),
"Number of recursive query sending timeouts",
nil,
nil,
),
WinsQueries: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "wins_queries_total"),
"Number of WINS lookup requests received by the server",
[]string{"direction"},
nil,
),
WinsResponses: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "wins_responses_total"),
"Number of WINS lookup responses sent by the server",
[]string{"direction"},
nil,
),
UnmatchedResponsesReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "unmatched_responses_total"),
"Number of response packets received by the DNS server that do not match any outstanding remote query",
nil,
nil,
),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *DNSCollector) Collect(ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Println("[ERROR] failed collecting dns metrics:", desc, err)
return err
}
return nil
}
type Win32_PerfRawData_DNS_DNS struct {
AXFRRequestReceived uint32
AXFRRequestSent uint32
AXFRResponseReceived uint32
AXFRSuccessReceived uint32
AXFRSuccessSent uint32
CachingMemory uint32
DatabaseNodeMemory uint32
DynamicUpdateNoOperation uint32
DynamicUpdateQueued uint32
DynamicUpdateRejected uint32
DynamicUpdateTimeOuts uint32
DynamicUpdateWrittentoDatabase uint32
IXFRRequestReceived uint32
IXFRRequestSent uint32
IXFRResponseReceived uint32
IXFRSuccessSent uint32
IXFRTCPSuccessReceived uint32
IXFRUDPSuccessReceived uint32
NbstatMemory uint32
NotifyReceived uint32
NotifySent uint32
RecordFlowMemory uint32
RecursiveQueries uint32
RecursiveQueryFailure uint32
RecursiveSendTimeOuts uint32
SecureUpdateFailure uint32
SecureUpdateReceived uint32
TCPMessageMemory uint32
TCPQueryReceived uint32
TCPResponseSent uint32
UDPMessageMemory uint32
UDPQueryReceived uint32
UDPResponseSent uint32
UnmatchedResponsesReceived uint32
WINSLookupReceived uint32
WINSResponseSent uint32
WINSReverseLookupReceived uint32
WINSReverseResponseSent uint32
ZoneTransferFailure uint32
ZoneTransferSOARequestSent uint32
}
func (c *DNSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_DNS_DNS
q := wmi.CreateQuery(&dst, "")
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
ch <- prometheus.MustNewConstMetric(
c.ZoneTransferRequestsReceived,
prometheus.CounterValue,
float64(dst[0].AXFRRequestReceived),
"full",
)
ch <- prometheus.MustNewConstMetric(
c.ZoneTransferRequestsReceived,
prometheus.CounterValue,
float64(dst[0].IXFRRequestReceived),
"incremental",
)
ch <- prometheus.MustNewConstMetric(
c.ZoneTransferRequestsSent,
prometheus.CounterValue,
float64(dst[0].AXFRRequestSent),
"full",
)
ch <- prometheus.MustNewConstMetric(
c.ZoneTransferRequestsSent,
prometheus.CounterValue,
float64(dst[0].IXFRRequestSent),
"incremental",
)
ch <- prometheus.MustNewConstMetric(
c.ZoneTransferRequestsSent,
prometheus.CounterValue,
float64(dst[0].ZoneTransferSOARequestSent),
"soa",
)
ch <- prometheus.MustNewConstMetric(
c.ZoneTransferResponsesReceived,
prometheus.CounterValue,
float64(dst[0].AXFRResponseReceived),
"full",
)
ch <- prometheus.MustNewConstMetric(
c.ZoneTransferResponsesReceived,
prometheus.CounterValue,
float64(dst[0].IXFRResponseReceived),
"incremental",
)
ch <- prometheus.MustNewConstMetric(
c.ZoneTransferSuccessReceived,
prometheus.CounterValue,
float64(dst[0].AXFRSuccessReceived),
"full",
"tcp",
)
ch <- prometheus.MustNewConstMetric(
c.ZoneTransferSuccessReceived,
prometheus.CounterValue,
float64(dst[0].IXFRTCPSuccessReceived),
"incremental",
"tcp",
)
ch <- prometheus.MustNewConstMetric(
c.ZoneTransferSuccessReceived,
prometheus.CounterValue,
float64(dst[0].IXFRTCPSuccessReceived),
"incremental",
"udp",
)
ch <- prometheus.MustNewConstMetric(
c.ZoneTransferSuccessSent,
prometheus.CounterValue,
float64(dst[0].AXFRSuccessSent),
"full",
)
ch <- prometheus.MustNewConstMetric(
c.ZoneTransferSuccessSent,
prometheus.CounterValue,
float64(dst[0].IXFRSuccessSent),
"incremental",
)
ch <- prometheus.MustNewConstMetric(
c.ZoneTransferFailures,
prometheus.CounterValue,
float64(dst[0].ZoneTransferFailure),
)
ch <- prometheus.MustNewConstMetric(
c.MemoryUsedBytes,
prometheus.GaugeValue,
float64(dst[0].CachingMemory),
"caching",
)
ch <- prometheus.MustNewConstMetric(
c.MemoryUsedBytes,
prometheus.GaugeValue,
float64(dst[0].DatabaseNodeMemory),
"database_node",
)
ch <- prometheus.MustNewConstMetric(
c.MemoryUsedBytes,
prometheus.GaugeValue,
float64(dst[0].NbstatMemory),
"nbstat",
)
ch <- prometheus.MustNewConstMetric(
c.MemoryUsedBytes,
prometheus.GaugeValue,
float64(dst[0].RecordFlowMemory),
"record_flow",
)
ch <- prometheus.MustNewConstMetric(
c.MemoryUsedBytes,
prometheus.GaugeValue,
float64(dst[0].TCPMessageMemory),
"tcp_message",
)
ch <- prometheus.MustNewConstMetric(
c.MemoryUsedBytes,
prometheus.GaugeValue,
float64(dst[0].UDPMessageMemory),
"udp_message",
)
ch <- prometheus.MustNewConstMetric(
c.DynamicUpdatesReceived,
prometheus.CounterValue,
float64(dst[0].DynamicUpdateNoOperation),
"noop",
)
ch <- prometheus.MustNewConstMetric(
c.DynamicUpdatesReceived,
prometheus.CounterValue,
float64(dst[0].DynamicUpdateWrittentoDatabase),
"written",
)
ch <- prometheus.MustNewConstMetric(
c.DynamicUpdatesQueued,
prometheus.GaugeValue,
float64(dst[0].DynamicUpdateQueued),
)
ch <- prometheus.MustNewConstMetric(
c.DynamicUpdatesFailures,
prometheus.CounterValue,
float64(dst[0].DynamicUpdateRejected),
"rejected",
)
ch <- prometheus.MustNewConstMetric(
c.DynamicUpdatesFailures,
prometheus.CounterValue,
float64(dst[0].DynamicUpdateTimeOuts),
"timeout",
)
ch <- prometheus.MustNewConstMetric(
c.NotifyReceived,
prometheus.CounterValue,
float64(dst[0].NotifyReceived),
)
ch <- prometheus.MustNewConstMetric(
c.NotifySent,
prometheus.CounterValue,
float64(dst[0].NotifySent),
)
ch <- prometheus.MustNewConstMetric(
c.RecursiveQueries,
prometheus.CounterValue,
float64(dst[0].RecursiveQueries),
)
ch <- prometheus.MustNewConstMetric(
c.RecursiveQueryFailures,
prometheus.CounterValue,
float64(dst[0].RecursiveQueryFailure),
)
ch <- prometheus.MustNewConstMetric(
c.RecursiveQuerySendTimeouts,
prometheus.CounterValue,
float64(dst[0].RecursiveSendTimeOuts),
)
ch <- prometheus.MustNewConstMetric(
c.Queries,
prometheus.CounterValue,
float64(dst[0].TCPQueryReceived),
"tcp",
)
ch <- prometheus.MustNewConstMetric(
c.Queries,
prometheus.CounterValue,
float64(dst[0].UDPQueryReceived),
"udp",
)
ch <- prometheus.MustNewConstMetric(
c.Responses,
prometheus.CounterValue,
float64(dst[0].TCPResponseSent),
"tcp",
)
ch <- prometheus.MustNewConstMetric(
c.Responses,
prometheus.CounterValue,
float64(dst[0].UDPResponseSent),
"udp",
)
ch <- prometheus.MustNewConstMetric(
c.UnmatchedResponsesReceived,
prometheus.CounterValue,
float64(dst[0].UnmatchedResponsesReceived),
)
ch <- prometheus.MustNewConstMetric(
c.WinsQueries,
prometheus.CounterValue,
float64(dst[0].WINSLookupReceived),
"forward",
)
ch <- prometheus.MustNewConstMetric(
c.WinsQueries,
prometheus.CounterValue,
float64(dst[0].WINSReverseLookupReceived),
"reverse",
)
ch <- prometheus.MustNewConstMetric(
c.WinsResponses,
prometheus.CounterValue,
float64(dst[0].WINSResponseSent),
"forward",
)
ch <- prometheus.MustNewConstMetric(
c.WinsResponses,
prometheus.CounterValue,
float64(dst[0].WINSReverseResponseSent),
"reverse",
)
ch <- prometheus.MustNewConstMetric(
c.SecureUpdateFailures,
prometheus.CounterValue,
float64(dst[0].SecureUpdateFailure),
)
ch <- prometheus.MustNewConstMetric(
c.SecureUpdateReceived,
prometheus.CounterValue,
float64(dst[0].SecureUpdateReceived),
)
return nil, nil
}

File diff suppressed because it is too large Load Diff

View File

@@ -18,10 +18,6 @@ func init() {
Factories["logical_disk"] = NewLogicalDiskCollector
}
const (
ticksToSecondsScaleFactor = 1 / 1e7
)
var (
volumeWhitelist = flag.String("collector.logical_disk.volume-whitelist", ".+", "Regexp of volumes to whitelist. Volume name must both match whitelist and not match blacklist to be included.")
volumeBlacklist = flag.String("collector.logical_disk.volume-blacklist", "", "Regexp of volumes to blacklist. Volume name must both match whitelist and not match blacklist to be included.")

244
collector/net.go Normal file
View File

@@ -0,0 +1,244 @@
// returns data points from Win32_PerfRawData_Tcpip_NetworkInterface
// https://technet.microsoft.com/en-us/security/aa394340(v=vs.80) (Win32_PerfRawData_Tcpip_NetworkInterface class)
// https://msdn.microsoft.com/en-us/library/aa394216 (Win32_NetworkAdapter class)
// https://msdn.microsoft.com/en-us/library/aa394353 (Win32_PnPEntity class)
package collector
import (
"flag"
"fmt"
"log"
"regexp"
"github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
Factories["net"] = NewNetworkCollector
}
var (
nicWhitelist = flag.String("collector.net.nic-whitelist", ".+", "Regexp of NIC:s to whitelist. NIC name must both match whitelist and not match blacklist to be included.")
nicBlacklist = flag.String("collector.net.nic-blacklist", "", "Regexp of NIC:s to blacklist. NIC name must both match whitelist and not match blacklist to be included.")
nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]")
)
// A NetworkCollector is a Prometheus collector for WMI Win32_PerfRawData_Tcpip_NetworkInterface metrics
type NetworkCollector struct {
BytesReceivedTotal *prometheus.Desc
BytesSentTotal *prometheus.Desc
BytesTotal *prometheus.Desc
PacketsOutboundDiscarded *prometheus.Desc
PacketsOutboundErrors *prometheus.Desc
PacketsTotal *prometheus.Desc
PacketsReceivedDiscarded *prometheus.Desc
PacketsReceivedErrors *prometheus.Desc
PacketsReceivedTotal *prometheus.Desc
PacketsReceivedUnknown *prometheus.Desc
PacketsSentTotal *prometheus.Desc
nicWhitelistPattern *regexp.Regexp
nicBlacklistPattern *regexp.Regexp
}
// NewNetworkCollector ...
func NewNetworkCollector() (Collector, error) {
const subsystem = "net"
return &NetworkCollector{
BytesReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "bytes_received_total"),
"(Network.BytesReceivedPerSec)",
[]string{"nic"},
nil,
),
BytesSentTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "bytes_sent_total"),
"(Network.BytesSentPerSec)",
[]string{"nic"},
nil,
),
BytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "bytes_total"),
"(Network.BytesTotalPerSec)",
[]string{"nic"},
nil,
),
PacketsOutboundDiscarded: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_outbound_discarded"),
"(Network.PacketsOutboundDiscarded)",
[]string{"nic"},
nil,
),
PacketsOutboundErrors: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_outbound_errors"),
"(Network.PacketsOutboundErrors)",
[]string{"nic"},
nil,
),
PacketsReceivedDiscarded: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_received_discarded"),
"(Network.PacketsReceivedDiscarded)",
[]string{"nic"},
nil,
),
PacketsReceivedErrors: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_received_errors"),
"(Network.PacketsReceivedErrors)",
[]string{"nic"},
nil,
),
PacketsReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_received_total"),
"(Network.PacketsReceivedPerSec)",
[]string{"nic"},
nil,
),
PacketsReceivedUnknown: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_received_unknown"),
"(Network.PacketsReceivedUnknown)",
[]string{"nic"},
nil,
),
PacketsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_total"),
"(Network.PacketsPerSec)",
[]string{"nic"},
nil,
),
PacketsSentTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "packets_sent_total"),
"(Network.PacketsSentPerSec)",
[]string{"nic"},
nil,
),
nicWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *nicWhitelist)),
nicBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *nicBlacklist)),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *NetworkCollector) Collect(ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Println("[ERROR] failed collecting net metrics:", desc, err)
return err
}
return nil
}
// mangleNetworkName mangles Network Adapter name (non-alphanumeric to _)
// that is used in Win32_PerfRawData_Tcpip_NetworkInterface.
func mangleNetworkName(name string) string {
return nicNameToUnderscore.ReplaceAllString(name, "_")
}
type Win32_PerfRawData_Tcpip_NetworkInterface struct {
BytesReceivedPerSec uint64
BytesSentPerSec uint64
BytesTotalPerSec uint64
Name string
PacketsOutboundDiscarded uint64
PacketsOutboundErrors uint64
PacketsPerSec uint64
PacketsReceivedDiscarded uint64
PacketsReceivedErrors uint64
PacketsReceivedPerSec uint64
PacketsReceivedUnknown uint64
PacketsSentPerSec uint64
}
func (c *NetworkCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_Tcpip_NetworkInterface
q := wmi.CreateQuery(&dst, "")
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
for _, nic := range dst {
if c.nicBlacklistPattern.MatchString(nic.Name) ||
!c.nicWhitelistPattern.MatchString(nic.Name) {
continue
}
name := mangleNetworkName(nic.Name)
if name == "" {
continue
}
// Counters
ch <- prometheus.MustNewConstMetric(
c.BytesReceivedTotal,
prometheus.CounterValue,
float64(nic.BytesReceivedPerSec),
name,
)
ch <- prometheus.MustNewConstMetric(
c.BytesSentTotal,
prometheus.CounterValue,
float64(nic.BytesSentPerSec),
name,
)
ch <- prometheus.MustNewConstMetric(
c.BytesTotal,
prometheus.CounterValue,
float64(nic.BytesTotalPerSec),
name,
)
ch <- prometheus.MustNewConstMetric(
c.PacketsOutboundDiscarded,
prometheus.CounterValue,
float64(nic.PacketsOutboundDiscarded),
name,
)
ch <- prometheus.MustNewConstMetric(
c.PacketsOutboundErrors,
prometheus.CounterValue,
float64(nic.PacketsOutboundErrors),
name,
)
ch <- prometheus.MustNewConstMetric(
c.PacketsTotal,
prometheus.CounterValue,
float64(nic.PacketsPerSec),
name,
)
ch <- prometheus.MustNewConstMetric(
c.PacketsReceivedDiscarded,
prometheus.CounterValue,
float64(nic.PacketsReceivedDiscarded),
name,
)
ch <- prometheus.MustNewConstMetric(
c.PacketsReceivedErrors,
prometheus.CounterValue,
float64(nic.PacketsReceivedErrors),
name,
)
ch <- prometheus.MustNewConstMetric(
c.PacketsReceivedTotal,
prometheus.CounterValue,
float64(nic.PacketsReceivedPerSec),
name,
)
ch <- prometheus.MustNewConstMetric(
c.PacketsReceivedUnknown,
prometheus.CounterValue,
float64(nic.PacketsReceivedUnknown),
name,
)
ch <- prometheus.MustNewConstMetric(
c.PacketsSentTotal,
prometheus.CounterValue,
float64(nic.PacketsSentPerSec),
name,
)
}
return nil, nil
}

15
collector/net_test.go Normal file
View File

@@ -0,0 +1,15 @@
package collector
import "testing"
func TestNetworkToInstanceName(t *testing.T) {
data := map[string]string{
"Intel[R] Dual Band Wireless-AC 8260": "Intel_R__Dual_Band_Wireless_AC_8260",
}
for in, out := range data {
got := mangleNetworkName(in)
if got != out {
t.Error("expected", out, "got", got)
}
}
}

View File

@@ -5,7 +5,8 @@ package collector
import (
"log"
"time"
"github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus"
)
@@ -14,93 +15,96 @@ func init() {
Factories["os"] = NewOSCollector
}
// A OSCollector is a Prometheus collector for WMI Win32_OperatingSystem metrics
// A OSCollector is a Prometheus collector for WMI metrics
type OSCollector struct {
PhysicalMemoryFreeBytes *prometheus.Desc
PagingFreeBytes *prometheus.Desc
VirtualMemoryFreeBytes *prometheus.Desc
ProcessesMax *prometheus.Desc
ProcessMemoryMaxBytes *prometheus.Desc
ProcessesLimit *prometheus.Desc
ProcessMemoryLimitBytes *prometheus.Desc
Processes *prometheus.Desc
Users *prometheus.Desc
PagingMaxBytes *prometheus.Desc
PagingLimitBytes *prometheus.Desc
VirtualMemoryBytes *prometheus.Desc
VisibleMemoryBytes *prometheus.Desc
Time *prometheus.Desc
Timezone *prometheus.Desc
}
// NewOSCollector ...
func NewOSCollector() (Collector, error) {
const subsystem = "os"
return &OSCollector{
PagingMaxBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "paging_max_bytes"),
"SizeStoredInPagingFiles",
PagingLimitBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "paging_limit_bytes"),
"OperatingSystem.SizeStoredInPagingFiles",
nil,
nil,
),
PagingFreeBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "paging_free_bytes"),
"FreeSpaceInPagingFiles",
"OperatingSystem.FreeSpaceInPagingFiles",
nil,
nil,
),
PhysicalMemoryFreeBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "physical_memory_free_bytes"),
"FreePhysicalMemory",
"OperatingSystem.FreePhysicalMemory",
nil,
nil,
),
Time: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "time"),
"OperatingSystem.LocalDateTime",
nil,
nil,
),
Timezone: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "timezone"),
"OperatingSystem.LocalDateTime",
[]string{"timezone"},
nil,
),
Processes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "processes"),
"NumberOfProcesses",
"OperatingSystem.NumberOfProcesses",
nil,
nil,
),
ProcessesMax: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "processes_max"),
"MaxNumberOfProcesses",
ProcessesLimit: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "processes_limit"),
"OperatingSystem.MaxNumberOfProcesses",
nil,
nil,
),
ProcessMemoryMaxBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "process_memory_max_bytes"),
"MaxProcessMemorySize",
ProcessMemoryLimitBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "process_memory_limix_bytes"),
"OperatingSystem.MaxProcessMemorySize",
nil,
nil,
),
Users: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "users"),
"NumberOfUsers",
"OperatingSystem.NumberOfUsers",
nil,
nil,
),
VirtualMemoryBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "virtual_memory_bytes"),
"TotalVirtualMemorySize",
"OperatingSystem.TotalVirtualMemorySize",
nil,
nil,
),
VisibleMemoryBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "visible_memory_bytes"),
"TotalVisibleMemorySize",
"OperatingSystem.TotalVisibleMemorySize",
nil,
nil,
),
VirtualMemoryFreeBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "virtual_memory_free_bytes"),
"FreeVirtualMemory",
"OperatingSystem.FreeVirtualMemory",
nil,
nil,
),
@@ -128,12 +132,12 @@ type Win32_OperatingSystem struct {
SizeStoredInPagingFiles uint64
TotalVirtualMemorySize uint64
TotalVisibleMemorySize uint64
LocalDateTime time.Time
}
func (c *OSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_OperatingSystem
q := wmi.CreateQuery(&dst, "")
if err := wmi.Query(q, &dst); err != nil {
if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil {
return nil, err
}
@@ -143,6 +147,23 @@ func (c *OSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, er
float64(dst[0].FreePhysicalMemory*1024), // KiB -> bytes
)
time := dst[0].LocalDateTime
ch <- prometheus.MustNewConstMetric(
c.Time,
prometheus.GaugeValue,
float64(time.Unix()),
)
timezoneName, _ := time.Zone()
ch <- prometheus.MustNewConstMetric(
c.Timezone,
prometheus.GaugeValue,
1.0,
timezoneName,
)
ch <- prometheus.MustNewConstMetric(
c.PagingFreeBytes,
prometheus.GaugeValue,
@@ -156,13 +177,13 @@ func (c *OSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, er
)
ch <- prometheus.MustNewConstMetric(
c.ProcessesMax,
c.ProcessesLimit,
prometheus.GaugeValue,
float64(dst[0].MaxNumberOfProcesses),
)
ch <- prometheus.MustNewConstMetric(
c.ProcessMemoryMaxBytes,
c.ProcessMemoryLimitBytes,
prometheus.GaugeValue,
float64(dst[0].MaxProcessMemorySize*1024), // KiB -> bytes
)
@@ -180,7 +201,7 @@ func (c *OSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, er
)
ch <- prometheus.MustNewConstMetric(
c.PagingMaxBytes,
c.PagingLimitBytes,
prometheus.GaugeValue,
float64(dst[0].SizeStoredInPagingFiles*1024), // KiB -> bytes
)

383
collector/process.go Normal file
View File

@@ -0,0 +1,383 @@
// returns data points from Win32_PerfRawData_PerfProc_Process
// https://msdn.microsoft.com/en-us/library/aa394323(v=vs.85).aspx - Win32_PerfRawData_PerfProc_Process class
package collector
import (
"bytes"
"flag"
"log"
"strconv"
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
Factories["process"] = NewProcessCollector
}
var (
processWhereClause = flag.String("collector.process.processes-where", "", "WQL 'where' clause to use in WMI metrics query. Limits the response to the processes you specify and reduces the size of the response.")
)
// A ProcessCollector is a Prometheus collector for WMI Win32_PerfRawData_PerfProc_Process metrics
type ProcessCollector struct {
StartTime *prometheus.Desc
CPUTimeTotal *prometheus.Desc
HandleCount *prometheus.Desc
IOBytesTotal *prometheus.Desc
IOOperationsTotal *prometheus.Desc
PageFaultsTotal *prometheus.Desc
PageFileBytes *prometheus.Desc
PoolBytes *prometheus.Desc
PriorityBase *prometheus.Desc
PrivateBytes *prometheus.Desc
ThreadCount *prometheus.Desc
VirtualBytes *prometheus.Desc
WorkingSet *prometheus.Desc
queryWhereClause string
}
// NewProcessCollector ...
func NewProcessCollector() (Collector, error) {
const subsystem = "process"
var wc bytes.Buffer
if *processWhereClause != "" {
wc.WriteString("WHERE ")
wc.WriteString(*processWhereClause)
} else {
log.Println("warning: No where-clause specified for process collector. This will generate a very large number of metrics!")
}
return &ProcessCollector{
StartTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "start_time"),
"Time of process start.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
CPUTimeTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "cpu_time_total"),
"Returns elapsed time that all of the threads of this process used the processor to execute instructions by mode (privileged, user). An instruction is the basic unit of execution in a computer, a thread is the object that executes instructions, and a process is the object created when a program is run. Code executed to handle some hardware interrupts and trap conditions is included in this count.",
[]string{"process", "process_id", "creating_process_id", "mode"},
nil,
),
HandleCount: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "handle_count"),
"Total number of handles the process has open. This number is the sum of the handles currently open by each thread in the process.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
IOBytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "io_bytes_total"),
"Bytes issued to I/O operations in different modes (read, write, other). This property counts all I/O activity generated by the process to include file, network, and device I/Os. Read and write mode includes data operations; other mode includes those that do not involve data, such as control operations. ",
[]string{"process", "process_id", "creating_process_id", "mode"},
nil,
),
IOOperationsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "io_operations_total"),
"I/O operations issued in different modes (read, write, other). This property counts all I/O activity generated by the process to include file, network, and device I/Os. Read and write mode includes data operations; other mode includes those that do not involve data, such as control operations. ",
[]string{"process", "process_id", "creating_process_id", "mode"},
nil,
),
PageFaultsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "page_faults_total"),
"Page faults by the threads executing in this process. A page fault occurs when a thread refers to a virtual memory page that is not in its working set in main memory. This can cause the page not to be fetched from disk if it is on the standby list and hence already in main memory, or if it is in use by another process with which the page is shared.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
PageFileBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "page_file_bytes"),
"Current number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
PoolBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "pool_bytes"),
"Pool Bytes is the last observed number of bytes in the paged or nonpaged pool. The nonpaged pool is an area of system memory (physical memory used by the operating system) for objects that cannot be written to disk, but must remain in physical memory as long as they are allocated. The paged pool is an area of system memory (physical memory used by the operating system) for objects that can be written to disk when they are not being used. Nonpaged pool bytes is calculated differently than paged pool bytes, so it might not equal the total of paged pool bytes.",
[]string{"process", "process_id", "creating_process_id", "pool"},
nil,
),
PriorityBase: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "priority_base"),
"Current base priority of this process. Threads within a process can raise and lower their own base priority relative to the process base priority of the process.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
PrivateBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "private_bytes"),
"Current number of bytes this process has allocated that cannot be shared with other processes.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
ThreadCount: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "thread_count"),
"Number of threads currently active in this process. An instruction is the basic unit of execution in a processor, and a thread is the object that executes instructions. Every running process has at least one thread.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
VirtualBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "virtual_bytes"),
"Current size, in bytes, of the virtual address space that the process is using. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process can limit its ability to load libraries.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
WorkingSet: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "working_set"),
"Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory.",
[]string{"process", "process_id", "creating_process_id"},
nil,
),
queryWhereClause: wc.String(),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *ProcessCollector) Collect(ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Println("[ERROR] failed collecting process metrics:", desc, err)
return err
}
return nil
}
type Win32_PerfRawData_PerfProc_Process struct {
Name string
CreatingProcessID uint32
ElapsedTime uint64
Frequency_Object uint64
HandleCount uint32
IDProcess uint32
IODataBytesPersec uint64
IODataOperationsPersec uint64
IOOtherBytesPersec uint64
IOOtherOperationsPersec uint64
IOReadBytesPersec uint64
IOReadOperationsPersec uint64
IOWriteBytesPersec uint64
IOWriteOperationsPersec uint64
PageFaultsPersec uint32
PageFileBytes uint64
PageFileBytesPeak uint64
PercentPrivilegedTime uint64
PercentProcessorTime uint64
PercentUserTime uint64
PoolNonpagedBytes uint32
PoolPagedBytes uint32
PriorityBase uint32
PrivateBytes uint64
ThreadCount uint32
Timestamp_Object uint64
VirtualBytes uint64
VirtualBytesPeak uint64
WorkingSet uint64
WorkingSetPeak uint64
WorkingSetPrivate uint64
}
func (c *ProcessCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_PerfProc_Process
q := wmi.CreateQuery(&dst, c.queryWhereClause)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
for _, process := range dst {
if process.Name == "_Total" {
continue
}
// Duplicate processes are suffixed # and an index number. Remove those.
processName := strings.Split(process.Name, "#")[0]
pid := strconv.FormatUint(uint64(process.IDProcess), 10)
cpid := strconv.FormatUint(uint64(process.CreatingProcessID), 10)
ch <- prometheus.MustNewConstMetric(
c.StartTime,
prometheus.GaugeValue,
// convert from Windows timestamp (1 jan 1601) to unix timestamp (1 jan 1970)
float64(process.ElapsedTime-116444736000000000)/float64(process.Frequency_Object),
processName,
pid,
cpid,
)
ch <- prometheus.MustNewConstMetric(
c.HandleCount,
prometheus.GaugeValue,
float64(process.HandleCount),
processName,
pid,
cpid,
)
ch <- prometheus.MustNewConstMetric(
c.CPUTimeTotal,
prometheus.CounterValue,
float64(process.PercentPrivilegedTime)*ticksToSecondsScaleFactor,
processName,
pid,
cpid,
"privileged",
)
ch <- prometheus.MustNewConstMetric(
c.CPUTimeTotal,
prometheus.CounterValue,
float64(process.PercentUserTime)*ticksToSecondsScaleFactor,
processName,
pid,
cpid,
"user",
)
ch <- prometheus.MustNewConstMetric(
c.IOBytesTotal,
prometheus.CounterValue,
float64(process.IOOtherBytesPersec),
processName,
pid,
cpid,
"other",
)
ch <- prometheus.MustNewConstMetric(
c.IOOperationsTotal,
prometheus.CounterValue,
float64(process.IOOtherOperationsPersec),
processName,
pid,
cpid,
"other",
)
ch <- prometheus.MustNewConstMetric(
c.IOBytesTotal,
prometheus.CounterValue,
float64(process.IOReadBytesPersec),
processName,
pid,
cpid,
"read",
)
ch <- prometheus.MustNewConstMetric(
c.IOOperationsTotal,
prometheus.CounterValue,
float64(process.IOReadOperationsPersec),
processName,
pid,
cpid,
"read",
)
ch <- prometheus.MustNewConstMetric(
c.IOBytesTotal,
prometheus.CounterValue,
float64(process.IOWriteBytesPersec),
processName,
pid,
cpid,
"write",
)
ch <- prometheus.MustNewConstMetric(
c.IOOperationsTotal,
prometheus.CounterValue,
float64(process.IOWriteOperationsPersec),
processName,
pid,
cpid,
"write",
)
ch <- prometheus.MustNewConstMetric(
c.PageFaultsTotal,
prometheus.CounterValue,
float64(process.PageFaultsPersec),
processName,
pid,
cpid,
)
ch <- prometheus.MustNewConstMetric(
c.PageFileBytes,
prometheus.GaugeValue,
float64(process.PageFileBytes),
processName,
pid,
cpid,
)
ch <- prometheus.MustNewConstMetric(
c.PoolBytes,
prometheus.GaugeValue,
float64(process.PoolNonpagedBytes),
processName,
pid,
cpid,
"nonpaged",
)
ch <- prometheus.MustNewConstMetric(
c.PoolBytes,
prometheus.GaugeValue,
float64(process.PoolPagedBytes),
processName,
pid,
cpid,
"paged",
)
ch <- prometheus.MustNewConstMetric(
c.PriorityBase,
prometheus.GaugeValue,
float64(process.PriorityBase),
processName,
pid,
cpid,
)
ch <- prometheus.MustNewConstMetric(
c.PrivateBytes,
prometheus.GaugeValue,
float64(process.PrivateBytes),
processName,
pid,
cpid,
)
ch <- prometheus.MustNewConstMetric(
c.ThreadCount,
prometheus.GaugeValue,
float64(process.ThreadCount),
processName,
pid,
cpid,
)
ch <- prometheus.MustNewConstMetric(
c.VirtualBytes,
prometheus.GaugeValue,
float64(process.VirtualBytes),
processName,
pid,
cpid,
)
ch <- prometheus.MustNewConstMetric(
c.WorkingSet,
prometheus.GaugeValue,
float64(process.WorkingSet),
processName,
pid,
cpid,
)
}
return nil, nil
}

133
collector/service.go Normal file
View File

@@ -0,0 +1,133 @@
// returns data points from Win32_Service
// https://msdn.microsoft.com/en-us/library/aa394418(v=vs.85).aspx - Win32_Service class
package collector
import (
"bytes"
"flag"
"log"
"strings"
"github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
Factories["service"] = NewserviceCollector
}
var (
serviceWhereClause = flag.String("collector.service.services-where", "", "WQL 'where' clause to use in WMI metrics query. Limits the response to the services you specify and reduces the size of the response.")
)
// A serviceCollector is a Prometheus collector for WMI Win32_Service metrics
type serviceCollector struct {
State *prometheus.Desc
StartMode *prometheus.Desc
queryWhereClause string
}
// NewserviceCollector ...
func NewserviceCollector() (Collector, error) {
const subsystem = "service"
var wc bytes.Buffer
if *serviceWhereClause != "" {
wc.WriteString("WHERE ")
wc.WriteString(*serviceWhereClause)
} else {
log.Println("warning: No where-clause specified for process collector. This will generate a very large number of metrics!")
}
return &serviceCollector{
State: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "state"),
"The state of the service (State)",
[]string{"name", "state"},
nil,
),
StartMode: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "start_mode"),
"The start mode of the service (StartMode)",
[]string{"name", "start_mode"},
nil,
),
queryWhereClause: wc.String(),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *serviceCollector) Collect(ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Println("[ERROR] failed collecting service metrics:", desc, err)
return err
}
return nil
}
type Win32_Service struct {
Name string
State string
StartMode string
}
var (
allStates = []string{
"stopped",
"start pending",
"stop pending",
"running",
"continue pending",
"pause pending",
"paused",
"unknown",
}
allStartModes = []string{
"boot",
"system",
"auto",
"manual",
"disabled",
}
)
func (c *serviceCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_Service
q := wmi.CreateQuery(&dst, c.queryWhereClause)
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
for _, service := range dst {
for _, state := range allStates {
isCurrentState := 0.0
if state == strings.ToLower(service.State) {
isCurrentState = 1.0
}
ch <- prometheus.MustNewConstMetric(
c.State,
prometheus.GaugeValue,
isCurrentState,
strings.ToLower(service.Name),
state,
)
}
for _, startMode := range allStartModes {
isCurrentStartMode := 0.0
if startMode == strings.ToLower(service.StartMode) {
isCurrentStartMode = 1.0
}
ch <- prometheus.MustNewConstMetric(
c.StartMode,
prometheus.GaugeValue,
isCurrentStartMode,
strings.ToLower(service.Name),
startMode,
)
}
}
return nil, nil
}

130
collector/system.go Normal file
View File

@@ -0,0 +1,130 @@
// returns data points from Win32_PerfRawData_PerfOS_System class
// https://web.archive.org/web/20050830140516/http://msdn.microsoft.com/library/en-us/wmisdk/wmi/win32_perfrawdata_perfos_system.asp
package collector
import (
"log"
"github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
Factories["system"] = NewSystemCollector
}
// A SystemCollector is a Prometheus collector for WMI metrics
type SystemCollector struct {
ContextSwitchesTotal *prometheus.Desc
ExceptionDispatchesTotal *prometheus.Desc
ProcessorQueueLength *prometheus.Desc
SystemCallsTotal *prometheus.Desc
SystemUpTime *prometheus.Desc
Threads *prometheus.Desc
}
// NewSystemCollector ...
func NewSystemCollector() (Collector, error) {
const subsystem = "system"
return &SystemCollector{
ContextSwitchesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "context_switches_total"),
"PerfOS_System.ContextSwitchesPersec",
nil,
nil,
),
ExceptionDispatchesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "exception_dispatches_total"),
"PerfOS_System.ExceptionDispatchesPersec",
nil,
nil,
),
ProcessorQueueLength: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "processor_queue_length"),
"PerfOS_System.ProcessorQueueLength",
nil,
nil,
),
SystemCallsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "system_calls_total"),
"PerfOS_System.SystemCallsPersec",
nil,
nil,
),
SystemUpTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "system_up_time"),
"SystemUpTime/Frequency_Object",
nil,
nil,
),
Threads: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "threads"),
"PerfOS_System.Threads",
nil,
nil,
),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *SystemCollector) Collect(ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Println("[ERROR] failed collecting system metrics:", desc, err)
return err
}
return nil
}
type Win32_PerfRawData_PerfOS_System struct {
ContextSwitchesPersec uint32
ExceptionDispatchesPersec uint32
Frequency_Object uint64
ProcessorQueueLength uint32
SystemCallsPersec uint32
SystemUpTime uint64
Threads uint32
Timestamp_Object uint64
}
func (c *SystemCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_PerfOS_System
if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil {
return nil, err
}
ch <- prometheus.MustNewConstMetric(
c.ContextSwitchesTotal,
prometheus.GaugeValue,
float64(dst[0].ContextSwitchesPersec),
)
ch <- prometheus.MustNewConstMetric(
c.ExceptionDispatchesTotal,
prometheus.GaugeValue,
float64(dst[0].ExceptionDispatchesPersec),
)
ch <- prometheus.MustNewConstMetric(
c.ProcessorQueueLength,
prometheus.GaugeValue,
float64(dst[0].ProcessorQueueLength),
)
ch <- prometheus.MustNewConstMetric(
c.SystemCallsTotal,
prometheus.GaugeValue,
float64(dst[0].SystemCallsPersec),
)
ch <- prometheus.MustNewConstMetric(
c.SystemUpTime,
prometheus.GaugeValue,
// convert from Windows timestamp (1 jan 1601) to unix timestamp (1 jan 1970)
float64(dst[0].SystemUpTime-116444736000000000)/float64(dst[0].Frequency_Object),
)
ch <- prometheus.MustNewConstMetric(
c.Threads,
prometheus.GaugeValue,
float64(dst[0].Threads),
)
return nil, nil
}

335
collector/vmware.go Normal file
View File

@@ -0,0 +1,335 @@
// returns data points from Win32_PerfRawData_vmGuestLib_VMem and Win32_PerfRawData_vmGuestLib_VCPU
package collector
import (
"log"
"github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
Factories["vmware"] = NewVmwareCollector
}
// A VmwareCollector is a Prometheus collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics
type VmwareCollector struct {
MemActive *prometheus.Desc
MemBallooned *prometheus.Desc
MemLimit *prometheus.Desc
MemMapped *prometheus.Desc
MemOverhead *prometheus.Desc
MemReservation *prometheus.Desc
MemShared *prometheus.Desc
MemSharedSaved *prometheus.Desc
MemShares *prometheus.Desc
MemSwapped *prometheus.Desc
MemTargetSize *prometheus.Desc
MemUsed *prometheus.Desc
CpuLimitMHz *prometheus.Desc
CpuReservationMHz *prometheus.Desc
CpuShares *prometheus.Desc
CpuStolenTotal *prometheus.Desc
CpuTimeTotal *prometheus.Desc
EffectiveVMSpeedMHz *prometheus.Desc
HostProcessorSpeedMHz *prometheus.Desc
}
func NewVmwareCollector() (Collector, error) {
const subsystem = "vmware"
return &VmwareCollector{
MemActive: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mem_active_bytes"),
"(MemActiveMB)",
nil,
nil,
),
MemBallooned: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mem_ballooned_bytes"),
"(MemBalloonedMB)",
nil,
nil,
),
MemLimit: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mem_limit_bytes"),
"(MemLimitMB)",
nil,
nil,
),
MemMapped: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mem_mapped_bytes"),
"(MemMappedMB)",
nil,
nil,
),
MemOverhead: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mem_overhead_bytes"),
"(MemOverheadMB)",
nil,
nil,
),
MemReservation: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mem_reservation_bytes"),
"(MemReservationMB)",
nil,
nil,
),
MemShared: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mem_shared_bytes"),
"(MemSharedMB)",
nil,
nil,
),
MemSharedSaved: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mem_shared_saved_bytes"),
"(MemSharedSavedMB)",
nil,
nil,
),
MemShares: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mem_shares"),
"(MemShares)",
nil,
nil,
),
MemSwapped: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mem_swapped_bytes"),
"(MemSwappedMB)",
nil,
nil,
),
MemTargetSize: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mem_target_size_bytes"),
"(MemTargetSizeMB)",
nil,
nil,
),
MemUsed: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "mem_used_bytes"),
"(MemUsedMB)",
nil,
nil,
),
CpuLimitMHz: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "cpu_limit_mhz"),
"(CpuLimitMHz)",
nil,
nil,
),
CpuReservationMHz: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "cpu_reservation_mhz"),
"(CpuReservationMHz)",
nil,
nil,
),
CpuShares: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "cpu_shares"),
"(CpuShares)",
nil,
nil,
),
CpuStolenTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "cpu_stolen_seconds_total"),
"(CpuStolenMs)",
nil,
nil,
),
CpuTimeTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "cpu_time_seconds_total"),
"(CpuTimePercents)",
nil,
nil,
),
EffectiveVMSpeedMHz: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "effective_vm_speed_mhz"),
"(EffectiveVMSpeedMHz)",
nil,
nil,
),
HostProcessorSpeedMHz: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "host_processor_speed_mhz"),
"(HostProcessorSpeedMHz)",
nil,
nil,
),
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *VmwareCollector) Collect(ch chan<- prometheus.Metric) error {
if desc, err := c.collectMem(ch); err != nil {
log.Println("[ERROR] failed collecting vmware memory metrics:", desc, err)
return err
}
if desc, err := c.collectCpu(ch); err != nil {
log.Println("[ERROR] failed collecting vmware cpu metrics:", desc, err)
return err
}
return nil
}
type Win32_PerfRawData_vmGuestLib_VMem struct {
MemActiveMB uint64
MemBalloonedMB uint64
MemLimitMB uint64
MemMappedMB uint64
MemOverheadMB uint64
MemReservationMB uint64
MemSharedMB uint64
MemSharedSavedMB uint64
MemShares uint64
MemSwappedMB uint64
MemTargetSizeMB uint64
MemUsedMB uint64
}
type Win32_PerfRawData_vmGuestLib_VCPU struct {
CpuLimitMHz uint64
CpuReservationMHz uint64
CpuShares uint64
CpuStolenMs uint64
CpuTimePercents uint64
EffectiveVMSpeedMHz uint64
HostProcessorSpeedMHz uint64
}
func (c *VmwareCollector) collectMem(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_vmGuestLib_VMem
q := wmi.CreateQuery(&dst, "")
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
ch <- prometheus.MustNewConstMetric(
c.MemActive,
prometheus.GaugeValue,
mbToBytes(dst[0].MemActiveMB),
)
ch <- prometheus.MustNewConstMetric(
c.MemBallooned,
prometheus.GaugeValue,
mbToBytes(dst[0].MemBalloonedMB),
)
ch <- prometheus.MustNewConstMetric(
c.MemLimit,
prometheus.GaugeValue,
mbToBytes(dst[0].MemLimitMB),
)
ch <- prometheus.MustNewConstMetric(
c.MemMapped,
prometheus.GaugeValue,
mbToBytes(dst[0].MemMappedMB),
)
ch <- prometheus.MustNewConstMetric(
c.MemOverhead,
prometheus.GaugeValue,
mbToBytes(dst[0].MemOverheadMB),
)
ch <- prometheus.MustNewConstMetric(
c.MemReservation,
prometheus.GaugeValue,
mbToBytes(dst[0].MemReservationMB),
)
ch <- prometheus.MustNewConstMetric(
c.MemShared,
prometheus.GaugeValue,
mbToBytes(dst[0].MemSharedMB),
)
ch <- prometheus.MustNewConstMetric(
c.MemSharedSaved,
prometheus.GaugeValue,
mbToBytes(dst[0].MemSharedSavedMB),
)
ch <- prometheus.MustNewConstMetric(
c.MemShares,
prometheus.GaugeValue,
float64(dst[0].MemShares),
)
ch <- prometheus.MustNewConstMetric(
c.MemSwapped,
prometheus.GaugeValue,
mbToBytes(dst[0].MemSwappedMB),
)
ch <- prometheus.MustNewConstMetric(
c.MemTargetSize,
prometheus.GaugeValue,
mbToBytes(dst[0].MemTargetSizeMB),
)
ch <- prometheus.MustNewConstMetric(
c.MemUsed,
prometheus.GaugeValue,
mbToBytes(dst[0].MemUsedMB),
)
return nil, nil
}
func mbToBytes(mb uint64) float64 {
return float64(mb * 1024 * 1024)
}
func (c *VmwareCollector) collectCpu(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_vmGuestLib_VCPU
q := wmi.CreateQuery(&dst, "")
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
ch <- prometheus.MustNewConstMetric(
c.CpuLimitMHz,
prometheus.GaugeValue,
float64(dst[0].CpuLimitMHz),
)
ch <- prometheus.MustNewConstMetric(
c.CpuReservationMHz,
prometheus.GaugeValue,
float64(dst[0].CpuReservationMHz),
)
ch <- prometheus.MustNewConstMetric(
c.CpuShares,
prometheus.GaugeValue,
float64(dst[0].CpuShares),
)
ch <- prometheus.MustNewConstMetric(
c.CpuStolenTotal,
prometheus.CounterValue,
float64(dst[0].CpuStolenMs)*ticksToSecondsScaleFactor,
)
ch <- prometheus.MustNewConstMetric(
c.CpuTimeTotal,
prometheus.CounterValue,
float64(dst[0].CpuTimePercents)*ticksToSecondsScaleFactor,
)
ch <- prometheus.MustNewConstMetric(
c.EffectiveVMSpeedMHz,
prometheus.GaugeValue,
float64(dst[0].EffectiveVMSpeedMHz),
)
ch <- prometheus.MustNewConstMetric(
c.HostProcessorSpeedMHz,
prometheus.GaugeValue,
float64(dst[0].HostProcessorSpeedMHz),
)
return nil, nil
}

View File

@@ -1,10 +1,19 @@
package collector
import "github.com/prometheus/client_golang/prometheus"
import (
"bytes"
"reflect"
"strings"
"github.com/prometheus/client_golang/prometheus"
)
// ...
const (
Namespace = "wmi"
// Conversion factors
ticksToSecondsScaleFactor = 1 / 1e7
)
// Factories ...
@@ -15,3 +24,30 @@ type Collector interface {
// Get new metrics and expose them via prometheus registry.
Collect(ch chan<- prometheus.Metric) (err error)
}
// This is adapted from StackExchange/wmi/wmi.go, and lets us change the class
// name being queried for:
// CreateQuery returns a WQL query string that queries all columns of src. where
// is an optional string that is appended to the query, to be used with WHERE
// clauses. In such a case, the "WHERE" string should appear at the beginning.
func createQuery(src interface{}, class, where string) string {
var b bytes.Buffer
b.WriteString("SELECT ")
s := reflect.Indirect(reflect.ValueOf(src))
t := s.Type()
if s.Kind() == reflect.Slice {
t = t.Elem()
}
if t.Kind() != reflect.Struct {
return ""
}
var fields []string
for i := 0; i < t.NumField(); i++ {
fields = append(fields, t.Field(i).Name)
}
b.WriteString(strings.Join(fields, ", "))
b.WriteString(" FROM ")
b.WriteString(class)
b.WriteString(" " + where)
return b.String()
}

View File

@@ -3,6 +3,7 @@ package main
import (
"flag"
"fmt"
"io"
"net/http"
"os"
"sort"
@@ -12,8 +13,10 @@ import (
"golang.org/x/sys/windows/svc"
"github.com/StackExchange/wmi"
"github.com/martinlindhe/wmi_exporter/collector"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/prometheus/common/log"
"github.com/prometheus/common/version"
)
@@ -24,26 +27,31 @@ type WmiCollector struct {
}
const (
defaultCollectors = "logical_disk,os"
serviceName = "wmi_exporter"
defaultCollectors = "cpu,cs,logical_disk,net,os,service,system"
defaultCollectorsPlaceholder = "[defaults]"
serviceName = "wmi_exporter"
)
var (
scrapeDurations = prometheus.NewSummaryVec(
prometheus.SummaryOpts{
Namespace: collector.Namespace,
Subsystem: "exporter",
Name: "scrape_duration_seconds",
Help: "wmi_exporter: Duration of a scrape job.",
},
[]string{"collector", "result"},
scrapeDurationDesc = prometheus.NewDesc(
prometheus.BuildFQName(collector.Namespace, "exporter", "collector_duration_seconds"),
"wmi_exporter: Duration of a collection.",
[]string{"collector"},
nil,
)
scrapeSuccessDesc = prometheus.NewDesc(
prometheus.BuildFQName(collector.Namespace, "exporter", "collector_success"),
"wmi_exporter: Whether the collector was successful.",
[]string{"collector"},
nil,
)
)
// Describe sends all the descriptors of the collectors included to
// the provided channel.
func (coll WmiCollector) Describe(ch chan<- *prometheus.Desc) {
scrapeDurations.Describe(ch)
ch <- scrapeDurationDesc
ch <- scrapeSuccessDesc
}
// Collect sends the collected metrics from each of the collectors to
@@ -59,7 +67,6 @@ func (coll WmiCollector) Collect(ch chan<- prometheus.Metric) {
}(name, c)
}
wg.Wait()
scrapeDurations.Collect(ch)
}
func filterAvailableCollectors(collectors string) string {
@@ -77,21 +84,50 @@ func execute(name string, c collector.Collector, ch chan<- prometheus.Metric) {
begin := time.Now()
err := c.Collect(ch)
duration := time.Since(begin)
var result string
var success float64
if err != nil {
log.Errorf("ERROR: %s collector failed after %fs: %s", name, duration.Seconds(), err)
result = "error"
success = 0
} else {
log.Debugf("OK: %s collector succeeded after %fs.", name, duration.Seconds())
result = "success"
success = 1
}
scrapeDurations.WithLabelValues(name, result).Observe(duration.Seconds())
ch <- prometheus.MustNewConstMetric(
scrapeDurationDesc,
prometheus.GaugeValue,
duration.Seconds(),
name,
)
ch <- prometheus.MustNewConstMetric(
scrapeSuccessDesc,
prometheus.GaugeValue,
success,
name,
)
}
func expandEnabledCollectors(enabled string) []string {
expanded := strings.Replace(enabled, defaultCollectorsPlaceholder, defaultCollectors, -1)
separated := strings.Split(expanded, ",")
unique := map[string]bool{}
for _, s := range separated {
if s != "" {
unique[s] = true
}
}
result := make([]string, 0, len(unique))
for s, _ := range unique {
result = append(result, s)
}
return result
}
func loadCollectors(list string) (map[string]collector.Collector, error) {
collectors := map[string]collector.Collector{}
for _, name := range strings.Split(list, ",") {
enabled := expandEnabledCollectors(list)
for _, name := range enabled {
fn, ok := collector.Factories[name]
if !ok {
return nil, fmt.Errorf("collector '%s' not available", name)
@@ -109,14 +145,34 @@ func init() {
prometheus.MustRegister(version.NewCollector("wmi_exporter"))
}
func initWbem() {
// This initialization prevents a memory leak on WMF 5+. See
// https://github.com/martinlindhe/wmi_exporter/issues/77 and linked issues
// for details.
log.Debugf("Initializing SWbemServices")
s, err := wmi.InitializeSWbemServices(wmi.DefaultClient)
if err != nil {
log.Fatal(err)
}
wmi.DefaultClient.SWbemServicesClient = s
}
func usage() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, "\nNote: If executing from Powershell, the flags need to quoted. For example:\n%s\n",
"\twmi_exporter \"-collectors.enabled\" iis")
}
func main() {
var (
showVersion = flag.Bool("version", false, "Print version information.")
listenAddress = flag.String("telemetry.addr", ":9182", "host:port for WMI exporter.")
metricsPath = flag.String("telemetry.path", "/metrics", "URL path for surfacing collected metrics.")
enabledCollectors = flag.String("collectors.enabled", filterAvailableCollectors(defaultCollectors), "Comma-separated list of collectors to use.")
enabledCollectors = flag.String("collectors.enabled", filterAvailableCollectors(defaultCollectors), "Comma-separated list of collectors to use. Use '[default]' as a placeholder for all the collectors enabled by default")
printCollectors = flag.Bool("collectors.print", false, "If true, print available collectors and exit.")
)
flag.Usage = usage
flag.Parse()
if *showVersion {
@@ -137,6 +193,8 @@ func main() {
return
}
initWbem()
isInteractive, err := svc.IsAnInteractiveSession()
if err != nil {
log.Fatal(err)
@@ -157,7 +215,8 @@ func main() {
nodeCollector := WmiCollector{collectors: collectors}
prometheus.MustRegister(nodeCollector)
http.Handle(*metricsPath, prometheus.Handler())
http.Handle(*metricsPath, promhttp.Handler())
http.HandleFunc("/health", healthCheck)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, *metricsPath, http.StatusMovedPermanently)
})
@@ -167,9 +226,7 @@ func main() {
go func() {
log.Infoln("Starting server on", *listenAddress)
if err := http.ListenAndServe(*listenAddress, nil); err != nil {
log.Fatalf("cannot start WMI exporter: %s", err)
}
log.Fatalf("cannot start WMI exporter: %s", http.ListenAndServe(*listenAddress, nil))
}()
for {
@@ -180,9 +237,14 @@ func main() {
}
}
func healthCheck(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
io.WriteString(w, `{"status":"ok"}`)
}
func keys(m map[string]collector.Collector) []string {
ret := make([]string, 0, len(m))
for key, _ := range m {
for key := range m {
ret = append(ret, key)
}
return ret

49
exporter_test.go Normal file
View File

@@ -0,0 +1,49 @@
package main
import (
"sort"
"strings"
"testing"
)
type expansionTestCase struct {
input string
expectedOutput []string
}
func TestExpandEnabled(t *testing.T) {
expansionTests := []expansionTestCase{
{"", []string{}},
// Default case
{"cs,os", []string{"cs", "os"}},
// Placeholder expansion
{defaultCollectorsPlaceholder, strings.Split(defaultCollectors, ",")},
// De-duplication
{"cs,cs", []string{"cs"}},
// De-duplicate placeholder
{defaultCollectorsPlaceholder + "," + defaultCollectorsPlaceholder, strings.Split(defaultCollectors, ",")},
// Composite case
{"foo," + defaultCollectorsPlaceholder + ",bar", append(strings.Split(defaultCollectors, ","), "foo", "bar")},
}
for _, testCase := range expansionTests {
output := expandEnabledCollectors(testCase.input)
sort.Strings(output)
success := true
if len(output) != len(testCase.expectedOutput) {
success = false
} else {
sort.Strings(testCase.expectedOutput)
for idx := range output {
if output[idx] != testCase.expectedOutput[idx] {
success = false
break
}
}
}
if !success {
t.Error("For", testCase.input, "expected", testCase.expectedOutput, "got", output)
}
}
}

View File

@@ -42,10 +42,8 @@ function Get-FileIfNotExists {
$sourceDir = mkdir -Force Source
mkdir -Force Work,Output | Out-Null
Write-Verbose "Downloading files"
# Somewhat obscure url, points to WiX 3.10 binary release
Write-Verbose "Downloading WiX..."
Get-FileIfNotExists "http://download-codeplex.sec.s-msft.com/Download/Release?ProjectName=wix&DownloadId=1504735&FileTime=130906491728530000&Build=21031" "$sourceDir\wix-binaries.zip"
Get-FileIfNotExists "https://github.com/wixtoolset/wix3/releases/download/wix311rtm/wix311-binaries.zip" "$sourceDir\wix-binaries.zip"
mkdir -Force WiX | Out-Null
Expand-Archive -Path "${sourceDir}\wix-binaries.zip" -DestinationPath WiX -Force
@@ -58,4 +56,4 @@ Invoke-Expression "WiX\candle.exe -nologo -arch $wixArch $wixOpts -out Work\wmi_
Invoke-Expression "WiX\light.exe -nologo -spdb $wixOpts -out `"Output\wmi_exporter-${Version}-${Arch}.msi`" Work\wmi_exporter.wixobj"
Write-Verbose "Done!"
Pop-Location
Pop-Location

View File

@@ -34,9 +34,9 @@
<ComponentGroup Id="Files" Directory="APPLICATIONROOTDIRECTORY">
<Component>
<File Id="wmi_exporter.exe" Name="wmi_exporter.exe" Source="Work\wmi_exporter.exe" KeyPath="yes">
<fw:FirewallException Id="MetricsEndpoint" Name="WMI Exporter (HTTP [LISTEN_PORT])" Description="WMI Exporter HTTP endpoint" Port="[LISTEN_PORT]" Protocol="tcp" Scope="any" />
<fw:FirewallException Id="MetricsEndpoint" Name="WMI Exporter (HTTP [LISTEN_PORT])" Description="WMI Exporter HTTP endpoint" Port="[LISTEN_PORT]" Protocol="tcp" Scope="any" IgnoreFailure="yes" />
</File>
<ServiceInstall Id="InstallExporterService" Name="wmi_exporter" ErrorControl="normal" Start="auto" Type="ownProcess" Arguments="-log.format logger:eventlog?name=wmi_exporter [CollectorsFlag] [ListenFlag] [MetricsPathFlag]" />
<ServiceInstall Id="InstallExporterService" Name="wmi_exporter" DisplayName="WMI exporter" Description="Exports Prometheus metrics from WMI queries" ErrorControl="normal" Start="auto" Type="ownProcess" Arguments="-log.format logger:eventlog?name=wmi_exporter [CollectorsFlag] [ListenFlag] [MetricsPathFlag]" />
<ServiceControl Id="ServiceStateControl" Name="wmi_exporter" Remove="uninstall" Start="install" Stop="both" />
</Component>
</ComponentGroup>

View File

@@ -0,0 +1,31 @@
Param(
[Parameter(Mandatory=$true)]
$Class,
[Parameter(Mandatory=$false)]
$CollectorName = ($Class -replace 'Win32_PerfRawData_Perf',''),
[Parameter(Mandatory=$false)]
$ComputerName = "localhost",
[Parameter(Mandatory=$false)]
$Credential
)
$ErrorActionPreference = "Stop"
if($Credential -ne $null) {
$wmiObject = Get-WMIObject -ComputerName $ComputerName -Credential $Credential -Class $Class
}
else {
$wmiObject = Get-WMIObject -ComputerName $ComputerName -Class $Class
}
$members = $wmiObject `
| Get-Member -MemberType Properties `
| Where-Object { $_.Definition -Match '^u?int' -and $_.Name -NotMatch '_' } `
| Select-Object Name, @{Name="Type";Expression={$_.Definition.Split(" ")[0]}}
$input = @{
"Class"=$Class;
"CollectorName"=$CollectorName;
"Members"=$members
} | ConvertTo-Json
$outFileName = "..\..\collector\$CollectorName.go".ToLower()
$input | .\collector-generator.exe | Out-File -NoClobber -Encoding UTF8 $outFileName
go fmt $outFileName

View File

@@ -0,0 +1,17 @@
# Collector generator
Generates a collector skeleton implementation from a WMI class.
## Usage
Build the generator:
```bash
go build .
```
Run the script to query the WMI service and send the output to the generator:
```powershell
.\New-Collector.ps1 -Class Win32_PerfRawData_PerfOS_Processor
```
This will generate a collector. The collector name is generated by first removing `Win32_PerfRawData_Perf` and lower-casing, so `Win32_PerfRawData_PerfOS_Processor` will generate `os_processor.go`. This can be overridden by passing `-CollectorName` to the script.

View File

@@ -0,0 +1,62 @@
// returns data points from {{ .Class }}
// <add link to documentation here> - {{ .Class }} class
package collector
import (
"log"
"github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus"
)
func init() {
Factories["{{ .CollectorName | toLower }}"] = New{{ .CollectorName }}Collector
}
// A {{ .CollectorName }}Collector is a Prometheus collector for WMI {{ .Class }} metrics
type {{ .CollectorName }}Collector struct {
{{- range $m := .Members }}
{{ $m.Name }} *prometheus.Desc
{{- end }}
}
// New{{ .CollectorName }}Collector ...
func New{{ .CollectorName }}Collector() (Collector, error) {
const subsystem = "{{ .CollectorName | toLower }}"
return &{{ .CollectorName }}Collector{
{{- range $m := .Members }}
{{ $m.Name }}: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "{{ $m.Name | toSnakeCase }}"),
"({{ $m.Name }})",
nil,
nil,
),
{{- end }}
}, nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *{{ .CollectorName }}Collector) Collect(ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
log.Println("[ERROR] failed collecting {{ .CollectorName | toLower }} metrics:", desc, err)
return err
}
return nil
}
type {{ .Class }} struct {
Name string
{{ range $m := .Members }}
{{ $m.Name }} {{ $m.Type }}
{{- end }}
}
func (c *{{ .CollectorName }}Collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []{{ .Class }}
q := wmi.CreateQuery(&dst, "")
if err := wmi.Query(q, &dst); err != nil {
return nil, err
}
{{ range $m := .Members }}
ch <- prometheus.MustNewConstMetric(
c.{{ $m.Name }},
prometheus.GaugeValue,
float64(dst[0].{{ $m.Name }}),
)
{{ end }}
return nil, nil
}

View File

@@ -0,0 +1,60 @@
package main
import (
"encoding/json"
"io/ioutil"
"os"
"strings"
"text/template"
"unicode"
)
type TemplateData struct {
CollectorName string
Class string
Members []Member
}
type Member struct {
Name string
Type string
}
func main() {
bytes, err := ioutil.ReadAll(os.Stdin)
if err != nil {
panic(err)
}
var data TemplateData
if err := json.Unmarshal(bytes, &data); err != nil {
panic(err)
}
funcs := template.FuncMap{
"toLower": strings.ToLower,
"toSnakeCase": toSnakeCase,
}
template, err := template.New("template").Funcs(funcs).ParseFiles("collector.template")
if err != nil {
panic(err)
}
err = template.ExecuteTemplate(os.Stdout, "collector.template", data)
if err != nil {
panic(err)
}
}
// https://gist.github.com/elwinar/14e1e897fdbe4d3432e1
func toSnakeCase(in string) string {
runes := []rune(in)
length := len(runes)
var out []rune
for i := 0; i < length; i++ {
if i > 0 && unicode.IsUpper(runes[i]) && ((i+1 < length && unicode.IsLower(runes[i+1])) || unicode.IsLower(runes[i-1])) {
out = append(out, '_')
}
out = append(out, unicode.ToLower(runes[i]))
}
return string(out)
}

View File

@@ -1,4 +1,6 @@
wmi
===
Package wmi provides a WQL interface for WMI on Windows.
Package wmi provides a WQL interface to Windows WMI.
Note: It interfaces with WMI on the local machine, therefore it only runs on Windows.

260
vendor/github.com/StackExchange/wmi/swbemservices.go generated vendored Normal file
View File

@@ -0,0 +1,260 @@
// +build windows
package wmi
import (
"fmt"
"reflect"
"runtime"
"sync"
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
// SWbemServices is used to access wmi. See https://msdn.microsoft.com/en-us/library/aa393719(v=vs.85).aspx
type SWbemServices struct {
//TODO: track namespace. Not sure if we can re connect to a different namespace using the same instance
cWMIClient *Client //This could also be an embedded struct, but then we would need to branch on Client vs SWbemServices in the Query method
sWbemLocatorIUnknown *ole.IUnknown
sWbemLocatorIDispatch *ole.IDispatch
queries chan *queryRequest
closeError chan error
lQueryorClose sync.Mutex
}
type queryRequest struct {
query string
dst interface{}
args []interface{}
finished chan error
}
// InitializeSWbemServices will return a new SWbemServices object that can be used to query WMI
func InitializeSWbemServices(c *Client, connectServerArgs ...interface{}) (*SWbemServices, error) {
//fmt.Println("InitializeSWbemServices: Starting")
//TODO: implement connectServerArgs as optional argument for init with connectServer call
s := new(SWbemServices)
s.cWMIClient = c
s.queries = make(chan *queryRequest)
initError := make(chan error)
go s.process(initError)
err, ok := <-initError
if ok {
return nil, err //Send error to caller
}
//fmt.Println("InitializeSWbemServices: Finished")
return s, nil
}
// Close will clear and release all of the SWbemServices resources
func (s *SWbemServices) Close() error {
s.lQueryorClose.Lock()
if s == nil || s.sWbemLocatorIDispatch == nil {
s.lQueryorClose.Unlock()
return fmt.Errorf("SWbemServices is not Initialized")
}
if s.queries == nil {
s.lQueryorClose.Unlock()
return fmt.Errorf("SWbemServices has been closed")
}
//fmt.Println("Close: sending close request")
var result error
ce := make(chan error)
s.closeError = ce //Race condition if multiple callers to close. May need to lock here
close(s.queries) //Tell background to shut things down
s.lQueryorClose.Unlock()
err, ok := <-ce
if ok {
result = err
}
//fmt.Println("Close: finished")
return result
}
func (s *SWbemServices) process(initError chan error) {
//fmt.Println("process: starting background thread initialization")
//All OLE/WMI calls must happen on the same initialized thead, so lock this goroutine
runtime.LockOSThread()
defer runtime.LockOSThread()
err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED)
if err != nil {
oleCode := err.(*ole.OleError).Code()
if oleCode != ole.S_OK && oleCode != S_FALSE {
initError <- fmt.Errorf("ole.CoInitializeEx error: %v", err)
return
}
}
defer ole.CoUninitialize()
unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator")
if err != nil {
initError <- fmt.Errorf("CreateObject SWbemLocator error: %v", err)
return
} else if unknown == nil {
initError <- ErrNilCreateObject
return
}
defer unknown.Release()
s.sWbemLocatorIUnknown = unknown
dispatch, err := s.sWbemLocatorIUnknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
initError <- fmt.Errorf("SWbemLocator QueryInterface error: %v", err)
return
}
defer dispatch.Release()
s.sWbemLocatorIDispatch = dispatch
// we can't do the ConnectServer call outside the loop unless we find a way to track and re-init the connectServerArgs
//fmt.Println("process: initialized. closing initError")
close(initError)
//fmt.Println("process: waiting for queries")
for q := range s.queries {
//fmt.Printf("process: new query: len(query)=%d\n", len(q.query))
errQuery := s.queryBackground(q)
//fmt.Println("process: s.queryBackground finished")
if errQuery != nil {
q.finished <- errQuery
}
close(q.finished)
}
//fmt.Println("process: queries channel closed")
s.queries = nil //set channel to nil so we know it is closed
//TODO: I think the Release/Clear calls can panic if things are in a bad state.
//TODO: May need to recover from panics and send error to method caller instead.
close(s.closeError)
}
// Query runs the WQL query using a SWbemServices instance and appends the values to dst.
//
// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in
// the query must have the same name in dst. Supported types are all signed and
// unsigned integers, time.Time, string, bool, or a pointer to one of those.
// Array types are not supported.
//
// By default, the local machine and default namespace are used. These can be
// changed using connectServerArgs. See
// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details.
func (s *SWbemServices) Query(query string, dst interface{}, connectServerArgs ...interface{}) error {
s.lQueryorClose.Lock()
if s == nil || s.sWbemLocatorIDispatch == nil {
s.lQueryorClose.Unlock()
return fmt.Errorf("SWbemServices is not Initialized")
}
if s.queries == nil {
s.lQueryorClose.Unlock()
return fmt.Errorf("SWbemServices has been closed")
}
//fmt.Println("Query: Sending query request")
qr := queryRequest{
query: query,
dst: dst,
args: connectServerArgs,
finished: make(chan error),
}
s.queries <- &qr
s.lQueryorClose.Unlock()
err, ok := <-qr.finished
if ok {
//fmt.Println("Query: Finished with error")
return err //Send error to caller
}
//fmt.Println("Query: Finished")
return nil
}
func (s *SWbemServices) queryBackground(q *queryRequest) error {
if s == nil || s.sWbemLocatorIDispatch == nil {
return fmt.Errorf("SWbemServices is not Initialized")
}
wmi := s.sWbemLocatorIDispatch //Should just rename in the code, but this will help as we break things apart
//fmt.Println("queryBackground: Starting")
dv := reflect.ValueOf(q.dst)
if dv.Kind() != reflect.Ptr || dv.IsNil() {
return ErrInvalidEntityType
}
dv = dv.Elem()
mat, elemType := checkMultiArg(dv)
if mat == multiArgTypeInvalid {
return ErrInvalidEntityType
}
// service is a SWbemServices
serviceRaw, err := oleutil.CallMethod(wmi, "ConnectServer", q.args...)
if err != nil {
return err
}
service := serviceRaw.ToIDispatch()
defer serviceRaw.Clear()
// result is a SWBemObjectSet
resultRaw, err := oleutil.CallMethod(service, "ExecQuery", q.query)
if err != nil {
return err
}
result := resultRaw.ToIDispatch()
defer resultRaw.Clear()
count, err := oleInt64(result, "Count")
if err != nil {
return err
}
enumProperty, err := result.GetProperty("_NewEnum")
if err != nil {
return err
}
defer enumProperty.Clear()
enum, err := enumProperty.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant)
if err != nil {
return err
}
if enum == nil {
return fmt.Errorf("can't get IEnumVARIANT, enum is nil")
}
defer enum.Release()
// Initialize a slice with Count capacity
dv.Set(reflect.MakeSlice(dv.Type(), 0, int(count)))
var errFieldMismatch error
for itemRaw, length, err := enum.Next(1); length > 0; itemRaw, length, err = enum.Next(1) {
if err != nil {
return err
}
err := func() error {
// item is a SWbemObject, but really a Win32_Process
item := itemRaw.ToIDispatch()
defer item.Release()
ev := reflect.New(elemType)
if err = s.cWMIClient.loadEntity(ev.Interface(), item); err != nil {
if _, ok := err.(*ErrFieldMismatch); ok {
// We continue loading entities even in the face of field mismatch errors.
// If we encounter any other error, that other error is returned. Otherwise,
// an ErrFieldMismatch is returned.
errFieldMismatch = err
} else {
return err
}
}
if mat != multiArgTypeStructPtr {
ev = ev.Elem()
}
dv.Set(reflect.Append(dv, ev))
return nil
}()
if err != nil {
return err
}
}
//fmt.Println("queryBackground: Finished")
return errFieldMismatch
}

View File

@@ -72,7 +72,10 @@ func QueryNamespace(query string, dst interface{}, namespace string) error {
//
// Query is a wrapper around DefaultClient.Query.
func Query(query string, dst interface{}, connectServerArgs ...interface{}) error {
return DefaultClient.Query(query, dst, connectServerArgs...)
if DefaultClient.SWbemServicesClient == nil {
return DefaultClient.Query(query, dst, connectServerArgs...)
}
return DefaultClient.SWbemServicesClient.Query(query, dst, connectServerArgs...)
}
// A Client is an WMI query client.
@@ -99,6 +102,11 @@ type Client struct {
// Setting this to true allows custom queries to be used with full
// struct definitions instead of having to define multiple structs.
AllowMissingFields bool
// SWbemServiceClient is an optional SWbemServices object that can be
// initialized and then reused across multiple queries. If it is null
// then the method will initialize a new temporary client each time.
SWbemServicesClient *SWbemServices
}
// DefaultClient is the default Client and is used by Query, QueryNamespace
@@ -362,6 +370,21 @@ func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismat
}
}
default:
// Only support []string slices for now
if f.Kind() == reflect.Slice && f.Type().Elem().Kind() == reflect.String {
safeArray := prop.ToArray()
if safeArray != nil {
arr := safeArray.ToValueArray()
fArr := reflect.MakeSlice(f.Type(), len(arr), len(arr))
for i, v := range arr {
s := fArr.Index(i)
s.SetString(v.(string))
}
f.Set(fArr)
break
}
}
typeof := reflect.TypeOf(val)
if typeof == nil && (isPtr || c.NonePtrZero) {
if (isPtr && c.PtrNil) || (!isPtr && c.NonePtrZero) {

12
vendor/github.com/go-ole/go-ole/variant_s390x.go generated vendored Normal file
View File

@@ -0,0 +1,12 @@
// +build s390x
package ole
type VARIANT struct {
VT VT // 2
wReserved1 uint16 // 4
wReserved2 uint16 // 6
wReserved3 uint16 // 8
Val int64 // 16
_ [8]byte // 24
}

View File

@@ -61,7 +61,6 @@ var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
func DecodeVarint(buf []byte) (x uint64, n int) {
// x, n already 0
for shift := uint(0); shift < 64; shift += 7 {
if n >= len(buf) {
return 0, 0
@@ -78,13 +77,7 @@ func DecodeVarint(buf []byte) (x uint64, n int) {
return 0, 0
}
// DecodeVarint reads a varint-encoded integer from the Buffer.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
func (p *Buffer) DecodeVarint() (x uint64, err error) {
// x, err already 0
func (p *Buffer) decodeVarintSlow() (x uint64, err error) {
i := p.index
l := len(p.buf)
@@ -107,6 +100,107 @@ func (p *Buffer) DecodeVarint() (x uint64, err error) {
return
}
// DecodeVarint reads a varint-encoded integer from the Buffer.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
func (p *Buffer) DecodeVarint() (x uint64, err error) {
i := p.index
buf := p.buf
if i >= len(buf) {
return 0, io.ErrUnexpectedEOF
} else if buf[i] < 0x80 {
p.index++
return uint64(buf[i]), nil
} else if len(buf)-i < 10 {
return p.decodeVarintSlow()
}
var b uint64
// we already checked the first byte
x = uint64(buf[i]) - 0x80
i++
b = uint64(buf[i])
i++
x += b << 7
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 7
b = uint64(buf[i])
i++
x += b << 14
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 14
b = uint64(buf[i])
i++
x += b << 21
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 21
b = uint64(buf[i])
i++
x += b << 28
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 28
b = uint64(buf[i])
i++
x += b << 35
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 35
b = uint64(buf[i])
i++
x += b << 42
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 42
b = uint64(buf[i])
i++
x += b << 49
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 49
b = uint64(buf[i])
i++
x += b << 56
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 56
b = uint64(buf[i])
i++
x += b << 63
if b&0x80 == 0 {
goto done
}
// x -= 0x80 << 63 // Always zero.
return 0, errOverflow
done:
p.index = i
return x, nil
}
// DecodeFixed64 reads a 64-bit integer from the Buffer.
// This is the format for the
// fixed64, sfixed64, and double protocol buffer types.
@@ -340,6 +434,8 @@ func (p *Buffer) DecodeGroup(pb Message) error {
// Buffer and places the decoded result in pb. If the struct
// underlying pb does not match the data in the buffer, the results can be
// unpredictable.
//
// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
func (p *Buffer) Unmarshal(pb Message) error {
// If the object can unmarshal itself, let it.
if u, ok := pb.(Unmarshaler); ok {

View File

@@ -234,10 +234,6 @@ func Marshal(pb Message) ([]byte, error) {
}
p := NewBuffer(nil)
err := p.Marshal(pb)
var state errorState
if err != nil && !state.shouldContinue(err, nil) {
return nil, err
}
if p.buf == nil && err == nil {
// Return a non-nil slice on success.
return []byte{}, nil
@@ -266,11 +262,8 @@ func (p *Buffer) Marshal(pb Message) error {
// Can the object marshal itself?
if m, ok := pb.(Marshaler); ok {
data, err := m.Marshal()
if err != nil {
return err
}
p.buf = append(p.buf, data...)
return nil
return err
}
t, base, err := getbase(pb)
@@ -282,7 +275,7 @@ func (p *Buffer) Marshal(pb Message) error {
}
if collectStats {
stats.Encode++
(stats).Encode++ // Parens are to work around a goimports bug.
}
if len(p.buf) > maxMarshalSize {
@@ -309,7 +302,7 @@ func Size(pb Message) (n int) {
}
if collectStats {
stats.Size++
(stats).Size++ // Parens are to work around a goimports bug.
}
return
@@ -1014,7 +1007,6 @@ func size_slice_struct_message(p *Properties, base structPointer) (n int) {
if p.isMarshaler {
m := structPointer_Interface(structp, p.stype).(Marshaler)
data, _ := m.Marshal()
n += len(p.tagcode)
n += sizeRawBytes(data)
continue
}
@@ -1083,10 +1075,17 @@ func (o *Buffer) enc_map(p *Properties, base structPointer) error {
func (o *Buffer) enc_exts(p *Properties, base structPointer) error {
exts := structPointer_Extensions(base, p.field)
if err := encodeExtensions(exts); err != nil {
v, mu := exts.extensionsRead()
if v == nil {
return nil
}
mu.Lock()
defer mu.Unlock()
if err := encodeExtensionsMap(v); err != nil {
return err
}
v, _ := exts.extensionsRead()
return o.enc_map_body(v)
}

View File

@@ -154,6 +154,7 @@ type ExtensionDesc struct {
Field int32 // field number
Name string // fully-qualified name of extension, for text formatting
Tag string // protobuf tag style
Filename string // name of the file in which the extension is defined
}
func (ed *ExtensionDesc) repeated() bool {

View File

@@ -592,7 +592,11 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
props = oop.Prop
nv := reflect.New(oop.Type.Elem())
dst = nv.Elem().Field(0)
sv.Field(oop.Field).Set(nv)
field := sv.Field(oop.Field)
if !field.IsNil() {
return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, sv.Type().Field(oop.Field).Name)
}
field.Set(nv)
}
if !dst.IsValid() {
return p.errorf("unknown field name %q in %v", name, st)

View File

@@ -267,12 +267,7 @@ func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.Respo
now := time.Now()
delegate := &responseWriterDelegator{ResponseWriter: w}
out := make(chan int)
urlLen := 0
if r.URL != nil {
urlLen = len(r.URL.String())
}
go computeApproximateRequestSize(r, out, urlLen)
out := computeApproximateRequestSize(r)
_, cn := w.(http.CloseNotifier)
_, fl := w.(http.Flusher)
@@ -297,23 +292,37 @@ func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.Respo
})
}
func computeApproximateRequestSize(r *http.Request, out chan int, s int) {
s += len(r.Method)
s += len(r.Proto)
for name, values := range r.Header {
s += len(name)
for _, value := range values {
s += len(value)
func computeApproximateRequestSize(r *http.Request) <-chan int {
// Get URL length in current go routine for avoiding a race condition.
// HandlerFunc that runs in parallel may modify the URL.
s := 0
if r.URL != nil {
s += len(r.URL.String())
}
out := make(chan int, 1)
go func() {
s += len(r.Method)
s += len(r.Proto)
for name, values := range r.Header {
s += len(name)
for _, value := range values {
s += len(value)
}
}
}
s += len(r.Host)
s += len(r.Host)
// N.B. r.Form and r.MultipartForm are assumed to be included in r.URL.
// N.B. r.Form and r.MultipartForm are assumed to be included in r.URL.
if r.ContentLength != -1 {
s += int(r.ContentLength)
}
out <- s
if r.ContentLength != -1 {
s += int(r.ContentLength)
}
out <- s
close(out)
}()
return out
}
type responseWriterDelegator struct {

View File

@@ -0,0 +1,201 @@
// Copyright 2016 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright (c) 2013, The Prometheus Authors
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
// Package promhttp contains functions to create http.Handler instances to
// expose Prometheus metrics via HTTP. In later versions of this package, it
// will also contain tooling to instrument instances of http.Handler and
// http.RoundTripper.
//
// promhttp.Handler acts on the prometheus.DefaultGatherer. With HandlerFor,
// you can create a handler for a custom registry or anything that implements
// the Gatherer interface. It also allows to create handlers that act
// differently on errors or allow to log errors.
package promhttp
import (
"bytes"
"compress/gzip"
"fmt"
"io"
"net/http"
"strings"
"sync"
"github.com/prometheus/common/expfmt"
"github.com/prometheus/client_golang/prometheus"
)
const (
contentTypeHeader = "Content-Type"
contentLengthHeader = "Content-Length"
contentEncodingHeader = "Content-Encoding"
acceptEncodingHeader = "Accept-Encoding"
)
var bufPool sync.Pool
func getBuf() *bytes.Buffer {
buf := bufPool.Get()
if buf == nil {
return &bytes.Buffer{}
}
return buf.(*bytes.Buffer)
}
func giveBuf(buf *bytes.Buffer) {
buf.Reset()
bufPool.Put(buf)
}
// Handler returns an HTTP handler for the prometheus.DefaultGatherer. The
// Handler uses the default HandlerOpts, i.e. report the first error as an HTTP
// error, no error logging, and compression if requested by the client.
//
// If you want to create a Handler for the DefaultGatherer with different
// HandlerOpts, create it with HandlerFor with prometheus.DefaultGatherer and
// your desired HandlerOpts.
func Handler() http.Handler {
return HandlerFor(prometheus.DefaultGatherer, HandlerOpts{})
}
// HandlerFor returns an http.Handler for the provided Gatherer. The behavior
// of the Handler is defined by the provided HandlerOpts.
func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
mfs, err := reg.Gather()
if err != nil {
if opts.ErrorLog != nil {
opts.ErrorLog.Println("error gathering metrics:", err)
}
switch opts.ErrorHandling {
case PanicOnError:
panic(err)
case ContinueOnError:
if len(mfs) == 0 {
http.Error(w, "No metrics gathered, last error:\n\n"+err.Error(), http.StatusInternalServerError)
return
}
case HTTPErrorOnError:
http.Error(w, "An error has occurred during metrics gathering:\n\n"+err.Error(), http.StatusInternalServerError)
return
}
}
contentType := expfmt.Negotiate(req.Header)
buf := getBuf()
defer giveBuf(buf)
writer, encoding := decorateWriter(req, buf, opts.DisableCompression)
enc := expfmt.NewEncoder(writer, contentType)
var lastErr error
for _, mf := range mfs {
if err := enc.Encode(mf); err != nil {
lastErr = err
if opts.ErrorLog != nil {
opts.ErrorLog.Println("error encoding metric family:", err)
}
switch opts.ErrorHandling {
case PanicOnError:
panic(err)
case ContinueOnError:
// Handled later.
case HTTPErrorOnError:
http.Error(w, "An error has occurred during metrics encoding:\n\n"+err.Error(), http.StatusInternalServerError)
return
}
}
}
if closer, ok := writer.(io.Closer); ok {
closer.Close()
}
if lastErr != nil && buf.Len() == 0 {
http.Error(w, "No metrics encoded, last error:\n\n"+err.Error(), http.StatusInternalServerError)
return
}
header := w.Header()
header.Set(contentTypeHeader, string(contentType))
header.Set(contentLengthHeader, fmt.Sprint(buf.Len()))
if encoding != "" {
header.Set(contentEncodingHeader, encoding)
}
w.Write(buf.Bytes())
// TODO(beorn7): Consider streaming serving of metrics.
})
}
// HandlerErrorHandling defines how a Handler serving metrics will handle
// errors.
type HandlerErrorHandling int
// These constants cause handlers serving metrics to behave as described if
// errors are encountered.
const (
// Serve an HTTP status code 500 upon the first error
// encountered. Report the error message in the body.
HTTPErrorOnError HandlerErrorHandling = iota
// Ignore errors and try to serve as many metrics as possible. However,
// if no metrics can be served, serve an HTTP status code 500 and the
// last error message in the body. Only use this in deliberate "best
// effort" metrics collection scenarios. It is recommended to at least
// log errors (by providing an ErrorLog in HandlerOpts) to not mask
// errors completely.
ContinueOnError
// Panic upon the first error encountered (useful for "crash only" apps).
PanicOnError
)
// Logger is the minimal interface HandlerOpts needs for logging. Note that
// log.Logger from the standard library implements this interface, and it is
// easy to implement by custom loggers, if they don't do so already anyway.
type Logger interface {
Println(v ...interface{})
}
// HandlerOpts specifies options how to serve metrics via an http.Handler. The
// zero value of HandlerOpts is a reasonable default.
type HandlerOpts struct {
// ErrorLog specifies an optional logger for errors collecting and
// serving metrics. If nil, errors are not logged at all.
ErrorLog Logger
// ErrorHandling defines how errors are handled. Note that errors are
// logged regardless of the configured ErrorHandling provided ErrorLog
// is not nil.
ErrorHandling HandlerErrorHandling
// If DisableCompression is true, the handler will never compress the
// response, even if requested by the client.
DisableCompression bool
}
// decorateWriter wraps a writer to handle gzip compression if requested. It
// returns the decorated writer and the appropriate "Content-Encoding" header
// (which is empty if no compression is enabled).
func decorateWriter(request *http.Request, writer io.Writer, compressionDisabled bool) (io.Writer, string) {
if compressionDisabled {
return writer, ""
}
header := request.Header.Get(acceptEncodingHeader)
parts := strings.Split(header, ",")
for _, part := range parts {
part := strings.TrimSpace(part)
if part == "gzip" || strings.HasPrefix(part, "gzip;") {
return gzip.NewWriter(writer), "gzip"
}
}
return writer, ""
}

View File

@@ -25,9 +25,12 @@ import (
// MetricFamilyToText converts a MetricFamily proto message into text format and
// writes the resulting lines to 'out'. It returns the number of bytes written
// and any error encountered. This function does not perform checks on the
// content of the metric and label names, i.e. invalid metric or label names
// and any error encountered. The output will have the same order as the input,
// no further sorting is performed. Furthermore, this function assumes the input
// is already sanitized and does not perform any sanity checks. If the input
// contains duplicate metrics or invalid metric or label names, the conversion
// will result in invalid text format output.
//
// This method fulfills the type 'prometheus.encoder'.
func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (int, error) {
var written int

View File

@@ -47,7 +47,7 @@ func (e ParseError) Error() string {
}
// TextParser is used to parse the simple and flat text-based exchange format. Its
// nil value is ready to use.
// zero value is ready to use.
type TextParser struct {
metricFamiliesByName map[string]*dto.MetricFamily
buf *bufio.Reader // Where the parsed input is read through.

View File

@@ -1,29 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo
#include "textflag.h"
//
// System call support for 386, FreeBSD
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-32
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-44
JMP syscall·Syscall6(SB)
TEXT ·Syscall9(SB),NOSPLIT,$0-56
JMP syscall·Syscall9(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-32
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-44
JMP syscall·RawSyscall6(SB)

28
vendor/golang.org/x/sys/unix/asm_linux_s390x.s generated vendored Normal file
View File

@@ -0,0 +1,28 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build s390x
// +build linux
// +build !gccgo
#include "textflag.h"
//
// System calls for s390x, Linux
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-56
BR syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
BR syscall·Syscall6(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
BR syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
BR syscall·RawSyscall6(SB)

17
vendor/golang.org/x/sys/unix/mkall.sh generated vendored Normal file → Executable file
View File

@@ -161,7 +161,7 @@ freebsd_arm)
mkerrors="$mkerrors"
mksyscall="./mksyscall.pl -l32 -arm"
mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
# Let the type of C char be singed for making the bare syscall
# Let the type of C char be signed for making the bare syscall
# API consistent across over platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;;
@@ -194,7 +194,7 @@ linux_arm64)
exit 1
fi
mksysnum="./mksysnum_linux.pl $unistd_h"
# Let the type of C char be singed for making the bare syscall
# Let the type of C char be signed for making the bare syscall
# API consistent across over platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;;
@@ -212,6 +212,17 @@ linux_ppc64le)
mksysnum="./mksysnum_linux.pl $unistd_h"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;;
linux_s390x)
GOOSARCH_in=syscall_linux_s390x.go
unistd_h=/usr/include/asm/unistd.h
mkerrors="$mkerrors -m64"
mksysnum="./mksysnum_linux.pl $unistd_h"
# Let the type of C char be signed to make the bare sys
# API more consistent between platforms.
# This is a deliberate departure from the way the syscall
# package generates its version of the types file.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;;
netbsd_386)
mkerrors="$mkerrors -m32"
mksyscall="./mksyscall.pl -l32 -netbsd"
@@ -269,6 +280,6 @@ esac
if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
if [ -n "$mktypes" ]; then
echo "echo // +build $GOARCH,$GOOS > ztypes_$GOOSARCH.go";
echo "$mktypes types_$GOOS.go | gofmt >>ztypes_$GOOSARCH.go";
echo "$mktypes types_$GOOS.go | go run mkpost.go >>ztypes_$GOOSARCH.go";
fi
) | $run

0
vendor/golang.org/x/sys/unix/mkerrors.sh generated vendored Normal file → Executable file
View File

62
vendor/golang.org/x/sys/unix/mkpost.go generated vendored Normal file
View File

@@ -0,0 +1,62 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// mkpost processes the output of cgo -godefs to
// modify the generated types. It is used to clean up
// the sys API in an architecture specific manner.
//
// mkpost is run after cgo -godefs by mkall.sh.
package main
import (
"fmt"
"go/format"
"io/ioutil"
"log"
"os"
"regexp"
)
func main() {
b, err := ioutil.ReadAll(os.Stdin)
if err != nil {
log.Fatal(err)
}
s := string(b)
goarch := os.Getenv("GOARCH")
goos := os.Getenv("GOOS")
if goarch == "s390x" && goos == "linux" {
// Export the types of PtraceRegs fields.
re := regexp.MustCompile("ptrace(Psw|Fpregs|Per)")
s = re.ReplaceAllString(s, "Ptrace$1")
// Replace padding fields inserted by cgo with blank identifiers.
re = regexp.MustCompile("Pad_cgo[A-Za-z0-9_]*")
s = re.ReplaceAllString(s, "_")
// Replace other unwanted fields with blank identifiers.
re = regexp.MustCompile("X_[A-Za-z0-9_]*")
s = re.ReplaceAllString(s, "_")
// Replace the control_regs union with a blank identifier for now.
re = regexp.MustCompile("(Control_regs)\\s+\\[0\\]uint64")
s = re.ReplaceAllString(s, "_ [0]uint64")
}
// gofmt
b, err = format.Source([]byte(s))
if err != nil {
log.Fatal(err)
}
// Append this command to the header to show where the new file
// came from.
re := regexp.MustCompile("(cgo -godefs [a-zA-Z0-9_]+\\.go.*)")
b = re.ReplaceAll(b, []byte("$1 | go run mkpost.go"))
fmt.Printf("%s", b)
}

0
vendor/golang.org/x/sys/unix/mksyscall.pl generated vendored Normal file → Executable file
View File

0
vendor/golang.org/x/sys/unix/mksyscall_solaris.pl generated vendored Normal file → Executable file
View File

0
vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl generated vendored Normal file → Executable file
View File

0
vendor/golang.org/x/sys/unix/mksysnum_darwin.pl generated vendored Normal file → Executable file
View File

0
vendor/golang.org/x/sys/unix/mksysnum_dragonfly.pl generated vendored Normal file → Executable file
View File

0
vendor/golang.org/x/sys/unix/mksysnum_freebsd.pl generated vendored Normal file → Executable file
View File

0
vendor/golang.org/x/sys/unix/mksysnum_linux.pl generated vendored Normal file → Executable file
View File

0
vendor/golang.org/x/sys/unix/mksysnum_netbsd.pl generated vendored Normal file → Executable file
View File

0
vendor/golang.org/x/sys/unix/mksysnum_openbsd.pl generated vendored Normal file → Executable file
View File

View File

@@ -144,6 +144,7 @@ func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (
uintptr(options),
0,
)
use(unsafe.Pointer(_p0))
if e1 != 0 {
return nil, e1
}
@@ -196,6 +197,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
}
r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(_p0), bufsize, uintptr(flags))
use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1

View File

@@ -109,6 +109,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
}
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1

View File

@@ -1,61 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build 386,dragonfly
package unix
import (
"syscall"
"unsafe"
)
func Getpagesize() int { return 4096 }
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = int32(nsec / 1e9)
ts.Nsec = int32(nsec % 1e9)
return
}
func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3)
tv.Sec = int32(nsec / 1e9)
return
}
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint32(fd)
k.Filter = int16(mode)
k.Flags = uint16(flags)
}
func (iov *Iovec) SetLen(length int) {
iov.Len = uint32(length)
}
func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}
func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
var writtenOut uint64 = 0
_, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr((*offset)>>32), uintptr(count), 0, uintptr(unsafe.Pointer(&writtenOut)), 0, 0)
written = int(writtenOut)
if e1 != 0 {
err = e1
}
return
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)

View File

@@ -129,6 +129,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
}
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1

View File

@@ -60,6 +60,15 @@ func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
return openat(dirfd, path, flags|O_LARGEFILE, mode)
}
//sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error)
func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
if len(fds) == 0 {
return ppoll(nil, 0, timeout, sigmask)
}
return ppoll(&fds[0], len(fds), timeout, sigmask)
}
//sys readlinkat(dirfd int, path string, buf []byte) (n int, err error)
func Readlink(path string, buf []byte) (n int, err error) {
@@ -1043,8 +1052,6 @@ func Munmap(b []byte) (err error) {
// Newfstatat
// Nfsservctl
// Personality
// Poll
// Ppoll
// Pselect6
// Ptrace
// Putpmsg

View File

@@ -388,3 +388,12 @@ func (msghdr *Msghdr) SetControllen(length int) {
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}

View File

@@ -146,3 +146,12 @@ func (msghdr *Msghdr) SetControllen(length int) {
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length)
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}

View File

@@ -252,3 +252,12 @@ func (msghdr *Msghdr) SetControllen(length int) {
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}

View File

@@ -178,3 +178,15 @@ const (
SYS_EPOLL_CREATE = 1042
SYS_EPOLL_WAIT = 1069
)
func Poll(fds []PollFd, timeout int) (n int, err error) {
var ts *Timespec
if timeout >= 0 {
ts = new(Timespec)
*ts = NsecToTimespec(int64(timeout) * 1e6)
}
if len(fds) == 0 {
return ppoll(nil, 0, ts, nil)
}
return ppoll(&fds[0], len(fds), ts, nil)
}

View File

@@ -204,3 +204,12 @@ func (msghdr *Msghdr) SetControllen(length int) {
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length)
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}

View File

@@ -124,3 +124,12 @@ func Pipe2(p []int, flags int) (err error) {
p[1] = int(pp[1])
return
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}

329
vendor/golang.org/x/sys/unix/syscall_linux_s390x.go generated vendored Normal file
View File

@@ -0,0 +1,329 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build s390x,linux
package unix
import (
"unsafe"
)
//sys Dup2(oldfd int, newfd int) (err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error)
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
//sys Ftruncate(fd int, length int64) (err error)
//sysnb Getegid() (egid int)
//sysnb Geteuid() (euid int)
//sysnb Getgid() (gid int)
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
//sysnb Getuid() (uid int)
//sysnb InotifyInit() (fd int, err error)
//sys Lchown(path string, uid int, gid int) (err error)
//sys Lstat(path string, stat *Stat_t) (err error)
//sys Pause() (err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
//sysnb Setreuid(ruid int, euid int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
//sys Stat(path string, stat *Stat_t) (err error)
//sys Statfs(path string, buf *Statfs_t) (err error)
//sys SyncFileRange(fd int, off int64, n int64, flags int) (err error)
//sys Truncate(path string, length int64) (err error)
//sysnb getgroups(n int, list *_Gid_t) (nn int, err error)
//sysnb setgroups(n int, list *_Gid_t) (err error)
func Getpagesize() int { return 4096 }
//sysnb Gettimeofday(tv *Timeval) (err error)
func Time(t *Time_t) (tt Time_t, err error) {
var tv Timeval
err = Gettimeofday(&tv)
if err != nil {
return 0, err
}
if t != nil {
*t = Time_t(tv.Sec)
}
return Time_t(tv.Sec), nil
}
//sys Utime(path string, buf *Utimbuf) (err error)
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = nsec / 1e9
ts.Nsec = nsec % 1e9
return
}
func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond
tv.Sec = nsec / 1e9
tv.Usec = nsec % 1e9 / 1e3
return
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, 0) // pipe2 is the same as pipe when flags are set to 0.
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
func Pipe2(p []int, flags int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
func Ioperm(from int, num int, on int) (err error) {
return ENOSYS
}
func Iopl(level int) (err error) {
return ENOSYS
}
func (r *PtraceRegs) PC() uint64 { return r.Psw.Addr }
func (r *PtraceRegs) SetPC(pc uint64) { r.Psw.Addr = pc }
func (iov *Iovec) SetLen(length int) {
iov.Len = uint64(length)
}
func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint64(length)
}
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length)
}
// Linux on s390x uses the old mmap interface, which requires arguments to be passed in a struct.
// mmap2 also requires arguments to be passed in a struct; it is currently not exposed in <asm/unistd.h>.
func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
mmap_args := [6]uintptr{addr, length, uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset)}
r0, _, e1 := Syscall(SYS_MMAP, uintptr(unsafe.Pointer(&mmap_args[0])), 0, 0)
use(unsafe.Pointer(&mmap_args[0]))
xaddr = uintptr(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// On s390x Linux, all the socket calls go through an extra indirection.
// The arguments to the underlying system call (SYS_SOCKETCALL) are the
// number below and a pointer to an array of uintptr.
const (
// see linux/net.h
netSocket = 1
netBind = 2
netConnect = 3
netListen = 4
netAccept = 5
netGetSockName = 6
netGetPeerName = 7
netSocketPair = 8
netSend = 9
netRecv = 10
netSendTo = 11
netRecvFrom = 12
netShutdown = 13
netSetSockOpt = 14
netGetSockOpt = 15
netSendMsg = 16
netRecvMsg = 17
netAccept4 = 18
netRecvMMsg = 19
netSendMMsg = 20
)
func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (int, error) {
args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))}
fd, _, err := Syscall(SYS_SOCKETCALL, netAccept, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return 0, err
}
return int(fd), nil
}
func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (int, error) {
args := [4]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags)}
fd, _, err := Syscall(SYS_SOCKETCALL, netAccept4, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return 0, err
}
return int(fd), nil
}
func getsockname(s int, rsa *RawSockaddrAny, addrlen *_Socklen) error {
args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))}
_, _, err := RawSyscall(SYS_SOCKETCALL, netGetSockName, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return err
}
return nil
}
func getpeername(s int, rsa *RawSockaddrAny, addrlen *_Socklen) error {
args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))}
_, _, err := RawSyscall(SYS_SOCKETCALL, netGetPeerName, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return err
}
return nil
}
func socketpair(domain int, typ int, flags int, fd *[2]int32) error {
args := [4]uintptr{uintptr(domain), uintptr(typ), uintptr(flags), uintptr(unsafe.Pointer(fd))}
_, _, err := RawSyscall(SYS_SOCKETCALL, netSocketPair, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return err
}
return nil
}
func bind(s int, addr unsafe.Pointer, addrlen _Socklen) error {
args := [3]uintptr{uintptr(s), uintptr(addr), uintptr(addrlen)}
_, _, err := Syscall(SYS_SOCKETCALL, netBind, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return err
}
return nil
}
func connect(s int, addr unsafe.Pointer, addrlen _Socklen) error {
args := [3]uintptr{uintptr(s), uintptr(addr), uintptr(addrlen)}
_, _, err := Syscall(SYS_SOCKETCALL, netConnect, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return err
}
return nil
}
func socket(domain int, typ int, proto int) (int, error) {
args := [3]uintptr{uintptr(domain), uintptr(typ), uintptr(proto)}
fd, _, err := RawSyscall(SYS_SOCKETCALL, netSocket, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return 0, err
}
return int(fd), nil
}
func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) error {
args := [5]uintptr{uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen))}
_, _, err := Syscall(SYS_SOCKETCALL, netGetSockOpt, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return err
}
return nil
}
func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) error {
args := [4]uintptr{uintptr(s), uintptr(level), uintptr(name), uintptr(val)}
_, _, err := Syscall(SYS_SOCKETCALL, netSetSockOpt, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return err
}
return nil
}
func recvfrom(s int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (int, error) {
var base uintptr
if len(p) > 0 {
base = uintptr(unsafe.Pointer(&p[0]))
}
args := [6]uintptr{uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))}
n, _, err := Syscall(SYS_SOCKETCALL, netRecvFrom, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return 0, err
}
return int(n), nil
}
func sendto(s int, p []byte, flags int, to unsafe.Pointer, addrlen _Socklen) error {
var base uintptr
if len(p) > 0 {
base = uintptr(unsafe.Pointer(&p[0]))
}
args := [6]uintptr{uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(to), uintptr(addrlen)}
_, _, err := Syscall(SYS_SOCKETCALL, netSendTo, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return err
}
return nil
}
func recvmsg(s int, msg *Msghdr, flags int) (int, error) {
args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)}
n, _, err := Syscall(SYS_SOCKETCALL, netRecvMsg, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return 0, err
}
return int(n), nil
}
func sendmsg(s int, msg *Msghdr, flags int) (int, error) {
args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)}
n, _, err := Syscall(SYS_SOCKETCALL, netSendMsg, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return 0, err
}
return int(n), nil
}
func Listen(s int, n int) error {
args := [2]uintptr{uintptr(s), uintptr(n)}
_, _, err := Syscall(SYS_SOCKETCALL, netListen, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return err
}
return nil
}
func Shutdown(s, how int) error {
args := [2]uintptr{uintptr(s), uintptr(how)}
_, _, err := Syscall(SYS_SOCKETCALL, netShutdown, uintptr(unsafe.Pointer(&args)), 0)
if err != 0 {
return err
}
return nil
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}

View File

@@ -111,6 +111,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
}
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1

View File

@@ -24,6 +24,7 @@ package unix
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netpacket/packet.h>
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <sys/epoll.h>
@@ -102,10 +103,22 @@ typedef struct user_pt_regs PtraceRegs;
typedef struct pt_regs PtraceRegs;
#elif defined(__mips__)
typedef struct user PtraceRegs;
#elif defined(__s390x__)
typedef struct _user_regs_struct PtraceRegs;
#else
typedef struct user_regs_struct PtraceRegs;
#endif
#if defined(__s390x__)
typedef struct _user_psw_struct ptracePsw;
typedef struct _user_fpregs_struct ptraceFpregs;
typedef struct _user_per_struct ptracePer;
#else
typedef struct {} ptracePsw;
typedef struct {} ptraceFpregs;
typedef struct {} ptracePer;
#endif
// The real epoll_event is a union, and godefs doesn't handle it well.
struct my_epoll_event {
uint32_t events;
@@ -113,8 +126,7 @@ struct my_epoll_event {
// padding is not specified in linux/eventpoll.h but added to conform to the
// alignment requirements of EABI
int32_t padFd;
#endif
#ifdef __powerpc64__
#elif defined(__powerpc64__) || defined(__s390x__)
int32_t _padFd;
#endif
int32_t fd;
@@ -393,6 +405,13 @@ const SizeofInotifyEvent = C.sizeof_struct_inotify_event
// Register structures
type PtraceRegs C.PtraceRegs
// Structures contained in PtraceRegs on s390x (exported by mkpost.go)
type ptracePsw C.ptracePsw
type ptraceFpregs C.ptraceFpregs
type ptracePer C.ptracePer
// Misc
type FdSet C.fd_set
@@ -412,6 +431,20 @@ const (
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
)
type PollFd C.struct_pollfd
const (
POLLIN = C.POLLIN
POLLPRI = C.POLLPRI
POLLOUT = C.POLLOUT
POLLRDHUP = C.POLLRDHUP
POLLERR = C.POLLERR
POLLHUP = C.POLLHUP
POLLNVAL = C.POLLNVAL
)
type Sigset_t C.sigset_t
// Terminal handling
type Termios C.termios_t

File diff suppressed because it is too large Load Diff

View File

@@ -216,6 +216,7 @@ const (
CLONE_FILES = 0x400
CLONE_FS = 0x200
CLONE_IO = 0x80000000
CLONE_NEWCGROUP = 0x2000000
CLONE_NEWIPC = 0x8000000
CLONE_NEWNET = 0x40000000
CLONE_NEWNS = 0x20000

View File

@@ -216,6 +216,7 @@ const (
CLONE_FILES = 0x400
CLONE_FS = 0x200
CLONE_IO = 0x80000000
CLONE_NEWCGROUP = 0x2000000
CLONE_NEWIPC = 0x8000000
CLONE_NEWNET = 0x40000000
CLONE_NEWNS = 0x20000

View File

@@ -212,6 +212,7 @@ const (
CLONE_FILES = 0x400
CLONE_FS = 0x200
CLONE_IO = 0x80000000
CLONE_NEWCGROUP = 0x2000000
CLONE_NEWIPC = 0x8000000
CLONE_NEWNET = 0x40000000
CLONE_NEWNS = 0x20000

View File

@@ -222,6 +222,7 @@ const (
CLONE_FILES = 0x400
CLONE_FS = 0x200
CLONE_IO = 0x80000000
CLONE_NEWCGROUP = 0x2000000
CLONE_NEWIPC = 0x8000000
CLONE_NEWNET = 0x40000000
CLONE_NEWNS = 0x20000

View File

@@ -221,6 +221,7 @@ const (
CLONE_FILES = 0x400
CLONE_FS = 0x200
CLONE_IO = 0x80000000
CLONE_NEWCGROUP = 0x2000000
CLONE_NEWIPC = 0x8000000
CLONE_NEWNET = 0x40000000
CLONE_NEWNS = 0x20000

View File

@@ -221,6 +221,7 @@ const (
CLONE_FILES = 0x400
CLONE_FS = 0x200
CLONE_IO = 0x80000000
CLONE_NEWCGROUP = 0x2000000
CLONE_NEWIPC = 0x8000000
CLONE_NEWNET = 0x40000000
CLONE_NEWNS = 0x20000

View File

@@ -223,6 +223,7 @@ const (
CLONE_FILES = 0x400
CLONE_FS = 0x200
CLONE_IO = 0x80000000
CLONE_NEWCGROUP = 0x2000000
CLONE_NEWIPC = 0x8000000
CLONE_NEWNET = 0x40000000
CLONE_NEWNS = 0x20000

View File

@@ -222,6 +222,7 @@ const (
CLONE_FILES = 0x400
CLONE_FS = 0x200
CLONE_IO = 0x80000000
CLONE_NEWCGROUP = 0x2000000
CLONE_NEWIPC = 0x8000000
CLONE_NEWNET = 0x40000000
CLONE_NEWNS = 0x20000

2027
vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
use(_p0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
use(_p0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
use(_p0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
use(_p0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
use(_p0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
use(_p0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
use(_p0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
use(_p0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
@@ -1636,3 +1647,14 @@ func Utime(path string, buf *Utimbuf) (err error) {
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
@@ -1830,3 +1841,14 @@ func pipe2(p *[2]_C_int, flags int) (err error) {
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
@@ -1737,3 +1748,14 @@ func setrlimit(resource int, rlim *rlimit32) (err error) {
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)

View File

@@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
@@ -1779,3 +1790,14 @@ func stat(path string, st *stat_t) (err error) {
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
@@ -1779,3 +1790,14 @@ func stat(path string, st *stat_t) (err error) {
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
@@ -1841,3 +1852,14 @@ func pipe2(p *[2]_C_int, flags int) (err error) {
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
@@ -1841,3 +1852,14 @@ func pipe2(p *[2]_C_int, flags int) (err error) {
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
use(_p0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
use(_p0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
use(_p0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
use(_p0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@@ -222,6 +222,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
use(_p0)
if e1 != 0 {
err = errnoErr(e1)
}

Some files were not shown because too many files have changed in this diff Show More