mi: replace all WMI calls with MI calls (#1714)
This commit is contained in:
parent
45d3eabab9
commit
bf233ad3e3
|
@ -51,7 +51,7 @@ linters-settings:
|
||||||
forbidigo:
|
forbidigo:
|
||||||
forbid:
|
forbid:
|
||||||
- "^(fmt\\.Print(|f|ln)|print|println)$"
|
- "^(fmt\\.Print(|f|ln)|print|println)$"
|
||||||
- p: "^syscall\\..*$"
|
- p: "^syscall\\.(.{1,7}|.{7}[^N]|.{9,})$"
|
||||||
msg: use golang.org/x/sys/windows instead of syscall
|
msg: use golang.org/x/sys/windows instead of syscall
|
||||||
- p: "^windows\\.NewLazyDLL$"
|
- p: "^windows\\.NewLazyDLL$"
|
||||||
msg: use NewLazySystemDLL instead NewLazyDLL
|
msg: use NewLazySystemDLL instead NewLazyDLL
|
||||||
|
|
17
go.mod
17
go.mod
|
@ -14,14 +14,13 @@ require (
|
||||||
github.com/prometheus/common v0.60.1
|
github.com/prometheus/common v0.60.1
|
||||||
github.com/prometheus/exporter-toolkit v0.13.0
|
github.com/prometheus/exporter-toolkit v0.13.0
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
github.com/yusufpapurcu/wmi v1.2.4
|
|
||||||
golang.org/x/sys v0.26.0
|
golang.org/x/sys v0.26.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 // indirect
|
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/containerd/cgroups/v3 v3.0.3 // indirect
|
github.com/containerd/cgroups/v3 v3.0.3 // indirect
|
||||||
|
@ -31,7 +30,7 @@ require (
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/jpillora/backoff v1.0.0 // indirect
|
github.com/jpillora/backoff v1.0.0 // indirect
|
||||||
github.com/klauspost/compress v1.17.10 // indirect
|
github.com/klauspost/compress v1.17.11 // indirect
|
||||||
github.com/mdlayher/socket v0.5.1 // indirect
|
github.com/mdlayher/socket v0.5.1 // indirect
|
||||||
github.com/mdlayher/vsock v1.2.1 // indirect
|
github.com/mdlayher/vsock v1.2.1 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
|
@ -42,13 +41,13 @@ require (
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
golang.org/x/crypto v0.27.0 // indirect
|
golang.org/x/crypto v0.28.0 // indirect
|
||||||
golang.org/x/net v0.29.0 // indirect
|
golang.org/x/net v0.30.0 // indirect
|
||||||
golang.org/x/oauth2 v0.23.0 // indirect
|
golang.org/x/oauth2 v0.23.0 // indirect
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
golang.org/x/text v0.18.0 // indirect
|
golang.org/x/text v0.19.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect
|
||||||
google.golang.org/grpc v1.67.0 // indirect
|
google.golang.org/grpc v1.67.1 // indirect
|
||||||
google.golang.org/protobuf v1.34.2 // indirect
|
google.golang.org/protobuf v1.35.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
36
go.sum
36
go.sum
|
@ -6,8 +6,8 @@ github.com/Microsoft/hcsshim v0.12.8 h1:BtDWYlFMcWhorrvSSo2M7z0csPdw6t7no/C3FsSv
|
||||||
github.com/Microsoft/hcsshim v0.12.8/go.mod h1:cibQ4BqhJ32FXDwPdQhKhwrwophnh3FuT4nwQZF907w=
|
github.com/Microsoft/hcsshim v0.12.8/go.mod h1:cibQ4BqhJ32FXDwPdQhKhwrwophnh3FuT4nwQZF907w=
|
||||||
github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY=
|
github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY=
|
||||||
github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
|
github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
|
||||||
github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 h1:t3eaIm0rUkzbrIewtiFmMK5RXHej2XnoXNhxVsAYUfg=
|
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0=
|
||||||
github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs=
|
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q=
|
github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q=
|
||||||
|
@ -34,7 +34,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
|
||||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
@ -65,8 +64,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
||||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||||
github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0=
|
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||||
github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
@ -113,14 +112,12 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
|
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
|
||||||
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
||||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
|
||||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
|
||||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
@ -131,8 +128,8 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||||
|
@ -144,7 +141,6 @@ golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
@ -152,8 +148,8 @@ golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
@ -165,15 +161,15 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 h1:N9BgCIAUvn/M+p4NJccWPWb3BWh88+zyL0ll9HgbEeM=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
|
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
|
||||||
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
@ -183,8 +179,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
|
|
@ -8,10 +8,10 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "ad"
|
const Name = "ad"
|
||||||
|
@ -118,7 +118,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
counters := []string{
|
counters := []string{
|
||||||
abANRPerSec,
|
abANRPerSec,
|
||||||
abBrowsesPerSec,
|
abBrowsesPerSec,
|
||||||
|
|
|
@ -8,12 +8,12 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "adcs"
|
const Name = "adcs"
|
||||||
|
@ -74,7 +74,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
if utils.PDHEnabled() {
|
if utils.PDHEnabled() {
|
||||||
counters := []string{
|
counters := []string{
|
||||||
requestsPerSecond,
|
requestsPerSecond,
|
||||||
|
|
|
@ -11,12 +11,12 @@ import (
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "adfs"
|
const Name = "adfs"
|
||||||
|
@ -107,7 +107,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
if utils.PDHEnabled() {
|
if utils.PDHEnabled() {
|
||||||
counters := []string{
|
counters := []string{
|
||||||
adLoginConnectionFailures,
|
adLoginConnectionFailures,
|
||||||
|
|
|
@ -8,13 +8,13 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "cache"
|
const Name = "cache"
|
||||||
|
@ -92,7 +92,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
if utils.PDHEnabled() {
|
if utils.PDHEnabled() {
|
||||||
counters := []string{
|
counters := []string{
|
||||||
asyncCopyReadsTotal,
|
asyncCopyReadsTotal,
|
||||||
|
|
|
@ -10,10 +10,10 @@ import (
|
||||||
|
|
||||||
"github.com/Microsoft/hcsshim"
|
"github.com/Microsoft/hcsshim"
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "container"
|
const Name = "container"
|
||||||
|
@ -86,7 +86,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
c.containerAvailable = prometheus.NewDesc(
|
c.containerAvailable = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "available"),
|
prometheus.BuildFQName(types.Namespace, Name, "available"),
|
||||||
"Available",
|
"Available",
|
||||||
|
|
|
@ -8,12 +8,12 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "cpu"
|
const Name = "cpu"
|
||||||
|
@ -83,7 +83,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
if utils.PDHEnabled() {
|
if utils.PDHEnabled() {
|
||||||
counters := []string{
|
counters := []string{
|
||||||
c1TimeSeconds,
|
c1TimeSeconds,
|
||||||
|
|
|
@ -4,14 +4,15 @@ package cpu_info
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "cpu_info"
|
const Name = "cpu_info"
|
||||||
|
@ -22,9 +23,9 @@ var ConfigDefaults = Config{}
|
||||||
|
|
||||||
// A Collector is a Prometheus Collector for a few WMI metrics in Win32_Processor.
|
// A Collector is a Prometheus Collector for a few WMI metrics in Win32_Processor.
|
||||||
type Collector struct {
|
type Collector struct {
|
||||||
config Config
|
config Config
|
||||||
|
miSession *mi.Session
|
||||||
wmiClient *wmi.Client
|
miQuery mi.Query
|
||||||
|
|
||||||
cpuInfo *prometheus.Desc
|
cpuInfo *prometheus.Desc
|
||||||
cpuCoreCount *prometheus.Desc
|
cpuCoreCount *prometheus.Desc
|
||||||
|
@ -63,12 +64,19 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
if miSession == nil {
|
||||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
return errors.New("miSession is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.wmiClient = wmiClient
|
miQuery, err := mi.NewQuery("SELECT Architecture, DeviceId, Description, Family, L2CacheSize, L3CacheSize, Name, ThreadCount, NumberOfCores, NumberOfEnabledCore, NumberOfLogicalProcessors FROM Win32_Processor")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create WMI query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.miQuery = miQuery
|
||||||
|
c.miSession = miSession
|
||||||
|
|
||||||
c.cpuInfo = prometheus.NewDesc(
|
c.cpuInfo = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, "", Name),
|
prometheus.BuildFQName(types.Namespace, "", Name),
|
||||||
"Labelled CPU information as provided by Win32_Processor",
|
"Labelled CPU information as provided by Win32_Processor",
|
||||||
|
@ -133,18 +141,20 @@ func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type win32Processor struct {
|
type miProcessor struct {
|
||||||
Architecture uint32
|
Architecture uint32 `mi:"Architecture"`
|
||||||
DeviceID string
|
DeviceID string `mi:"DeviceID"`
|
||||||
Description string
|
Description string `mi:"Description"`
|
||||||
Family uint16
|
Family uint16 `mi:"Family"`
|
||||||
L2CacheSize uint32
|
L2CacheSize uint32 `mi:"L2CacheSize"`
|
||||||
L3CacheSize uint32
|
L3CacheSize uint32 `mi:"L3CacheSize"`
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
ThreadCount uint32
|
ThreadCount uint32 `mi:"ThreadCount"`
|
||||||
NumberOfCores uint32
|
NumberOfCores uint32 `mi:"NumberOfCores"`
|
||||||
NumberOfEnabledCore uint32
|
NumberOfEnabledCore uint32 `mi:"NumberOfEnabledCore"`
|
||||||
NumberOfLogicalProcessors uint32
|
NumberOfLogicalProcessors uint32 `mi:"NumberOfLogicalProcessors"`
|
||||||
|
|
||||||
|
Total int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect sends the metric values for each metric
|
// Collect sends the metric values for each metric
|
||||||
|
@ -163,16 +173,9 @@ func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
|
||||||
var dst []win32Processor
|
var dst []miProcessor
|
||||||
// We use a static query here because the provided methods in wmi.go all issue a SELECT *;
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
|
||||||
// This results in the time-consuming LoadPercentage field being read which seems to measure each CPU
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
// serially over a 1 second interval, so the scrape time is at least 1s * num_sockets
|
|
||||||
if err := c.wmiClient.Query("SELECT Architecture, DeviceId, Description, Family, L2CacheSize, L3CacheSize, Name, ThreadCount, NumberOfCores, NumberOfEnabledCore, NumberOfLogicalProcessors FROM Win32_Processor", &dst); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(dst) == 0 {
|
|
||||||
return errors.New("WMI query returned empty result set")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some CPUs end up exposing trailing spaces for certain strings, so clean them up
|
// Some CPUs end up exposing trailing spaces for certain strings, so clean them up
|
||||||
|
|
|
@ -7,9 +7,9 @@ import (
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi"
|
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "cs"
|
const Name = "cs"
|
||||||
|
@ -61,7 +61,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||||
logger.Warn("The cs collector is deprecated and will be removed in a future release. " +
|
logger.Warn("The cs collector is deprecated and will be removed in a future release. " +
|
||||||
"Logical processors has been moved to cpu_info collector. " +
|
"Logical processors has been moved to cpu_info collector. " +
|
||||||
"Physical memory has been moved to memory collector. " +
|
"Physical memory has been moved to memory collector. " +
|
||||||
|
|
|
@ -10,12 +10,12 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "dfsr"
|
const Name = "dfsr"
|
||||||
|
@ -167,7 +167,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||||
logger = logger.With(slog.String("collector", Name))
|
logger = logger.With(slog.String("collector", Name))
|
||||||
|
|
||||||
logger.Info("dfsr collector is in an experimental state! Metrics for this collector have not been tested.")
|
logger.Info("dfsr collector is in an experimental state! Metrics for this collector have not been tested.")
|
||||||
|
|
|
@ -8,13 +8,13 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "dhcp"
|
const Name = "dhcp"
|
||||||
|
@ -88,7 +88,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
if utils.PDHEnabled() {
|
if utils.PDHEnabled() {
|
||||||
counters := []string{
|
counters := []string{
|
||||||
acksTotal,
|
acksTotal,
|
||||||
|
|
|
@ -4,19 +4,17 @@ package diskdrive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const Name = "diskdrive"
|
||||||
Name = "diskdrive"
|
|
||||||
win32DiskQuery = "SELECT DeviceID, Model, Caption, Name, Partitions, Size, Status, Availability FROM WIN32_DiskDrive"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Config struct{}
|
type Config struct{}
|
||||||
|
|
||||||
|
@ -25,7 +23,8 @@ var ConfigDefaults = Config{}
|
||||||
// A Collector is a Prometheus Collector for a few WMI metrics in Win32_DiskDrive.
|
// A Collector is a Prometheus Collector for a few WMI metrics in Win32_DiskDrive.
|
||||||
type Collector struct {
|
type Collector struct {
|
||||||
config Config
|
config Config
|
||||||
wmiClient *wmi.Client
|
miSession *mi.Session
|
||||||
|
miQuery mi.Query
|
||||||
|
|
||||||
availability *prometheus.Desc
|
availability *prometheus.Desc
|
||||||
diskInfo *prometheus.Desc
|
diskInfo *prometheus.Desc
|
||||||
|
@ -62,12 +61,19 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
if miSession == nil {
|
||||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
return errors.New("miSession is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.wmiClient = wmiClient
|
miQuery, err := mi.NewQuery("SELECT DeviceID, Model, Caption, Name, Partitions, Size, Status, Availability FROM WIN32_DiskDrive")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create WMI query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.miQuery = miQuery
|
||||||
|
c.miSession = miSession
|
||||||
|
|
||||||
c.diskInfo = prometheus.NewDesc(
|
c.diskInfo = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "info"),
|
prometheus.BuildFQName(types.Namespace, Name, "info"),
|
||||||
"General drive information",
|
"General drive information",
|
||||||
|
@ -108,14 +114,14 @@ func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type win32_DiskDrive struct {
|
type win32_DiskDrive struct {
|
||||||
DeviceID string
|
DeviceID string `mi:"DeviceID"`
|
||||||
Model string
|
Model string `mi:"Model"`
|
||||||
Size uint64
|
Size uint64 `mi:"Size"`
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
Caption string
|
Caption string `mi:"Caption"`
|
||||||
Partitions uint32
|
Partitions uint32 `mi:"Partitions"`
|
||||||
Status string
|
Status string `mi:"Status"`
|
||||||
Availability uint16
|
Availability uint16 `mi:"Availability"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -175,9 +181,8 @@ func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan
|
||||||
|
|
||||||
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
|
||||||
var dst []win32_DiskDrive
|
var dst []win32_DiskDrive
|
||||||
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
|
||||||
if err := c.wmiClient.Query(win32DiskQuery, &dst); err != nil {
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(dst) == 0 {
|
if len(dst) == 0 {
|
||||||
|
|
|
@ -8,11 +8,11 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "dns"
|
const Name = "dns"
|
||||||
|
@ -79,7 +79,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
counters := []string{
|
counters := []string{
|
||||||
axfrRequestReceived,
|
axfrRequestReceived,
|
||||||
axfrRequestSent,
|
axfrRequestSent,
|
||||||
|
|
|
@ -10,11 +10,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "exchange"
|
const Name = "exchange"
|
||||||
|
@ -207,7 +207,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
if utils.PDHEnabled() {
|
if utils.PDHEnabled() {
|
||||||
collectorFuncs := map[string]func() error{
|
collectorFuncs := map[string]func() error{
|
||||||
adAccessProcesses: c.buildADAccessProcesses,
|
adAccessProcesses: c.buildADAccessProcesses,
|
||||||
|
|
|
@ -12,9 +12,9 @@ import (
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
"github.com/bmatcuk/doublestar/v4"
|
"github.com/bmatcuk/doublestar/v4"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "filetime"
|
const Name = "filetime"
|
||||||
|
@ -85,7 +85,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||||
logger.Info("filetime collector is in an experimental state! It may subject to change.",
|
logger.Info("filetime collector is in an experimental state! It may subject to change.",
|
||||||
slog.String("collector", Name),
|
slog.String("collector", Name),
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,13 +4,14 @@ package fsrmquota
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "fsrmquota"
|
const Name = "fsrmquota"
|
||||||
|
@ -21,7 +22,8 @@ var ConfigDefaults = Config{}
|
||||||
|
|
||||||
type Collector struct {
|
type Collector struct {
|
||||||
config Config
|
config Config
|
||||||
wmiClient *wmi.Client
|
miSession *mi.Session
|
||||||
|
miQuery mi.Query
|
||||||
|
|
||||||
quotasCount *prometheus.Desc
|
quotasCount *prometheus.Desc
|
||||||
peakUsage *prometheus.Desc
|
peakUsage *prometheus.Desc
|
||||||
|
@ -63,12 +65,18 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
if miSession == nil {
|
||||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
return errors.New("miSession is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.wmiClient = wmiClient
|
miQuery, err := mi.NewQuery("SELECT * FROM MSFT_FSRMQuota")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create WMI query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.miQuery = miQuery
|
||||||
|
c.miSession = miSession
|
||||||
|
|
||||||
c.quotasCount = prometheus.NewDesc(
|
c.quotasCount = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "count"),
|
prometheus.BuildFQName(types.Namespace, Name, "count"),
|
||||||
|
@ -146,29 +154,28 @@ func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan
|
||||||
// MSFT_FSRMQuota docs:
|
// MSFT_FSRMQuota docs:
|
||||||
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/fsrm/msft-fsrmquota
|
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/fsrm/msft-fsrmquota
|
||||||
type MSFT_FSRMQuota struct {
|
type MSFT_FSRMQuota struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
Path string
|
Path string `mi:"Path"`
|
||||||
PeakUsage uint64
|
PeakUsage uint64 `mi:"PeakUsage"`
|
||||||
Size uint64
|
Size uint64 `mi:"Size"`
|
||||||
Usage uint64
|
Usage uint64 `mi:"Usage"`
|
||||||
Description string
|
Description string `mi:"Description"`
|
||||||
Template string
|
Template string `mi:"Template"`
|
||||||
// Threshold string
|
// Threshold string `mi:"Threshold"`
|
||||||
Disabled bool
|
Disabled bool `mi:"Disabled"`
|
||||||
MatchesTemplate bool
|
MatchesTemplate bool `mi:"MatchesTemplate"`
|
||||||
SoftLimit bool
|
SoftLimit bool `mi:"SoftLimit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
|
||||||
var dst []MSFT_FSRMQuota
|
var dst []MSFT_FSRMQuota
|
||||||
|
if err := c.miSession.Query(&dst, mi.NamespaceRootWindowsFSRM, c.miQuery); err != nil {
|
||||||
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
var count int
|
var count int
|
||||||
|
|
||||||
if err := c.wmiClient.Query("SELECT * FROM MSFT_FSRMQuota", &dst, nil, "root/microsoft/windows/fsrm"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, quota := range dst {
|
for _, quota := range dst {
|
||||||
count++
|
count++
|
||||||
path := quota.Path
|
path := quota.Path
|
||||||
|
|
|
@ -9,9 +9,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "hyperv"
|
const Name = "hyperv"
|
||||||
|
@ -23,7 +24,7 @@ var ConfigDefaults = Config{}
|
||||||
// Collector is a Prometheus Collector for hyper-v.
|
// Collector is a Prometheus Collector for hyper-v.
|
||||||
type Collector struct {
|
type Collector struct {
|
||||||
config Config
|
config Config
|
||||||
wmiClient *wmi.Client
|
miSession *mi.Session
|
||||||
|
|
||||||
// Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary
|
// Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary
|
||||||
healthCritical *prometheus.Desc
|
healthCritical *prometheus.Desc
|
||||||
|
@ -168,12 +169,12 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
if miSession == nil {
|
||||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
return errors.New("miSession is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.wmiClient = wmiClient
|
c.miSession = miSession
|
||||||
|
|
||||||
buildSubsystemName := func(component string) string { return "hyperv_" + component }
|
buildSubsystemName := func(component string) string { return "hyperv_" + component }
|
||||||
|
|
||||||
|
@ -858,14 +859,14 @@ func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan
|
||||||
|
|
||||||
// Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary vm health status.
|
// Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary vm health status.
|
||||||
type Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary struct {
|
type Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary struct {
|
||||||
HealthCritical uint32
|
HealthCritical uint32 `mi:"HealthCritical"`
|
||||||
HealthOk uint32
|
HealthOk uint32 `mi:"HealthOK"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectVmHealth(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectVmHealth(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary
|
var dst []Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, health := range dst {
|
for _, health := range dst {
|
||||||
|
@ -887,16 +888,16 @@ func (c *Collector) collectVmHealth(ch chan<- prometheus.Metric) error {
|
||||||
|
|
||||||
// Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition ..,.
|
// Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition ..,.
|
||||||
type Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition struct {
|
type Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
PhysicalPagesAllocated uint64
|
PhysicalPagesAllocated uint64 `mi:"PhysicalPagesAllocated"`
|
||||||
PreferredNUMANodeIndex uint64
|
PreferredNUMANodeIndex uint64 `mi:"PreferredNUMANodeIndex"`
|
||||||
RemotePhysicalPages uint64
|
RemotePhysicalPages uint64 `mi:"RemotePhysicalPages"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectVmVid(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectVmVid(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition
|
var dst []Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, page := range dst {
|
for _, page := range dst {
|
||||||
|
@ -931,34 +932,34 @@ func (c *Collector) collectVmVid(ch chan<- prometheus.Metric) error {
|
||||||
|
|
||||||
// Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition ...
|
// Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition ...
|
||||||
type Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition struct {
|
type Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
AddressSpaces uint64
|
AddressSpaces uint64 `mi:"AddressSpaces"`
|
||||||
AttachedDevices uint64
|
AttachedDevices uint64 `mi:"AttachedDevices"`
|
||||||
DepositedPages uint64
|
DepositedPages uint64 `mi:"DepositedPages"`
|
||||||
DeviceDMAErrors uint64
|
DeviceDMAErrors uint64 `mi:"DeviceDMAErrors"`
|
||||||
DeviceInterruptErrors uint64
|
DeviceInterruptErrors uint64 `mi:"DeviceInterruptErrors"`
|
||||||
DeviceInterruptMappings uint64
|
DeviceInterruptMappings uint64 `mi:"DeviceInterruptMappings"`
|
||||||
DeviceInterruptThrottleEvents uint64
|
DeviceInterruptThrottleEvents uint64 `mi:"DeviceInterruptThrottleEvents"`
|
||||||
GPAPages uint64
|
GPAPages uint64 `mi:"GPAPages"`
|
||||||
GPASpaceModificationsPersec uint64
|
GPASpaceModificationsPersec uint64 `mi:"GPASpaceModificationsPersec"`
|
||||||
IOTLBFlushCost uint64
|
IOTLBFlushCost uint64 `mi:"IOTLBFlushCost"`
|
||||||
IOTLBFlushesPersec uint64
|
IOTLBFlushesPersec uint64 `mi:"IOTLBFlushesPersec"`
|
||||||
RecommendedVirtualTLBSize uint64
|
RecommendedVirtualTLBSize uint64 `mi:"RecommendedVirtualTLBSize"`
|
||||||
SkippedTimerTicks uint64
|
SkippedTimerTicks uint64 `mi:"SkippedTimerTicks"`
|
||||||
Value1Gdevicepages uint64
|
Value1Gdevicepages uint64 `mi:"Value1Gdevicepages"`
|
||||||
Value1GGPApages uint64
|
Value1GGPApages uint64 `mi:"Value1GGPApages"`
|
||||||
Value2Mdevicepages uint64
|
Value2Mdevicepages uint64 `mi:"Value2Mdevicepages"`
|
||||||
Value2MGPApages uint64
|
Value2MGPApages uint64 `mi:"Value2MGPApages"`
|
||||||
Value4Kdevicepages uint64
|
Value4Kdevicepages uint64 `mi:"Value4Kdevicepages"`
|
||||||
Value4KGPApages uint64
|
Value4KGPApages uint64 `mi:"Value4KGPApages"`
|
||||||
VirtualTLBFlushEntiresPersec uint64
|
VirtualTLBFlushEntiresPersec uint64 `mi:"VirtualTLBFlushEntiresPersec"`
|
||||||
VirtualTLBPages uint64
|
VirtualTLBPages uint64 `mi:"VirtualTLBPages"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectVmHv(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectVmHv(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition
|
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, obj := range dst {
|
for _, obj := range dst {
|
||||||
|
@ -1087,14 +1088,14 @@ func (c *Collector) collectVmHv(ch chan<- prometheus.Metric) error {
|
||||||
|
|
||||||
// Win32_PerfRawData_HvStats_HyperVHypervisor ...
|
// Win32_PerfRawData_HvStats_HyperVHypervisor ...
|
||||||
type Win32_PerfRawData_HvStats_HyperVHypervisor struct {
|
type Win32_PerfRawData_HvStats_HyperVHypervisor struct {
|
||||||
LogicalProcessors uint64
|
LogicalProcessors uint64 `mi:"LogicalProcessors"`
|
||||||
VirtualProcessors uint64
|
VirtualProcessors uint64 `mi:"VirtualProcessors"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectVmProcessor(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectVmProcessor(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisor
|
var dst []Win32_PerfRawData_HvStats_HyperVHypervisor
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisor", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisor"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, obj := range dst {
|
for _, obj := range dst {
|
||||||
|
@ -1116,16 +1117,16 @@ func (c *Collector) collectVmProcessor(ch chan<- prometheus.Metric) error {
|
||||||
|
|
||||||
// Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor ...
|
// Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor ...
|
||||||
type Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor struct {
|
type Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
PercentGuestRunTime uint64
|
PercentGuestRunTime uint64 `mi:"PercentGuestRunTime"`
|
||||||
PercentHypervisorRunTime uint64
|
PercentHypervisorRunTime uint64 `mi:"PercentHypervisorRunTime"`
|
||||||
PercentTotalRunTime uint
|
PercentTotalRunTime uint64 `mi:"PercentTotalRunTime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectHostLPUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectHostLPUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor
|
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, obj := range dst {
|
for _, obj := range dst {
|
||||||
|
@ -1170,18 +1171,18 @@ func (c *Collector) collectHostLPUsage(logger *slog.Logger, ch chan<- prometheus
|
||||||
|
|
||||||
// Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor ...
|
// Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor ...
|
||||||
type Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor struct {
|
type Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
PercentGuestRunTime uint64
|
PercentGuestRunTime uint64 `mi:"PercentGuestRunTime"`
|
||||||
PercentHypervisorRunTime uint64
|
PercentHypervisorRunTime uint64 `mi:"PercentHypervisorRunTime"`
|
||||||
PercentRemoteRunTime uint64
|
PercentRemoteRunTime uint64 `mi:"PercentRemoteRunTime"`
|
||||||
PercentTotalRunTime uint64
|
PercentTotalRunTime uint64 `mi:"PercentTotalRunTime"`
|
||||||
CPUWaitTimePerDispatch uint64
|
CPUWaitTimePerDispatch uint64 `mi:"CPUWaitTimePerDispatch"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectHostCpuUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectHostCpuUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor
|
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, obj := range dst {
|
for _, obj := range dst {
|
||||||
|
@ -1240,18 +1241,18 @@ func (c *Collector) collectHostCpuUsage(logger *slog.Logger, ch chan<- prometheu
|
||||||
|
|
||||||
// Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor ...
|
// Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor ...
|
||||||
type Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor struct {
|
type Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
PercentGuestRunTime uint64
|
PercentGuestRunTime uint64 `mi:"PercentGuestRunTime"`
|
||||||
PercentHypervisorRunTime uint64
|
PercentHypervisorRunTime uint64 `mi:"PercentHypervisorRunTime"`
|
||||||
PercentRemoteRunTime uint64
|
PercentRemoteRunTime uint64 `mi:"PercentRemoteRunTime"`
|
||||||
PercentTotalRunTime uint64
|
PercentTotalRunTime uint64 `mi:"PercentTotalRunTime"`
|
||||||
CPUWaitTimePerDispatch uint64
|
CPUWaitTimePerDispatch uint64 `mi:"CPUWaitTimePerDispatch"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectVmCpuUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectVmCpuUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor
|
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, obj := range dst {
|
for _, obj := range dst {
|
||||||
|
@ -1318,37 +1319,37 @@ func (c *Collector) collectVmCpuUsage(logger *slog.Logger, ch chan<- prometheus.
|
||||||
|
|
||||||
// Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch ...
|
// Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch ...
|
||||||
type Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch struct {
|
type Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
BroadcastPacketsReceivedPersec uint64
|
BroadcastPacketsReceivedPersec uint64 `mi:"BroadcastPacketsReceivedPersec"`
|
||||||
BroadcastPacketsSentPersec uint64
|
BroadcastPacketsSentPersec uint64 `mi:"BroadcastPacketsSentPersec"`
|
||||||
BytesPersec uint64
|
BytesPersec uint64 `mi:"BytesPersec"`
|
||||||
BytesReceivedPersec uint64
|
BytesReceivedPersec uint64 `mi:"BytesReceivedPersec"`
|
||||||
BytesSentPersec uint64
|
BytesSentPersec uint64 `mi:"BytesSentPersec"`
|
||||||
DirectedPacketsReceivedPersec uint64
|
DirectedPacketsReceivedPersec uint64 `mi:"DirectedPacketsReceivedPersec"`
|
||||||
DirectedPacketsSentPersec uint64
|
DirectedPacketsSentPersec uint64 `mi:"DirectedPacketsSentPersec"`
|
||||||
DroppedPacketsIncomingPersec uint64
|
DroppedPacketsIncomingPersec uint64 `mi:"DroppedPacketsIncomingPersec"`
|
||||||
DroppedPacketsOutgoingPersec uint64
|
DroppedPacketsOutgoingPersec uint64 `mi:"DroppedPacketsOutgoingPersec"`
|
||||||
ExtensionsDroppedPacketsIncomingPersec uint64
|
ExtensionsDroppedPacketsIncomingPersec uint64 `mi:"ExtensionsDroppedPacketsIncomingPersec"`
|
||||||
ExtensionsDroppedPacketsOutgoingPersec uint64
|
ExtensionsDroppedPacketsOutgoingPersec uint64 `mi:"ExtensionsDroppedPacketsOutgoingPersec"`
|
||||||
LearnedMacAddresses uint64
|
LearnedMacAddresses uint64 `mi:"LearnedMacAddresses"`
|
||||||
LearnedMacAddressesPersec uint64
|
LearnedMacAddressesPersec uint64 `mi:"LearnedMacAddressesPersec"`
|
||||||
MulticastPacketsReceivedPersec uint64
|
MulticastPacketsReceivedPersec uint64 `mi:"MulticastPacketsReceivedPersec"`
|
||||||
MulticastPacketsSentPersec uint64
|
MulticastPacketsSentPersec uint64 `mi:"MulticastPacketsSentPersec"`
|
||||||
NumberofSendChannelMovesPersec uint64
|
NumberofSendChannelMovesPersec uint64 `mi:"NumberofSendChannelMovesPersec"`
|
||||||
NumberofVMQMovesPersec uint64
|
NumberofVMQMovesPersec uint64 `mi:"NumberofVMQMovesPersec"`
|
||||||
PacketsFlooded uint64
|
PacketsFlooded uint64 `mi:"PacketsFlooded"`
|
||||||
PacketsFloodedPersec uint64
|
PacketsFloodedPersec uint64 `mi:"PacketsFloodedPersec"`
|
||||||
PacketsPersec uint64
|
PacketsPersec uint64 `mi:"PacketsPersec"`
|
||||||
PacketsReceivedPersec uint64
|
PacketsReceivedPersec uint64 `mi:"PacketsReceivedPersec"`
|
||||||
PacketsSentPersec uint64
|
PacketsSentPersec uint64 `mi:"PacketsSentPersec"`
|
||||||
PurgedMacAddresses uint64
|
PurgedMacAddresses uint64 `mi:"PurgedMacAddresses"`
|
||||||
PurgedMacAddressesPersec uint64
|
PurgedMacAddressesPersec uint64 `mi:"PurgedMacAddressesPersec"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectVmSwitch(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectVmSwitch(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch
|
var dst []Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, obj := range dst {
|
for _, obj := range dst {
|
||||||
|
@ -1500,19 +1501,19 @@ func (c *Collector) collectVmSwitch(ch chan<- prometheus.Metric) error {
|
||||||
|
|
||||||
// Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter ...
|
// Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter ...
|
||||||
type Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter struct {
|
type Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
BytesDropped uint64
|
BytesDropped uint64 `mi:"BytesDropped"`
|
||||||
BytesReceivedPersec uint64
|
BytesReceivedPersec uint64 `mi:"BytesReceivedPersec"`
|
||||||
BytesSentPersec uint64
|
BytesSentPersec uint64 `mi:"BytesSentPersec"`
|
||||||
FramesDropped uint64
|
FramesDropped uint64 `mi:"FramesDropped"`
|
||||||
FramesReceivedPersec uint64
|
FramesReceivedPersec uint64 `mi:"FramesReceivedPersec"`
|
||||||
FramesSentPersec uint64
|
FramesSentPersec uint64 `mi:"FramesSentPersec"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectVmEthernet(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectVmEthernet(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter
|
var dst []Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, obj := range dst {
|
for _, obj := range dst {
|
||||||
|
@ -1568,19 +1569,19 @@ func (c *Collector) collectVmEthernet(ch chan<- prometheus.Metric) error {
|
||||||
|
|
||||||
// Win32_PerfRawData_Counters_HyperVVirtualStorageDevice ...
|
// Win32_PerfRawData_Counters_HyperVVirtualStorageDevice ...
|
||||||
type Win32_PerfRawData_Counters_HyperVVirtualStorageDevice struct {
|
type Win32_PerfRawData_Counters_HyperVVirtualStorageDevice struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
ErrorCount uint64
|
ErrorCount uint64 `mi:"ErrorCount"`
|
||||||
QueueLength uint32
|
QueueLength uint32 `mi:"QueueLength"`
|
||||||
ReadBytesPersec uint64
|
ReadBytesPersec uint64 `mi:"ReadBytesPersec"`
|
||||||
ReadOperationsPerSec uint64
|
ReadOperationsPerSec uint64 `mi:"ReadOperationsPerSec"`
|
||||||
WriteBytesPersec uint64
|
WriteBytesPersec uint64 `mi:"WriteBytesPersec"`
|
||||||
WriteOperationsPerSec uint64
|
WriteOperationsPerSec uint64 `mi:"WriteOperationsPerSec"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectVmStorage(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectVmStorage(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_Counters_HyperVVirtualStorageDevice
|
var dst []Win32_PerfRawData_Counters_HyperVVirtualStorageDevice
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_Counters_HyperVVirtualStorageDevice", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_Counters_HyperVVirtualStorageDevice"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, obj := range dst {
|
for _, obj := range dst {
|
||||||
|
@ -1636,19 +1637,19 @@ func (c *Collector) collectVmStorage(ch chan<- prometheus.Metric) error {
|
||||||
|
|
||||||
// Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter ...
|
// Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter ...
|
||||||
type Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter struct {
|
type Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
BytesReceivedPersec uint64
|
BytesReceivedPersec uint64 `mi:"BytesReceivedPersec"`
|
||||||
BytesSentPersec uint64
|
BytesSentPersec uint64 `mi:"BytesSentPersec"`
|
||||||
DroppedPacketsIncomingPersec uint64
|
DroppedPacketsIncomingPersec uint64 `mi:"DroppedPacketsIncomingPersec"`
|
||||||
DroppedPacketsOutgoingPersec uint64
|
DroppedPacketsOutgoingPersec uint64 `mi:"DroppedPacketsOutgoingPersec"`
|
||||||
PacketsReceivedPersec uint64
|
PacketsReceivedPersec uint64 `mi:"PacketsReceivedPersec"`
|
||||||
PacketsSentPersec uint64
|
PacketsSentPersec uint64 `mi:"PacketsSentPersec"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectVmNetwork(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectVmNetwork(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter
|
var dst []Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, obj := range dst {
|
for _, obj := range dst {
|
||||||
|
@ -1704,23 +1705,23 @@ func (c *Collector) collectVmNetwork(ch chan<- prometheus.Metric) error {
|
||||||
|
|
||||||
// Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM ...
|
// Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM ...
|
||||||
type Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM struct {
|
type Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
AddedMemory uint64
|
AddedMemory uint64 `mi:"AddedMemory"`
|
||||||
AveragePressure uint64
|
AveragePressure uint64 `mi:"AveragePressure"`
|
||||||
CurrentPressure uint64
|
CurrentPressure uint64 `mi:"CurrentPressure"`
|
||||||
GuestVisiblePhysicalMemory uint64
|
GuestVisiblePhysicalMemory uint64 `mi:"GuestVisiblePhysicalMemory"`
|
||||||
MaximumPressure uint64
|
MaximumPressure uint64 `mi:"MaximumPressure"`
|
||||||
MemoryAddOperations uint64
|
MemoryAddOperations uint64 `mi:"MemoryAddOperations"`
|
||||||
MemoryRemoveOperations uint64
|
MemoryRemoveOperations uint64 `mi:"MemoryRemoveOperations"`
|
||||||
MinimumPressure uint64
|
MinimumPressure uint64 `mi:"MinimumPressure"`
|
||||||
PhysicalMemory uint64
|
PhysicalMemory uint64 `mi:"PhysicalMemory"`
|
||||||
RemovedMemory uint64
|
RemovedMemory uint64 `mi:"RemovedMemory"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectVmMemory(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectVmMemory(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM
|
var dst []Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, obj := range dst {
|
for _, obj := range dst {
|
||||||
|
|
|
@ -10,10 +10,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
"golang.org/x/sys/windows/registry"
|
"golang.org/x/sys/windows/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -262,7 +262,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||||
logger = logger.With(slog.String("collector", Name))
|
logger = logger.With(slog.String("collector", Name))
|
||||||
|
|
||||||
c.iisVersion = getIISVersion(logger)
|
c.iisVersion = getIISVersion(logger)
|
||||||
|
|
|
@ -7,9 +7,9 @@ import (
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/headers/slc"
|
"github.com/prometheus-community/windows_exporter/internal/headers/slc"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "license"
|
const Name = "license"
|
||||||
|
@ -61,7 +61,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
c.licenseStatus = prometheus.NewDesc(
|
c.licenseStatus = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "status"),
|
prometheus.BuildFQName(types.Namespace, Name, "status"),
|
||||||
"Status of windows license",
|
"Status of windows license",
|
||||||
|
|
|
@ -13,13 +13,13 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
if utils.PDHEnabled() {
|
if utils.PDHEnabled() {
|
||||||
counters := []string{
|
counters := []string{
|
||||||
currentDiskQueueLength,
|
currentDiskQueueLength,
|
||||||
|
|
|
@ -8,9 +8,9 @@ import (
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/headers/secur32"
|
"github.com/prometheus-community/windows_exporter/internal/headers/secur32"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "logon"
|
const Name = "logon"
|
||||||
|
@ -54,7 +54,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
c.sessionInfo = prometheus.NewDesc(
|
c.sessionInfo = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "session_logon_timestamp_seconds"),
|
prometheus.BuildFQName(types.Namespace, Name, "session_logon_timestamp_seconds"),
|
||||||
"timestamp of the logon session in seconds.",
|
"timestamp of the logon session in seconds.",
|
||||||
|
|
|
@ -12,13 +12,13 @@ import (
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi"
|
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "memory"
|
const Name = "memory"
|
||||||
|
@ -105,7 +105,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
if utils.PDHEnabled() {
|
if utils.PDHEnabled() {
|
||||||
counters := []string{
|
counters := []string{
|
||||||
availableBytes,
|
availableBytes,
|
||||||
|
|
|
@ -8,9 +8,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "mscluster"
|
const Name = "mscluster"
|
||||||
|
@ -32,7 +32,7 @@ var ConfigDefaults = Config{
|
||||||
// A Collector is a Prometheus Collector for WMI MSCluster_Cluster metrics.
|
// A Collector is a Prometheus Collector for WMI MSCluster_Cluster metrics.
|
||||||
type Collector struct {
|
type Collector struct {
|
||||||
config Config
|
config Config
|
||||||
wmiClient *wmi.Client
|
miSession *mi.Session
|
||||||
|
|
||||||
// cluster
|
// cluster
|
||||||
clusterAddEvictDelay *prometheus.Desc
|
clusterAddEvictDelay *prometheus.Desc
|
||||||
|
@ -221,16 +221,16 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||||
if len(c.config.CollectorsEnabled) == 0 {
|
if len(c.config.CollectorsEnabled) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
if miSession == nil {
|
||||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
return errors.New("miSession is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.wmiClient = wmiClient
|
c.miSession = miSession
|
||||||
|
|
||||||
if slices.Contains(c.config.CollectorsEnabled, "cluster") {
|
if slices.Contains(c.config.CollectorsEnabled, "cluster") {
|
||||||
c.buildCluster()
|
c.buildCluster()
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package mscluster
|
package mscluster
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,85 +14,85 @@ const nameCluster = Name + "_cluster"
|
||||||
// msClusterCluster represents the MSCluster_Cluster WMI class
|
// msClusterCluster represents the MSCluster_Cluster WMI class
|
||||||
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-cluster
|
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-cluster
|
||||||
type msClusterCluster struct {
|
type msClusterCluster struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
AddEvictDelay uint
|
AddEvictDelay uint `mi:"AddEvictDelay"`
|
||||||
AdminAccessPoint uint
|
AdminAccessPoint uint `mi:"AdminAccessPoint"`
|
||||||
AutoAssignNodeSite uint
|
AutoAssignNodeSite uint `mi:"AutoAssignNodeSite"`
|
||||||
AutoBalancerLevel uint
|
AutoBalancerLevel uint `mi:"AutoBalancerLevel"`
|
||||||
AutoBalancerMode uint
|
AutoBalancerMode uint `mi:"AutoBalancerMode"`
|
||||||
BackupInProgress uint
|
BackupInProgress uint `mi:"BackupInProgress"`
|
||||||
BlockCacheSize uint
|
BlockCacheSize uint `mi:"BlockCacheSize"`
|
||||||
ClusSvcHangTimeout uint
|
ClusSvcHangTimeout uint `mi:"ClusSvcHangTimeout"`
|
||||||
ClusSvcRegroupOpeningTimeout uint
|
ClusSvcRegroupOpeningTimeout uint `mi:"ClusSvcRegroupOpeningTimeout"`
|
||||||
ClusSvcRegroupPruningTimeout uint
|
ClusSvcRegroupPruningTimeout uint `mi:"ClusSvcRegroupPruningTimeout"`
|
||||||
ClusSvcRegroupStageTimeout uint
|
ClusSvcRegroupStageTimeout uint `mi:"ClusSvcRegroupStageTimeout"`
|
||||||
ClusSvcRegroupTickInMilliseconds uint
|
ClusSvcRegroupTickInMilliseconds uint `mi:"ClusSvcRegroupTickInMilliseconds"`
|
||||||
ClusterEnforcedAntiAffinity uint
|
ClusterEnforcedAntiAffinity uint `mi:"ClusterEnforcedAntiAffinity"`
|
||||||
ClusterFunctionalLevel uint
|
ClusterFunctionalLevel uint `mi:"ClusterFunctionalLevel"`
|
||||||
ClusterGroupWaitDelay uint
|
ClusterGroupWaitDelay uint `mi:"ClusterGroupWaitDelay"`
|
||||||
ClusterLogLevel uint
|
ClusterLogLevel uint `mi:"ClusterLogLevel"`
|
||||||
ClusterLogSize uint
|
ClusterLogSize uint `mi:"ClusterLogSize"`
|
||||||
ClusterUpgradeVersion uint
|
ClusterUpgradeVersion uint `mi:"ClusterUpgradeVersion"`
|
||||||
CrossSiteDelay uint
|
CrossSiteDelay uint `mi:"CrossSiteDelay"`
|
||||||
CrossSiteThreshold uint
|
CrossSiteThreshold uint `mi:"CrossSiteThreshold"`
|
||||||
CrossSubnetDelay uint
|
CrossSubnetDelay uint `mi:"CrossSubnetDelay"`
|
||||||
CrossSubnetThreshold uint
|
CrossSubnetThreshold uint `mi:"CrossSubnetThreshold"`
|
||||||
CsvBalancer uint
|
CsvBalancer uint `mi:"CsvBalancer"`
|
||||||
DatabaseReadWriteMode uint
|
DatabaseReadWriteMode uint `mi:"DatabaseReadWriteMode"`
|
||||||
DefaultNetworkRole uint
|
DefaultNetworkRole uint `mi:"DefaultNetworkRole"`
|
||||||
DetectedCloudPlatform uint
|
DetectedCloudPlatform uint `mi:"DetectedCloudPlatform"`
|
||||||
DetectManagedEvents uint
|
DetectManagedEvents uint `mi:"DetectManagedEvents"`
|
||||||
DetectManagedEventsThreshold uint
|
DetectManagedEventsThreshold uint `mi:"DetectManagedEventsThreshold"`
|
||||||
DisableGroupPreferredOwnerRandomization uint
|
DisableGroupPreferredOwnerRandomization uint `mi:"DisableGroupPreferredOwnerRandomization"`
|
||||||
DrainOnShutdown uint
|
DrainOnShutdown uint `mi:"DrainOnShutdown"`
|
||||||
DynamicQuorumEnabled uint
|
DynamicQuorumEnabled uint `mi:"DynamicQuorumEnabled"`
|
||||||
EnableSharedVolumes uint
|
EnableSharedVolumes uint `mi:"EnableSharedVolumes"`
|
||||||
FixQuorum uint
|
FixQuorum uint `mi:"FixQuorum"`
|
||||||
GracePeriodEnabled uint
|
GracePeriodEnabled uint `mi:"GracePeriodEnabled"`
|
||||||
GracePeriodTimeout uint
|
GracePeriodTimeout uint `mi:"GracePeriodTimeout"`
|
||||||
GroupDependencyTimeout uint
|
GroupDependencyTimeout uint `mi:"GroupDependencyTimeout"`
|
||||||
HangRecoveryAction uint
|
HangRecoveryAction uint `mi:"HangRecoveryAction"`
|
||||||
IgnorePersistentStateOnStartup uint
|
IgnorePersistentStateOnStartup uint `mi:"IgnorePersistentStateOnStartup"`
|
||||||
LogResourceControls uint
|
LogResourceControls uint `mi:"LogResourceControls"`
|
||||||
LowerQuorumPriorityNodeId uint
|
LowerQuorumPriorityNodeId uint `mi:"LowerQuorumPriorityNodeId"`
|
||||||
MaxNumberOfNodes uint
|
MaxNumberOfNodes uint `mi:"MaxNumberOfNodes"`
|
||||||
MessageBufferLength uint
|
MessageBufferLength uint `mi:"MessageBufferLength"`
|
||||||
MinimumNeverPreemptPriority uint
|
MinimumNeverPreemptPriority uint `mi:"MinimumNeverPreemptPriority"`
|
||||||
MinimumPreemptorPriority uint
|
MinimumPreemptorPriority uint `mi:"MinimumPreemptorPriority"`
|
||||||
NetftIPSecEnabled uint
|
NetftIPSecEnabled uint `mi:"NetftIPSecEnabled"`
|
||||||
PlacementOptions uint
|
PlacementOptions uint `mi:"PlacementOptions"`
|
||||||
PlumbAllCrossSubnetRoutes uint
|
PlumbAllCrossSubnetRoutes uint `mi:"PlumbAllCrossSubnetRoutes"`
|
||||||
PreventQuorum uint
|
PreventQuorum uint `mi:"PreventQuorum"`
|
||||||
QuarantineDuration uint
|
QuarantineDuration uint `mi:"QuarantineDuration"`
|
||||||
QuarantineThreshold uint
|
QuarantineThreshold uint `mi:"QuarantineThreshold"`
|
||||||
QuorumArbitrationTimeMax uint
|
QuorumArbitrationTimeMax uint `mi:"QuorumArbitrationTimeMax"`
|
||||||
QuorumArbitrationTimeMin uint
|
QuorumArbitrationTimeMin uint `mi:"QuorumArbitrationTimeMin"`
|
||||||
QuorumLogFileSize uint
|
QuorumLogFileSize uint `mi:"QuorumLogFileSize"`
|
||||||
QuorumTypeValue uint
|
QuorumTypeValue uint `mi:"QuorumTypeValue"`
|
||||||
RequestReplyTimeout uint
|
RequestReplyTimeout uint `mi:"RequestReplyTimeout"`
|
||||||
ResiliencyDefaultPeriod uint
|
ResiliencyDefaultPeriod uint `mi:"ResiliencyDefaultPeriod"`
|
||||||
ResiliencyLevel uint
|
ResiliencyLevel uint `mi:"ResiliencyLevel"`
|
||||||
ResourceDllDeadlockPeriod uint
|
ResourceDllDeadlockPeriod uint `mi:"ResourceDllDeadlockPeriod"`
|
||||||
RootMemoryReserved uint
|
RootMemoryReserved uint `mi:"RootMemoryReserved"`
|
||||||
RouteHistoryLength uint
|
RouteHistoryLength uint `mi:"RouteHistoryLength"`
|
||||||
S2DBusTypes uint
|
S2DBusTypes uint `mi:"S2DBusTypes"`
|
||||||
S2DCacheDesiredState uint
|
S2DCacheDesiredState uint `mi:"S2DCacheDesiredState"`
|
||||||
S2DCacheFlashReservePercent uint
|
S2DCacheFlashReservePercent uint `mi:"S2DCacheFlashReservePercent"`
|
||||||
S2DCachePageSizeKBytes uint
|
S2DCachePageSizeKBytes uint `mi:"S2DCachePageSizeKBytes"`
|
||||||
S2DEnabled uint
|
S2DEnabled uint `mi:"S2DEnabled"`
|
||||||
S2DIOLatencyThreshold uint
|
S2DIOLatencyThreshold uint `mi:"S2DIOLatencyThreshold"`
|
||||||
S2DOptimizations uint
|
S2DOptimizations uint `mi:"S2DOptimizations"`
|
||||||
SameSubnetDelay uint
|
SameSubnetDelay uint `mi:"SameSubnetDelay"`
|
||||||
SameSubnetThreshold uint
|
SameSubnetThreshold uint `mi:"SameSubnetThreshold"`
|
||||||
SecurityLevel uint
|
SecurityLevel uint `mi:"SecurityLevel"`
|
||||||
SecurityLevelForStorage uint
|
SecurityLevelForStorage uint `mi:"SecurityLevelForStorage"`
|
||||||
SharedVolumeVssWriterOperationTimeout uint
|
SharedVolumeVssWriterOperationTimeout uint `mi:"SharedVolumeVssWriterOperationTimeout"`
|
||||||
ShutdownTimeoutInMinutes uint
|
ShutdownTimeoutInMinutes uint `mi:"ShutdownTimeoutInMinutes"`
|
||||||
UseClientAccessNetworksForSharedVolumes uint
|
UseClientAccessNetworksForSharedVolumes uint `mi:"UseClientAccessNetworksForSharedVolumes"`
|
||||||
WitnessDatabaseWriteTimeout uint
|
WitnessDatabaseWriteTimeout uint `mi:"WitnessDatabaseWriteTimeout"`
|
||||||
WitnessDynamicWeight uint
|
WitnessDynamicWeight uint `mi:"WitnessDynamicWeight"`
|
||||||
WitnessRestartInterval uint
|
WitnessRestartInterval uint `mi:"WitnessRestartInterval"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) buildCluster() {
|
func (c *Collector) buildCluster() {
|
||||||
|
@ -558,8 +562,8 @@ func (c *Collector) buildCluster() {
|
||||||
|
|
||||||
func (c *Collector) collectCluster(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectCluster(ch chan<- prometheus.Metric) error {
|
||||||
var dst []msClusterCluster
|
var dst []msClusterCluster
|
||||||
if err := c.wmiClient.Query("SELECT * FROM MSCluster_Cluster", &dst, nil, "root/MSCluster"); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, utils.Must(mi.NewQuery("SELECT * MSCluster_Cluster"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range dst {
|
for _, v := range dst {
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package mscluster
|
package mscluster
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,13 +14,13 @@ const nameNetwork = Name + "_network"
|
||||||
// msClusterNetwork represents the MSCluster_Network WMI class
|
// msClusterNetwork represents the MSCluster_Network WMI class
|
||||||
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-network
|
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-network
|
||||||
type msClusterNetwork struct {
|
type msClusterNetwork struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
Characteristics uint
|
Characteristics uint `mi:"Characteristics"`
|
||||||
Flags uint
|
Flags uint `mi:"Flags"`
|
||||||
Metric uint
|
Metric uint `mi:"Metric"`
|
||||||
Role uint
|
Role uint `mi:"Role"`
|
||||||
State uint
|
State uint `mi:"State"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) buildNetwork() {
|
func (c *Collector) buildNetwork() {
|
||||||
|
@ -57,8 +61,8 @@ func (c *Collector) buildNetwork() {
|
||||||
func (c *Collector) collectNetwork(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectNetwork(ch chan<- prometheus.Metric) error {
|
||||||
var dst []msClusterNetwork
|
var dst []msClusterNetwork
|
||||||
|
|
||||||
if err := c.wmiClient.Query("SELECT * FROM MSCluster_Network", &dst, nil, "root/MSCluster"); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, utils.Must(mi.NewQuery("SELECT * MSCluster_Node"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range dst {
|
for _, v := range dst {
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package mscluster
|
package mscluster
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,22 +14,22 @@ const nameNode = Name + "_node"
|
||||||
// msClusterNode represents the MSCluster_Node WMI class
|
// msClusterNode represents the MSCluster_Node WMI class
|
||||||
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-node
|
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-node
|
||||||
type msClusterNode struct {
|
type msClusterNode struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
BuildNumber uint
|
BuildNumber uint `mi:"BuildNumber"`
|
||||||
Characteristics uint
|
Characteristics uint `mi:"Characteristics"`
|
||||||
DetectedCloudPlatform uint
|
DetectedCloudPlatform uint `mi:"DetectedCloudPlatform"`
|
||||||
DynamicWeight uint
|
DynamicWeight uint `mi:"DynamicWeight"`
|
||||||
Flags uint
|
Flags uint `mi:"Flags"`
|
||||||
MajorVersion uint
|
MajorVersion uint `mi:"MajorVersion"`
|
||||||
MinorVersion uint
|
MinorVersion uint `mi:"MinorVersion"`
|
||||||
NeedsPreventQuorum uint
|
NeedsPreventQuorum uint `mi:"NeedsPreventQuorum"`
|
||||||
NodeDrainStatus uint
|
NodeDrainStatus uint `mi:"NodeDrainStatus"`
|
||||||
NodeHighestVersion uint
|
NodeHighestVersion uint `mi:"NodeHighestVersion"`
|
||||||
NodeLowestVersion uint
|
NodeLowestVersion uint `mi:"NodeLowestVersion"`
|
||||||
NodeWeight uint
|
NodeWeight uint `mi:"NodeWeight"`
|
||||||
State uint
|
State uint `mi:"State"`
|
||||||
StatusInformation uint
|
StatusInformation uint `mi:"StatusInformation"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) buildNode() {
|
func (c *Collector) buildNode() {
|
||||||
|
@ -120,8 +124,8 @@ func (c *Collector) buildNode() {
|
||||||
func (c *Collector) collectNode(ch chan<- prometheus.Metric) ([]string, error) {
|
func (c *Collector) collectNode(ch chan<- prometheus.Metric) ([]string, error) {
|
||||||
var dst []msClusterNode
|
var dst []msClusterNode
|
||||||
|
|
||||||
if err := c.wmiClient.Query("SELECT * FROM MSCluster_Node", &dst, nil, "root/MSCluster"); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, utils.Must(mi.NewQuery("SELECT * FROM MSCluster_Node"))); err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeNames := make([]string, 0, len(dst))
|
nodeNames := make([]string, 0, len(dst))
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package mscluster
|
package mscluster
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,27 +14,27 @@ const nameResource = Name + "_resource"
|
||||||
// msClusterResource represents the MSCluster_Resource WMI class
|
// msClusterResource represents the MSCluster_Resource WMI class
|
||||||
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resource
|
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resource
|
||||||
type msClusterResource struct {
|
type msClusterResource struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
Type string
|
Type string `mi:"Type"`
|
||||||
OwnerGroup string
|
OwnerGroup string `mi:"OwnerGroup"`
|
||||||
OwnerNode string
|
OwnerNode string `mi:"OwnerNode"`
|
||||||
|
|
||||||
Characteristics uint
|
Characteristics uint `mi:"Characteristics"`
|
||||||
DeadlockTimeout uint
|
DeadlockTimeout uint `mi:"DeadlockTimeout"`
|
||||||
EmbeddedFailureAction uint
|
EmbeddedFailureAction uint `mi:"EmbeddedFailureAction"`
|
||||||
Flags uint
|
Flags uint `mi:"Flags"`
|
||||||
IsAlivePollInterval uint
|
IsAlivePollInterval uint `mi:"IsAlivePollInterval"`
|
||||||
LooksAlivePollInterval uint
|
LooksAlivePollInterval uint `mi:"LooksAlivePollInterval"`
|
||||||
MonitorProcessId uint
|
MonitorProcessId uint `mi:"MonitorProcessId"`
|
||||||
PendingTimeout uint
|
PendingTimeout uint `mi:"PendingTimeout"`
|
||||||
ResourceClass uint
|
ResourceClass uint `mi:"ResourceClass"`
|
||||||
RestartAction uint
|
RestartAction uint `mi:"RestartAction"`
|
||||||
RestartDelay uint
|
RestartDelay uint `mi:"RestartDelay"`
|
||||||
RestartPeriod uint
|
RestartPeriod uint `mi:"RestartPeriod"`
|
||||||
RestartThreshold uint
|
RestartThreshold uint `mi:"RestartThreshold"`
|
||||||
RetryPeriodOnFailure uint
|
RetryPeriodOnFailure uint `mi:"RetryPeriodOnFailure"`
|
||||||
State uint
|
State uint `mi:"State"`
|
||||||
Subclass uint
|
Subclass uint `mi:"Subclass"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) buildResource() {
|
func (c *Collector) buildResource() {
|
||||||
|
@ -149,8 +153,8 @@ func (c *Collector) buildResource() {
|
||||||
func (c *Collector) collectResource(ch chan<- prometheus.Metric, nodeNames []string) error {
|
func (c *Collector) collectResource(ch chan<- prometheus.Metric, nodeNames []string) error {
|
||||||
var dst []msClusterResource
|
var dst []msClusterResource
|
||||||
|
|
||||||
if err := c.wmiClient.Query("SELECT * FROM MSCluster_Resource", &dst, nil, "root/MSCluster"); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, utils.Must(mi.NewQuery("SELECT * FROM MSCluster_Resource"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range dst {
|
for _, v := range dst {
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package mscluster
|
package mscluster
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,22 +14,22 @@ const nameResourceGroup = Name + "_resourcegroup"
|
||||||
// msClusterResourceGroup represents the MSCluster_ResourceGroup WMI class
|
// msClusterResourceGroup represents the MSCluster_ResourceGroup WMI class
|
||||||
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resourcegroup
|
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resourcegroup
|
||||||
type msClusterResourceGroup struct {
|
type msClusterResourceGroup struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
AutoFailbackType uint
|
AutoFailbackType uint `mi:"AutoFailbackType"`
|
||||||
Characteristics uint
|
Characteristics uint `mi:"Characteristics"`
|
||||||
ColdStartSetting uint
|
ColdStartSetting uint `mi:"ColdStartSetting"`
|
||||||
DefaultOwner uint
|
DefaultOwner uint `mi:"DefaultOwner"`
|
||||||
FailbackWindowEnd int
|
FailbackWindowEnd int `mi:"FailbackWindowEnd"`
|
||||||
FailbackWindowStart int
|
FailbackWindowStart int `mi:"FailbackWindowStart"`
|
||||||
FailoverPeriod uint
|
FailoverPeriod uint `mi:"FailoverPeriod"`
|
||||||
FailoverThreshold uint
|
FailoverThreshold uint `mi:"FailoverThreshold"`
|
||||||
Flags uint
|
Flags uint `mi:"Flags"`
|
||||||
GroupType uint
|
GroupType uint `mi:"GroupType"`
|
||||||
OwnerNode string
|
OwnerNode string `mi:"OwnerNode"`
|
||||||
Priority uint
|
Priority uint `mi:"Priority"`
|
||||||
ResiliencyPeriod uint
|
ResiliencyPeriod uint `mi:"ResiliencyPeriod"`
|
||||||
State uint
|
State uint `mi:"State"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) buildResourceGroup() {
|
func (c *Collector) buildResourceGroup() {
|
||||||
|
@ -126,8 +130,8 @@ func (c *Collector) buildResourceGroup() {
|
||||||
func (c *Collector) collectResourceGroup(ch chan<- prometheus.Metric, nodeNames []string) error {
|
func (c *Collector) collectResourceGroup(ch chan<- prometheus.Metric, nodeNames []string) error {
|
||||||
var dst []msClusterResourceGroup
|
var dst []msClusterResourceGroup
|
||||||
|
|
||||||
if err := c.wmiClient.Query("SELECT * FROM MSCluster_ResourceGroup", &dst, nil, "root/MSCluster"); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, utils.Must(mi.NewQuery("SELECT * FROM MSCluster_ResourceGroup"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range dst {
|
for _, v := range dst {
|
||||||
|
|
|
@ -4,14 +4,15 @@ package msmq
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "msmq"
|
const Name = "msmq"
|
||||||
|
@ -27,7 +28,7 @@ var ConfigDefaults = Config{
|
||||||
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics.
|
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics.
|
||||||
type Collector struct {
|
type Collector struct {
|
||||||
config Config
|
config Config
|
||||||
wmiClient *wmi.Client
|
miSession *mi.Session
|
||||||
|
|
||||||
bytesInJournalQueue *prometheus.Desc
|
bytesInJournalQueue *prometheus.Desc
|
||||||
bytesInQueue *prometheus.Desc
|
bytesInQueue *prometheus.Desc
|
||||||
|
@ -75,14 +76,14 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, wmiClient *wmi.Client) error {
|
func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
|
||||||
logger = logger.With(slog.String("collector", Name))
|
logger = logger.With(slog.String("collector", Name))
|
||||||
|
|
||||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
if miSession == nil {
|
||||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
return errors.New("miSession is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.wmiClient = wmiClient
|
c.miSession = miSession
|
||||||
|
|
||||||
if *c.config.QueryWhereClause == "" {
|
if *c.config.QueryWhereClause == "" {
|
||||||
logger.Warn("No where-clause specified for msmq collector. This will generate a very large number of metrics!")
|
logger.Warn("No where-clause specified for msmq collector. This will generate a very large number of metrics!")
|
||||||
|
@ -132,12 +133,12 @@ func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan
|
||||||
}
|
}
|
||||||
|
|
||||||
type msmqQueue struct {
|
type msmqQueue struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
BytesInJournalQueue uint64
|
BytesInJournalQueue uint64 `mi:"BytesInJournalQueue"`
|
||||||
BytesInQueue uint64
|
BytesInQueue uint64 `mi:"BytesInQueue"`
|
||||||
MessagesInJournalQueue uint64
|
MessagesInJournalQueue uint64 `mi:"MessagesInJournalQueue"`
|
||||||
MessagesInQueue uint64
|
MessagesInQueue uint64 `mi:"MessagesInQueue"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
|
||||||
|
@ -148,8 +149,13 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
|
||||||
query += " WHERE " + *c.config.QueryWhereClause
|
query += " WHERE " + *c.config.QueryWhereClause
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.wmiClient.Query(query, &dst); err != nil {
|
queryExpression, err := mi.NewQuery(query)
|
||||||
return err
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create WMI query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, queryExpression); err != nil {
|
||||||
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, msmq := range dst {
|
for _, msmq := range dst {
|
||||||
|
|
|
@ -13,10 +13,10 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
"golang.org/x/sys/windows/registry"
|
"golang.org/x/sys/windows/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -508,7 +508,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
// Result must order, to prevent test failures.
|
// Result must order, to prevent test failures.
|
||||||
sort.Strings(c.config.CollectorsEnabled)
|
sort.Strings(c.config.CollectorsEnabled)
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,12 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||||
if utils.PDHEnabled() {
|
if utils.PDHEnabled() {
|
||||||
counters := []string{
|
counters := []string{
|
||||||
BytesReceivedPerSec,
|
BytesReceivedPerSec,
|
||||||
|
|
|
@ -9,9 +9,9 @@ import (
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "netframework"
|
const Name = "netframework"
|
||||||
|
@ -47,7 +47,7 @@ const (
|
||||||
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics.
|
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics.
|
||||||
type Collector struct {
|
type Collector struct {
|
||||||
config Config
|
config Config
|
||||||
wmiClient *wmi.Client
|
miSession *mi.Session
|
||||||
|
|
||||||
// clrexceptions
|
// clrexceptions
|
||||||
numberOfExceptionsThrown *prometheus.Desc
|
numberOfExceptionsThrown *prometheus.Desc
|
||||||
|
@ -143,12 +143,12 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
if miSession == nil {
|
||||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
return errors.New("miSession is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.wmiClient = wmiClient
|
c.miSession = miSession
|
||||||
|
|
||||||
if slices.Contains(c.config.CollectorsEnabled, collectorClrExceptions) {
|
if slices.Contains(c.config.CollectorsEnabled, collectorClrExceptions) {
|
||||||
c.buildClrExceptions()
|
c.buildClrExceptions()
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
package netframework
|
package netframework
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,19 +39,19 @@ func (c *Collector) buildClrExceptions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Win32_PerfRawData_NETFramework_NETCLRExceptions struct {
|
type Win32_PerfRawData_NETFramework_NETCLRExceptions struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
NumberofExcepsThrown uint32
|
NumberofExcepsThrown uint32 `mi:"NumberofExcepsThrown"`
|
||||||
NumberofExcepsThrownPersec uint32
|
NumberofExcepsThrownPersec uint32 `mi:"NumberofExcepsThrownPersec"`
|
||||||
NumberofFiltersPersec uint32
|
NumberofFiltersPersec uint32 `mi:"NumberofFiltersPersec"`
|
||||||
NumberofFinallysPersec uint32
|
NumberofFinallysPersec uint32 `mi:"NumberofFinallysPersec"`
|
||||||
ThrowToCatchDepthPersec uint32
|
ThrowToCatchDepthPersec uint32 `mi:"ThrowToCatchDepthPersec"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectClrExceptions(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectClrExceptions(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_NETFramework_NETCLRExceptions
|
var dst []Win32_PerfRawData_NETFramework_NETCLRExceptions
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRExceptions", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRExceptions"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, process := range dst {
|
for _, process := range dst {
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
package netframework
|
package netframework
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,19 +33,19 @@ func (c *Collector) buildClrInterop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Win32_PerfRawData_NETFramework_NETCLRInterop struct {
|
type Win32_PerfRawData_NETFramework_NETCLRInterop struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
NumberofCCWs uint32
|
NumberofCCWs uint32 `mi:"NumberofCCWs"`
|
||||||
Numberofmarshalling uint32
|
Numberofmarshalling uint32 `mi:"Numberofmarshalling"`
|
||||||
NumberofStubs uint32
|
NumberofStubs uint32 `mi:"NumberofStubs"`
|
||||||
NumberofTLBexportsPersec uint32
|
NumberofTLBexportsPersec uint32 `mi:"NumberofTLBexportsPersec"`
|
||||||
NumberofTLBimportsPersec uint32
|
NumberofTLBimportsPersec uint32 `mi:"NumberofTLBimportsPersec"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectClrInterop(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectClrInterop(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_NETFramework_NETCLRInterop
|
var dst []Win32_PerfRawData_NETFramework_NETCLRInterop
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRInterop", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRInterop"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, process := range dst {
|
for _, process := range dst {
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
package netframework
|
package netframework
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,21 +39,21 @@ func (c *Collector) buildClrJIT() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Win32_PerfRawData_NETFramework_NETCLRJit struct {
|
type Win32_PerfRawData_NETFramework_NETCLRJit struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
Frequency_PerfTime uint32
|
Frequency_PerfTime uint32 `mi:"Frequency_PerfTime"`
|
||||||
ILBytesJittedPersec uint32
|
ILBytesJittedPersec uint32 `mi:"ILBytesJittedPersec"`
|
||||||
NumberofILBytesJitted uint32
|
NumberofILBytesJitted uint32 `mi:"NumberofILBytesJitted"`
|
||||||
NumberofMethodsJitted uint32
|
NumberofMethodsJitted uint32 `mi:"NumberofMethodsJitted"`
|
||||||
PercentTimeinJit uint32
|
PercentTimeinJit uint32 `mi:"PercentTimeinJit"`
|
||||||
StandardJitFailures uint32
|
StandardJitFailures uint32 `mi:"StandardJitFailures"`
|
||||||
TotalNumberofILBytesJitted uint32
|
TotalNumberofILBytesJitted uint32 `mi:"TotalNumberofILBytesJitted"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectClrJIT(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectClrJIT(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_NETFramework_NETCLRJit
|
var dst []Win32_PerfRawData_NETFramework_NETCLRJit
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRJit", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRJit"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, process := range dst {
|
for _, process := range dst {
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
package netframework
|
package netframework
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -65,30 +69,30 @@ func (c *Collector) buildClrLoading() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Win32_PerfRawData_NETFramework_NETCLRLoading struct {
|
type Win32_PerfRawData_NETFramework_NETCLRLoading struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
AssemblySearchLength uint32
|
AssemblySearchLength uint32 `mi:"AssemblySearchLength"`
|
||||||
BytesinLoaderHeap uint64
|
BytesinLoaderHeap uint64 `mi:"BytesinLoaderHeap"`
|
||||||
Currentappdomains uint32
|
Currentappdomains uint32 `mi:"Currentappdomains"`
|
||||||
CurrentAssemblies uint32
|
CurrentAssemblies uint32 `mi:"CurrentAssemblies"`
|
||||||
CurrentClassesLoaded uint32
|
CurrentClassesLoaded uint32 `mi:"CurrentClassesLoaded"`
|
||||||
PercentTimeLoading uint64
|
PercentTimeLoading uint64 `mi:"PercentTimeLoading"`
|
||||||
Rateofappdomains uint32
|
Rateofappdomains uint32 `mi:"Rateofappdomains"`
|
||||||
Rateofappdomainsunloaded uint32
|
Rateofappdomainsunloaded uint32 `mi:"Rateofappdomainsunloaded"`
|
||||||
RateofAssemblies uint32
|
RateofAssemblies uint32 `mi:"RateofAssemblies"`
|
||||||
RateofClassesLoaded uint32
|
RateofClassesLoaded uint32 `mi:"RateofClassesLoaded"`
|
||||||
RateofLoadFailures uint32
|
RateofLoadFailures uint32 `mi:"RateofLoadFailures"`
|
||||||
TotalAppdomains uint32
|
TotalAppdomains uint32 `mi:"TotalAppdomains"`
|
||||||
Totalappdomainsunloaded uint32
|
Totalappdomainsunloaded uint32 `mi:"Totalappdomainsunloaded"`
|
||||||
TotalAssemblies uint32
|
TotalAssemblies uint32 `mi:"TotalAssemblies"`
|
||||||
TotalClassesLoaded uint32
|
TotalClassesLoaded uint32 `mi:"TotalClassesLoaded"`
|
||||||
TotalNumberofLoadFailures uint32
|
TotalNumberofLoadFailures uint32 `mi:"TotalNumberofLoadFailures"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectClrLoading(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectClrLoading(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_NETFramework_NETCLRLoading
|
var dst []Win32_PerfRawData_NETFramework_NETCLRLoading
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRLoading", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRLoading"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, process := range dst {
|
for _, process := range dst {
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
package netframework
|
package netframework
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -53,24 +57,24 @@ func (c *Collector) buildClrLocksAndThreads() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads struct {
|
type Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
ContentionRatePersec uint32
|
ContentionRatePersec uint32 `mi:"ContentionRatePersec"`
|
||||||
CurrentQueueLength uint32
|
CurrentQueueLength uint32 `mi:"CurrentQueueLength"`
|
||||||
NumberofcurrentlogicalThreads uint32
|
NumberofcurrentlogicalThreads uint32 `mi:"NumberofcurrentlogicalThreads"`
|
||||||
NumberofcurrentphysicalThreads uint32
|
NumberofcurrentphysicalThreads uint32 `mi:"NumberofcurrentphysicalThreads"`
|
||||||
Numberofcurrentrecognizedthreads uint32
|
Numberofcurrentrecognizedthreads uint32 `mi:"Numberofcurrentrecognizedthreads"`
|
||||||
Numberoftotalrecognizedthreads uint32
|
Numberoftotalrecognizedthreads uint32 `mi:"Numberoftotalrecognizedthreads"`
|
||||||
QueueLengthPeak uint32
|
QueueLengthPeak uint32 `mi:"QueueLengthPeak"`
|
||||||
QueueLengthPersec uint32
|
QueueLengthPersec uint32 `mi:"QueueLengthPersec"`
|
||||||
RateOfRecognizedThreadsPersec uint32
|
RateOfRecognizedThreadsPersec uint32 `mi:"RateOfRecognizedThreadsPersec"`
|
||||||
TotalNumberofContentions uint32
|
TotalNumberofContentions uint32 `mi:"TotalNumberofContentions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectClrLocksAndThreads(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectClrLocksAndThreads(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads
|
var dst []Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, process := range dst {
|
for _, process := range dst {
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
package netframework
|
package netframework
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -83,43 +87,43 @@ func (c *Collector) buildClrMemory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Win32_PerfRawData_NETFramework_NETCLRMemory struct {
|
type Win32_PerfRawData_NETFramework_NETCLRMemory struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
AllocatedBytesPersec uint64
|
AllocatedBytesPersec uint64 `mi:"AllocatedBytesPersec"`
|
||||||
FinalizationSurvivors uint64
|
FinalizationSurvivors uint64 `mi:"FinalizationSurvivors"`
|
||||||
Frequency_PerfTime uint64
|
Frequency_PerfTime uint64 `mi:"Frequency_PerfTime"`
|
||||||
Gen0heapsize uint64
|
Gen0heapsize uint64 `mi:"Gen0heapsize"`
|
||||||
Gen0PromotedBytesPerSec uint64
|
Gen0PromotedBytesPerSec uint64 `mi:"Gen0PromotedBytesPersec"`
|
||||||
Gen1heapsize uint64
|
Gen1heapsize uint64 `mi:"Gen1heapsize"`
|
||||||
Gen1PromotedBytesPerSec uint64
|
Gen1PromotedBytesPerSec uint64 `mi:"Gen1PromotedBytesPersec"`
|
||||||
Gen2heapsize uint64
|
Gen2heapsize uint64 `mi:"Gen2heapsize"`
|
||||||
LargeObjectHeapsize uint64
|
LargeObjectHeapsize uint64 `mi:"LargeObjectHeapsize"`
|
||||||
NumberBytesinallHeaps uint64
|
NumberBytesinallHeaps uint64 `mi:"NumberBytesinallHeaps"`
|
||||||
NumberGCHandles uint64
|
NumberGCHandles uint64 `mi:"NumberGCHandles"`
|
||||||
NumberGen0Collections uint64
|
NumberGen0Collections uint64 `mi:"NumberGen0Collections"`
|
||||||
NumberGen1Collections uint64
|
NumberGen1Collections uint64 `mi:"NumberGen1Collections"`
|
||||||
NumberGen2Collections uint64
|
NumberGen2Collections uint64 `mi:"NumberGen2Collections"`
|
||||||
NumberInducedGC uint64
|
NumberInducedGC uint64 `mi:"NumberInducedGC"`
|
||||||
NumberofPinnedObjects uint64
|
NumberofPinnedObjects uint64 `mi:"NumberofPinnedObjects"`
|
||||||
NumberofSinkBlocksinuse uint64
|
NumberofSinkBlocksinuse uint64 `mi:"NumberofSinkBlocksinuse"`
|
||||||
NumberTotalcommittedBytes uint64
|
NumberTotalcommittedBytes uint64 `mi:"NumberTotalcommittedBytes"`
|
||||||
NumberTotalreservedBytes uint64
|
NumberTotalreservedBytes uint64 `mi:"NumberTotalreservedBytes"`
|
||||||
// PercentTimeinGC has countertype=PERF_RAW_FRACTION.
|
// PercentTimeinGC has countertype=PERF_RAW_FRACTION.
|
||||||
// Formula: (100 * CounterValue) / BaseValue
|
// Formula: (100 * CounterValue) / BaseValue
|
||||||
// By docs https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/scripting-articles/ms974615(v=msdn.10)#perf_raw_fraction
|
// By docs https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/scripting-articles/ms974615(v=msdn.10)#perf_raw_fraction
|
||||||
PercentTimeinGC uint32
|
PercentTimeinGC uint32 `mi:"PercentTimeinGC"`
|
||||||
// BaseValue is just a "magic" number used to make the calculation come out right.
|
// BaseValue is just a "magic" number used to make the calculation come out right.
|
||||||
PercentTimeinGC_base uint32
|
PercentTimeinGC_base uint32 `mi:"PercentTimeinGC_base"`
|
||||||
ProcessID uint64
|
ProcessID uint64 `mi:"ProcessID"`
|
||||||
PromotedFinalizationMemoryfromGen0 uint64
|
PromotedFinalizationMemoryfromGen0 uint64 `mi:"PromotedFinalizationMemoryfromGen0"`
|
||||||
PromotedMemoryfromGen0 uint64
|
PromotedMemoryfromGen0 uint64 `mi:"PromotedMemoryfromGen0"`
|
||||||
PromotedMemoryfromGen1 uint64
|
PromotedMemoryfromGen1 uint64 `mi:"PromotedMemoryfromGen1"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_NETFramework_NETCLRMemory
|
var dst []Win32_PerfRawData_NETFramework_NETCLRMemory
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRMemory", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRMemory"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, process := range dst {
|
for _, process := range dst {
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
package netframework
|
package netframework
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -47,21 +51,21 @@ func (c *Collector) buildClrRemoting() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Win32_PerfRawData_NETFramework_NETCLRRemoting struct {
|
type Win32_PerfRawData_NETFramework_NETCLRRemoting struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
Channels uint32
|
Channels uint32 `mi:"Channels"`
|
||||||
ContextBoundClassesLoaded uint32
|
ContextBoundClassesLoaded uint32 `mi:"ContextBoundClassesLoaded"`
|
||||||
ContextBoundObjectsAllocPersec uint32
|
ContextBoundObjectsAllocPersec uint32 `mi:"ContextBoundObjectsAllocPersec"`
|
||||||
ContextProxies uint32
|
ContextProxies uint32 `mi:"ContextProxies"`
|
||||||
Contexts uint32
|
Contexts uint32 `mi:"Contexts"`
|
||||||
RemoteCallsPersec uint32
|
RemoteCallsPersec uint32 `mi:"RemoteCallsPersec"`
|
||||||
TotalRemoteCalls uint32
|
TotalRemoteCalls uint32 `mi:"TotalRemoteCalls"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectClrRemoting(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectClrRemoting(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_NETFramework_NETCLRRemoting
|
var dst []Win32_PerfRawData_NETFramework_NETCLRRemoting
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRRemoting", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRRemoting"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, process := range dst {
|
for _, process := range dst {
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
package netframework
|
package netframework
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,20 +39,20 @@ func (c *Collector) buildClrSecurity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Win32_PerfRawData_NETFramework_NETCLRSecurity struct {
|
type Win32_PerfRawData_NETFramework_NETCLRSecurity struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
Frequency_PerfTime uint32
|
Frequency_PerfTime uint32 `mi:"Frequency_PerfTime"`
|
||||||
NumberLinkTimeChecks uint32
|
NumberLinkTimeChecks uint32 `mi:"NumberLinkTimeChecks"`
|
||||||
PercentTimeinRTchecks uint32
|
PercentTimeinRTchecks uint32 `mi:"PercentTimeinRTchecks"`
|
||||||
PercentTimeSigAuthenticating uint64
|
PercentTimeSigAuthenticating uint64 `mi:"PercentTimeSigAuthenticating"`
|
||||||
StackWalkDepth uint32
|
StackWalkDepth uint32 `mi:"StackWalkDepth"`
|
||||||
TotalRuntimeChecks uint32
|
TotalRuntimeChecks uint32 `mi:"TotalRuntimeChecks"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectClrSecurity(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectClrSecurity(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_NETFramework_NETCLRSecurity
|
var dst []Win32_PerfRawData_NETFramework_NETCLRSecurity
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRSecurity", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRSecurity"))); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, process := range dst {
|
for _, process := range dst {
|
||||||
|
|
|
@ -6,9 +6,9 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "nps"
|
const Name = "nps"
|
||||||
|
@ -20,7 +20,10 @@ var ConfigDefaults = Config{}
|
||||||
// Collector is a Prometheus Collector for WMI Win32_PerfRawData_IAS_NPSAuthenticationServer and Win32_PerfRawData_IAS_NPSAccountingServer metrics.
|
// Collector is a Prometheus Collector for WMI Win32_PerfRawData_IAS_NPSAuthenticationServer and Win32_PerfRawData_IAS_NPSAccountingServer metrics.
|
||||||
type Collector struct {
|
type Collector struct {
|
||||||
config Config
|
config Config
|
||||||
wmiClient *wmi.Client
|
miSession *mi.Session
|
||||||
|
|
||||||
|
miQueryAuthenticationServer mi.Query
|
||||||
|
miQueryAccountingServer mi.Query
|
||||||
|
|
||||||
accessAccepts *prometheus.Desc
|
accessAccepts *prometheus.Desc
|
||||||
accessChallenges *prometheus.Desc
|
accessChallenges *prometheus.Desc
|
||||||
|
@ -78,12 +81,26 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
if miSession == nil {
|
||||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
return errors.New("miSession is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.wmiClient = wmiClient
|
miQuery, err := mi.NewQuery("SELECT Name, AccessAccepts, AccessChallenges, AccessRejects, AccessRequests, AccessBadAuthenticators, AccessDroppedPackets, AccessInvalidRequests, AccessMalformedPackets, AccessPacketsReceived, AccessPacketsSent, AccessServerResetTime, AccessServerUpTime, AccessUnknownType FROM Win32_PerfRawData_IAS_NPSAuthenticationServer")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create WMI query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.miQueryAuthenticationServer = miQuery
|
||||||
|
|
||||||
|
miQuery, err = mi.NewQuery("SELECT Name, AccountingRequests, AccountingResponses, AccountingBadAuthenticators, AccountingDroppedPackets, AccountingInvalidRequests, AccountingMalformedPackets, AccountingNoRecord, AccountingPacketsReceived, AccountingPacketsSent, AccountingServerResetTime, AccountingServerUpTime, AccountingUnknownType FROM Win32_PerfRawData_IAS_NPSAccountingServer")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create WMI query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.miQueryAccountingServer = miQuery
|
||||||
|
c.miSession = miSession
|
||||||
|
|
||||||
c.accessAccepts = prometheus.NewDesc(
|
c.accessAccepts = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "access_accepts"),
|
prometheus.BuildFQName(types.Namespace, Name, "access_accepts"),
|
||||||
"(AccessAccepts)",
|
"(AccessAccepts)",
|
||||||
|
@ -261,46 +278,46 @@ func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan
|
||||||
// Win32_PerfRawData_IAS_NPSAuthenticationServer docs:
|
// Win32_PerfRawData_IAS_NPSAuthenticationServer docs:
|
||||||
// at the moment there is no Microsoft documentation.
|
// at the moment there is no Microsoft documentation.
|
||||||
type Win32_PerfRawData_IAS_NPSAuthenticationServer struct {
|
type Win32_PerfRawData_IAS_NPSAuthenticationServer struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
AccessAccepts uint32
|
AccessAccepts uint32 `mi:"AccessAccepts"`
|
||||||
AccessChallenges uint32
|
AccessChallenges uint32 `mi:"AccessChallenges"`
|
||||||
AccessRejects uint32
|
AccessRejects uint32 `mi:"AccessRejects"`
|
||||||
AccessRequests uint32
|
AccessRequests uint32 `mi:"AccessRequests"`
|
||||||
AccessBadAuthenticators uint32
|
AccessBadAuthenticators uint32 `mi:"AccessBadAuthenticators"`
|
||||||
AccessDroppedPackets uint32
|
AccessDroppedPackets uint32 `mi:"AccessDroppedPackets"`
|
||||||
AccessInvalidRequests uint32
|
AccessInvalidRequests uint32 `mi:"AccessInvalidRequests"`
|
||||||
AccessMalformedPackets uint32
|
AccessMalformedPackets uint32 `mi:"AccessMalformedPackets"`
|
||||||
AccessPacketsReceived uint32
|
AccessPacketsReceived uint32 `mi:"AccessPacketsReceived"`
|
||||||
AccessPacketsSent uint32
|
AccessPacketsSent uint32 `mi:"AccessPacketsSent"`
|
||||||
AccessServerResetTime uint32
|
AccessServerResetTime uint32 `mi:"AccessServerResetTime"`
|
||||||
AccessServerUpTime uint32
|
AccessServerUpTime uint32 `mi:"AccessServerUpTime"`
|
||||||
AccessUnknownType uint32
|
AccessUnknownType uint32 `mi:"AccessUnknownType"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Win32_PerfRawData_IAS_NPSAccountingServer struct {
|
type Win32_PerfRawData_IAS_NPSAccountingServer struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
|
||||||
AccountingRequests uint32
|
AccountingRequests uint32 `mi:"AccountingRequests"`
|
||||||
AccountingResponses uint32
|
AccountingResponses uint32 `mi:"AccountingResponses"`
|
||||||
AccountingBadAuthenticators uint32
|
AccountingBadAuthenticators uint32 `mi:"AccountingBadAuthenticators"`
|
||||||
AccountingDroppedPackets uint32
|
AccountingDroppedPackets uint32 `mi:"AccountingDroppedPackets"`
|
||||||
AccountingInvalidRequests uint32
|
AccountingInvalidRequests uint32 `mi:"AccountingInvalidRequests"`
|
||||||
AccountingMalformedPackets uint32
|
AccountingMalformedPackets uint32 `mi:"AccountingMalformedPackets"`
|
||||||
AccountingNoRecord uint32
|
AccountingNoRecord uint32 `mi:"AccountingNoRecord"`
|
||||||
AccountingPacketsReceived uint32
|
AccountingPacketsReceived uint32 `mi:"AccountingPacketsReceived"`
|
||||||
AccountingPacketsSent uint32
|
AccountingPacketsSent uint32 `mi:"AccountingPacketsSent"`
|
||||||
AccountingServerResetTime uint32
|
AccountingServerResetTime uint32 `mi:"AccountingServerResetTime"`
|
||||||
AccountingServerUpTime uint32
|
AccountingServerUpTime uint32 `mi:"AccountingServerUpTime"`
|
||||||
AccountingUnknownType uint32
|
AccountingUnknownType uint32 `mi:"AccountingUnknownType"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CollectAccept sends the metric values for each metric
|
// CollectAccept sends the metric values for each metric
|
||||||
// to the provided prometheus Metric channel.
|
// to the provided prometheus Metric channel.
|
||||||
func (c *Collector) CollectAccept(ch chan<- prometheus.Metric) error {
|
func (c *Collector) CollectAccept(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_IAS_NPSAuthenticationServer
|
var dst []Win32_PerfRawData_IAS_NPSAuthenticationServer
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_IAS_NPSAuthenticationServer", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQueryAuthenticationServer); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
@ -386,8 +403,8 @@ func (c *Collector) CollectAccept(ch chan<- prometheus.Metric) error {
|
||||||
|
|
||||||
func (c *Collector) CollectAccounting(ch chan<- prometheus.Metric) error {
|
func (c *Collector) CollectAccounting(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_IAS_NPSAccountingServer
|
var dst []Win32_PerfRawData_IAS_NPSAccountingServer
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_IAS_NPSAccountingServer", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQueryAccountingServer); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
|
|
@ -16,10 +16,10 @@ import (
|
||||||
"github.com/prometheus-community/windows_exporter/internal/headers/netapi32"
|
"github.com/prometheus-community/windows_exporter/internal/headers/netapi32"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/headers/psapi"
|
"github.com/prometheus-community/windows_exporter/internal/headers/psapi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi"
|
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
"golang.org/x/sys/windows/registry"
|
"golang.org/x/sys/windows/registry"
|
||||||
)
|
)
|
||||||
|
@ -109,9 +109,11 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||||
logger.Warn("The os collect holds a number of deprecated metrics and will be removed mid 2025. " +
|
logger.Warn("The os collect holds a number of deprecated metrics and will be removed mid 2025. "+
|
||||||
"See https://github.com/prometheus-community/windows_exporter/pull/1596 for more information.")
|
"See https://github.com/prometheus-community/windows_exporter/pull/1596 for more information.",
|
||||||
|
slog.String("collector", Name),
|
||||||
|
)
|
||||||
|
|
||||||
workstationInfo, err := netapi32.GetWorkstationInfo()
|
workstationInfo, err := netapi32.GetWorkstationInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -11,11 +11,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "perfdata"
|
const Name = "perfdata"
|
||||||
|
@ -92,7 +92,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||||
logger.Warn("The perfdata collector is in an experimental state! The configuration may change in future. Please report any issues.")
|
logger.Warn("The perfdata collector is in an experimental state! The configuration may change in future. Please report any issues.")
|
||||||
|
|
||||||
for i, object := range c.config.Objects {
|
for i, object := range c.config.Objects {
|
||||||
|
|
|
@ -9,11 +9,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "physical_disk"
|
const Name = "physical_disk"
|
||||||
|
@ -114,7 +114,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
c.requestsQueued = prometheus.NewDesc(
|
c.requestsQueued = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "requests_queued"),
|
prometheus.BuildFQName(types.Namespace, Name, "requests_queued"),
|
||||||
"The number of requests queued to the disk (PhysicalDisk.CurrentDiskQueueLength)",
|
"The number of requests queued to the disk (PhysicalDisk.CurrentDiskQueueLength)",
|
||||||
|
|
|
@ -10,9 +10,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "printer"
|
const Name = "printer"
|
||||||
|
@ -39,8 +39,10 @@ var ConfigDefaults = Config{
|
||||||
}
|
}
|
||||||
|
|
||||||
type Collector struct {
|
type Collector struct {
|
||||||
config Config
|
config Config
|
||||||
wmiClient *wmi.Client
|
miSession *mi.Session
|
||||||
|
miQueryPrinterJobs mi.Query
|
||||||
|
miQueryPrinter mi.Query
|
||||||
|
|
||||||
printerStatus *prometheus.Desc
|
printerStatus *prometheus.Desc
|
||||||
printerJobStatus *prometheus.Desc
|
printerJobStatus *prometheus.Desc
|
||||||
|
@ -107,12 +109,25 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
if miSession == nil {
|
||||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
return errors.New("miSession is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.wmiClient = wmiClient
|
miQuery, err := mi.NewQuery("SELECT Name, Default, PrinterStatus, JobCountSinceLastReset FROM win32_Printer")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create WMI query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.miQueryPrinter = miQuery
|
||||||
|
|
||||||
|
miQuery, err = mi.NewQuery("SELECT Name, Status FROM win32_PrintJob")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create WMI query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.miQueryPrinterJobs = miQuery
|
||||||
|
c.miSession = miSession
|
||||||
|
|
||||||
c.printerJobStatus = prometheus.NewDesc(
|
c.printerJobStatus = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "job_status"),
|
prometheus.BuildFQName(types.Namespace, Name, "job_status"),
|
||||||
|
@ -143,42 +158,35 @@ func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type wmiPrinter struct {
|
type wmiPrinter struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
Default bool
|
Default bool `mi:"Default"`
|
||||||
PrinterStatus uint16
|
PrinterStatus uint16 `mi:"PrinterStatus"`
|
||||||
JobCountSinceLastReset uint32
|
JobCountSinceLastReset uint32 `mi:"JobCountSinceLastReset"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type wmiPrintJob struct {
|
type wmiPrintJob struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
Status string
|
Status string `mi:"Status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||||
logger = logger.With(slog.String("collector", Name))
|
var errs []error
|
||||||
if err := c.collectPrinterStatus(ch); err != nil {
|
|
||||||
logger.Error("failed to collect printer status metrics",
|
|
||||||
slog.Any("err", err),
|
|
||||||
)
|
|
||||||
|
|
||||||
return err
|
if err := c.collectPrinterStatus(ch); err != nil {
|
||||||
|
errs = append(errs, fmt.Errorf("failed to collect printer status metrics: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.collectPrinterJobStatus(ch); err != nil {
|
if err := c.collectPrinterJobStatus(ch); err != nil {
|
||||||
logger.Error("failed to collect printer job status metrics",
|
errs = append(errs, fmt.Errorf("failed to collect printer job status metrics: %w", err))
|
||||||
slog.Any("err", err),
|
|
||||||
)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectPrinterStatus(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectPrinterStatus(ch chan<- prometheus.Metric) error {
|
||||||
var printers []wmiPrinter
|
var printers []wmiPrinter
|
||||||
if err := c.wmiClient.Query("SELECT * FROM win32_Printer", &printers); err != nil {
|
if err := c.miSession.Query(&printers, mi.NamespaceRootCIMv2, c.miQueryPrinter); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, printer := range printers {
|
for _, printer := range printers {
|
||||||
|
@ -215,8 +223,8 @@ func (c *Collector) collectPrinterStatus(ch chan<- prometheus.Metric) error {
|
||||||
|
|
||||||
func (c *Collector) collectPrinterJobStatus(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectPrinterJobStatus(ch chan<- prometheus.Metric) error {
|
||||||
var printJobs []wmiPrintJob
|
var printJobs []wmiPrintJob
|
||||||
if err := c.wmiClient.Query("SELECT * FROM win32_PrintJob", &printJobs); err != nil {
|
if err := c.miSession.Query(&printJobs, mi.NamespaceRootCIMv2, c.miQueryPrinterJobs); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
groupedPrintJobs := c.groupPrintJobs(printJobs)
|
groupedPrintJobs := c.groupPrintJobs(printJobs)
|
||||||
|
|
|
@ -12,13 +12,13 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
v2 "github.com/prometheus-community/windows_exporter/internal/perfdata/v2"
|
v2 "github.com/prometheus-community/windows_exporter/internal/perfdata/v2"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,7 +38,9 @@ var ConfigDefaults = Config{
|
||||||
|
|
||||||
type Collector struct {
|
type Collector struct {
|
||||||
config Config
|
config Config
|
||||||
wmiClient *wmi.Client
|
miSession *mi.Session
|
||||||
|
|
||||||
|
workerProcessMIQueryQuery mi.Query
|
||||||
|
|
||||||
perfDataCollector perfdata.Collector
|
perfDataCollector perfdata.Collector
|
||||||
|
|
||||||
|
@ -139,14 +141,20 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, wmiClient *wmi.Client) error {
|
func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
|
||||||
logger = logger.With(slog.String("collector", Name))
|
logger = logger.With(slog.String("collector", Name))
|
||||||
|
|
||||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
if miSession == nil {
|
||||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
return errors.New("miSession is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.wmiClient = wmiClient
|
miQuery, err := mi.NewQuery("SELECT AppPoolName, ProcessId FROM WorkerProcess")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create WMI query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.workerProcessMIQueryQuery = miQuery
|
||||||
|
c.miSession = miSession
|
||||||
|
|
||||||
if utils.PDHEnabled() {
|
if utils.PDHEnabled() {
|
||||||
counters := []string{
|
counters := []string{
|
||||||
|
@ -302,8 +310,8 @@ func (c *Collector) Build(logger *slog.Logger, wmiClient *wmi.Client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type WorkerProcess struct {
|
type WorkerProcess struct {
|
||||||
AppPoolName string
|
AppPoolName string `mi:"AppPoolName"`
|
||||||
ProcessId uint64
|
ProcessId uint64 `mi:"ProcessId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||||
|
@ -333,10 +341,8 @@ func (c *Collector) collect(ctx *types.ScrapeContext, logger *slog.Logger, ch ch
|
||||||
|
|
||||||
var workerProcesses []WorkerProcess
|
var workerProcesses []WorkerProcess
|
||||||
if c.config.EnableWorkerProcess {
|
if c.config.EnableWorkerProcess {
|
||||||
if err := c.wmiClient.Query("SELECT * FROM WorkerProcess", &workerProcesses, nil, "root\\WebAdministration"); err != nil {
|
if err := c.miSession.Query(&workerProcesses, mi.NamespaceRootWebAdministration, c.workerProcessMIQueryQuery); err != nil {
|
||||||
logger.Debug("Could not query WebAdministration namespace for IIS worker processes",
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
slog.Any("err", err),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,10 +546,8 @@ func (c *Collector) collectPDH(logger *slog.Logger, ch chan<- prometheus.Metric)
|
||||||
|
|
||||||
var workerProcesses []WorkerProcess
|
var workerProcesses []WorkerProcess
|
||||||
if c.config.EnableWorkerProcess {
|
if c.config.EnableWorkerProcess {
|
||||||
if err := c.wmiClient.Query("SELECT * FROM WorkerProcess", &workerProcesses, nil, "root\\WebAdministration"); err != nil {
|
if err := c.miSession.Query(&workerProcesses, mi.NamespaceRootWebAdministration, c.workerProcessMIQueryQuery); err != nil {
|
||||||
logger.Debug("Could not query WebAdministration namespace for IIS worker processes",
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
slog.Any("err", err),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "remote_fx"
|
const Name = "remote_fx"
|
||||||
|
@ -81,7 +81,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(*slog.Logger, *wmi.Client) error {
|
func (c *Collector) Build(*slog.Logger, *mi.Session) error {
|
||||||
// net
|
// net
|
||||||
c.baseTCPRTT = prometheus.NewDesc(
|
c.baseTCPRTT = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "net_base_tcp_rtt_seconds"),
|
prometheus.BuildFQName(types.Namespace, Name, "net_base_tcp_rtt_seconds"),
|
||||||
|
|
|
@ -13,9 +13,9 @@ import (
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
"github.com/go-ole/go-ole"
|
"github.com/go-ole/go-ole"
|
||||||
"github.com/go-ole/go-ole/oleutil"
|
"github.com/go-ole/go-ole/oleutil"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "scheduled_task"
|
const Name = "scheduled_task"
|
||||||
|
@ -148,7 +148,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
initErrCh := make(chan error)
|
initErrCh := make(chan error)
|
||||||
c.scheduledTasksReqCh = make(chan struct{})
|
c.scheduledTasksReqCh = make(chan struct{})
|
||||||
c.scheduledTasksCh = make(chan *scheduledTaskResults)
|
c.scheduledTasksCh = make(chan *scheduledTaskResults)
|
||||||
|
@ -281,7 +281,7 @@ func (c *Collector) initializeScheduleService(initErrCh chan<- error) {
|
||||||
|
|
||||||
if err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED); err != nil {
|
if err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED); err != nil {
|
||||||
var oleCode *ole.OleError
|
var oleCode *ole.OleError
|
||||||
if errors.As(err, &oleCode) && oleCode.Code() != ole.S_OK && oleCode.Code() != wmi.S_FALSE {
|
if errors.As(err, &oleCode) && oleCode.Code() != ole.S_OK && oleCode.Code() != 0x00000001 {
|
||||||
initErrCh <- err
|
initErrCh <- err
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
@ -11,9 +11,9 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
"golang.org/x/sys/windows/svc/mgr"
|
"golang.org/x/sys/windows/svc/mgr"
|
||||||
)
|
)
|
||||||
|
@ -106,7 +106,7 @@ func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
|
||||||
return []string{}, nil
|
return []string{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||||
logger = logger.With(slog.String("collector", Name))
|
logger = logger.With(slog.String("collector", Name))
|
||||||
|
|
||||||
if c.config.ServiceInclude.String() == "^(?:.*)$" && c.config.ServiceExclude.String() == "^(?:)$" {
|
if c.config.ServiceInclude.String() == "^(?:.*)$" && c.config.ServiceExclude.String() == "^(?:)$" {
|
||||||
|
|
|
@ -7,10 +7,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "smb"
|
const Name = "smb"
|
||||||
|
@ -56,7 +56,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
// desc creates a new prometheus description
|
// desc creates a new prometheus description
|
||||||
desc := func(metricName string, description string, labels ...string) *prometheus.Desc {
|
desc := func(metricName string, description string, labels ...string) *prometheus.Desc {
|
||||||
return prometheus.NewDesc(
|
return prometheus.NewDesc(
|
||||||
|
|
|
@ -7,11 +7,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -79,7 +79,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
// desc creates a new prometheus description
|
// desc creates a new prometheus description
|
||||||
desc := func(metricName string, description string, labels []string) *prometheus.Desc {
|
desc := func(metricName string, description string, labels []string) *prometheus.Desc {
|
||||||
return prometheus.NewDesc(
|
return prometheus.NewDesc(
|
||||||
|
|
|
@ -8,10 +8,10 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "smtp"
|
const Name = "smtp"
|
||||||
|
@ -141,10 +141,10 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||||
logger = logger.With(slog.String("collector", Name))
|
logger.Info("smtp collector is in an experimental state! Metrics for this collector have not been tested.",
|
||||||
|
slog.String("collector", Name),
|
||||||
logger.Info("smtp collector is in an experimental state! Metrics for this collector have not been tested.")
|
)
|
||||||
|
|
||||||
c.badMailedMessagesBadPickupFileTotal = prometheus.NewDesc(
|
c.badMailedMessagesBadPickupFileTotal = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "badmailed_messages_bad_pickup_file_total"),
|
prometheus.BuildFQName(types.Namespace, Name, "badmailed_messages_bad_pickup_file_total"),
|
||||||
|
|
|
@ -7,10 +7,10 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "system"
|
const Name = "system"
|
||||||
|
@ -61,7 +61,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
c.contextSwitchesTotal = prometheus.NewDesc(
|
c.contextSwitchesTotal = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "context_switches_total"),
|
prometheus.BuildFQName(types.Namespace, Name, "context_switches_total"),
|
||||||
"Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)",
|
"Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)",
|
||||||
|
|
|
@ -10,11 +10,11 @@ import (
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/headers/iphlpapi"
|
"github.com/prometheus-community/windows_exporter/internal/headers/iphlpapi"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
counters := []string{
|
counters := []string{
|
||||||
connectionFailures,
|
connectionFailures,
|
||||||
connectionsActive,
|
connectionsActive,
|
||||||
|
|
|
@ -11,10 +11,11 @@ import (
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/headers/wtsapi32"
|
"github.com/prometheus-community/windows_exporter/internal/headers/wtsapi32"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,9 +32,9 @@ type Win32_ServerFeature struct {
|
||||||
ID uint32
|
ID uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func isConnectionBrokerServer(logger *slog.Logger, wmiClient *wmi.Client) bool {
|
func isConnectionBrokerServer(logger *slog.Logger, miSession *mi.Session) bool {
|
||||||
var dst []Win32_ServerFeature
|
var dst []Win32_ServerFeature
|
||||||
if err := wmiClient.Query("SELECT * FROM Win32_ServerFeature", &dst); err != nil {
|
if err := miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_ServerFeature"))); err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,10 +113,14 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, wmiClient *wmi.Client) error {
|
func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
|
||||||
|
if miSession == nil {
|
||||||
|
return errors.New("miSession is nil")
|
||||||
|
}
|
||||||
|
|
||||||
logger = logger.With(slog.String("collector", Name))
|
logger = logger.With(slog.String("collector", Name))
|
||||||
|
|
||||||
c.connectionBrokerEnabled = isConnectionBrokerServer(logger, wmiClient)
|
c.connectionBrokerEnabled = isConnectionBrokerServer(logger, miSession)
|
||||||
|
|
||||||
c.sessionInfo = prometheus.NewDesc(
|
c.sessionInfo = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "session_info"),
|
prometheus.BuildFQName(types.Namespace, Name, "session_info"),
|
||||||
|
|
|
@ -29,11 +29,11 @@ import (
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
"github.com/dimchansky/utfbom"
|
"github.com/dimchansky/utfbom"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
"github.com/prometheus/common/expfmt"
|
"github.com/prometheus/common/expfmt"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "textfile"
|
const Name = "textfile"
|
||||||
|
@ -104,7 +104,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||||
logger.Info("textfile Collector directories: "+strings.Join(c.config.TextFileDirectories, ","),
|
logger.Info("textfile Collector directories: "+strings.Join(c.config.TextFileDirectories, ","),
|
||||||
slog.String("collector", Name),
|
slog.String("collector", Name),
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,12 +4,13 @@ package thermalzone
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "thermalzone"
|
const Name = "thermalzone"
|
||||||
|
@ -21,7 +22,8 @@ var ConfigDefaults = Config{}
|
||||||
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics.
|
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics.
|
||||||
type Collector struct {
|
type Collector struct {
|
||||||
config Config
|
config Config
|
||||||
wmiClient *wmi.Client
|
miSession *mi.Session
|
||||||
|
miQuery mi.Query
|
||||||
|
|
||||||
percentPassiveLimit *prometheus.Desc
|
percentPassiveLimit *prometheus.Desc
|
||||||
temperature *prometheus.Desc
|
temperature *prometheus.Desc
|
||||||
|
@ -56,12 +58,19 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
if miSession == nil {
|
||||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
return errors.New("miSession is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.wmiClient = wmiClient
|
miQuery, err := mi.NewQuery("SELECT Name, HighPrecisionTemperature, PercentPassiveLimit, ThrottleReasons FROM Win32_PerfRawData_Counters_ThermalZoneInformation")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create WMI query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.miQuery = miQuery
|
||||||
|
c.miSession = miSession
|
||||||
|
|
||||||
c.temperature = prometheus.NewDesc(
|
c.temperature = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "temperature_celsius"),
|
prometheus.BuildFQName(types.Namespace, Name, "temperature_celsius"),
|
||||||
"(Temperature)",
|
"(Temperature)",
|
||||||
|
@ -108,22 +117,20 @@ func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan
|
||||||
// Win32_PerfRawData_Counters_ThermalZoneInformation docs:
|
// Win32_PerfRawData_Counters_ThermalZoneInformation docs:
|
||||||
// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_thermalzoneinformation/
|
// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_thermalzoneinformation/
|
||||||
type Win32_PerfRawData_Counters_ThermalZoneInformation struct {
|
type Win32_PerfRawData_Counters_ThermalZoneInformation struct {
|
||||||
Name string
|
Name string `mi:"Name"`
|
||||||
|
HighPrecisionTemperature uint32 `mi:"HighPrecisionTemperature"`
|
||||||
HighPrecisionTemperature uint32
|
PercentPassiveLimit uint32 `mi:"PercentPassiveLimit"`
|
||||||
PercentPassiveLimit uint32
|
ThrottleReasons uint32 `mi:"ThrottleReasons"`
|
||||||
ThrottleReasons uint32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_Counters_ThermalZoneInformation
|
var dst []Win32_PerfRawData_Counters_ThermalZoneInformation
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_Counters_ThermalZoneInformation", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ThermalZone collector has been known to 'successfully' return an empty result.
|
|
||||||
if len(dst) == 0 {
|
if len(dst) == 0 {
|
||||||
return errors.New("empty results set for collector")
|
return errors.New("WMI query returned empty result set")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, info := range dst {
|
for _, info := range dst {
|
||||||
|
|
|
@ -9,10 +9,10 @@ import (
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/headers/kernel32"
|
"github.com/prometheus-community/windows_exporter/internal/headers/kernel32"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||||
c.currentTime = prometheus.NewDesc(
|
c.currentTime = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "current_timestamp_seconds"),
|
prometheus.BuildFQName(types.Namespace, Name, "current_timestamp_seconds"),
|
||||||
"OperatingSystem.LocalDateTime",
|
"OperatingSystem.LocalDateTime",
|
||||||
|
|
|
@ -15,9 +15,9 @@ import (
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
"github.com/go-ole/go-ole"
|
"github.com/go-ole/go-ole"
|
||||||
"github.com/go-ole/go-ole/oleutil"
|
"github.com/go-ole/go-ole/oleutil"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "update"
|
const Name = "update"
|
||||||
|
@ -80,7 +80,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(logger *slog.Logger, _ *wmi.Client) error {
|
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||||
logger = logger.With(slog.String("collector", Name))
|
logger = logger.With(slog.String("collector", Name))
|
||||||
|
|
||||||
logger.Info("update collector is in an experimental state! The configuration and metrics may change in future. Please report any issues.")
|
logger.Info("update collector is in an experimental state! The configuration and metrics may change in future. Please report any issues.")
|
||||||
|
@ -147,7 +147,7 @@ func (c *Collector) scheduleUpdateStatus(logger *slog.Logger, initErrCh chan<- e
|
||||||
|
|
||||||
if err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED); err != nil {
|
if err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED); err != nil {
|
||||||
var oleCode *ole.OleError
|
var oleCode *ole.OleError
|
||||||
if errors.As(err, &oleCode) && oleCode.Code() != ole.S_OK && oleCode.Code() != wmi.S_FALSE {
|
if errors.As(err, &oleCode) && oleCode.Code() != ole.S_OK && oleCode.Code() != 0x00000001 {
|
||||||
initErrCh <- fmt.Errorf("CoInitializeEx: %w", err)
|
initErrCh <- fmt.Errorf("CoInitializeEx: %w", err)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
@ -4,13 +4,14 @@ package vmware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Name = "vmware"
|
const Name = "vmware"
|
||||||
|
@ -21,8 +22,10 @@ var ConfigDefaults = Config{}
|
||||||
|
|
||||||
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics.
|
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics.
|
||||||
type Collector struct {
|
type Collector struct {
|
||||||
config Config
|
config Config
|
||||||
wmiClient *wmi.Client
|
miSession *mi.Session
|
||||||
|
miQueryCPU mi.Query
|
||||||
|
miQueryMem mi.Query
|
||||||
|
|
||||||
memActive *prometheus.Desc
|
memActive *prometheus.Desc
|
||||||
memBallooned *prometheus.Desc
|
memBallooned *prometheus.Desc
|
||||||
|
@ -74,12 +77,25 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
if miSession == nil {
|
||||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
return errors.New("miSession is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.wmiClient = wmiClient
|
miQuery, err := mi.NewQuery("SELECT * FROM Win32_PerfRawData_vmGuestLib_VCPU")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create WMI query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.miQueryCPU = miQuery
|
||||||
|
|
||||||
|
miQuery, err = mi.NewQuery("SELECT * FROM Win32_PerfRawData_vmGuestLib_VMem")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create WMI query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.miQueryMem = miQuery
|
||||||
|
c.miSession = miSession
|
||||||
|
|
||||||
c.memActive = prometheus.NewDesc(
|
c.memActive = prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(types.Namespace, Name, "mem_active_bytes"),
|
prometheus.BuildFQName(types.Namespace, Name, "mem_active_bytes"),
|
||||||
|
@ -224,34 +240,34 @@ func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan
|
||||||
}
|
}
|
||||||
|
|
||||||
type Win32_PerfRawData_vmGuestLib_VMem struct {
|
type Win32_PerfRawData_vmGuestLib_VMem struct {
|
||||||
MemActiveMB uint64
|
MemActiveMB uint64 `mi:"MemActiveMB"`
|
||||||
MemBalloonedMB uint64
|
MemBalloonedMB uint64 `mi:"MemBalloonedMB"`
|
||||||
MemLimitMB uint64
|
MemLimitMB uint64 `mi:"MemLimitMB"`
|
||||||
MemMappedMB uint64
|
MemMappedMB uint64 `mi:"MemMappedMB"`
|
||||||
MemOverheadMB uint64
|
MemOverheadMB uint64 `mi:"MemOverheadMB"`
|
||||||
MemReservationMB uint64
|
MemReservationMB uint64 `mi:"MemReservationMB"`
|
||||||
MemSharedMB uint64
|
MemSharedMB uint64 `mi:"MemSharedMB"`
|
||||||
MemSharedSavedMB uint64
|
MemSharedSavedMB uint64 `mi:"MemSharedSavedMB"`
|
||||||
MemShares uint64
|
MemShares uint64 `mi:"MemShares"`
|
||||||
MemSwappedMB uint64
|
MemSwappedMB uint64 `mi:"MemSwappedMB"`
|
||||||
MemTargetSizeMB uint64
|
MemTargetSizeMB uint64 `mi:"MemTargetSizeMB"`
|
||||||
MemUsedMB uint64
|
MemUsedMB uint64 `mi:"MemUsedMB"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Win32_PerfRawData_vmGuestLib_VCPU struct {
|
type Win32_PerfRawData_vmGuestLib_VCPU struct {
|
||||||
CpuLimitMHz uint64
|
CpuLimitMHz uint64 `mi:"CpuLimitMHz"`
|
||||||
CpuReservationMHz uint64
|
CpuReservationMHz uint64 `mi:"CpuReservationMHz"`
|
||||||
CpuShares uint64
|
CpuShares uint64 `mi:"CpuShares"`
|
||||||
CpuStolenMs uint64
|
CpuStolenMs uint64 `mi:"CpuStolenMs"`
|
||||||
CpuTimePercents uint64
|
CpuTimePercents uint64 `mi:"CpuTimePercents"`
|
||||||
EffectiveVMSpeedMHz uint64
|
EffectiveVMSpeedMHz uint64 `mi:"EffectiveVMSpeedMHz"`
|
||||||
HostProcessorSpeedMHz uint64
|
HostProcessorSpeedMHz uint64 `mi:"HostProcessorSpeedMHz"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectMem(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectMem(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_vmGuestLib_VMem
|
var dst []Win32_PerfRawData_vmGuestLib_VMem
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_vmGuestLib_VMem", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQueryMem); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(dst) == 0 {
|
if len(dst) == 0 {
|
||||||
|
@ -333,14 +349,15 @@ func (c *Collector) collectMem(ch chan<- prometheus.Metric) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mbToBytes moved to utils package
|
||||||
func mbToBytes(mb uint64) float64 {
|
func mbToBytes(mb uint64) float64 {
|
||||||
return float64(mb * 1024 * 1024)
|
return float64(mb * 1024 * 1024)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collector) collectCpu(ch chan<- prometheus.Metric) error {
|
func (c *Collector) collectCpu(ch chan<- prometheus.Metric) error {
|
||||||
var dst []Win32_PerfRawData_vmGuestLib_VCPU
|
var dst []Win32_PerfRawData_vmGuestLib_VCPU
|
||||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_vmGuestLib_VCPU", &dst); err != nil {
|
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQueryCPU); err != nil {
|
||||||
return err
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(dst) == 0 {
|
if len(dst) == 0 {
|
||||||
|
|
|
@ -129,7 +129,7 @@ func (c *MetricsHTTPHandler) handlerFactory(logger *slog.Logger, scrapeTimeout t
|
||||||
|
|
||||||
metricCollectors = &collector.MetricCollectors{
|
metricCollectors = &collector.MetricCollectors{
|
||||||
Collectors: filteredCollectors,
|
Collectors: filteredCollectors,
|
||||||
WMIClient: c.metricCollectors.WMIClient,
|
MISession: c.metricCollectors.MISession,
|
||||||
PerfCounterQuery: c.metricCollectors.PerfCounterQuery,
|
PerfCounterQuery: c.metricCollectors.PerfCounterQuery,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,283 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package mi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
applicationID = "windows_exporter"
|
||||||
|
|
||||||
|
LocaleEnglish = "en-us"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// DestinationOptionsTimeout is the key for the timeout option.
|
||||||
|
//
|
||||||
|
// https://github.com/microsoft/win32metadata/blob/527806d20d83d3abd43d16cd3fa8795d8deba343/generation/WinSDK/RecompiledIdlHeaders/um/mi.h#L7830
|
||||||
|
DestinationOptionsTimeout = UTF16PtrFromString[*uint16]("__MI_DESTINATIONOPTIONS_TIMEOUT")
|
||||||
|
|
||||||
|
// DestinationOptionsUILocale is the key for the UI locale option.
|
||||||
|
//
|
||||||
|
// https://github.com/microsoft/win32metadata/blob/527806d20d83d3abd43d16cd3fa8795d8deba343/generation/WinSDK/RecompiledIdlHeaders/um/mi.h#L8248
|
||||||
|
DestinationOptionsUILocale = UTF16PtrFromString[*uint16]("__MI_DESTINATIONOPTIONS_UI_LOCALE")
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
modMi = windows.NewLazySystemDLL("mi.dll")
|
||||||
|
|
||||||
|
procMIApplicationInitialize = modMi.NewProc("MI_Application_InitializeV1")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Application represents the MI application.
|
||||||
|
// https://learn.microsoft.com/de-de/windows/win32/api/mi/ns-mi-mi_application
|
||||||
|
type Application struct {
|
||||||
|
reserved1 uint64
|
||||||
|
reserved2 uintptr
|
||||||
|
ft *ApplicationFT
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplicationFT represents the function table of the MI application.
|
||||||
|
// https://learn.microsoft.com/de-de/windows/win32/api/mi/ns-mi-mi_applicationft
|
||||||
|
type ApplicationFT struct {
|
||||||
|
Close uintptr
|
||||||
|
NewSession uintptr
|
||||||
|
NewHostedProvider uintptr
|
||||||
|
NewInstance uintptr
|
||||||
|
NewDestinationOptions uintptr
|
||||||
|
NewOperationOptions uintptr
|
||||||
|
NewSubscriptionDeliveryOptions uintptr
|
||||||
|
NewSerializer uintptr
|
||||||
|
NewDeserializer uintptr
|
||||||
|
NewInstanceFromClass uintptr
|
||||||
|
NewClass uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type DestinationOptions struct {
|
||||||
|
reserved1 uint64
|
||||||
|
reserved2 uintptr
|
||||||
|
ft *DestinationOptionsFT
|
||||||
|
}
|
||||||
|
|
||||||
|
type DestinationOptionsFT struct {
|
||||||
|
Delete uintptr
|
||||||
|
SetString uintptr
|
||||||
|
SetNumber uintptr
|
||||||
|
AddCredentials uintptr
|
||||||
|
GetString uintptr
|
||||||
|
GetNumber uintptr
|
||||||
|
GetOptionCount uintptr
|
||||||
|
GetOptionAt uintptr
|
||||||
|
GetOption uintptr
|
||||||
|
GetCredentialsCount uintptr
|
||||||
|
GetCredentialsAt uintptr
|
||||||
|
GetCredentialsPasswordAt uintptr
|
||||||
|
Clone uintptr
|
||||||
|
SetInterval uintptr
|
||||||
|
GetInterval uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Application_Initialize initializes the MI [Application].
|
||||||
|
// It is recommended to have only one Application per process.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_application_initializev1
|
||||||
|
func Application_Initialize() (*Application, error) {
|
||||||
|
application := &Application{}
|
||||||
|
|
||||||
|
applicationId, err := windows.UTF16PtrFromString(applicationID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r0, _, err := procMIApplicationInitialize.Call(
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(applicationId)),
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(application)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if !errors.Is(err, windows.NOERROR) {
|
||||||
|
return nil, fmt.Errorf("syscall returned: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return nil, result
|
||||||
|
}
|
||||||
|
|
||||||
|
return application, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close deinitializes the management infrastructure client API that was initialized through a call to Application_Initialize.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_application_close
|
||||||
|
func (application *Application) Close() error {
|
||||||
|
if application == nil || application.ft == nil {
|
||||||
|
return ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(application.ft.Close, uintptr(unsafe.Pointer(application)))
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSession creates a session used to share connections for a set of operations to a single destination.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_application_newsession
|
||||||
|
func (application *Application) NewSession(options *DestinationOptions) (*Session, error) {
|
||||||
|
if application == nil || application.ft == nil {
|
||||||
|
return nil, ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
session := &Session{}
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
application.ft.NewSession,
|
||||||
|
uintptr(unsafe.Pointer(application)),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(options)),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(session)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return nil, result
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultOperationOptions, err := application.NewOperationOptions()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create default operation options: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = defaultOperationOptions.SetTimeout(5 * time.Second); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to set timeout: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
session.defaultOperationOptions = defaultOperationOptions
|
||||||
|
|
||||||
|
return session, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOperationOptions creates an OperationOptions object that can be used with the operation functions on the Session object.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_application_newoperationoptions
|
||||||
|
func (application *Application) NewOperationOptions() (*OperationOptions, error) {
|
||||||
|
if application == nil || application.ft == nil {
|
||||||
|
return nil, ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
operationOptions := &OperationOptions{}
|
||||||
|
mustUnderstand := True
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
application.ft.NewOperationOptions,
|
||||||
|
uintptr(unsafe.Pointer(application)),
|
||||||
|
uintptr(mustUnderstand),
|
||||||
|
uintptr(unsafe.Pointer(operationOptions)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return nil, result
|
||||||
|
}
|
||||||
|
|
||||||
|
return operationOptions, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDestinationOptions creates an DestinationOptions object that can be used with the Application.NewSession function.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_application_newdestinationoptions
|
||||||
|
func (application *Application) NewDestinationOptions() (*DestinationOptions, error) {
|
||||||
|
if application == nil || application.ft == nil {
|
||||||
|
return nil, ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
operationOptions := &DestinationOptions{}
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
application.ft.NewDestinationOptions,
|
||||||
|
uintptr(unsafe.Pointer(application)),
|
||||||
|
uintptr(unsafe.Pointer(operationOptions)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return nil, result
|
||||||
|
}
|
||||||
|
|
||||||
|
return operationOptions, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTimeout sets the timeout for the destination options.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_destinationoptions_settimeout
|
||||||
|
func (do *DestinationOptions) SetTimeout(timeout time.Duration) error {
|
||||||
|
if do == nil || do.ft == nil {
|
||||||
|
return ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
do.ft.SetInterval,
|
||||||
|
uintptr(unsafe.Pointer(do)),
|
||||||
|
uintptr(unsafe.Pointer(DestinationOptionsTimeout)),
|
||||||
|
uintptr(unsafe.Pointer(NewInterval(timeout))),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLocale sets the locale for the destination options.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_destinationoptions_setuilocale
|
||||||
|
func (do *DestinationOptions) SetLocale(locale string) error {
|
||||||
|
if do == nil || do.ft == nil {
|
||||||
|
return ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
localeUTF16, err := windows.UTF16PtrFromString(locale)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to convert locale: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
do.ft.SetString,
|
||||||
|
uintptr(unsafe.Pointer(do)),
|
||||||
|
uintptr(unsafe.Pointer(DestinationOptionsUILocale)),
|
||||||
|
uintptr(unsafe.Pointer(localeUTF16)),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (do *DestinationOptions) Delete() error {
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
do.ft.Delete,
|
||||||
|
uintptr(unsafe.Pointer(do)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,154 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package mi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
// We have to registry a global callback function, since the amount of callbacks is limited.
|
||||||
|
var operationUnmarshalCallbacksInstanceResult = sync.OnceValue[uintptr](func() uintptr {
|
||||||
|
return windows.NewCallback(func(
|
||||||
|
operation *Operation,
|
||||||
|
callbacks *OperationUnmarshalCallbacks,
|
||||||
|
instance *Instance,
|
||||||
|
moreResults Boolean,
|
||||||
|
instanceResult ResultError,
|
||||||
|
errorMessageUTF16 *uint16,
|
||||||
|
errorDetails *Instance,
|
||||||
|
_ uintptr,
|
||||||
|
) uintptr {
|
||||||
|
if moreResults == False {
|
||||||
|
defer operation.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return callbacks.InstanceResult(operation, instance, moreResults, instanceResult, errorMessageUTF16, errorDetails)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
type OperationUnmarshalCallbacks struct {
|
||||||
|
dst any
|
||||||
|
dv reflect.Value
|
||||||
|
errCh chan<- error
|
||||||
|
|
||||||
|
elemType reflect.Type
|
||||||
|
elemValue reflect.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUnmarshalOperationsCallbacks(dst any, errCh chan<- error) (*OperationCallbacks[OperationUnmarshalCallbacks], error) {
|
||||||
|
dv := reflect.ValueOf(dst)
|
||||||
|
if dv.Kind() != reflect.Ptr || dv.IsNil() {
|
||||||
|
return nil, ErrInvalidEntityType
|
||||||
|
}
|
||||||
|
|
||||||
|
dv = dv.Elem()
|
||||||
|
|
||||||
|
elemType := dv.Type().Elem()
|
||||||
|
elemValue := reflect.ValueOf(reflect.New(elemType).Interface()).Elem()
|
||||||
|
|
||||||
|
if dv.Kind() != reflect.Slice || elemType.Kind() != reflect.Struct {
|
||||||
|
return nil, ErrInvalidEntityType
|
||||||
|
}
|
||||||
|
|
||||||
|
dv.Set(reflect.MakeSlice(dv.Type(), 0, 0))
|
||||||
|
|
||||||
|
return &OperationCallbacks[OperationUnmarshalCallbacks]{
|
||||||
|
CallbackContext: &OperationUnmarshalCallbacks{
|
||||||
|
errCh: errCh,
|
||||||
|
dst: dst,
|
||||||
|
dv: dv,
|
||||||
|
elemType: elemType,
|
||||||
|
elemValue: elemValue,
|
||||||
|
},
|
||||||
|
InstanceResult: operationUnmarshalCallbacksInstanceResult(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OperationUnmarshalCallbacks) InstanceResult(
|
||||||
|
_ *Operation,
|
||||||
|
instance *Instance,
|
||||||
|
moreResults Boolean,
|
||||||
|
instanceResult ResultError,
|
||||||
|
errorMessageUTF16 *uint16,
|
||||||
|
_ *Instance,
|
||||||
|
) uintptr {
|
||||||
|
defer func() {
|
||||||
|
if moreResults == False {
|
||||||
|
close(o.errCh)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if !errors.Is(instanceResult, MI_RESULT_OK) {
|
||||||
|
o.errCh <- fmt.Errorf("%w: %s", instanceResult, windows.UTF16PtrToString(errorMessageUTF16))
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if instance == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
counter, err := instance.GetElementCount()
|
||||||
|
if err != nil {
|
||||||
|
o.errCh <- fmt.Errorf("failed to get element count: %w", err)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if counter == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range o.elemType.NumField() {
|
||||||
|
field := o.elemValue.Field(i)
|
||||||
|
|
||||||
|
// Check if the field has an `mi` tag
|
||||||
|
miTag := o.elemType.Field(i).Tag.Get("mi")
|
||||||
|
if miTag == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
element, err := instance.GetElement(miTag)
|
||||||
|
if err != nil {
|
||||||
|
o.errCh <- fmt.Errorf("failed to get element: %w", err)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
switch element.valueType {
|
||||||
|
case ValueTypeBOOLEAN:
|
||||||
|
field.SetBool(element.value == 1)
|
||||||
|
case ValueTypeUINT8, ValueTypeUINT16, ValueTypeUINT32, ValueTypeUINT64:
|
||||||
|
field.SetUint(uint64(element.value))
|
||||||
|
case ValueTypeSINT8, ValueTypeSINT16, ValueTypeSINT32, ValueTypeSINT64:
|
||||||
|
field.SetInt(int64(element.value))
|
||||||
|
case ValueTypeSTRING:
|
||||||
|
if element.value == 0 {
|
||||||
|
o.errCh <- fmt.Errorf("%s: invalid pointer: value is nil", miTag)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the UTF-16 string to a Go string
|
||||||
|
stringValue := windows.UTF16PtrToString((*uint16)(unsafe.Pointer(element.value)))
|
||||||
|
|
||||||
|
field.SetString(stringValue)
|
||||||
|
case ValueTypeREAL32, ValueTypeREAL64:
|
||||||
|
field.SetFloat(float64(element.value))
|
||||||
|
default:
|
||||||
|
o.errCh <- fmt.Errorf("unsupported value type: %d", element.valueType)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
o.dv.Set(reflect.Append(o.dv, o.elemValue))
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
// mi is a package that provides a Go API for Windows Management Infrastructure (MI) functions.
|
||||||
|
// It requires Windows Management Framework 3.0 or later.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/de-de/previous-versions/windows/desktop/wmi_v2/why-use-mi-
|
||||||
|
package mi
|
|
@ -0,0 +1,10 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package mi
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrNotInitialized = errors.New("not initialized")
|
||||||
|
ErrInvalidEntityType = errors.New("invalid entity type")
|
||||||
|
)
|
|
@ -0,0 +1,179 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package mi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Instance struct {
|
||||||
|
ft *InstanceFT
|
||||||
|
classDecl *ClassDecl
|
||||||
|
serverName *uint16
|
||||||
|
nameSpace *uint16
|
||||||
|
_ [4]uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type InstanceFT struct {
|
||||||
|
Clone uintptr
|
||||||
|
Destruct uintptr
|
||||||
|
Delete uintptr
|
||||||
|
IsA uintptr
|
||||||
|
GetClassName uintptr
|
||||||
|
SetNameSpace uintptr
|
||||||
|
GetNameSpace uintptr
|
||||||
|
GetElementCount uintptr
|
||||||
|
AddElement uintptr
|
||||||
|
SetElement uintptr
|
||||||
|
SetElementAt uintptr
|
||||||
|
GetElement uintptr
|
||||||
|
GetElementAt uintptr
|
||||||
|
ClearElement uintptr
|
||||||
|
ClearElementAt uintptr
|
||||||
|
GetServerName uintptr
|
||||||
|
SetServerName uintptr
|
||||||
|
GetClass uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClassDecl struct {
|
||||||
|
Flags uint32
|
||||||
|
Code uint32
|
||||||
|
Name *uint16
|
||||||
|
Mqualifiers uintptr
|
||||||
|
NumQualifiers uint32
|
||||||
|
Mproperties uintptr
|
||||||
|
NumProperties uint32
|
||||||
|
Size uint32
|
||||||
|
SuperClass *uint16
|
||||||
|
SuperClassDecl uintptr
|
||||||
|
Methods uintptr
|
||||||
|
NumMethods uint32
|
||||||
|
|
||||||
|
Schema uintptr
|
||||||
|
ProviderFT uintptr
|
||||||
|
OwningClass uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (instance *Instance) Delete() error {
|
||||||
|
if instance == nil || instance.ft == nil {
|
||||||
|
return ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(instance.ft.Delete, uintptr(unsafe.Pointer(instance)))
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (instance *Instance) GetElement(elementName string) (*Element, error) {
|
||||||
|
if instance == nil || instance.ft == nil {
|
||||||
|
return nil, ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
elementNameUTF16, err := windows.UTF16PtrFromString(elementName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to convert element name %s to UTF-16: %w", elementName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
value uintptr
|
||||||
|
valueType ValueType
|
||||||
|
)
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
instance.ft.GetElement,
|
||||||
|
uintptr(unsafe.Pointer(instance)),
|
||||||
|
uintptr(unsafe.Pointer(elementNameUTF16)),
|
||||||
|
uintptr(unsafe.Pointer(&value)),
|
||||||
|
uintptr(unsafe.Pointer(&valueType)),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return nil, result
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Element{
|
||||||
|
value: value,
|
||||||
|
valueType: valueType,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (instance *Instance) GetElementCount() (uint32, error) {
|
||||||
|
if instance == nil || instance.ft == nil {
|
||||||
|
return 0, ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
var count uint32
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
instance.ft.GetElementCount,
|
||||||
|
uintptr(unsafe.Pointer(instance)),
|
||||||
|
uintptr(unsafe.Pointer(&count)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return 0, result
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (instance *Instance) GetClassName() (string, error) {
|
||||||
|
if instance == nil || instance.ft == nil {
|
||||||
|
return "", ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
var classNameUTF16 *uint16
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
instance.ft.GetClassName,
|
||||||
|
uintptr(unsafe.Pointer(instance)),
|
||||||
|
uintptr(unsafe.Pointer(&classNameUTF16)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return "", result
|
||||||
|
}
|
||||||
|
|
||||||
|
if classNameUTF16 == nil {
|
||||||
|
return "", errors.New("class name is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
return windows.UTF16PtrToString(classNameUTF16), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Instance_Print(instance *Instance) (string, error) {
|
||||||
|
elementMap := map[string]any{}
|
||||||
|
|
||||||
|
properties := instance.classDecl.Properties()
|
||||||
|
|
||||||
|
count, err := instance.GetElementCount()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, property := range properties {
|
||||||
|
name := windows.UTF16PtrToString(property.Name)
|
||||||
|
|
||||||
|
element, _ := instance.GetElement(name)
|
||||||
|
value, _ := element.GetValue()
|
||||||
|
|
||||||
|
elementMap[windows.UTF16PtrToString(property.Name)] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%v", elementMap), nil
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package mi_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Benchmark_MI_Query_Unmarshal(b *testing.B) {
|
||||||
|
application, err := mi.Application_Initialize()
|
||||||
|
require.NoError(b, err)
|
||||||
|
require.NotEmpty(b, application)
|
||||||
|
|
||||||
|
session, err := application.NewSession(nil)
|
||||||
|
require.NoError(b, err)
|
||||||
|
require.NotEmpty(b, session)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
var processes []win32Process
|
||||||
|
|
||||||
|
query, err := mi.NewQuery("SELECT Name FROM Win32_Process WHERE Handle = 0 OR Handle = 4")
|
||||||
|
require.NoError(b, err)
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
err := session.QueryUnmarshal(&processes, mi.OperationFlagsStandardRTTI, nil, mi.NamespaceRootCIMv2, mi.QueryDialectWQL, query)
|
||||||
|
require.NoError(b, err)
|
||||||
|
require.Equal(b, []win32Process{{Name: "System Idle Process"}, {Name: "System"}}, processes)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
|
||||||
|
err = session.Close()
|
||||||
|
require.NoError(b, err)
|
||||||
|
|
||||||
|
err = application.Close()
|
||||||
|
require.NoError(b, err)
|
||||||
|
|
||||||
|
b.ReportAllocs()
|
||||||
|
}
|
|
@ -0,0 +1,294 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package mi_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/testutils"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
type win32Process struct {
|
||||||
|
Name string `mi:"Name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type wmiPrinter struct {
|
||||||
|
Name string `mi:"Name"`
|
||||||
|
Default bool `mi:"Default"`
|
||||||
|
PrinterStatus uint16 `mi:"PrinterStatus"`
|
||||||
|
JobCountSinceLastReset uint32 `mi:"JobCountSinceLastReset"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type wmiPrintJob struct {
|
||||||
|
Name string `mi:"Name"`
|
||||||
|
Status string `mi:"Status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_MI_Application_Initialize(t *testing.T) {
|
||||||
|
application, err := mi.Application_Initialize()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, application)
|
||||||
|
|
||||||
|
err = application.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_MI_Application_TestConnection(t *testing.T) {
|
||||||
|
application, err := mi.Application_Initialize()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, application)
|
||||||
|
|
||||||
|
destinationOptions, err := application.NewDestinationOptions()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, destinationOptions)
|
||||||
|
|
||||||
|
err = destinationOptions.SetTimeout(1 * time.Second)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = destinationOptions.SetLocale(mi.LocaleEnglish)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
session, err := application.NewSession(destinationOptions)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, session)
|
||||||
|
|
||||||
|
err = session.TestConnection()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, session)
|
||||||
|
|
||||||
|
err = session.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = application.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_MI_Query(t *testing.T) {
|
||||||
|
application, err := mi.Application_Initialize()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, application)
|
||||||
|
|
||||||
|
destinationOptions, err := application.NewDestinationOptions()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, destinationOptions)
|
||||||
|
|
||||||
|
err = destinationOptions.SetTimeout(1 * time.Second)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = destinationOptions.SetLocale(mi.LocaleEnglish)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
session, err := application.NewSession(destinationOptions)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, session)
|
||||||
|
|
||||||
|
operation, err := session.QueryInstances(mi.OperationFlagsStandardRTTI, nil, mi.NamespaceRootCIMv2, mi.QueryDialectWQL, "select Name from win32_process where handle = 0")
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, operation)
|
||||||
|
|
||||||
|
instance, moreResults, err := operation.GetInstance()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, instance)
|
||||||
|
|
||||||
|
count, err := instance.GetElementCount()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotZero(t, count)
|
||||||
|
|
||||||
|
element, err := instance.GetElement("Name")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, element)
|
||||||
|
|
||||||
|
value, err := element.GetValue()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "System Idle Process", value)
|
||||||
|
require.NotEmpty(t, value)
|
||||||
|
|
||||||
|
require.False(t, moreResults)
|
||||||
|
|
||||||
|
err = operation.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = session.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = application.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_MI_QueryUnmarshal(t *testing.T) {
|
||||||
|
application, err := mi.Application_Initialize()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, application)
|
||||||
|
|
||||||
|
destinationOptions, err := application.NewDestinationOptions()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, destinationOptions)
|
||||||
|
|
||||||
|
err = destinationOptions.SetTimeout(1 * time.Second)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = destinationOptions.SetLocale(mi.LocaleEnglish)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
session, err := application.NewSession(destinationOptions)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, session)
|
||||||
|
|
||||||
|
var processes []win32Process
|
||||||
|
|
||||||
|
queryProcess, err := mi.NewQuery("select Name from win32_process where handle = 0")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = session.QueryUnmarshal(&processes, mi.OperationFlagsStandardRTTI, nil, mi.NamespaceRootCIMv2, mi.QueryDialectWQL, queryProcess)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, []win32Process{{Name: "System Idle Process"}}, processes)
|
||||||
|
|
||||||
|
err = session.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = application.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_MI_EmptyQuery(t *testing.T) {
|
||||||
|
application, err := mi.Application_Initialize()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, application)
|
||||||
|
|
||||||
|
destinationOptions, err := application.NewDestinationOptions()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, destinationOptions)
|
||||||
|
|
||||||
|
err = destinationOptions.SetTimeout(1 * time.Second)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = destinationOptions.SetLocale(mi.LocaleEnglish)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
session, err := application.NewSession(destinationOptions)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, session)
|
||||||
|
|
||||||
|
operation, err := session.QueryInstances(mi.OperationFlagsStandardRTTI, nil, mi.NamespaceRootCIMv2, mi.QueryDialectWQL, "SELECT Name, Status FROM win32_PrintJob")
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, operation)
|
||||||
|
|
||||||
|
instance, moreResults, err := operation.GetInstance()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Empty(t, instance)
|
||||||
|
require.False(t, moreResults)
|
||||||
|
|
||||||
|
err = operation.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = session.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = application.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_MI_Query_Unmarshal(t *testing.T) {
|
||||||
|
application, err := mi.Application_Initialize()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, application)
|
||||||
|
|
||||||
|
destinationOptions, err := application.NewDestinationOptions()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, destinationOptions)
|
||||||
|
|
||||||
|
err = destinationOptions.SetTimeout(1 * time.Second)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = destinationOptions.SetLocale(mi.LocaleEnglish)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
session, err := application.NewSession(destinationOptions)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, session)
|
||||||
|
|
||||||
|
operation, err := session.QueryInstances(mi.OperationFlagsStandardRTTI, nil, mi.NamespaceRootCIMv2, mi.QueryDialectWQL, "SELECT Name FROM Win32_Process WHERE Handle = 0 OR Handle = 4")
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, operation)
|
||||||
|
|
||||||
|
var processes []win32Process
|
||||||
|
|
||||||
|
err = operation.Unmarshal(&processes)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, []win32Process{{Name: "System Idle Process"}, {Name: "System"}}, processes)
|
||||||
|
|
||||||
|
err = operation.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = session.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = application.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_MI_FD_Leak(t *testing.T) {
|
||||||
|
t.Skip("This test is disabled because it is not deterministic and may fail on some systems.")
|
||||||
|
|
||||||
|
application, err := mi.Application_Initialize()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, application)
|
||||||
|
|
||||||
|
session, err := application.NewSession(nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, session)
|
||||||
|
|
||||||
|
currentFileHandle, err := testutils.GetProcessHandleCount(windows.CurrentProcess())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Log("Current File Handle Count: ", currentFileHandle)
|
||||||
|
|
||||||
|
queryPrinter, err := mi.NewQuery("SELECT Name, Default, PrinterStatus, JobCountSinceLastReset FROM win32_Printer")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
queryPrinterJob, err := mi.NewQuery("SELECT Name, Status FROM win32_PrintJob")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
for range 1000 {
|
||||||
|
var wmiPrinters []wmiPrinter
|
||||||
|
err := session.Query(&wmiPrinters, mi.NamespaceRootCIMv2, queryPrinter)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var wmiPrintJobs []wmiPrintJob
|
||||||
|
err = session.Query(&wmiPrintJobs, mi.NamespaceRootCIMv2, queryPrinterJob)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
currentFileHandle, err = testutils.GetProcessHandleCount(windows.CurrentProcess())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Log("Current File Handle Count: ", currentFileHandle)
|
||||||
|
}
|
||||||
|
|
||||||
|
currentFileHandle, err = testutils.GetProcessHandleCount(windows.CurrentProcess())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Log("Current File Handle Count: ", currentFileHandle)
|
||||||
|
|
||||||
|
err = session.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
currentFileHandle, err = testutils.GetProcessHandleCount(windows.CurrentProcess())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Log("Current File Handle Count: ", currentFileHandle)
|
||||||
|
|
||||||
|
err = application.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
currentFileHandle, err = testutils.GetProcessHandleCount(windows.CurrentProcess())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Log("Current File Handle Count: ", currentFileHandle)
|
||||||
|
}
|
|
@ -0,0 +1,272 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package mi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OperationOptionsTimeout is the key for the timeout option.
|
||||||
|
//
|
||||||
|
// https://github.com/microsoft/win32metadata/blob/527806d20d83d3abd43d16cd3fa8795d8deba343/generation/WinSDK/RecompiledIdlHeaders/um/mi.h#L9240
|
||||||
|
var OperationOptionsTimeout = UTF16PtrFromString[*uint16]("__MI_OPERATIONOPTIONS_TIMEOUT")
|
||||||
|
|
||||||
|
// OperationFlags represents the flags for an operation.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/previous-versions/windows/desktop/wmi_v2/mi-flags
|
||||||
|
type OperationFlags uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
OperationFlagsDefaultRTTI OperationFlags = 0x0000
|
||||||
|
OperationFlagsBasicRTTI OperationFlags = 0x0002
|
||||||
|
OperationFlagsNoRTTI OperationFlags = 0x0400
|
||||||
|
OperationFlagsStandardRTTI OperationFlags = 0x0800
|
||||||
|
OperationFlagsFullRTTI OperationFlags = 0x0004
|
||||||
|
)
|
||||||
|
|
||||||
|
// Operation represents an operation.
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/ns-mi-mi_operation
|
||||||
|
type Operation struct {
|
||||||
|
reserved1 uint64
|
||||||
|
reserved2 uintptr
|
||||||
|
ft *OperationFT
|
||||||
|
}
|
||||||
|
|
||||||
|
// OperationFT represents the function table for Operation.
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/ns-mi-mi_operationft
|
||||||
|
type OperationFT struct {
|
||||||
|
Close uintptr
|
||||||
|
Cancel uintptr
|
||||||
|
GetSession uintptr
|
||||||
|
GetInstance uintptr
|
||||||
|
GetIndication uintptr
|
||||||
|
GetClass uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type OperationOptions struct {
|
||||||
|
reserved1 uint64
|
||||||
|
reserved2 uintptr
|
||||||
|
ft *OperationOptionsFT
|
||||||
|
}
|
||||||
|
|
||||||
|
type OperationOptionsFT struct {
|
||||||
|
Delete uintptr
|
||||||
|
SetString uintptr
|
||||||
|
SetNumber uintptr
|
||||||
|
SetCustomOption uintptr
|
||||||
|
GetString uintptr
|
||||||
|
GetNumber uintptr
|
||||||
|
GetOptionCount uintptr
|
||||||
|
GetOptionAt uintptr
|
||||||
|
GetOption uintptr
|
||||||
|
GetEnabledChannels uintptr
|
||||||
|
Clone uintptr
|
||||||
|
SetInterval uintptr
|
||||||
|
GetInterval uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type OperationCallbacks[T any] struct {
|
||||||
|
CallbackContext *T
|
||||||
|
PromptUser uintptr
|
||||||
|
WriteError uintptr
|
||||||
|
WriteMessage uintptr
|
||||||
|
WriteProgress uintptr
|
||||||
|
InstanceResult uintptr
|
||||||
|
IndicationResult uintptr
|
||||||
|
ClassResult uintptr
|
||||||
|
StreamedParameterResult uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes an operation handle.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_operation_close
|
||||||
|
func (o *Operation) Close() error {
|
||||||
|
if o == nil || o.ft == nil {
|
||||||
|
return ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(o.ft.Close, uintptr(unsafe.Pointer(o)))
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Operation) Cancel() error {
|
||||||
|
if o == nil || o.ft == nil {
|
||||||
|
return ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(o.ft.Close, uintptr(unsafe.Pointer(o)), 0)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Operation) GetInstance() (*Instance, bool, error) {
|
||||||
|
if o == nil || o.ft == nil {
|
||||||
|
return nil, false, ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
instance *Instance
|
||||||
|
errorDetails *Instance
|
||||||
|
moreResults Boolean
|
||||||
|
instanceResult ResultError
|
||||||
|
errorMessageUTF16 *uint16
|
||||||
|
)
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
o.ft.GetInstance,
|
||||||
|
uintptr(unsafe.Pointer(o)),
|
||||||
|
uintptr(unsafe.Pointer(&instance)),
|
||||||
|
uintptr(unsafe.Pointer(&moreResults)),
|
||||||
|
uintptr(unsafe.Pointer(&instanceResult)),
|
||||||
|
uintptr(unsafe.Pointer(&errorMessageUTF16)),
|
||||||
|
uintptr(unsafe.Pointer(&errorDetails)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if !errors.Is(instanceResult, MI_RESULT_OK) {
|
||||||
|
return nil, false, fmt.Errorf("instance result: %w (%s)", instanceResult, windows.UTF16PtrToString(errorMessageUTF16))
|
||||||
|
}
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return nil, false, result
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance, moreResults == True, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Operation) Unmarshal(dst any) error {
|
||||||
|
if o == nil || o.ft == nil {
|
||||||
|
return ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
dv := reflect.ValueOf(dst)
|
||||||
|
if dv.Kind() != reflect.Ptr || dv.IsNil() {
|
||||||
|
return ErrInvalidEntityType
|
||||||
|
}
|
||||||
|
|
||||||
|
dv = dv.Elem()
|
||||||
|
|
||||||
|
elemType := dv.Type().Elem()
|
||||||
|
elemValue := reflect.ValueOf(reflect.New(elemType).Interface()).Elem()
|
||||||
|
|
||||||
|
if dv.Kind() != reflect.Slice || elemType.Kind() != reflect.Struct {
|
||||||
|
return ErrInvalidEntityType
|
||||||
|
}
|
||||||
|
|
||||||
|
dv.Set(reflect.MakeSlice(dv.Type(), 0, 0))
|
||||||
|
|
||||||
|
for {
|
||||||
|
instance, moreResults, err := o.GetInstance()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get instance: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If WMI returns nil, it means there are no more results.
|
||||||
|
if instance == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
counter, err := instance.GetElementCount()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get element count: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if counter == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range elemType.NumField() {
|
||||||
|
field := elemValue.Field(i)
|
||||||
|
|
||||||
|
// Check if the field has an `mi` tag
|
||||||
|
miTag := elemType.Field(i).Tag.Get("mi")
|
||||||
|
if miTag == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
element, err := instance.GetElement(miTag)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get element: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch element.valueType {
|
||||||
|
case ValueTypeBOOLEAN:
|
||||||
|
field.SetBool(element.value == 1)
|
||||||
|
case ValueTypeUINT8, ValueTypeUINT16, ValueTypeUINT32, ValueTypeUINT64:
|
||||||
|
field.SetUint(uint64(element.value))
|
||||||
|
case ValueTypeSINT8, ValueTypeSINT16, ValueTypeSINT32, ValueTypeSINT64:
|
||||||
|
field.SetInt(int64(element.value))
|
||||||
|
case ValueTypeSTRING:
|
||||||
|
if element.value == 0 {
|
||||||
|
return fmt.Errorf("%s: invalid pointer: value is nil", miTag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the UTF-16 string to a Go string
|
||||||
|
stringValue := windows.UTF16PtrToString((*uint16)(unsafe.Pointer(element.value)))
|
||||||
|
|
||||||
|
field.SetString(stringValue)
|
||||||
|
case ValueTypeREAL32, ValueTypeREAL64:
|
||||||
|
field.SetFloat(float64(element.value))
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported value type: %d", element.valueType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dv.Set(reflect.Append(dv, elemValue))
|
||||||
|
|
||||||
|
if !moreResults {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OperationOptions) SetTimeout(timeout time.Duration) error {
|
||||||
|
if o == nil || o.ft == nil {
|
||||||
|
return ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
o.ft.SetInterval,
|
||||||
|
uintptr(unsafe.Pointer(o)),
|
||||||
|
uintptr(unsafe.Pointer(OperationOptionsTimeout)),
|
||||||
|
uintptr(unsafe.Pointer(NewInterval(timeout))),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OperationOptions) Delete() error {
|
||||||
|
if o == nil || o.ft == nil {
|
||||||
|
return ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(o.ft.Delete, uintptr(unsafe.Pointer(o)))
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package mi
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
type ResultError uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
MI_RESULT_OK ResultError = iota
|
||||||
|
MI_RESULT_FAILED
|
||||||
|
MI_RESULT_ACCESS_DENIED
|
||||||
|
MI_RESULT_INVALID_NAMESPACE
|
||||||
|
MI_RESULT_INVALID_PARAMETER
|
||||||
|
MI_RESULT_INVALID_CLASS
|
||||||
|
MI_RESULT_NOT_FOUND
|
||||||
|
MI_RESULT_NOT_SUPPORTED
|
||||||
|
MI_RESULT_CLASS_HAS_CHILDREN
|
||||||
|
MI_RESULT_CLASS_HAS_INSTANCES
|
||||||
|
MI_RESULT_INVALID_SUPERCLASS
|
||||||
|
MI_RESULT_ALREADY_EXISTS
|
||||||
|
MI_RESULT_NO_SUCH_PROPERTY
|
||||||
|
MI_RESULT_TYPE_MISMATCH
|
||||||
|
MI_RESULT_QUERY_LANGUAGE_NOT_SUPPORTED
|
||||||
|
MI_RESULT_INVALID_QUERY
|
||||||
|
MI_RESULT_METHOD_NOT_AVAILABLE
|
||||||
|
MI_RESULT_METHOD_NOT_FOUND
|
||||||
|
MI_RESULT_NAMESPACE_NOT_EMPTY
|
||||||
|
MI_RESULT_INVALID_ENUMERATION_CONTEXT
|
||||||
|
MI_RESULT_INVALID_OPERATION_TIMEOUT
|
||||||
|
MI_RESULT_PULL_HAS_BEEN_ABANDONED
|
||||||
|
MI_RESULT_PULL_CANNOT_BE_ABANDONED
|
||||||
|
MI_RESULT_FILTERED_ENUMERATION_NOT_SUPPORTED
|
||||||
|
MI_RESULT_CONTINUATION_ON_ERROR_NOT_SUPPORTED
|
||||||
|
MI_RESULT_SERVER_LIMITS_EXCEEDED
|
||||||
|
MI_RESULT_SERVER_IS_SHUTTING_DOWN
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r ResultError) Error() string {
|
||||||
|
return r.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r ResultError) String() string {
|
||||||
|
switch {
|
||||||
|
case errors.Is(r, MI_RESULT_OK):
|
||||||
|
return "MI_RESULT_OK"
|
||||||
|
case errors.Is(r, MI_RESULT_FAILED):
|
||||||
|
return "MI_RESULT_FAILED"
|
||||||
|
case errors.Is(r, MI_RESULT_ACCESS_DENIED):
|
||||||
|
return "MI_RESULT_ACCESS_DENIED"
|
||||||
|
case errors.Is(r, MI_RESULT_INVALID_NAMESPACE):
|
||||||
|
return "MI_RESULT_INVALID_NAMESPACE"
|
||||||
|
case errors.Is(r, MI_RESULT_INVALID_PARAMETER):
|
||||||
|
return "MI_RESULT_INVALID_PARAMETER"
|
||||||
|
case errors.Is(r, MI_RESULT_INVALID_CLASS):
|
||||||
|
return "MI_RESULT_INVALID_CLASS"
|
||||||
|
case errors.Is(r, MI_RESULT_NOT_FOUND):
|
||||||
|
return "MI_RESULT_NOT_FOUND"
|
||||||
|
case errors.Is(r, MI_RESULT_NOT_SUPPORTED):
|
||||||
|
return "MI_RESULT_NOT_SUPPORTED"
|
||||||
|
case errors.Is(r, MI_RESULT_CLASS_HAS_CHILDREN):
|
||||||
|
return "MI_RESULT_CLASS_HAS_CHILDREN"
|
||||||
|
case errors.Is(r, MI_RESULT_CLASS_HAS_INSTANCES):
|
||||||
|
return "MI_RESULT_CLASS_HAS_INSTANCES"
|
||||||
|
case errors.Is(r, MI_RESULT_INVALID_SUPERCLASS):
|
||||||
|
return "MI_RESULT_INVALID_SUPERCLASS"
|
||||||
|
case errors.Is(r, MI_RESULT_ALREADY_EXISTS):
|
||||||
|
return "MI_RESULT_ALREADY_EXISTS"
|
||||||
|
case errors.Is(r, MI_RESULT_NO_SUCH_PROPERTY):
|
||||||
|
return "MI_RESULT_NO_SUCH_PROPERTY"
|
||||||
|
case errors.Is(r, MI_RESULT_TYPE_MISMATCH):
|
||||||
|
return "MI_RESULT_TYPE_MISMATCH"
|
||||||
|
case errors.Is(r, MI_RESULT_QUERY_LANGUAGE_NOT_SUPPORTED):
|
||||||
|
return "MI_RESULT_QUERY_LANGUAGE_NOT_SUPPORTED"
|
||||||
|
case errors.Is(r, MI_RESULT_INVALID_QUERY):
|
||||||
|
return "MI_RESULT_INVALID_QUERY"
|
||||||
|
case errors.Is(r, MI_RESULT_METHOD_NOT_AVAILABLE):
|
||||||
|
return "MI_RESULT_METHOD_NOT_AVAILABLE"
|
||||||
|
case errors.Is(r, MI_RESULT_METHOD_NOT_FOUND):
|
||||||
|
return "MI_RESULT_METHOD_NOT_FOUND"
|
||||||
|
case errors.Is(r, MI_RESULT_NAMESPACE_NOT_EMPTY):
|
||||||
|
return "MI_RESULT_NAMESPACE_NOT_EMPTY"
|
||||||
|
case errors.Is(r, MI_RESULT_INVALID_ENUMERATION_CONTEXT):
|
||||||
|
return "MI_RESULT_INVALID_ENUMERATION_CONTEXT"
|
||||||
|
case errors.Is(r, MI_RESULT_INVALID_OPERATION_TIMEOUT):
|
||||||
|
return "MI_RESULT_INVALID_OPERATION_TIMEOUT"
|
||||||
|
case errors.Is(r, MI_RESULT_PULL_HAS_BEEN_ABANDONED):
|
||||||
|
return "MI_RESULT_PULL_HAS_BEEN_ABANDONED"
|
||||||
|
case errors.Is(r, MI_RESULT_PULL_CANNOT_BE_ABANDONED):
|
||||||
|
return "MI_RESULT_PULL_CANNOT_BE_ABANDONED"
|
||||||
|
case errors.Is(r, MI_RESULT_FILTERED_ENUMERATION_NOT_SUPPORTED):
|
||||||
|
return "MI_RESULT_FILTERED_ENUMERATION_NOT_SUPPORTED"
|
||||||
|
case errors.Is(r, MI_RESULT_CONTINUATION_ON_ERROR_NOT_SUPPORTED):
|
||||||
|
return "MI_RESULT_CONTINUATION_ON_ERROR_NOT_SUPPORTED"
|
||||||
|
case errors.Is(r, MI_RESULT_SERVER_LIMITS_EXCEEDED):
|
||||||
|
return "MI_RESULT_SERVER_LIMITS_EXCEEDED"
|
||||||
|
case errors.Is(r, MI_RESULT_SERVER_IS_SHUTTING_DOWN):
|
||||||
|
return "MI_RESULT_SERVER_IS_SHUTTING_DOWN"
|
||||||
|
default:
|
||||||
|
return "MI_RESULT_UNKNOWN"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,235 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package mi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Session represents a session.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/ns-mi-mi_session
|
||||||
|
type Session struct {
|
||||||
|
reserved1 uint64
|
||||||
|
reserved2 uintptr
|
||||||
|
ft *SessionFT
|
||||||
|
|
||||||
|
defaultOperationOptions *OperationOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionFT represents the function table for Session.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/ns-mi-mi_session
|
||||||
|
type SessionFT struct {
|
||||||
|
Close uintptr
|
||||||
|
GetApplication uintptr
|
||||||
|
GetInstance uintptr
|
||||||
|
ModifyInstance uintptr
|
||||||
|
CreateInstance uintptr
|
||||||
|
DeleteInstance uintptr
|
||||||
|
Invoke uintptr
|
||||||
|
EnumerateInstances uintptr
|
||||||
|
QueryInstances uintptr
|
||||||
|
AssociatorInstances uintptr
|
||||||
|
ReferenceInstances uintptr
|
||||||
|
Subscribe uintptr
|
||||||
|
GetClass uintptr
|
||||||
|
EnumerateClasses uintptr
|
||||||
|
TestConnection uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes a session and releases all associated memory.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_session_close
|
||||||
|
func (s *Session) Close() error {
|
||||||
|
if s == nil || s.ft == nil {
|
||||||
|
return ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.defaultOperationOptions != nil {
|
||||||
|
_ = s.defaultOperationOptions.Delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(s.ft.Close,
|
||||||
|
uintptr(unsafe.Pointer(s)),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestConnection queries instances. It is used to test the connection.
|
||||||
|
// The function returns an operation that can be used to retrieve the result with [Operation.GetInstance]. The operation must be closed with [Operation.Close].
|
||||||
|
// The instance returned by [Operation.GetInstance] is always nil.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_session_testconnection
|
||||||
|
func (s *Session) TestConnection() error {
|
||||||
|
if s == nil || s.ft == nil {
|
||||||
|
return ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
operation := &Operation{}
|
||||||
|
|
||||||
|
// ref: https://github.com/KurtDeGreeff/omi/blob/9caa55032a1070a665e14fd282a091f6247d13c3/Unix/scriptext/py/PMI_Session.c#L92-L105
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
s.ft.TestConnection,
|
||||||
|
uintptr(unsafe.Pointer(s)),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(operation)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if _, _, err = operation.GetInstance(); err != nil {
|
||||||
|
return fmt.Errorf("failed to get instance: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = operation.Close(); err != nil {
|
||||||
|
return fmt.Errorf("failed to close operation: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetApplication gets the Application handle that was used to create the specified session.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_session_getapplication
|
||||||
|
func (s *Session) GetApplication() (*Application, error) {
|
||||||
|
if s == nil || s.ft == nil {
|
||||||
|
return nil, ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
application := &Application{}
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
s.ft.GetApplication,
|
||||||
|
uintptr(unsafe.Pointer(s)),
|
||||||
|
uintptr(unsafe.Pointer(application)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return nil, result
|
||||||
|
}
|
||||||
|
|
||||||
|
return application, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryInstances queries for a set of instances based on a query expression.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_session_queryinstances
|
||||||
|
func (s *Session) QueryInstances(flags OperationFlags, operationOptions *OperationOptions, namespaceName Namespace,
|
||||||
|
queryDialect QueryDialect, queryExpression string,
|
||||||
|
) (*Operation, error) {
|
||||||
|
if s == nil || s.ft == nil {
|
||||||
|
return nil, ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
queryExpressionUTF16, err := windows.UTF16PtrFromString(queryExpression)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
operation := &Operation{}
|
||||||
|
|
||||||
|
if operationOptions == nil {
|
||||||
|
operationOptions = s.defaultOperationOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
s.ft.QueryInstances,
|
||||||
|
uintptr(unsafe.Pointer(s)),
|
||||||
|
uintptr(flags),
|
||||||
|
uintptr(unsafe.Pointer(operationOptions)),
|
||||||
|
uintptr(unsafe.Pointer(namespaceName)),
|
||||||
|
uintptr(unsafe.Pointer(queryDialect)),
|
||||||
|
uintptr(unsafe.Pointer(queryExpressionUTF16)),
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(operation)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return nil, result
|
||||||
|
}
|
||||||
|
|
||||||
|
return operation, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryUnmarshal queries for a set of instances based on a query expression.
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_session_queryinstances
|
||||||
|
func (s *Session) QueryUnmarshal(dst any,
|
||||||
|
flags OperationFlags, operationOptions *OperationOptions,
|
||||||
|
namespaceName Namespace, queryDialect QueryDialect, queryExpression Query,
|
||||||
|
) error {
|
||||||
|
if s == nil || s.ft == nil {
|
||||||
|
return ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
operation := &Operation{}
|
||||||
|
|
||||||
|
if operationOptions == nil {
|
||||||
|
operationOptions = s.defaultOperationOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
errCh := make(chan error, 1)
|
||||||
|
|
||||||
|
operationCallbacks, err := NewUnmarshalOperationsCallbacks(dst, errCh)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
r0, _, _ := syscall.SyscallN(
|
||||||
|
s.ft.QueryInstances,
|
||||||
|
uintptr(unsafe.Pointer(s)),
|
||||||
|
uintptr(flags),
|
||||||
|
uintptr(unsafe.Pointer(operationOptions)),
|
||||||
|
uintptr(unsafe.Pointer(namespaceName)),
|
||||||
|
uintptr(unsafe.Pointer(queryDialect)),
|
||||||
|
uintptr(unsafe.Pointer(queryExpression)),
|
||||||
|
uintptr(unsafe.Pointer(operationCallbacks)),
|
||||||
|
uintptr(unsafe.Pointer(operation)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
errs := make([]error, 0)
|
||||||
|
|
||||||
|
for err := range errCh {
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeepAlive is used to ensure that the callbacks are not garbage collected before the operation is closed.
|
||||||
|
runtime.KeepAlive(operationCallbacks.CallbackContext)
|
||||||
|
|
||||||
|
return errors.Join(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query queries for a set of instances based on a query expression.
|
||||||
|
func (s *Session) Query(dst any, namespaceName Namespace, queryExpression Query) error {
|
||||||
|
err := s.QueryUnmarshal(dst, OperationFlagsStandardRTTI, nil, namespaceName, QueryDialectWQL, queryExpression)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("WMI query failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package mi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Boolean uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
False Boolean = 0
|
||||||
|
True Boolean = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
type QueryDialect *uint16
|
||||||
|
|
||||||
|
func NewQueryDialect(queryDialect string) (QueryDialect, error) {
|
||||||
|
return windows.UTF16PtrFromString(queryDialect)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
QueryDialectWQL = utils.Must(NewQueryDialect("WQL"))
|
||||||
|
QueryDialectCQL = utils.Must(NewQueryDialect("CQL"))
|
||||||
|
)
|
||||||
|
|
||||||
|
type Namespace *uint16
|
||||||
|
|
||||||
|
func NewNamespace(namespace string) (Namespace, error) {
|
||||||
|
return windows.UTF16PtrFromString(namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
NamespaceRootCIMv2 = utils.Must(NewNamespace("root/CIMv2"))
|
||||||
|
NamespaceRootWindowsFSRM = utils.Must(NewNamespace("root/microsoft/windows/fsrm"))
|
||||||
|
NamespaceRootWebAdministration = utils.Must(NewNamespace("root/WebAdministration"))
|
||||||
|
NamespaceRootMSCluster = utils.Must(NewNamespace("root/MSCluster"))
|
||||||
|
)
|
||||||
|
|
||||||
|
type Query *uint16
|
||||||
|
|
||||||
|
func NewQuery(query string) (Query, error) {
|
||||||
|
return windows.UTF16PtrFromString(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UTF16PtrFromString converts a string to a UTF-16 pointer at initialization time.
|
||||||
|
//
|
||||||
|
//nolint:ireturn
|
||||||
|
func UTF16PtrFromString[T *uint16](s string) T {
|
||||||
|
val, err := windows.UTF16PtrFromString(s)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
type Timestamp struct {
|
||||||
|
Year uint32
|
||||||
|
Month uint32
|
||||||
|
Day uint32
|
||||||
|
Hour uint32
|
||||||
|
Minute uint32
|
||||||
|
Second uint32
|
||||||
|
Microseconds uint32
|
||||||
|
UTC int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Interval struct {
|
||||||
|
Days uint32
|
||||||
|
Hours uint32
|
||||||
|
Minutes uint32
|
||||||
|
Seconds uint32
|
||||||
|
Microseconds uint32
|
||||||
|
Padding1 uint32
|
||||||
|
Padding2 uint32
|
||||||
|
Padding3 uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewInterval(interval time.Duration) *Interval {
|
||||||
|
// Convert the duration to a number of microseconds
|
||||||
|
microseconds := interval.Microseconds()
|
||||||
|
|
||||||
|
// Create a new interval with the microseconds
|
||||||
|
return &Interval{
|
||||||
|
Days: uint32(microseconds / (24 * 60 * 60 * 1000000)),
|
||||||
|
Hours: uint32(microseconds / (60 * 60 * 1000000)),
|
||||||
|
Minutes: uint32(microseconds / (60 * 1000000)),
|
||||||
|
Seconds: uint32(microseconds / 1000000),
|
||||||
|
Microseconds: uint32(microseconds % 1000000),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Datetime struct {
|
||||||
|
IsTimestamp bool
|
||||||
|
Timestamp *Timestamp // Used when IsTimestamp is true
|
||||||
|
Interval *Interval // Used when IsTimestamp is false
|
||||||
|
}
|
||||||
|
|
||||||
|
type PropertyDecl struct {
|
||||||
|
Flags uint32
|
||||||
|
Code uint32
|
||||||
|
Name *uint16
|
||||||
|
Mqualifiers uintptr
|
||||||
|
NumQualifiers uint32
|
||||||
|
PropertyType ValueType
|
||||||
|
ClassName *uint16
|
||||||
|
Subscript uint32
|
||||||
|
Offset uint32
|
||||||
|
Origin *uint16
|
||||||
|
Propagator *uint16
|
||||||
|
Value uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClassDecl) Properties() []*PropertyDecl {
|
||||||
|
// Create a slice to hold the properties
|
||||||
|
properties := make([]*PropertyDecl, c.NumProperties)
|
||||||
|
|
||||||
|
// Mproperties is a pointer to an array of pointers to PropertyDecl
|
||||||
|
propertiesArray := (**PropertyDecl)(unsafe.Pointer(c.Mproperties))
|
||||||
|
|
||||||
|
// Iterate over the number of properties and fetch each property
|
||||||
|
for i := range c.NumProperties {
|
||||||
|
// Get the property pointer at index i
|
||||||
|
propertyPtr := *(**PropertyDecl)(unsafe.Pointer(uintptr(unsafe.Pointer(propertiesArray)) + uintptr(i)*unsafe.Sizeof(uintptr(0))))
|
||||||
|
|
||||||
|
// Append the property to the slice
|
||||||
|
properties[i] = propertyPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the slice of properties
|
||||||
|
return properties
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package mi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ValueType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
ValueTypeBOOLEAN ValueType = iota
|
||||||
|
ValueTypeUINT8
|
||||||
|
ValueTypeSINT8
|
||||||
|
ValueTypeUINT16
|
||||||
|
ValueTypeSINT16
|
||||||
|
ValueTypeUINT32
|
||||||
|
ValueTypeSINT32
|
||||||
|
ValueTypeUINT64
|
||||||
|
ValueTypeSINT64
|
||||||
|
ValueTypeREAL32
|
||||||
|
ValueTypeREAL64
|
||||||
|
ValueTypeCHAR16
|
||||||
|
ValueTypeDATETIME
|
||||||
|
ValueTypeSTRING
|
||||||
|
ValueTypeREFERENCE
|
||||||
|
ValueTypeINSTANCE
|
||||||
|
ValueTypeBOOLEANA
|
||||||
|
ValueTypeUINT8A
|
||||||
|
ValueTypeSINT8A
|
||||||
|
ValueTypeUINT16A
|
||||||
|
ValueTypeSINT16A
|
||||||
|
ValueTypeUINT32A
|
||||||
|
ValueTypeSINT32A
|
||||||
|
ValueTypeUINT64A
|
||||||
|
ValueTypeSINT64A
|
||||||
|
ValueTypeREAL32A
|
||||||
|
ValueTypeREAL64A
|
||||||
|
ValueTypeCHAR16A
|
||||||
|
ValueTypeDATETIMEA
|
||||||
|
ValueTypeSTRINGA
|
||||||
|
ValueTypeREFERENCEA
|
||||||
|
ValueTypeINSTANCEA
|
||||||
|
ValueTypeARRAY ValueType = 16
|
||||||
|
)
|
||||||
|
|
||||||
|
type Element struct {
|
||||||
|
value uintptr
|
||||||
|
valueType ValueType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Element) GetValue() (any, error) {
|
||||||
|
switch e.valueType {
|
||||||
|
case ValueTypeBOOLEAN:
|
||||||
|
return e.value == 1, nil
|
||||||
|
case ValueTypeUINT8:
|
||||||
|
return uint8(e.value), nil
|
||||||
|
case ValueTypeSINT8:
|
||||||
|
return int8(e.value), nil
|
||||||
|
case ValueTypeUINT16:
|
||||||
|
return uint16(e.value), nil
|
||||||
|
case ValueTypeSINT16:
|
||||||
|
return int16(e.value), nil
|
||||||
|
case ValueTypeUINT32:
|
||||||
|
return uint32(e.value), nil
|
||||||
|
case ValueTypeSINT32:
|
||||||
|
return int32(e.value), nil
|
||||||
|
case ValueTypeUINT64:
|
||||||
|
return uint64(e.value), nil
|
||||||
|
case ValueTypeSINT64:
|
||||||
|
return int64(e.value), nil
|
||||||
|
case ValueTypeREAL32:
|
||||||
|
return float32(e.value), nil
|
||||||
|
case ValueTypeREAL64:
|
||||||
|
return float64(e.value), nil
|
||||||
|
case ValueTypeCHAR16:
|
||||||
|
return uint16(e.value), nil
|
||||||
|
case ValueTypeDATETIME:
|
||||||
|
if e.value == 0 {
|
||||||
|
return nil, errors.New("invalid pointer: value is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
return *(*Datetime)(unsafe.Pointer(e.value)), nil
|
||||||
|
case ValueTypeSTRING:
|
||||||
|
if e.value == 0 {
|
||||||
|
return nil, errors.New("invalid pointer: value is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the UTF-16 string to a Go string
|
||||||
|
return windows.UTF16PtrToString((*uint16)(unsafe.Pointer(e.value))), nil
|
||||||
|
case ValueTypeSTRINGA:
|
||||||
|
if e.value == 0 {
|
||||||
|
return nil, errors.New("invalid pointer: value is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assuming array of pointers to UTF-16 strings
|
||||||
|
ptrArray := *(*[]*uint16)(unsafe.Pointer(e.value))
|
||||||
|
strArray := make([]string, len(ptrArray))
|
||||||
|
|
||||||
|
for i, ptr := range ptrArray {
|
||||||
|
strArray[i] = windows.UTF16PtrToString(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strArray, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported value type: %d", e.valueType)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package testutils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||||
|
|
||||||
|
procGetProcessHandleCount = modkernel32.NewProc("GetProcessHandleCount")
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetProcessHandleCount(handle windows.Handle) (uint32, error) {
|
||||||
|
var count uint32
|
||||||
|
|
||||||
|
r1, _, err := procGetProcessHandleCount.Call(
|
||||||
|
uintptr(handle),
|
||||||
|
uintptr(unsafe.Pointer(&count)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if r1 != 1 {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
|
@ -10,10 +10,10 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/pkg/collector"
|
"github.com/prometheus-community/windows_exporter/pkg/collector"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func FuncBenchmarkCollector[C collector.Collector](b *testing.B, name string, collectFunc collector.BuilderWithFlags[C]) {
|
func FuncBenchmarkCollector[C collector.Collector](b *testing.B, name string, collectFunc collector.BuilderWithFlags[C]) {
|
||||||
|
@ -57,14 +57,16 @@ func TestCollector[C collector.Collector, V interface{}](t *testing.T, fn func(*
|
||||||
c := fn(conf)
|
c := fn(conf)
|
||||||
ch := make(chan prometheus.Metric, 10000)
|
ch := make(chan prometheus.Metric, 10000)
|
||||||
|
|
||||||
wmiClient := &wmi.Client{
|
miApp, err := mi.Application_Initialize()
|
||||||
AllowMissingFields: true,
|
require.NoError(t, err)
|
||||||
}
|
|
||||||
wmiClient.SWbemServicesClient, err = wmi.InitializeSWbemServices(wmiClient)
|
miSession, err := miApp.NewSession(nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Cleanup(func() {
|
t.Cleanup(func() {
|
||||||
require.NoError(t, c.Close(logger))
|
require.NoError(t, c.Close(logger))
|
||||||
|
require.NoError(t, miSession.Close())
|
||||||
|
require.NoError(t, miApp.Close())
|
||||||
})
|
})
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
|
@ -78,7 +80,7 @@ func TestCollector[C collector.Collector, V interface{}](t *testing.T, fn func(*
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
require.NoError(t, c.Build(logger, wmiClient))
|
require.NoError(t, c.Build(logger, miSession))
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
|
|
||||||
|
|
|
@ -35,3 +35,11 @@ func PDHEnabled() bool {
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MIEnabled() bool {
|
||||||
|
if v, ok := os.LookupEnv("WINDOWS_EXPORTER_WMI_ENGINE"); ok && v == "mi" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -17,3 +17,14 @@ func BoolToFloat(b bool) float64 {
|
||||||
func ToPTR[t any](v t) *t {
|
func ToPTR[t any](v t) *t {
|
||||||
return &v
|
return &v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Must panics if the error is not nil.
|
||||||
|
//
|
||||||
|
//nolint:ireturn
|
||||||
|
func Must[T any](v T, err error) T {
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
|
@ -57,9 +57,9 @@ import (
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/time"
|
"github.com/prometheus-community/windows_exporter/internal/collector/time"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/update"
|
"github.com/prometheus-community/windows_exporter/internal/collector/update"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/collector/vmware"
|
"github.com/prometheus-community/windows_exporter/internal/collector/vmware"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewWithFlags To be called by the exporter for collector initialization before running kingpin.Parse.
|
// NewWithFlags To be called by the exporter for collector initialization before running kingpin.Parse.
|
||||||
|
@ -132,9 +132,6 @@ func NewWithConfig(config Config) *MetricCollectors {
|
||||||
func New(collectors Map) *MetricCollectors {
|
func New(collectors Map) *MetricCollectors {
|
||||||
return &MetricCollectors{
|
return &MetricCollectors{
|
||||||
Collectors: collectors,
|
Collectors: collectors,
|
||||||
WMIClient: &wmi.Client{
|
|
||||||
AllowMissingFields: true,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,11 +183,9 @@ func (c *MetricCollectors) Enable(enabledCollectors []string) error {
|
||||||
|
|
||||||
// Build To be called by the exporter for collector initialization.
|
// Build To be called by the exporter for collector initialization.
|
||||||
func (c *MetricCollectors) Build(logger *slog.Logger) error {
|
func (c *MetricCollectors) Build(logger *slog.Logger) error {
|
||||||
var err error
|
err := c.initMI()
|
||||||
|
|
||||||
c.WMIClient.SWbemServicesClient, err = wmi.InitializeSWbemServices(c.WMIClient)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("initialize SWbemServices: %w", err)
|
return fmt.Errorf("error from initialize MI: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
|
@ -203,7 +198,7 @@ func (c *MetricCollectors) Build(logger *slog.Logger) error {
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
if err = collector.Build(logger, c.WMIClient); err != nil {
|
if err = collector.Build(logger, c.MISession); err != nil {
|
||||||
errCh <- fmt.Errorf("error build collector %s: %w", collector.GetName(), err)
|
errCh <- fmt.Errorf("error build collector %s: %w", collector.GetName(), err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -245,11 +240,42 @@ func (c *MetricCollectors) Close(logger *slog.Logger) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.WMIClient != nil && c.WMIClient.SWbemServicesClient != nil {
|
app, err := c.MISession.GetApplication()
|
||||||
if err := c.WMIClient.SWbemServicesClient.Close(); err != nil {
|
if err != nil && !errors.Is(err, mi.ErrNotInitialized) {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := c.MISession.Close(); err != nil && !errors.Is(err, mi.ErrNotInitialized) {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := app.Close(); err != nil && !errors.Is(err, mi.ErrNotInitialized) {
|
||||||
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.Join(errs...)
|
return errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close To be called by the exporter for collector cleanup.
|
||||||
|
func (c *MetricCollectors) initMI() error {
|
||||||
|
app, err := mi.Application_Initialize()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error from initialize MI application: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
destinationOptions, err := app.NewDestinationOptions()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error from create NewDestinationOptions: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = destinationOptions.SetLocale(mi.LocaleEnglish); err != nil {
|
||||||
|
return fmt.Errorf("error from set locale: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.MISession, err = app.NewSession(destinationOptions)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error from create NewSession: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -4,14 +4,14 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/yusufpapurcu/wmi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type MetricCollectors struct {
|
type MetricCollectors struct {
|
||||||
Collectors Map
|
Collectors Map
|
||||||
WMIClient *wmi.Client
|
MISession *mi.Session
|
||||||
PerfCounterQuery string
|
PerfCounterQuery string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ type (
|
||||||
|
|
||||||
// Collector interface that a collector has to implement.
|
// Collector interface that a collector has to implement.
|
||||||
type Collector interface {
|
type Collector interface {
|
||||||
Build(logger *slog.Logger, wmiClient *wmi.Client) error
|
Build(logger *slog.Logger, miSession *mi.Session) error
|
||||||
// Close closes the collector
|
// Close closes the collector
|
||||||
Close(logger *slog.Logger) error
|
Close(logger *slog.Logger) error
|
||||||
// GetName get the name of the collector
|
// GetName get the name of the collector
|
||||||
|
|
Loading…
Reference in New Issue