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:
|
||||
forbid:
|
||||
- "^(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
|
||||
- p: "^windows\\.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/exporter-toolkit v0.13.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/yusufpapurcu/wmi v1.2.4
|
||||
golang.org/x/sys v0.26.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
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/cespare/xxhash/v2 v2.3.0 // 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/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // 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/vsock v1.2.1 // 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/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
golang.org/x/crypto v0.27.0 // indirect
|
||||
golang.org/x/net v0.29.0 // indirect
|
||||
golang.org/x/crypto v0.28.0 // indirect
|
||||
golang.org/x/net v0.30.0 // indirect
|
||||
golang.org/x/oauth2 v0.23.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 // indirect
|
||||
google.golang.org/grpc v1.67.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
golang.org/x/text v0.19.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect
|
||||
google.golang.org/grpc v1.67.1 // indirect
|
||||
google.golang.org/protobuf v1.35.1 // 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/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY=
|
||||
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-20240626203959-61d1e3462e30/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs=
|
||||
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0=
|
||||
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/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
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.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
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/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
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/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
||||
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.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
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/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
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/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/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/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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
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/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=
|
||||
|
@ -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-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.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
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.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||
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-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-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-20220715151400-c0bba94af5f8/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/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.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
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-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
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-20240924160255-9d4c2d233b61/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE=
|
||||
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.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
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.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
|
||||
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
|
||||
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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
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.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.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
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 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
|
|
|
@ -8,10 +8,10 @@ import (
|
|||
"log/slog"
|
||||
|
||||
"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/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "ad"
|
||||
|
@ -118,7 +118,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
counters := []string{
|
||||
abANRPerSec,
|
||||
abBrowsesPerSec,
|
||||
|
|
|
@ -8,12 +8,12 @@ import (
|
|||
"log/slog"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "adcs"
|
||||
|
@ -74,7 +74,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
if utils.PDHEnabled() {
|
||||
counters := []string{
|
||||
requestsPerSecond,
|
||||
|
|
|
@ -11,12 +11,12 @@ import (
|
|||
"slices"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "adfs"
|
||||
|
@ -107,7 +107,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
if utils.PDHEnabled() {
|
||||
counters := []string{
|
||||
adLoginConnectionFailures,
|
||||
|
|
|
@ -8,13 +8,13 @@ import (
|
|||
"log/slog"
|
||||
|
||||
"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/perftypes"
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "cache"
|
||||
|
@ -92,7 +92,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
if utils.PDHEnabled() {
|
||||
counters := []string{
|
||||
asyncCopyReadsTotal,
|
||||
|
|
|
@ -10,10 +10,10 @@ import (
|
|||
|
||||
"github.com/Microsoft/hcsshim"
|
||||
"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/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "container"
|
||||
|
@ -86,7 +86,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
c.containerAvailable = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "available"),
|
||||
"Available",
|
||||
|
|
|
@ -8,12 +8,12 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "cpu"
|
||||
|
@ -83,7 +83,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
if utils.PDHEnabled() {
|
||||
counters := []string{
|
||||
c1TimeSeconds,
|
||||
|
|
|
@ -4,14 +4,15 @@ package cpu_info
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
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.
|
||||
type Collector struct {
|
||||
config Config
|
||||
|
||||
wmiClient *wmi.Client
|
||||
config Config
|
||||
miSession *mi.Session
|
||||
miQuery mi.Query
|
||||
|
||||
cpuInfo *prometheus.Desc
|
||||
cpuCoreCount *prometheus.Desc
|
||||
|
@ -63,12 +64,19 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
||||
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||
if miSession == 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(
|
||||
prometheus.BuildFQName(types.Namespace, "", Name),
|
||||
"Labelled CPU information as provided by Win32_Processor",
|
||||
|
@ -133,18 +141,20 @@ func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
type win32Processor struct {
|
||||
Architecture uint32
|
||||
DeviceID string
|
||||
Description string
|
||||
Family uint16
|
||||
L2CacheSize uint32
|
||||
L3CacheSize uint32
|
||||
Name string
|
||||
ThreadCount uint32
|
||||
NumberOfCores uint32
|
||||
NumberOfEnabledCore uint32
|
||||
NumberOfLogicalProcessors uint32
|
||||
type miProcessor struct {
|
||||
Architecture uint32 `mi:"Architecture"`
|
||||
DeviceID string `mi:"DeviceID"`
|
||||
Description string `mi:"Description"`
|
||||
Family uint16 `mi:"Family"`
|
||||
L2CacheSize uint32 `mi:"L2CacheSize"`
|
||||
L3CacheSize uint32 `mi:"L3CacheSize"`
|
||||
Name string `mi:"Name"`
|
||||
ThreadCount uint32 `mi:"ThreadCount"`
|
||||
NumberOfCores uint32 `mi:"NumberOfCores"`
|
||||
NumberOfEnabledCore uint32 `mi:"NumberOfEnabledCore"`
|
||||
NumberOfLogicalProcessors uint32 `mi:"NumberOfLogicalProcessors"`
|
||||
|
||||
Total int
|
||||
}
|
||||
|
||||
// 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 {
|
||||
var dst []win32Processor
|
||||
// We use a static query here because the provided methods in wmi.go all issue a SELECT *;
|
||||
// This results in the time-consuming LoadPercentage field being read which seems to measure each CPU
|
||||
// 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")
|
||||
var dst []miProcessor
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
// 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/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/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "cs"
|
||||
|
@ -61,7 +61,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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. " +
|
||||
"Logical processors has been moved to cpu_info collector. " +
|
||||
"Physical memory has been moved to memory collector. " +
|
||||
|
|
|
@ -10,12 +10,12 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "dfsr"
|
||||
|
@ -167,7 +167,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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("dfsr collector is in an experimental state! Metrics for this collector have not been tested.")
|
||||
|
|
|
@ -8,13 +8,13 @@ import (
|
|||
"log/slog"
|
||||
|
||||
"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/perftypes"
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "dhcp"
|
||||
|
@ -88,7 +88,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
if utils.PDHEnabled() {
|
||||
counters := []string{
|
||||
acksTotal,
|
||||
|
|
|
@ -4,19 +4,17 @@ package diskdrive
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const (
|
||||
Name = "diskdrive"
|
||||
win32DiskQuery = "SELECT DeviceID, Model, Caption, Name, Partitions, Size, Status, Availability FROM WIN32_DiskDrive"
|
||||
)
|
||||
const Name = "diskdrive"
|
||||
|
||||
type Config struct{}
|
||||
|
||||
|
@ -25,7 +23,8 @@ var ConfigDefaults = Config{}
|
|||
// A Collector is a Prometheus Collector for a few WMI metrics in Win32_DiskDrive.
|
||||
type Collector struct {
|
||||
config Config
|
||||
wmiClient *wmi.Client
|
||||
miSession *mi.Session
|
||||
miQuery mi.Query
|
||||
|
||||
availability *prometheus.Desc
|
||||
diskInfo *prometheus.Desc
|
||||
|
@ -62,12 +61,19 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
||||
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||
if miSession == 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(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "info"),
|
||||
"General drive information",
|
||||
|
@ -108,14 +114,14 @@ func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
|||
}
|
||||
|
||||
type win32_DiskDrive struct {
|
||||
DeviceID string
|
||||
Model string
|
||||
Size uint64
|
||||
Name string
|
||||
Caption string
|
||||
Partitions uint32
|
||||
Status string
|
||||
Availability uint16
|
||||
DeviceID string `mi:"DeviceID"`
|
||||
Model string `mi:"Model"`
|
||||
Size uint64 `mi:"Size"`
|
||||
Name string `mi:"Name"`
|
||||
Caption string `mi:"Caption"`
|
||||
Partitions uint32 `mi:"Partitions"`
|
||||
Status string `mi:"Status"`
|
||||
Availability uint16 `mi:"Availability"`
|
||||
}
|
||||
|
||||
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 {
|
||||
var dst []win32_DiskDrive
|
||||
|
||||
if err := c.wmiClient.Query(win32DiskQuery, &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
if len(dst) == 0 {
|
||||
|
|
|
@ -8,11 +8,11 @@ import (
|
|||
"log/slog"
|
||||
|
||||
"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/perftypes"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "dns"
|
||||
|
@ -79,7 +79,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
counters := []string{
|
||||
axfrRequestReceived,
|
||||
axfrRequestSent,
|
||||
|
|
|
@ -10,11 +10,11 @@ import (
|
|||
"strings"
|
||||
|
||||
"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/types"
|
||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "exchange"
|
||||
|
@ -207,7 +207,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
if utils.PDHEnabled() {
|
||||
collectorFuncs := map[string]func() error{
|
||||
adAccessProcesses: c.buildADAccessProcesses,
|
||||
|
|
|
@ -12,9 +12,9 @@ import (
|
|||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/bmatcuk/doublestar/v4"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "filetime"
|
||||
|
@ -85,7 +85,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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.",
|
||||
slog.String("collector", Name),
|
||||
)
|
||||
|
|
|
@ -4,13 +4,14 @@ package fsrmquota
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "fsrmquota"
|
||||
|
@ -21,7 +22,8 @@ var ConfigDefaults = Config{}
|
|||
|
||||
type Collector struct {
|
||||
config Config
|
||||
wmiClient *wmi.Client
|
||||
miSession *mi.Session
|
||||
miQuery mi.Query
|
||||
|
||||
quotasCount *prometheus.Desc
|
||||
peakUsage *prometheus.Desc
|
||||
|
@ -63,12 +65,18 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
||||
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||
if miSession == 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(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "count"),
|
||||
|
@ -146,29 +154,28 @@ func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan
|
|||
// MSFT_FSRMQuota docs:
|
||||
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/fsrm/msft-fsrmquota
|
||||
type MSFT_FSRMQuota struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
Path string
|
||||
PeakUsage uint64
|
||||
Size uint64
|
||||
Usage uint64
|
||||
Description string
|
||||
Template string
|
||||
// Threshold string
|
||||
Disabled bool
|
||||
MatchesTemplate bool
|
||||
SoftLimit bool
|
||||
Path string `mi:"Path"`
|
||||
PeakUsage uint64 `mi:"PeakUsage"`
|
||||
Size uint64 `mi:"Size"`
|
||||
Usage uint64 `mi:"Usage"`
|
||||
Description string `mi:"Description"`
|
||||
Template string `mi:"Template"`
|
||||
// Threshold string `mi:"Threshold"`
|
||||
Disabled bool `mi:"Disabled"`
|
||||
MatchesTemplate bool `mi:"MatchesTemplate"`
|
||||
SoftLimit bool `mi:"SoftLimit"`
|
||||
}
|
||||
|
||||
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
|
||||
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
|
||||
|
||||
if err := c.wmiClient.Query("SELECT * FROM MSFT_FSRMQuota", &dst, nil, "root/microsoft/windows/fsrm"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, quota := range dst {
|
||||
count++
|
||||
path := quota.Path
|
||||
|
|
|
@ -9,9 +9,10 @@ import (
|
|||
"strings"
|
||||
|
||||
"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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "hyperv"
|
||||
|
@ -23,7 +24,7 @@ var ConfigDefaults = Config{}
|
|||
// Collector is a Prometheus Collector for hyper-v.
|
||||
type Collector struct {
|
||||
config Config
|
||||
wmiClient *wmi.Client
|
||||
miSession *mi.Session
|
||||
|
||||
// Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary
|
||||
healthCritical *prometheus.Desc
|
||||
|
@ -168,12 +169,12 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
||||
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||
if miSession == nil {
|
||||
return errors.New("miSession is nil")
|
||||
}
|
||||
|
||||
c.wmiClient = wmiClient
|
||||
c.miSession = miSession
|
||||
|
||||
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.
|
||||
type Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary struct {
|
||||
HealthCritical uint32
|
||||
HealthOk uint32
|
||||
HealthCritical uint32 `mi:"HealthCritical"`
|
||||
HealthOk uint32 `mi:"HealthOK"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectVmHealth(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, health := range dst {
|
||||
|
@ -887,16 +888,16 @@ func (c *Collector) collectVmHealth(ch chan<- prometheus.Metric) error {
|
|||
|
||||
// Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition ..,.
|
||||
type Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition struct {
|
||||
Name string
|
||||
PhysicalPagesAllocated uint64
|
||||
PreferredNUMANodeIndex uint64
|
||||
RemotePhysicalPages uint64
|
||||
Name string `mi:"Name"`
|
||||
PhysicalPagesAllocated uint64 `mi:"PhysicalPagesAllocated"`
|
||||
PreferredNUMANodeIndex uint64 `mi:"PreferredNUMANodeIndex"`
|
||||
RemotePhysicalPages uint64 `mi:"RemotePhysicalPages"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectVmVid(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, page := range dst {
|
||||
|
@ -931,34 +932,34 @@ func (c *Collector) collectVmVid(ch chan<- prometheus.Metric) error {
|
|||
|
||||
// Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition ...
|
||||
type Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition struct {
|
||||
Name string
|
||||
AddressSpaces uint64
|
||||
AttachedDevices uint64
|
||||
DepositedPages uint64
|
||||
DeviceDMAErrors uint64
|
||||
DeviceInterruptErrors uint64
|
||||
DeviceInterruptMappings uint64
|
||||
DeviceInterruptThrottleEvents uint64
|
||||
GPAPages uint64
|
||||
GPASpaceModificationsPersec uint64
|
||||
IOTLBFlushCost uint64
|
||||
IOTLBFlushesPersec uint64
|
||||
RecommendedVirtualTLBSize uint64
|
||||
SkippedTimerTicks uint64
|
||||
Value1Gdevicepages uint64
|
||||
Value1GGPApages uint64
|
||||
Value2Mdevicepages uint64
|
||||
Value2MGPApages uint64
|
||||
Value4Kdevicepages uint64
|
||||
Value4KGPApages uint64
|
||||
VirtualTLBFlushEntiresPersec uint64
|
||||
VirtualTLBPages uint64
|
||||
Name string `mi:"Name"`
|
||||
AddressSpaces uint64 `mi:"AddressSpaces"`
|
||||
AttachedDevices uint64 `mi:"AttachedDevices"`
|
||||
DepositedPages uint64 `mi:"DepositedPages"`
|
||||
DeviceDMAErrors uint64 `mi:"DeviceDMAErrors"`
|
||||
DeviceInterruptErrors uint64 `mi:"DeviceInterruptErrors"`
|
||||
DeviceInterruptMappings uint64 `mi:"DeviceInterruptMappings"`
|
||||
DeviceInterruptThrottleEvents uint64 `mi:"DeviceInterruptThrottleEvents"`
|
||||
GPAPages uint64 `mi:"GPAPages"`
|
||||
GPASpaceModificationsPersec uint64 `mi:"GPASpaceModificationsPersec"`
|
||||
IOTLBFlushCost uint64 `mi:"IOTLBFlushCost"`
|
||||
IOTLBFlushesPersec uint64 `mi:"IOTLBFlushesPersec"`
|
||||
RecommendedVirtualTLBSize uint64 `mi:"RecommendedVirtualTLBSize"`
|
||||
SkippedTimerTicks uint64 `mi:"SkippedTimerTicks"`
|
||||
Value1Gdevicepages uint64 `mi:"Value1Gdevicepages"`
|
||||
Value1GGPApages uint64 `mi:"Value1GGPApages"`
|
||||
Value2Mdevicepages uint64 `mi:"Value2Mdevicepages"`
|
||||
Value2MGPApages uint64 `mi:"Value2MGPApages"`
|
||||
Value4Kdevicepages uint64 `mi:"Value4Kdevicepages"`
|
||||
Value4KGPApages uint64 `mi:"Value4KGPApages"`
|
||||
VirtualTLBFlushEntiresPersec uint64 `mi:"VirtualTLBFlushEntiresPersec"`
|
||||
VirtualTLBPages uint64 `mi:"VirtualTLBPages"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectVmHv(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, obj := range dst {
|
||||
|
@ -1087,14 +1088,14 @@ func (c *Collector) collectVmHv(ch chan<- prometheus.Metric) error {
|
|||
|
||||
// Win32_PerfRawData_HvStats_HyperVHypervisor ...
|
||||
type Win32_PerfRawData_HvStats_HyperVHypervisor struct {
|
||||
LogicalProcessors uint64
|
||||
VirtualProcessors uint64
|
||||
LogicalProcessors uint64 `mi:"LogicalProcessors"`
|
||||
VirtualProcessors uint64 `mi:"VirtualProcessors"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectVmProcessor(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisor
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisor", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisor"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, obj := range dst {
|
||||
|
@ -1116,16 +1117,16 @@ func (c *Collector) collectVmProcessor(ch chan<- prometheus.Metric) error {
|
|||
|
||||
// Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor ...
|
||||
type Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor struct {
|
||||
Name string
|
||||
PercentGuestRunTime uint64
|
||||
PercentHypervisorRunTime uint64
|
||||
PercentTotalRunTime uint
|
||||
Name string `mi:"Name"`
|
||||
PercentGuestRunTime uint64 `mi:"PercentGuestRunTime"`
|
||||
PercentHypervisorRunTime uint64 `mi:"PercentHypervisorRunTime"`
|
||||
PercentTotalRunTime uint64 `mi:"PercentTotalRunTime"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectHostLPUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, obj := range dst {
|
||||
|
@ -1170,18 +1171,18 @@ func (c *Collector) collectHostLPUsage(logger *slog.Logger, ch chan<- prometheus
|
|||
|
||||
// Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor ...
|
||||
type Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor struct {
|
||||
Name string
|
||||
PercentGuestRunTime uint64
|
||||
PercentHypervisorRunTime uint64
|
||||
PercentRemoteRunTime uint64
|
||||
PercentTotalRunTime uint64
|
||||
CPUWaitTimePerDispatch uint64
|
||||
Name string `mi:"Name"`
|
||||
PercentGuestRunTime uint64 `mi:"PercentGuestRunTime"`
|
||||
PercentHypervisorRunTime uint64 `mi:"PercentHypervisorRunTime"`
|
||||
PercentRemoteRunTime uint64 `mi:"PercentRemoteRunTime"`
|
||||
PercentTotalRunTime uint64 `mi:"PercentTotalRunTime"`
|
||||
CPUWaitTimePerDispatch uint64 `mi:"CPUWaitTimePerDispatch"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectHostCpuUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, obj := range dst {
|
||||
|
@ -1240,18 +1241,18 @@ func (c *Collector) collectHostCpuUsage(logger *slog.Logger, ch chan<- prometheu
|
|||
|
||||
// Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor ...
|
||||
type Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor struct {
|
||||
Name string
|
||||
PercentGuestRunTime uint64
|
||||
PercentHypervisorRunTime uint64
|
||||
PercentRemoteRunTime uint64
|
||||
PercentTotalRunTime uint64
|
||||
CPUWaitTimePerDispatch uint64
|
||||
Name string `mi:"Name"`
|
||||
PercentGuestRunTime uint64 `mi:"PercentGuestRunTime"`
|
||||
PercentHypervisorRunTime uint64 `mi:"PercentHypervisorRunTime"`
|
||||
PercentRemoteRunTime uint64 `mi:"PercentRemoteRunTime"`
|
||||
PercentTotalRunTime uint64 `mi:"PercentTotalRunTime"`
|
||||
CPUWaitTimePerDispatch uint64 `mi:"CPUWaitTimePerDispatch"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectVmCpuUsage(logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, obj := range dst {
|
||||
|
@ -1318,37 +1319,37 @@ func (c *Collector) collectVmCpuUsage(logger *slog.Logger, ch chan<- prometheus.
|
|||
|
||||
// Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch ...
|
||||
type Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch struct {
|
||||
Name string
|
||||
BroadcastPacketsReceivedPersec uint64
|
||||
BroadcastPacketsSentPersec uint64
|
||||
BytesPersec uint64
|
||||
BytesReceivedPersec uint64
|
||||
BytesSentPersec uint64
|
||||
DirectedPacketsReceivedPersec uint64
|
||||
DirectedPacketsSentPersec uint64
|
||||
DroppedPacketsIncomingPersec uint64
|
||||
DroppedPacketsOutgoingPersec uint64
|
||||
ExtensionsDroppedPacketsIncomingPersec uint64
|
||||
ExtensionsDroppedPacketsOutgoingPersec uint64
|
||||
LearnedMacAddresses uint64
|
||||
LearnedMacAddressesPersec uint64
|
||||
MulticastPacketsReceivedPersec uint64
|
||||
MulticastPacketsSentPersec uint64
|
||||
NumberofSendChannelMovesPersec uint64
|
||||
NumberofVMQMovesPersec uint64
|
||||
PacketsFlooded uint64
|
||||
PacketsFloodedPersec uint64
|
||||
PacketsPersec uint64
|
||||
PacketsReceivedPersec uint64
|
||||
PacketsSentPersec uint64
|
||||
PurgedMacAddresses uint64
|
||||
PurgedMacAddressesPersec uint64
|
||||
Name string `mi:"Name"`
|
||||
BroadcastPacketsReceivedPersec uint64 `mi:"BroadcastPacketsReceivedPersec"`
|
||||
BroadcastPacketsSentPersec uint64 `mi:"BroadcastPacketsSentPersec"`
|
||||
BytesPersec uint64 `mi:"BytesPersec"`
|
||||
BytesReceivedPersec uint64 `mi:"BytesReceivedPersec"`
|
||||
BytesSentPersec uint64 `mi:"BytesSentPersec"`
|
||||
DirectedPacketsReceivedPersec uint64 `mi:"DirectedPacketsReceivedPersec"`
|
||||
DirectedPacketsSentPersec uint64 `mi:"DirectedPacketsSentPersec"`
|
||||
DroppedPacketsIncomingPersec uint64 `mi:"DroppedPacketsIncomingPersec"`
|
||||
DroppedPacketsOutgoingPersec uint64 `mi:"DroppedPacketsOutgoingPersec"`
|
||||
ExtensionsDroppedPacketsIncomingPersec uint64 `mi:"ExtensionsDroppedPacketsIncomingPersec"`
|
||||
ExtensionsDroppedPacketsOutgoingPersec uint64 `mi:"ExtensionsDroppedPacketsOutgoingPersec"`
|
||||
LearnedMacAddresses uint64 `mi:"LearnedMacAddresses"`
|
||||
LearnedMacAddressesPersec uint64 `mi:"LearnedMacAddressesPersec"`
|
||||
MulticastPacketsReceivedPersec uint64 `mi:"MulticastPacketsReceivedPersec"`
|
||||
MulticastPacketsSentPersec uint64 `mi:"MulticastPacketsSentPersec"`
|
||||
NumberofSendChannelMovesPersec uint64 `mi:"NumberofSendChannelMovesPersec"`
|
||||
NumberofVMQMovesPersec uint64 `mi:"NumberofVMQMovesPersec"`
|
||||
PacketsFlooded uint64 `mi:"PacketsFlooded"`
|
||||
PacketsFloodedPersec uint64 `mi:"PacketsFloodedPersec"`
|
||||
PacketsPersec uint64 `mi:"PacketsPersec"`
|
||||
PacketsReceivedPersec uint64 `mi:"PacketsReceivedPersec"`
|
||||
PacketsSentPersec uint64 `mi:"PacketsSentPersec"`
|
||||
PurgedMacAddresses uint64 `mi:"PurgedMacAddresses"`
|
||||
PurgedMacAddressesPersec uint64 `mi:"PurgedMacAddressesPersec"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectVmSwitch(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, obj := range dst {
|
||||
|
@ -1500,19 +1501,19 @@ func (c *Collector) collectVmSwitch(ch chan<- prometheus.Metric) error {
|
|||
|
||||
// Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter ...
|
||||
type Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter struct {
|
||||
Name string
|
||||
BytesDropped uint64
|
||||
BytesReceivedPersec uint64
|
||||
BytesSentPersec uint64
|
||||
FramesDropped uint64
|
||||
FramesReceivedPersec uint64
|
||||
FramesSentPersec uint64
|
||||
Name string `mi:"Name"`
|
||||
BytesDropped uint64 `mi:"BytesDropped"`
|
||||
BytesReceivedPersec uint64 `mi:"BytesReceivedPersec"`
|
||||
BytesSentPersec uint64 `mi:"BytesSentPersec"`
|
||||
FramesDropped uint64 `mi:"FramesDropped"`
|
||||
FramesReceivedPersec uint64 `mi:"FramesReceivedPersec"`
|
||||
FramesSentPersec uint64 `mi:"FramesSentPersec"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectVmEthernet(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, obj := range dst {
|
||||
|
@ -1568,19 +1569,19 @@ func (c *Collector) collectVmEthernet(ch chan<- prometheus.Metric) error {
|
|||
|
||||
// Win32_PerfRawData_Counters_HyperVVirtualStorageDevice ...
|
||||
type Win32_PerfRawData_Counters_HyperVVirtualStorageDevice struct {
|
||||
Name string
|
||||
ErrorCount uint64
|
||||
QueueLength uint32
|
||||
ReadBytesPersec uint64
|
||||
ReadOperationsPerSec uint64
|
||||
WriteBytesPersec uint64
|
||||
WriteOperationsPerSec uint64
|
||||
Name string `mi:"Name"`
|
||||
ErrorCount uint64 `mi:"ErrorCount"`
|
||||
QueueLength uint32 `mi:"QueueLength"`
|
||||
ReadBytesPersec uint64 `mi:"ReadBytesPersec"`
|
||||
ReadOperationsPerSec uint64 `mi:"ReadOperationsPerSec"`
|
||||
WriteBytesPersec uint64 `mi:"WriteBytesPersec"`
|
||||
WriteOperationsPerSec uint64 `mi:"WriteOperationsPerSec"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectVmStorage(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_Counters_HyperVVirtualStorageDevice
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_Counters_HyperVVirtualStorageDevice", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_Counters_HyperVVirtualStorageDevice"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, obj := range dst {
|
||||
|
@ -1636,19 +1637,19 @@ func (c *Collector) collectVmStorage(ch chan<- prometheus.Metric) error {
|
|||
|
||||
// Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter ...
|
||||
type Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter struct {
|
||||
Name string
|
||||
BytesReceivedPersec uint64
|
||||
BytesSentPersec uint64
|
||||
DroppedPacketsIncomingPersec uint64
|
||||
DroppedPacketsOutgoingPersec uint64
|
||||
PacketsReceivedPersec uint64
|
||||
PacketsSentPersec uint64
|
||||
Name string `mi:"Name"`
|
||||
BytesReceivedPersec uint64 `mi:"BytesReceivedPersec"`
|
||||
BytesSentPersec uint64 `mi:"BytesSentPersec"`
|
||||
DroppedPacketsIncomingPersec uint64 `mi:"DroppedPacketsIncomingPersec"`
|
||||
DroppedPacketsOutgoingPersec uint64 `mi:"DroppedPacketsOutgoingPersec"`
|
||||
PacketsReceivedPersec uint64 `mi:"PacketsReceivedPersec"`
|
||||
PacketsSentPersec uint64 `mi:"PacketsSentPersec"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectVmNetwork(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, obj := range dst {
|
||||
|
@ -1704,23 +1705,23 @@ func (c *Collector) collectVmNetwork(ch chan<- prometheus.Metric) error {
|
|||
|
||||
// Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM ...
|
||||
type Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM struct {
|
||||
Name string
|
||||
AddedMemory uint64
|
||||
AveragePressure uint64
|
||||
CurrentPressure uint64
|
||||
GuestVisiblePhysicalMemory uint64
|
||||
MaximumPressure uint64
|
||||
MemoryAddOperations uint64
|
||||
MemoryRemoveOperations uint64
|
||||
MinimumPressure uint64
|
||||
PhysicalMemory uint64
|
||||
RemovedMemory uint64
|
||||
Name string `mi:"Name"`
|
||||
AddedMemory uint64 `mi:"AddedMemory"`
|
||||
AveragePressure uint64 `mi:"AveragePressure"`
|
||||
CurrentPressure uint64 `mi:"CurrentPressure"`
|
||||
GuestVisiblePhysicalMemory uint64 `mi:"GuestVisiblePhysicalMemory"`
|
||||
MaximumPressure uint64 `mi:"MaximumPressure"`
|
||||
MemoryAddOperations uint64 `mi:"MemoryAddOperations"`
|
||||
MemoryRemoveOperations uint64 `mi:"MemoryRemoveOperations"`
|
||||
MinimumPressure uint64 `mi:"MinimumPressure"`
|
||||
PhysicalMemory uint64 `mi:"PhysicalMemory"`
|
||||
RemovedMemory uint64 `mi:"RemovedMemory"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectVmMemory(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, obj := range dst {
|
||||
|
|
|
@ -10,10 +10,10 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
|
@ -262,7 +262,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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))
|
||||
|
||||
c.iisVersion = getIISVersion(logger)
|
||||
|
|
|
@ -7,9 +7,9 @@ import (
|
|||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"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/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "license"
|
||||
|
@ -61,7 +61,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
c.licenseStatus = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "status"),
|
||||
"Status of windows license",
|
||||
|
|
|
@ -13,13 +13,13 @@ import (
|
|||
"strings"
|
||||
|
||||
"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/perftypes"
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
|
@ -141,7 +141,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
if utils.PDHEnabled() {
|
||||
counters := []string{
|
||||
currentDiskQueueLength,
|
||||
|
|
|
@ -8,9 +8,9 @@ import (
|
|||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"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/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "logon"
|
||||
|
@ -54,7 +54,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
c.sessionInfo = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "session_logon_timestamp_seconds"),
|
||||
"timestamp of the logon session in seconds.",
|
||||
|
|
|
@ -12,13 +12,13 @@ import (
|
|||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"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/perftypes"
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "memory"
|
||||
|
@ -105,7 +105,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
if utils.PDHEnabled() {
|
||||
counters := []string{
|
||||
availableBytes,
|
||||
|
|
|
@ -8,9 +8,9 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "mscluster"
|
||||
|
@ -32,7 +32,7 @@ var ConfigDefaults = Config{
|
|||
// A Collector is a Prometheus Collector for WMI MSCluster_Cluster metrics.
|
||||
type Collector struct {
|
||||
config Config
|
||||
wmiClient *wmi.Client
|
||||
miSession *mi.Session
|
||||
|
||||
// cluster
|
||||
clusterAddEvictDelay *prometheus.Desc
|
||||
|
@ -221,16 +221,16 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
||||
if miSession == nil {
|
||||
return errors.New("miSession is nil")
|
||||
}
|
||||
|
||||
c.wmiClient = wmiClient
|
||||
c.miSession = miSession
|
||||
|
||||
if slices.Contains(c.config.CollectorsEnabled, "cluster") {
|
||||
c.buildCluster()
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package mscluster
|
||||
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
@ -10,85 +14,85 @@ const nameCluster = Name + "_cluster"
|
|||
// msClusterCluster represents the MSCluster_Cluster WMI class
|
||||
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-cluster
|
||||
type msClusterCluster struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
AddEvictDelay uint
|
||||
AdminAccessPoint uint
|
||||
AutoAssignNodeSite uint
|
||||
AutoBalancerLevel uint
|
||||
AutoBalancerMode uint
|
||||
BackupInProgress uint
|
||||
BlockCacheSize uint
|
||||
ClusSvcHangTimeout uint
|
||||
ClusSvcRegroupOpeningTimeout uint
|
||||
ClusSvcRegroupPruningTimeout uint
|
||||
ClusSvcRegroupStageTimeout uint
|
||||
ClusSvcRegroupTickInMilliseconds uint
|
||||
ClusterEnforcedAntiAffinity uint
|
||||
ClusterFunctionalLevel uint
|
||||
ClusterGroupWaitDelay uint
|
||||
ClusterLogLevel uint
|
||||
ClusterLogSize uint
|
||||
ClusterUpgradeVersion uint
|
||||
CrossSiteDelay uint
|
||||
CrossSiteThreshold uint
|
||||
CrossSubnetDelay uint
|
||||
CrossSubnetThreshold uint
|
||||
CsvBalancer uint
|
||||
DatabaseReadWriteMode uint
|
||||
DefaultNetworkRole uint
|
||||
DetectedCloudPlatform uint
|
||||
DetectManagedEvents uint
|
||||
DetectManagedEventsThreshold uint
|
||||
DisableGroupPreferredOwnerRandomization uint
|
||||
DrainOnShutdown uint
|
||||
DynamicQuorumEnabled uint
|
||||
EnableSharedVolumes uint
|
||||
FixQuorum uint
|
||||
GracePeriodEnabled uint
|
||||
GracePeriodTimeout uint
|
||||
GroupDependencyTimeout uint
|
||||
HangRecoveryAction uint
|
||||
IgnorePersistentStateOnStartup uint
|
||||
LogResourceControls uint
|
||||
LowerQuorumPriorityNodeId uint
|
||||
MaxNumberOfNodes uint
|
||||
MessageBufferLength uint
|
||||
MinimumNeverPreemptPriority uint
|
||||
MinimumPreemptorPriority uint
|
||||
NetftIPSecEnabled uint
|
||||
PlacementOptions uint
|
||||
PlumbAllCrossSubnetRoutes uint
|
||||
PreventQuorum uint
|
||||
QuarantineDuration uint
|
||||
QuarantineThreshold uint
|
||||
QuorumArbitrationTimeMax uint
|
||||
QuorumArbitrationTimeMin uint
|
||||
QuorumLogFileSize uint
|
||||
QuorumTypeValue uint
|
||||
RequestReplyTimeout uint
|
||||
ResiliencyDefaultPeriod uint
|
||||
ResiliencyLevel uint
|
||||
ResourceDllDeadlockPeriod uint
|
||||
RootMemoryReserved uint
|
||||
RouteHistoryLength uint
|
||||
S2DBusTypes uint
|
||||
S2DCacheDesiredState uint
|
||||
S2DCacheFlashReservePercent uint
|
||||
S2DCachePageSizeKBytes uint
|
||||
S2DEnabled uint
|
||||
S2DIOLatencyThreshold uint
|
||||
S2DOptimizations uint
|
||||
SameSubnetDelay uint
|
||||
SameSubnetThreshold uint
|
||||
SecurityLevel uint
|
||||
SecurityLevelForStorage uint
|
||||
SharedVolumeVssWriterOperationTimeout uint
|
||||
ShutdownTimeoutInMinutes uint
|
||||
UseClientAccessNetworksForSharedVolumes uint
|
||||
WitnessDatabaseWriteTimeout uint
|
||||
WitnessDynamicWeight uint
|
||||
WitnessRestartInterval uint
|
||||
AddEvictDelay uint `mi:"AddEvictDelay"`
|
||||
AdminAccessPoint uint `mi:"AdminAccessPoint"`
|
||||
AutoAssignNodeSite uint `mi:"AutoAssignNodeSite"`
|
||||
AutoBalancerLevel uint `mi:"AutoBalancerLevel"`
|
||||
AutoBalancerMode uint `mi:"AutoBalancerMode"`
|
||||
BackupInProgress uint `mi:"BackupInProgress"`
|
||||
BlockCacheSize uint `mi:"BlockCacheSize"`
|
||||
ClusSvcHangTimeout uint `mi:"ClusSvcHangTimeout"`
|
||||
ClusSvcRegroupOpeningTimeout uint `mi:"ClusSvcRegroupOpeningTimeout"`
|
||||
ClusSvcRegroupPruningTimeout uint `mi:"ClusSvcRegroupPruningTimeout"`
|
||||
ClusSvcRegroupStageTimeout uint `mi:"ClusSvcRegroupStageTimeout"`
|
||||
ClusSvcRegroupTickInMilliseconds uint `mi:"ClusSvcRegroupTickInMilliseconds"`
|
||||
ClusterEnforcedAntiAffinity uint `mi:"ClusterEnforcedAntiAffinity"`
|
||||
ClusterFunctionalLevel uint `mi:"ClusterFunctionalLevel"`
|
||||
ClusterGroupWaitDelay uint `mi:"ClusterGroupWaitDelay"`
|
||||
ClusterLogLevel uint `mi:"ClusterLogLevel"`
|
||||
ClusterLogSize uint `mi:"ClusterLogSize"`
|
||||
ClusterUpgradeVersion uint `mi:"ClusterUpgradeVersion"`
|
||||
CrossSiteDelay uint `mi:"CrossSiteDelay"`
|
||||
CrossSiteThreshold uint `mi:"CrossSiteThreshold"`
|
||||
CrossSubnetDelay uint `mi:"CrossSubnetDelay"`
|
||||
CrossSubnetThreshold uint `mi:"CrossSubnetThreshold"`
|
||||
CsvBalancer uint `mi:"CsvBalancer"`
|
||||
DatabaseReadWriteMode uint `mi:"DatabaseReadWriteMode"`
|
||||
DefaultNetworkRole uint `mi:"DefaultNetworkRole"`
|
||||
DetectedCloudPlatform uint `mi:"DetectedCloudPlatform"`
|
||||
DetectManagedEvents uint `mi:"DetectManagedEvents"`
|
||||
DetectManagedEventsThreshold uint `mi:"DetectManagedEventsThreshold"`
|
||||
DisableGroupPreferredOwnerRandomization uint `mi:"DisableGroupPreferredOwnerRandomization"`
|
||||
DrainOnShutdown uint `mi:"DrainOnShutdown"`
|
||||
DynamicQuorumEnabled uint `mi:"DynamicQuorumEnabled"`
|
||||
EnableSharedVolumes uint `mi:"EnableSharedVolumes"`
|
||||
FixQuorum uint `mi:"FixQuorum"`
|
||||
GracePeriodEnabled uint `mi:"GracePeriodEnabled"`
|
||||
GracePeriodTimeout uint `mi:"GracePeriodTimeout"`
|
||||
GroupDependencyTimeout uint `mi:"GroupDependencyTimeout"`
|
||||
HangRecoveryAction uint `mi:"HangRecoveryAction"`
|
||||
IgnorePersistentStateOnStartup uint `mi:"IgnorePersistentStateOnStartup"`
|
||||
LogResourceControls uint `mi:"LogResourceControls"`
|
||||
LowerQuorumPriorityNodeId uint `mi:"LowerQuorumPriorityNodeId"`
|
||||
MaxNumberOfNodes uint `mi:"MaxNumberOfNodes"`
|
||||
MessageBufferLength uint `mi:"MessageBufferLength"`
|
||||
MinimumNeverPreemptPriority uint `mi:"MinimumNeverPreemptPriority"`
|
||||
MinimumPreemptorPriority uint `mi:"MinimumPreemptorPriority"`
|
||||
NetftIPSecEnabled uint `mi:"NetftIPSecEnabled"`
|
||||
PlacementOptions uint `mi:"PlacementOptions"`
|
||||
PlumbAllCrossSubnetRoutes uint `mi:"PlumbAllCrossSubnetRoutes"`
|
||||
PreventQuorum uint `mi:"PreventQuorum"`
|
||||
QuarantineDuration uint `mi:"QuarantineDuration"`
|
||||
QuarantineThreshold uint `mi:"QuarantineThreshold"`
|
||||
QuorumArbitrationTimeMax uint `mi:"QuorumArbitrationTimeMax"`
|
||||
QuorumArbitrationTimeMin uint `mi:"QuorumArbitrationTimeMin"`
|
||||
QuorumLogFileSize uint `mi:"QuorumLogFileSize"`
|
||||
QuorumTypeValue uint `mi:"QuorumTypeValue"`
|
||||
RequestReplyTimeout uint `mi:"RequestReplyTimeout"`
|
||||
ResiliencyDefaultPeriod uint `mi:"ResiliencyDefaultPeriod"`
|
||||
ResiliencyLevel uint `mi:"ResiliencyLevel"`
|
||||
ResourceDllDeadlockPeriod uint `mi:"ResourceDllDeadlockPeriod"`
|
||||
RootMemoryReserved uint `mi:"RootMemoryReserved"`
|
||||
RouteHistoryLength uint `mi:"RouteHistoryLength"`
|
||||
S2DBusTypes uint `mi:"S2DBusTypes"`
|
||||
S2DCacheDesiredState uint `mi:"S2DCacheDesiredState"`
|
||||
S2DCacheFlashReservePercent uint `mi:"S2DCacheFlashReservePercent"`
|
||||
S2DCachePageSizeKBytes uint `mi:"S2DCachePageSizeKBytes"`
|
||||
S2DEnabled uint `mi:"S2DEnabled"`
|
||||
S2DIOLatencyThreshold uint `mi:"S2DIOLatencyThreshold"`
|
||||
S2DOptimizations uint `mi:"S2DOptimizations"`
|
||||
SameSubnetDelay uint `mi:"SameSubnetDelay"`
|
||||
SameSubnetThreshold uint `mi:"SameSubnetThreshold"`
|
||||
SecurityLevel uint `mi:"SecurityLevel"`
|
||||
SecurityLevelForStorage uint `mi:"SecurityLevelForStorage"`
|
||||
SharedVolumeVssWriterOperationTimeout uint `mi:"SharedVolumeVssWriterOperationTimeout"`
|
||||
ShutdownTimeoutInMinutes uint `mi:"ShutdownTimeoutInMinutes"`
|
||||
UseClientAccessNetworksForSharedVolumes uint `mi:"UseClientAccessNetworksForSharedVolumes"`
|
||||
WitnessDatabaseWriteTimeout uint `mi:"WitnessDatabaseWriteTimeout"`
|
||||
WitnessDynamicWeight uint `mi:"WitnessDynamicWeight"`
|
||||
WitnessRestartInterval uint `mi:"WitnessRestartInterval"`
|
||||
}
|
||||
|
||||
func (c *Collector) buildCluster() {
|
||||
|
@ -558,8 +562,8 @@ func (c *Collector) buildCluster() {
|
|||
|
||||
func (c *Collector) collectCluster(ch chan<- prometheus.Metric) error {
|
||||
var dst []msClusterCluster
|
||||
if err := c.wmiClient.Query("SELECT * FROM MSCluster_Cluster", &dst, nil, "root/MSCluster"); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, utils.Must(mi.NewQuery("SELECT * MSCluster_Cluster"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, v := range dst {
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package mscluster
|
||||
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
@ -10,13 +14,13 @@ const nameNetwork = Name + "_network"
|
|||
// msClusterNetwork represents the MSCluster_Network WMI class
|
||||
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-network
|
||||
type msClusterNetwork struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
Characteristics uint
|
||||
Flags uint
|
||||
Metric uint
|
||||
Role uint
|
||||
State uint
|
||||
Characteristics uint `mi:"Characteristics"`
|
||||
Flags uint `mi:"Flags"`
|
||||
Metric uint `mi:"Metric"`
|
||||
Role uint `mi:"Role"`
|
||||
State uint `mi:"State"`
|
||||
}
|
||||
|
||||
func (c *Collector) buildNetwork() {
|
||||
|
@ -57,8 +61,8 @@ func (c *Collector) buildNetwork() {
|
|||
func (c *Collector) collectNetwork(ch chan<- prometheus.Metric) error {
|
||||
var dst []msClusterNetwork
|
||||
|
||||
if err := c.wmiClient.Query("SELECT * FROM MSCluster_Network", &dst, nil, "root/MSCluster"); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, utils.Must(mi.NewQuery("SELECT * MSCluster_Node"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, v := range dst {
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package mscluster
|
||||
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
@ -10,22 +14,22 @@ const nameNode = Name + "_node"
|
|||
// msClusterNode represents the MSCluster_Node WMI class
|
||||
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-node
|
||||
type msClusterNode struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
BuildNumber uint
|
||||
Characteristics uint
|
||||
DetectedCloudPlatform uint
|
||||
DynamicWeight uint
|
||||
Flags uint
|
||||
MajorVersion uint
|
||||
MinorVersion uint
|
||||
NeedsPreventQuorum uint
|
||||
NodeDrainStatus uint
|
||||
NodeHighestVersion uint
|
||||
NodeLowestVersion uint
|
||||
NodeWeight uint
|
||||
State uint
|
||||
StatusInformation uint
|
||||
BuildNumber uint `mi:"BuildNumber"`
|
||||
Characteristics uint `mi:"Characteristics"`
|
||||
DetectedCloudPlatform uint `mi:"DetectedCloudPlatform"`
|
||||
DynamicWeight uint `mi:"DynamicWeight"`
|
||||
Flags uint `mi:"Flags"`
|
||||
MajorVersion uint `mi:"MajorVersion"`
|
||||
MinorVersion uint `mi:"MinorVersion"`
|
||||
NeedsPreventQuorum uint `mi:"NeedsPreventQuorum"`
|
||||
NodeDrainStatus uint `mi:"NodeDrainStatus"`
|
||||
NodeHighestVersion uint `mi:"NodeHighestVersion"`
|
||||
NodeLowestVersion uint `mi:"NodeLowestVersion"`
|
||||
NodeWeight uint `mi:"NodeWeight"`
|
||||
State uint `mi:"State"`
|
||||
StatusInformation uint `mi:"StatusInformation"`
|
||||
}
|
||||
|
||||
func (c *Collector) buildNode() {
|
||||
|
@ -120,8 +124,8 @@ func (c *Collector) buildNode() {
|
|||
func (c *Collector) collectNode(ch chan<- prometheus.Metric) ([]string, error) {
|
||||
var dst []msClusterNode
|
||||
|
||||
if err := c.wmiClient.Query("SELECT * FROM MSCluster_Node", &dst, nil, "root/MSCluster"); err != nil {
|
||||
return nil, err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, utils.Must(mi.NewQuery("SELECT * FROM MSCluster_Node"))); err != nil {
|
||||
return nil, fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
nodeNames := make([]string, 0, len(dst))
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package mscluster
|
||||
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
@ -10,27 +14,27 @@ const nameResource = Name + "_resource"
|
|||
// msClusterResource represents the MSCluster_Resource WMI class
|
||||
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resource
|
||||
type msClusterResource struct {
|
||||
Name string
|
||||
Type string
|
||||
OwnerGroup string
|
||||
OwnerNode string
|
||||
Name string `mi:"Name"`
|
||||
Type string `mi:"Type"`
|
||||
OwnerGroup string `mi:"OwnerGroup"`
|
||||
OwnerNode string `mi:"OwnerNode"`
|
||||
|
||||
Characteristics uint
|
||||
DeadlockTimeout uint
|
||||
EmbeddedFailureAction uint
|
||||
Flags uint
|
||||
IsAlivePollInterval uint
|
||||
LooksAlivePollInterval uint
|
||||
MonitorProcessId uint
|
||||
PendingTimeout uint
|
||||
ResourceClass uint
|
||||
RestartAction uint
|
||||
RestartDelay uint
|
||||
RestartPeriod uint
|
||||
RestartThreshold uint
|
||||
RetryPeriodOnFailure uint
|
||||
State uint
|
||||
Subclass uint
|
||||
Characteristics uint `mi:"Characteristics"`
|
||||
DeadlockTimeout uint `mi:"DeadlockTimeout"`
|
||||
EmbeddedFailureAction uint `mi:"EmbeddedFailureAction"`
|
||||
Flags uint `mi:"Flags"`
|
||||
IsAlivePollInterval uint `mi:"IsAlivePollInterval"`
|
||||
LooksAlivePollInterval uint `mi:"LooksAlivePollInterval"`
|
||||
MonitorProcessId uint `mi:"MonitorProcessId"`
|
||||
PendingTimeout uint `mi:"PendingTimeout"`
|
||||
ResourceClass uint `mi:"ResourceClass"`
|
||||
RestartAction uint `mi:"RestartAction"`
|
||||
RestartDelay uint `mi:"RestartDelay"`
|
||||
RestartPeriod uint `mi:"RestartPeriod"`
|
||||
RestartThreshold uint `mi:"RestartThreshold"`
|
||||
RetryPeriodOnFailure uint `mi:"RetryPeriodOnFailure"`
|
||||
State uint `mi:"State"`
|
||||
Subclass uint `mi:"Subclass"`
|
||||
}
|
||||
|
||||
func (c *Collector) buildResource() {
|
||||
|
@ -149,8 +153,8 @@ func (c *Collector) buildResource() {
|
|||
func (c *Collector) collectResource(ch chan<- prometheus.Metric, nodeNames []string) error {
|
||||
var dst []msClusterResource
|
||||
|
||||
if err := c.wmiClient.Query("SELECT * FROM MSCluster_Resource", &dst, nil, "root/MSCluster"); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, utils.Must(mi.NewQuery("SELECT * FROM MSCluster_Resource"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, v := range dst {
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package mscluster
|
||||
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
@ -10,22 +14,22 @@ const nameResourceGroup = Name + "_resourcegroup"
|
|||
// msClusterResourceGroup represents the MSCluster_ResourceGroup WMI class
|
||||
// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resourcegroup
|
||||
type msClusterResourceGroup struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
AutoFailbackType uint
|
||||
Characteristics uint
|
||||
ColdStartSetting uint
|
||||
DefaultOwner uint
|
||||
FailbackWindowEnd int
|
||||
FailbackWindowStart int
|
||||
FailoverPeriod uint
|
||||
FailoverThreshold uint
|
||||
Flags uint
|
||||
GroupType uint
|
||||
OwnerNode string
|
||||
Priority uint
|
||||
ResiliencyPeriod uint
|
||||
State uint
|
||||
AutoFailbackType uint `mi:"AutoFailbackType"`
|
||||
Characteristics uint `mi:"Characteristics"`
|
||||
ColdStartSetting uint `mi:"ColdStartSetting"`
|
||||
DefaultOwner uint `mi:"DefaultOwner"`
|
||||
FailbackWindowEnd int `mi:"FailbackWindowEnd"`
|
||||
FailbackWindowStart int `mi:"FailbackWindowStart"`
|
||||
FailoverPeriod uint `mi:"FailoverPeriod"`
|
||||
FailoverThreshold uint `mi:"FailoverThreshold"`
|
||||
Flags uint `mi:"Flags"`
|
||||
GroupType uint `mi:"GroupType"`
|
||||
OwnerNode string `mi:"OwnerNode"`
|
||||
Priority uint `mi:"Priority"`
|
||||
ResiliencyPeriod uint `mi:"ResiliencyPeriod"`
|
||||
State uint `mi:"State"`
|
||||
}
|
||||
|
||||
func (c *Collector) buildResourceGroup() {
|
||||
|
@ -126,8 +130,8 @@ func (c *Collector) buildResourceGroup() {
|
|||
func (c *Collector) collectResourceGroup(ch chan<- prometheus.Metric, nodeNames []string) error {
|
||||
var dst []msClusterResourceGroup
|
||||
|
||||
if err := c.wmiClient.Query("SELECT * FROM MSCluster_ResourceGroup", &dst, nil, "root/MSCluster"); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, utils.Must(mi.NewQuery("SELECT * FROM MSCluster_ResourceGroup"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, v := range dst {
|
||||
|
|
|
@ -4,14 +4,15 @@ package msmq
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "msmq"
|
||||
|
@ -27,7 +28,7 @@ var ConfigDefaults = Config{
|
|||
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics.
|
||||
type Collector struct {
|
||||
config Config
|
||||
wmiClient *wmi.Client
|
||||
miSession *mi.Session
|
||||
|
||||
bytesInJournalQueue *prometheus.Desc
|
||||
bytesInQueue *prometheus.Desc
|
||||
|
@ -75,14 +76,14 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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))
|
||||
|
||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
||||
if miSession == nil {
|
||||
return errors.New("miSession is nil")
|
||||
}
|
||||
|
||||
c.wmiClient = wmiClient
|
||||
c.miSession = miSession
|
||||
|
||||
if *c.config.QueryWhereClause == "" {
|
||||
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 {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
BytesInJournalQueue uint64
|
||||
BytesInQueue uint64
|
||||
MessagesInJournalQueue uint64
|
||||
MessagesInQueue uint64
|
||||
BytesInJournalQueue uint64 `mi:"BytesInJournalQueue"`
|
||||
BytesInQueue uint64 `mi:"BytesInQueue"`
|
||||
MessagesInJournalQueue uint64 `mi:"MessagesInJournalQueue"`
|
||||
MessagesInQueue uint64 `mi:"MessagesInQueue"`
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if err := c.wmiClient.Query(query, &dst); err != nil {
|
||||
return err
|
||||
queryExpression, err := mi.NewQuery(query)
|
||||
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 {
|
||||
|
|
|
@ -13,10 +13,10 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
|
@ -508,7 +508,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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.
|
||||
sort.Strings(c.config.CollectorsEnabled)
|
||||
|
||||
|
|
|
@ -13,12 +13,12 @@ import (
|
|||
"unsafe"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
|
@ -149,7 +149,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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() {
|
||||
counters := []string{
|
||||
BytesReceivedPerSec,
|
||||
|
|
|
@ -9,9 +9,9 @@ import (
|
|||
"slices"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "netframework"
|
||||
|
@ -47,7 +47,7 @@ const (
|
|||
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics.
|
||||
type Collector struct {
|
||||
config Config
|
||||
wmiClient *wmi.Client
|
||||
miSession *mi.Session
|
||||
|
||||
// clrexceptions
|
||||
numberOfExceptionsThrown *prometheus.Desc
|
||||
|
@ -143,12 +143,12 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
||||
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||
if miSession == nil {
|
||||
return errors.New("miSession is nil")
|
||||
}
|
||||
|
||||
c.wmiClient = wmiClient
|
||||
c.miSession = miSession
|
||||
|
||||
if slices.Contains(c.config.CollectorsEnabled, collectorClrExceptions) {
|
||||
c.buildClrExceptions()
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
package netframework
|
||||
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
@ -35,19 +39,19 @@ func (c *Collector) buildClrExceptions() {
|
|||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRExceptions struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
NumberofExcepsThrown uint32
|
||||
NumberofExcepsThrownPersec uint32
|
||||
NumberofFiltersPersec uint32
|
||||
NumberofFinallysPersec uint32
|
||||
ThrowToCatchDepthPersec uint32
|
||||
NumberofExcepsThrown uint32 `mi:"NumberofExcepsThrown"`
|
||||
NumberofExcepsThrownPersec uint32 `mi:"NumberofExcepsThrownPersec"`
|
||||
NumberofFiltersPersec uint32 `mi:"NumberofFiltersPersec"`
|
||||
NumberofFinallysPersec uint32 `mi:"NumberofFinallysPersec"`
|
||||
ThrowToCatchDepthPersec uint32 `mi:"ThrowToCatchDepthPersec"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectClrExceptions(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRExceptions
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRExceptions", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRExceptions"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
package netframework
|
||||
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
@ -29,19 +33,19 @@ func (c *Collector) buildClrInterop() {
|
|||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRInterop struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
NumberofCCWs uint32
|
||||
Numberofmarshalling uint32
|
||||
NumberofStubs uint32
|
||||
NumberofTLBexportsPersec uint32
|
||||
NumberofTLBimportsPersec uint32
|
||||
NumberofCCWs uint32 `mi:"NumberofCCWs"`
|
||||
Numberofmarshalling uint32 `mi:"Numberofmarshalling"`
|
||||
NumberofStubs uint32 `mi:"NumberofStubs"`
|
||||
NumberofTLBexportsPersec uint32 `mi:"NumberofTLBexportsPersec"`
|
||||
NumberofTLBimportsPersec uint32 `mi:"NumberofTLBimportsPersec"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectClrInterop(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRInterop
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRInterop", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRInterop"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
package netframework
|
||||
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
@ -35,21 +39,21 @@ func (c *Collector) buildClrJIT() {
|
|||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRJit struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
Frequency_PerfTime uint32
|
||||
ILBytesJittedPersec uint32
|
||||
NumberofILBytesJitted uint32
|
||||
NumberofMethodsJitted uint32
|
||||
PercentTimeinJit uint32
|
||||
StandardJitFailures uint32
|
||||
TotalNumberofILBytesJitted uint32
|
||||
Frequency_PerfTime uint32 `mi:"Frequency_PerfTime"`
|
||||
ILBytesJittedPersec uint32 `mi:"ILBytesJittedPersec"`
|
||||
NumberofILBytesJitted uint32 `mi:"NumberofILBytesJitted"`
|
||||
NumberofMethodsJitted uint32 `mi:"NumberofMethodsJitted"`
|
||||
PercentTimeinJit uint32 `mi:"PercentTimeinJit"`
|
||||
StandardJitFailures uint32 `mi:"StandardJitFailures"`
|
||||
TotalNumberofILBytesJitted uint32 `mi:"TotalNumberofILBytesJitted"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectClrJIT(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRJit
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRJit", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRJit"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
package netframework
|
||||
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
@ -65,30 +69,30 @@ func (c *Collector) buildClrLoading() {
|
|||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRLoading struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
AssemblySearchLength uint32
|
||||
BytesinLoaderHeap uint64
|
||||
Currentappdomains uint32
|
||||
CurrentAssemblies uint32
|
||||
CurrentClassesLoaded uint32
|
||||
PercentTimeLoading uint64
|
||||
Rateofappdomains uint32
|
||||
Rateofappdomainsunloaded uint32
|
||||
RateofAssemblies uint32
|
||||
RateofClassesLoaded uint32
|
||||
RateofLoadFailures uint32
|
||||
TotalAppdomains uint32
|
||||
Totalappdomainsunloaded uint32
|
||||
TotalAssemblies uint32
|
||||
TotalClassesLoaded uint32
|
||||
TotalNumberofLoadFailures uint32
|
||||
AssemblySearchLength uint32 `mi:"AssemblySearchLength"`
|
||||
BytesinLoaderHeap uint64 `mi:"BytesinLoaderHeap"`
|
||||
Currentappdomains uint32 `mi:"Currentappdomains"`
|
||||
CurrentAssemblies uint32 `mi:"CurrentAssemblies"`
|
||||
CurrentClassesLoaded uint32 `mi:"CurrentClassesLoaded"`
|
||||
PercentTimeLoading uint64 `mi:"PercentTimeLoading"`
|
||||
Rateofappdomains uint32 `mi:"Rateofappdomains"`
|
||||
Rateofappdomainsunloaded uint32 `mi:"Rateofappdomainsunloaded"`
|
||||
RateofAssemblies uint32 `mi:"RateofAssemblies"`
|
||||
RateofClassesLoaded uint32 `mi:"RateofClassesLoaded"`
|
||||
RateofLoadFailures uint32 `mi:"RateofLoadFailures"`
|
||||
TotalAppdomains uint32 `mi:"TotalAppdomains"`
|
||||
Totalappdomainsunloaded uint32 `mi:"Totalappdomainsunloaded"`
|
||||
TotalAssemblies uint32 `mi:"TotalAssemblies"`
|
||||
TotalClassesLoaded uint32 `mi:"TotalClassesLoaded"`
|
||||
TotalNumberofLoadFailures uint32 `mi:"TotalNumberofLoadFailures"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectClrLoading(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRLoading
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRLoading", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRLoading"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
package netframework
|
||||
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
@ -53,24 +57,24 @@ func (c *Collector) buildClrLocksAndThreads() {
|
|||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
ContentionRatePersec uint32
|
||||
CurrentQueueLength uint32
|
||||
NumberofcurrentlogicalThreads uint32
|
||||
NumberofcurrentphysicalThreads uint32
|
||||
Numberofcurrentrecognizedthreads uint32
|
||||
Numberoftotalrecognizedthreads uint32
|
||||
QueueLengthPeak uint32
|
||||
QueueLengthPersec uint32
|
||||
RateOfRecognizedThreadsPersec uint32
|
||||
TotalNumberofContentions uint32
|
||||
ContentionRatePersec uint32 `mi:"ContentionRatePersec"`
|
||||
CurrentQueueLength uint32 `mi:"CurrentQueueLength"`
|
||||
NumberofcurrentlogicalThreads uint32 `mi:"NumberofcurrentlogicalThreads"`
|
||||
NumberofcurrentphysicalThreads uint32 `mi:"NumberofcurrentphysicalThreads"`
|
||||
Numberofcurrentrecognizedthreads uint32 `mi:"Numberofcurrentrecognizedthreads"`
|
||||
Numberoftotalrecognizedthreads uint32 `mi:"Numberoftotalrecognizedthreads"`
|
||||
QueueLengthPeak uint32 `mi:"QueueLengthPeak"`
|
||||
QueueLengthPersec uint32 `mi:"QueueLengthPersec"`
|
||||
RateOfRecognizedThreadsPersec uint32 `mi:"RateOfRecognizedThreadsPersec"`
|
||||
TotalNumberofContentions uint32 `mi:"TotalNumberofContentions"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectClrLocksAndThreads(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
package netframework
|
||||
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
@ -83,43 +87,43 @@ func (c *Collector) buildClrMemory() {
|
|||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRMemory struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
AllocatedBytesPersec uint64
|
||||
FinalizationSurvivors uint64
|
||||
Frequency_PerfTime uint64
|
||||
Gen0heapsize uint64
|
||||
Gen0PromotedBytesPerSec uint64
|
||||
Gen1heapsize uint64
|
||||
Gen1PromotedBytesPerSec uint64
|
||||
Gen2heapsize uint64
|
||||
LargeObjectHeapsize uint64
|
||||
NumberBytesinallHeaps uint64
|
||||
NumberGCHandles uint64
|
||||
NumberGen0Collections uint64
|
||||
NumberGen1Collections uint64
|
||||
NumberGen2Collections uint64
|
||||
NumberInducedGC uint64
|
||||
NumberofPinnedObjects uint64
|
||||
NumberofSinkBlocksinuse uint64
|
||||
NumberTotalcommittedBytes uint64
|
||||
NumberTotalreservedBytes uint64
|
||||
AllocatedBytesPersec uint64 `mi:"AllocatedBytesPersec"`
|
||||
FinalizationSurvivors uint64 `mi:"FinalizationSurvivors"`
|
||||
Frequency_PerfTime uint64 `mi:"Frequency_PerfTime"`
|
||||
Gen0heapsize uint64 `mi:"Gen0heapsize"`
|
||||
Gen0PromotedBytesPerSec uint64 `mi:"Gen0PromotedBytesPersec"`
|
||||
Gen1heapsize uint64 `mi:"Gen1heapsize"`
|
||||
Gen1PromotedBytesPerSec uint64 `mi:"Gen1PromotedBytesPersec"`
|
||||
Gen2heapsize uint64 `mi:"Gen2heapsize"`
|
||||
LargeObjectHeapsize uint64 `mi:"LargeObjectHeapsize"`
|
||||
NumberBytesinallHeaps uint64 `mi:"NumberBytesinallHeaps"`
|
||||
NumberGCHandles uint64 `mi:"NumberGCHandles"`
|
||||
NumberGen0Collections uint64 `mi:"NumberGen0Collections"`
|
||||
NumberGen1Collections uint64 `mi:"NumberGen1Collections"`
|
||||
NumberGen2Collections uint64 `mi:"NumberGen2Collections"`
|
||||
NumberInducedGC uint64 `mi:"NumberInducedGC"`
|
||||
NumberofPinnedObjects uint64 `mi:"NumberofPinnedObjects"`
|
||||
NumberofSinkBlocksinuse uint64 `mi:"NumberofSinkBlocksinuse"`
|
||||
NumberTotalcommittedBytes uint64 `mi:"NumberTotalcommittedBytes"`
|
||||
NumberTotalreservedBytes uint64 `mi:"NumberTotalreservedBytes"`
|
||||
// PercentTimeinGC has countertype=PERF_RAW_FRACTION.
|
||||
// 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
|
||||
PercentTimeinGC uint32
|
||||
PercentTimeinGC uint32 `mi:"PercentTimeinGC"`
|
||||
// BaseValue is just a "magic" number used to make the calculation come out right.
|
||||
PercentTimeinGC_base uint32
|
||||
ProcessID uint64
|
||||
PromotedFinalizationMemoryfromGen0 uint64
|
||||
PromotedMemoryfromGen0 uint64
|
||||
PromotedMemoryfromGen1 uint64
|
||||
PercentTimeinGC_base uint32 `mi:"PercentTimeinGC_base"`
|
||||
ProcessID uint64 `mi:"ProcessID"`
|
||||
PromotedFinalizationMemoryfromGen0 uint64 `mi:"PromotedFinalizationMemoryfromGen0"`
|
||||
PromotedMemoryfromGen0 uint64 `mi:"PromotedMemoryfromGen0"`
|
||||
PromotedMemoryfromGen1 uint64 `mi:"PromotedMemoryfromGen1"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRMemory
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRMemory", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRMemory"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
package netframework
|
||||
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
@ -47,21 +51,21 @@ func (c *Collector) buildClrRemoting() {
|
|||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRRemoting struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
Channels uint32
|
||||
ContextBoundClassesLoaded uint32
|
||||
ContextBoundObjectsAllocPersec uint32
|
||||
ContextProxies uint32
|
||||
Contexts uint32
|
||||
RemoteCallsPersec uint32
|
||||
TotalRemoteCalls uint32
|
||||
Channels uint32 `mi:"Channels"`
|
||||
ContextBoundClassesLoaded uint32 `mi:"ContextBoundClassesLoaded"`
|
||||
ContextBoundObjectsAllocPersec uint32 `mi:"ContextBoundObjectsAllocPersec"`
|
||||
ContextProxies uint32 `mi:"ContextProxies"`
|
||||
Contexts uint32 `mi:"Contexts"`
|
||||
RemoteCallsPersec uint32 `mi:"RemoteCallsPersec"`
|
||||
TotalRemoteCalls uint32 `mi:"TotalRemoteCalls"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectClrRemoting(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRRemoting
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRRemoting", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRRemoting"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
package netframework
|
||||
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
|
@ -35,20 +39,20 @@ func (c *Collector) buildClrSecurity() {
|
|||
}
|
||||
|
||||
type Win32_PerfRawData_NETFramework_NETCLRSecurity struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
Frequency_PerfTime uint32
|
||||
NumberLinkTimeChecks uint32
|
||||
PercentTimeinRTchecks uint32
|
||||
PercentTimeSigAuthenticating uint64
|
||||
StackWalkDepth uint32
|
||||
TotalRuntimeChecks uint32
|
||||
Frequency_PerfTime uint32 `mi:"Frequency_PerfTime"`
|
||||
NumberLinkTimeChecks uint32 `mi:"NumberLinkTimeChecks"`
|
||||
PercentTimeinRTchecks uint32 `mi:"PercentTimeinRTchecks"`
|
||||
PercentTimeSigAuthenticating uint64 `mi:"PercentTimeSigAuthenticating"`
|
||||
StackWalkDepth uint32 `mi:"StackWalkDepth"`
|
||||
TotalRuntimeChecks uint32 `mi:"TotalRuntimeChecks"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectClrSecurity(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_NETFramework_NETCLRSecurity
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRSecurity", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * Win32_PerfRawData_NETFramework_NETCLRSecurity"))); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
for _, process := range dst {
|
||||
|
|
|
@ -6,9 +6,9 @@ import (
|
|||
"log/slog"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
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.
|
||||
type Collector struct {
|
||||
config Config
|
||||
wmiClient *wmi.Client
|
||||
miSession *mi.Session
|
||||
|
||||
miQueryAuthenticationServer mi.Query
|
||||
miQueryAccountingServer mi.Query
|
||||
|
||||
accessAccepts *prometheus.Desc
|
||||
accessChallenges *prometheus.Desc
|
||||
|
@ -78,12 +81,26 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
||||
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||
if miSession == 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(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "access_accepts"),
|
||||
"(AccessAccepts)",
|
||||
|
@ -261,46 +278,46 @@ func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan
|
|||
// Win32_PerfRawData_IAS_NPSAuthenticationServer docs:
|
||||
// at the moment there is no Microsoft documentation.
|
||||
type Win32_PerfRawData_IAS_NPSAuthenticationServer struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
AccessAccepts uint32
|
||||
AccessChallenges uint32
|
||||
AccessRejects uint32
|
||||
AccessRequests uint32
|
||||
AccessBadAuthenticators uint32
|
||||
AccessDroppedPackets uint32
|
||||
AccessInvalidRequests uint32
|
||||
AccessMalformedPackets uint32
|
||||
AccessPacketsReceived uint32
|
||||
AccessPacketsSent uint32
|
||||
AccessServerResetTime uint32
|
||||
AccessServerUpTime uint32
|
||||
AccessUnknownType uint32
|
||||
AccessAccepts uint32 `mi:"AccessAccepts"`
|
||||
AccessChallenges uint32 `mi:"AccessChallenges"`
|
||||
AccessRejects uint32 `mi:"AccessRejects"`
|
||||
AccessRequests uint32 `mi:"AccessRequests"`
|
||||
AccessBadAuthenticators uint32 `mi:"AccessBadAuthenticators"`
|
||||
AccessDroppedPackets uint32 `mi:"AccessDroppedPackets"`
|
||||
AccessInvalidRequests uint32 `mi:"AccessInvalidRequests"`
|
||||
AccessMalformedPackets uint32 `mi:"AccessMalformedPackets"`
|
||||
AccessPacketsReceived uint32 `mi:"AccessPacketsReceived"`
|
||||
AccessPacketsSent uint32 `mi:"AccessPacketsSent"`
|
||||
AccessServerResetTime uint32 `mi:"AccessServerResetTime"`
|
||||
AccessServerUpTime uint32 `mi:"AccessServerUpTime"`
|
||||
AccessUnknownType uint32 `mi:"AccessUnknownType"`
|
||||
}
|
||||
|
||||
type Win32_PerfRawData_IAS_NPSAccountingServer struct {
|
||||
Name string
|
||||
Name string `mi:"Name"`
|
||||
|
||||
AccountingRequests uint32
|
||||
AccountingResponses uint32
|
||||
AccountingBadAuthenticators uint32
|
||||
AccountingDroppedPackets uint32
|
||||
AccountingInvalidRequests uint32
|
||||
AccountingMalformedPackets uint32
|
||||
AccountingNoRecord uint32
|
||||
AccountingPacketsReceived uint32
|
||||
AccountingPacketsSent uint32
|
||||
AccountingServerResetTime uint32
|
||||
AccountingServerUpTime uint32
|
||||
AccountingUnknownType uint32
|
||||
AccountingRequests uint32 `mi:"AccountingRequests"`
|
||||
AccountingResponses uint32 `mi:"AccountingResponses"`
|
||||
AccountingBadAuthenticators uint32 `mi:"AccountingBadAuthenticators"`
|
||||
AccountingDroppedPackets uint32 `mi:"AccountingDroppedPackets"`
|
||||
AccountingInvalidRequests uint32 `mi:"AccountingInvalidRequests"`
|
||||
AccountingMalformedPackets uint32 `mi:"AccountingMalformedPackets"`
|
||||
AccountingNoRecord uint32 `mi:"AccountingNoRecord"`
|
||||
AccountingPacketsReceived uint32 `mi:"AccountingPacketsReceived"`
|
||||
AccountingPacketsSent uint32 `mi:"AccountingPacketsSent"`
|
||||
AccountingServerResetTime uint32 `mi:"AccountingServerResetTime"`
|
||||
AccountingServerUpTime uint32 `mi:"AccountingServerUpTime"`
|
||||
AccountingUnknownType uint32 `mi:"AccountingUnknownType"`
|
||||
}
|
||||
|
||||
// CollectAccept sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *Collector) CollectAccept(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_IAS_NPSAuthenticationServer
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_IAS_NPSAuthenticationServer", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQueryAuthenticationServer); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
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 {
|
||||
var dst []Win32_PerfRawData_IAS_NPSAccountingServer
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_IAS_NPSAccountingServer", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQueryAccountingServer); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
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/psapi"
|
||||
"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"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
@ -109,9 +109,11 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(logger *slog.Logger, _ *wmi.Client) error {
|
||||
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.")
|
||||
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. "+
|
||||
"See https://github.com/prometheus-community/windows_exporter/pull/1596 for more information.",
|
||||
slog.String("collector", Name),
|
||||
)
|
||||
|
||||
workstationInfo, err := netapi32.GetWorkstationInfo()
|
||||
if err != nil {
|
||||
|
|
|
@ -11,11 +11,11 @@ import (
|
|||
"strings"
|
||||
|
||||
"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/perftypes"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "perfdata"
|
||||
|
@ -92,7 +92,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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.")
|
||||
|
||||
for i, object := range c.config.Objects {
|
||||
|
|
|
@ -9,11 +9,11 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "physical_disk"
|
||||
|
@ -114,7 +114,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
c.requestsQueued = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "requests_queued"),
|
||||
"The number of requests queued to the disk (PhysicalDisk.CurrentDiskQueueLength)",
|
||||
|
|
|
@ -10,9 +10,9 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "printer"
|
||||
|
@ -39,8 +39,10 @@ var ConfigDefaults = Config{
|
|||
}
|
||||
|
||||
type Collector struct {
|
||||
config Config
|
||||
wmiClient *wmi.Client
|
||||
config Config
|
||||
miSession *mi.Session
|
||||
miQueryPrinterJobs mi.Query
|
||||
miQueryPrinter mi.Query
|
||||
|
||||
printerStatus *prometheus.Desc
|
||||
printerJobStatus *prometheus.Desc
|
||||
|
@ -107,12 +109,25 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
||||
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||
if miSession == 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(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "job_status"),
|
||||
|
@ -143,42 +158,35 @@ func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
|
|||
}
|
||||
|
||||
type wmiPrinter struct {
|
||||
Name string
|
||||
Default bool
|
||||
PrinterStatus uint16
|
||||
JobCountSinceLastReset uint32
|
||||
Name string `mi:"Name"`
|
||||
Default bool `mi:"Default"`
|
||||
PrinterStatus uint16 `mi:"PrinterStatus"`
|
||||
JobCountSinceLastReset uint32 `mi:"JobCountSinceLastReset"`
|
||||
}
|
||||
|
||||
type wmiPrintJob struct {
|
||||
Name string
|
||||
Status string
|
||||
Name string `mi:"Name"`
|
||||
Status string `mi:"Status"`
|
||||
}
|
||||
|
||||
func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||
logger = logger.With(slog.String("collector", Name))
|
||||
if err := c.collectPrinterStatus(ch); err != nil {
|
||||
logger.Error("failed to collect printer status metrics",
|
||||
slog.Any("err", err),
|
||||
)
|
||||
func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||
var errs []error
|
||||
|
||||
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 {
|
||||
logger.Error("failed to collect printer job status metrics",
|
||||
slog.Any("err", err),
|
||||
)
|
||||
|
||||
return err
|
||||
errs = append(errs, fmt.Errorf("failed to collect printer job status metrics: %w", err))
|
||||
}
|
||||
|
||||
return nil
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
func (c *Collector) collectPrinterStatus(ch chan<- prometheus.Metric) error {
|
||||
var printers []wmiPrinter
|
||||
if err := c.wmiClient.Query("SELECT * FROM win32_Printer", &printers); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&printers, mi.NamespaceRootCIMv2, c.miQueryPrinter); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
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 {
|
||||
var printJobs []wmiPrintJob
|
||||
if err := c.wmiClient.Query("SELECT * FROM win32_PrintJob", &printJobs); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&printJobs, mi.NamespaceRootCIMv2, c.miQueryPrinterJobs); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
groupedPrintJobs := c.groupPrintJobs(printJobs)
|
||||
|
|
|
@ -12,13 +12,13 @@ import (
|
|||
"unsafe"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
|
@ -38,7 +38,9 @@ var ConfigDefaults = Config{
|
|||
|
||||
type Collector struct {
|
||||
config Config
|
||||
wmiClient *wmi.Client
|
||||
miSession *mi.Session
|
||||
|
||||
workerProcessMIQueryQuery mi.Query
|
||||
|
||||
perfDataCollector perfdata.Collector
|
||||
|
||||
|
@ -139,14 +141,20 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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))
|
||||
|
||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
||||
if miSession == 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() {
|
||||
counters := []string{
|
||||
|
@ -302,8 +310,8 @@ func (c *Collector) Build(logger *slog.Logger, wmiClient *wmi.Client) error {
|
|||
}
|
||||
|
||||
type WorkerProcess struct {
|
||||
AppPoolName string
|
||||
ProcessId uint64
|
||||
AppPoolName string `mi:"AppPoolName"`
|
||||
ProcessId uint64 `mi:"ProcessId"`
|
||||
}
|
||||
|
||||
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
|
||||
if c.config.EnableWorkerProcess {
|
||||
if err := c.wmiClient.Query("SELECT * FROM WorkerProcess", &workerProcesses, nil, "root\\WebAdministration"); err != nil {
|
||||
logger.Debug("Could not query WebAdministration namespace for IIS worker processes",
|
||||
slog.Any("err", err),
|
||||
)
|
||||
if err := c.miSession.Query(&workerProcesses, mi.NamespaceRootWebAdministration, c.workerProcessMIQueryQuery); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -540,10 +546,8 @@ func (c *Collector) collectPDH(logger *slog.Logger, ch chan<- prometheus.Metric)
|
|||
|
||||
var workerProcesses []WorkerProcess
|
||||
if c.config.EnableWorkerProcess {
|
||||
if err := c.wmiClient.Query("SELECT * FROM WorkerProcess", &workerProcesses, nil, "root\\WebAdministration"); err != nil {
|
||||
logger.Debug("Could not query WebAdministration namespace for IIS worker processes",
|
||||
slog.Any("err", err),
|
||||
)
|
||||
if err := c.miSession.Query(&workerProcesses, mi.NamespaceRootWebAdministration, c.workerProcessMIQueryQuery); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,11 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
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/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "remote_fx"
|
||||
|
@ -81,7 +81,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(*slog.Logger, *wmi.Client) error {
|
||||
func (c *Collector) Build(*slog.Logger, *mi.Session) error {
|
||||
// net
|
||||
c.baseTCPRTT = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "net_base_tcp_rtt_seconds"),
|
||||
|
|
|
@ -13,9 +13,9 @@ import (
|
|||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/go-ole/go-ole"
|
||||
"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/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "scheduled_task"
|
||||
|
@ -148,7 +148,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
initErrCh := make(chan error)
|
||||
c.scheduledTasksReqCh = make(chan struct{})
|
||||
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 {
|
||||
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
|
||||
|
||||
return
|
||||
|
|
|
@ -11,9 +11,9 @@ import (
|
|||
"unsafe"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/svc/mgr"
|
||||
)
|
||||
|
@ -106,7 +106,7 @@ func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
|
|||
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))
|
||||
|
||||
if c.config.ServiceInclude.String() == "^(?:.*)$" && c.config.ServiceExclude.String() == "^(?:)$" {
|
||||
|
|
|
@ -7,10 +7,10 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "smb"
|
||||
|
@ -56,7 +56,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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 := func(metricName string, description string, labels ...string) *prometheus.Desc {
|
||||
return prometheus.NewDesc(
|
||||
|
|
|
@ -7,11 +7,11 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -79,7 +79,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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 := func(metricName string, description string, labels []string) *prometheus.Desc {
|
||||
return prometheus.NewDesc(
|
||||
|
|
|
@ -8,10 +8,10 @@ import (
|
|||
"regexp"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "smtp"
|
||||
|
@ -141,10 +141,10 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(logger *slog.Logger, _ *wmi.Client) 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.")
|
||||
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||
logger.Info("smtp collector is in an experimental state! Metrics for this collector have not been tested.",
|
||||
slog.String("collector", Name),
|
||||
)
|
||||
|
||||
c.badMailedMessagesBadPickupFileTotal = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "badmailed_messages_bad_pickup_file_total"),
|
||||
|
|
|
@ -7,10 +7,10 @@ import (
|
|||
"log/slog"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "system"
|
||||
|
@ -61,7 +61,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
c.contextSwitchesTotal = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "context_switches_total"),
|
||||
"Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)",
|
||||
|
|
|
@ -10,11 +10,11 @@ import (
|
|||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"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/perftypes"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
|
@ -100,7 +100,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
counters := []string{
|
||||
connectionFailures,
|
||||
connectionsActive,
|
||||
|
|
|
@ -11,10 +11,11 @@ import (
|
|||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"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"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus-community/windows_exporter/internal/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
|
@ -31,9 +32,9 @@ type Win32_ServerFeature struct {
|
|||
ID uint32
|
||||
}
|
||||
|
||||
func isConnectionBrokerServer(logger *slog.Logger, wmiClient *wmi.Client) bool {
|
||||
func isConnectionBrokerServer(logger *slog.Logger, miSession *mi.Session) bool {
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -112,10 +113,14 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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))
|
||||
|
||||
c.connectionBrokerEnabled = isConnectionBrokerServer(logger, wmiClient)
|
||||
c.connectionBrokerEnabled = isConnectionBrokerServer(logger, miSession)
|
||||
|
||||
c.sessionInfo = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "session_info"),
|
||||
|
|
|
@ -29,11 +29,11 @@ import (
|
|||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/dimchansky/utfbom"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
"github.com/prometheus/common/expfmt"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "textfile"
|
||||
|
@ -104,7 +104,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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, ","),
|
||||
slog.String("collector", Name),
|
||||
)
|
||||
|
|
|
@ -4,12 +4,13 @@ package thermalzone
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "thermalzone"
|
||||
|
@ -21,7 +22,8 @@ var ConfigDefaults = Config{}
|
|||
// A Collector is a Prometheus Collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics.
|
||||
type Collector struct {
|
||||
config Config
|
||||
wmiClient *wmi.Client
|
||||
miSession *mi.Session
|
||||
miQuery mi.Query
|
||||
|
||||
percentPassiveLimit *prometheus.Desc
|
||||
temperature *prometheus.Desc
|
||||
|
@ -56,12 +58,19 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
||||
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||
if miSession == 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(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "temperature_celsius"),
|
||||
"(Temperature)",
|
||||
|
@ -108,22 +117,20 @@ func (c *Collector) Collect(_ *types.ScrapeContext, logger *slog.Logger, ch chan
|
|||
// Win32_PerfRawData_Counters_ThermalZoneInformation docs:
|
||||
// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_thermalzoneinformation/
|
||||
type Win32_PerfRawData_Counters_ThermalZoneInformation struct {
|
||||
Name string
|
||||
|
||||
HighPrecisionTemperature uint32
|
||||
PercentPassiveLimit uint32
|
||||
ThrottleReasons uint32
|
||||
Name string `mi:"Name"`
|
||||
HighPrecisionTemperature uint32 `mi:"HighPrecisionTemperature"`
|
||||
PercentPassiveLimit uint32 `mi:"PercentPassiveLimit"`
|
||||
ThrottleReasons uint32 `mi:"ThrottleReasons"`
|
||||
}
|
||||
|
||||
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_Counters_ThermalZoneInformation
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_Counters_ThermalZoneInformation", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
// ThermalZone collector has been known to 'successfully' return an empty result.
|
||||
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 {
|
||||
|
|
|
@ -9,10 +9,10 @@ import (
|
|||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"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"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
|
@ -64,7 +64,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *wmi.Client) error {
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
c.currentTime = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "current_timestamp_seconds"),
|
||||
"OperatingSystem.LocalDateTime",
|
||||
|
|
|
@ -15,9 +15,9 @@ import (
|
|||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/go-ole/go-ole"
|
||||
"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/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
const Name = "update"
|
||||
|
@ -80,7 +80,7 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
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("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 {
|
||||
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)
|
||||
|
||||
return
|
||||
|
|
|
@ -4,13 +4,14 @@ package vmware
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"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/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
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.
|
||||
type Collector struct {
|
||||
config Config
|
||||
wmiClient *wmi.Client
|
||||
config Config
|
||||
miSession *mi.Session
|
||||
miQueryCPU mi.Query
|
||||
miQueryMem mi.Query
|
||||
|
||||
memActive *prometheus.Desc
|
||||
memBallooned *prometheus.Desc
|
||||
|
@ -74,12 +77,25 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, wmiClient *wmi.Client) error {
|
||||
if wmiClient == nil || wmiClient.SWbemServicesClient == nil {
|
||||
return errors.New("wmiClient or SWbemServicesClient is nil")
|
||||
func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
|
||||
if miSession == 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(
|
||||
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 {
|
||||
MemActiveMB uint64
|
||||
MemBalloonedMB uint64
|
||||
MemLimitMB uint64
|
||||
MemMappedMB uint64
|
||||
MemOverheadMB uint64
|
||||
MemReservationMB uint64
|
||||
MemSharedMB uint64
|
||||
MemSharedSavedMB uint64
|
||||
MemShares uint64
|
||||
MemSwappedMB uint64
|
||||
MemTargetSizeMB uint64
|
||||
MemUsedMB uint64
|
||||
MemActiveMB uint64 `mi:"MemActiveMB"`
|
||||
MemBalloonedMB uint64 `mi:"MemBalloonedMB"`
|
||||
MemLimitMB uint64 `mi:"MemLimitMB"`
|
||||
MemMappedMB uint64 `mi:"MemMappedMB"`
|
||||
MemOverheadMB uint64 `mi:"MemOverheadMB"`
|
||||
MemReservationMB uint64 `mi:"MemReservationMB"`
|
||||
MemSharedMB uint64 `mi:"MemSharedMB"`
|
||||
MemSharedSavedMB uint64 `mi:"MemSharedSavedMB"`
|
||||
MemShares uint64 `mi:"MemShares"`
|
||||
MemSwappedMB uint64 `mi:"MemSwappedMB"`
|
||||
MemTargetSizeMB uint64 `mi:"MemTargetSizeMB"`
|
||||
MemUsedMB uint64 `mi:"MemUsedMB"`
|
||||
}
|
||||
|
||||
type Win32_PerfRawData_vmGuestLib_VCPU struct {
|
||||
CpuLimitMHz uint64
|
||||
CpuReservationMHz uint64
|
||||
CpuShares uint64
|
||||
CpuStolenMs uint64
|
||||
CpuTimePercents uint64
|
||||
EffectiveVMSpeedMHz uint64
|
||||
HostProcessorSpeedMHz uint64
|
||||
CpuLimitMHz uint64 `mi:"CpuLimitMHz"`
|
||||
CpuReservationMHz uint64 `mi:"CpuReservationMHz"`
|
||||
CpuShares uint64 `mi:"CpuShares"`
|
||||
CpuStolenMs uint64 `mi:"CpuStolenMs"`
|
||||
CpuTimePercents uint64 `mi:"CpuTimePercents"`
|
||||
EffectiveVMSpeedMHz uint64 `mi:"EffectiveVMSpeedMHz"`
|
||||
HostProcessorSpeedMHz uint64 `mi:"HostProcessorSpeedMHz"`
|
||||
}
|
||||
|
||||
func (c *Collector) collectMem(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_vmGuestLib_VMem
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_vmGuestLib_VMem", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQueryMem); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
if len(dst) == 0 {
|
||||
|
@ -333,14 +349,15 @@ func (c *Collector) collectMem(ch chan<- prometheus.Metric) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// mbToBytes moved to utils package
|
||||
func mbToBytes(mb uint64) float64 {
|
||||
return float64(mb * 1024 * 1024)
|
||||
}
|
||||
|
||||
func (c *Collector) collectCpu(ch chan<- prometheus.Metric) error {
|
||||
var dst []Win32_PerfRawData_vmGuestLib_VCPU
|
||||
if err := c.wmiClient.Query("SELECT * FROM Win32_PerfRawData_vmGuestLib_VCPU", &dst); err != nil {
|
||||
return err
|
||||
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQueryCPU); err != nil {
|
||||
return fmt.Errorf("WMI query failed: %w", err)
|
||||
}
|
||||
|
||||
if len(dst) == 0 {
|
||||
|
|
|
@ -129,7 +129,7 @@ func (c *MetricsHTTPHandler) handlerFactory(logger *slog.Logger, scrapeTimeout t
|
|||
|
||||
metricCollectors = &collector.MetricCollectors{
|
||||
Collectors: filteredCollectors,
|
||||
WMIClient: c.metricCollectors.WMIClient,
|
||||
MISession: c.metricCollectors.MISession,
|
||||
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"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/pkg/collector"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
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)
|
||||
ch := make(chan prometheus.Metric, 10000)
|
||||
|
||||
wmiClient := &wmi.Client{
|
||||
AllowMissingFields: true,
|
||||
}
|
||||
wmiClient.SWbemServicesClient, err = wmi.InitializeSWbemServices(wmiClient)
|
||||
miApp, err := mi.Application_Initialize()
|
||||
require.NoError(t, err)
|
||||
|
||||
miSession, err := miApp.NewSession(nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, c.Close(logger))
|
||||
require.NoError(t, miSession.Close())
|
||||
require.NoError(t, miApp.Close())
|
||||
})
|
||||
|
||||
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)
|
||||
|
||||
|
|
|
@ -35,3 +35,11 @@ func PDHEnabled() bool {
|
|||
|
||||
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 {
|
||||
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/update"
|
||||
"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"
|
||||
"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.
|
||||
|
@ -132,9 +132,6 @@ func NewWithConfig(config Config) *MetricCollectors {
|
|||
func New(collectors Map) *MetricCollectors {
|
||||
return &MetricCollectors{
|
||||
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.
|
||||
func (c *MetricCollectors) Build(logger *slog.Logger) error {
|
||||
var err error
|
||||
|
||||
c.WMIClient.SWbemServicesClient, err = wmi.InitializeSWbemServices(c.WMIClient)
|
||||
err := c.initMI()
|
||||
if err != nil {
|
||||
return fmt.Errorf("initialize SWbemServices: %w", err)
|
||||
return fmt.Errorf("error from initialize MI: %w", err)
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
|
@ -203,7 +198,7 @@ func (c *MetricCollectors) Build(logger *slog.Logger) error {
|
|||
go func() {
|
||||
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)
|
||||
}
|
||||
}()
|
||||
|
@ -245,11 +240,42 @@ func (c *MetricCollectors) Close(logger *slog.Logger) error {
|
|||
}
|
||||
}
|
||||
|
||||
if c.WMIClient != nil && c.WMIClient.SWbemServicesClient != nil {
|
||||
if err := c.WMIClient.SWbemServicesClient.Close(); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
app, err := c.MISession.GetApplication()
|
||||
if err != nil && !errors.Is(err, mi.ErrNotInitialized) {
|
||||
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...)
|
||||
}
|
||||
|
||||
// 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"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
)
|
||||
|
||||
type MetricCollectors struct {
|
||||
Collectors Map
|
||||
WMIClient *wmi.Client
|
||||
MISession *mi.Session
|
||||
PerfCounterQuery string
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ type (
|
|||
|
||||
// Collector interface that a collector has to implement.
|
||||
type Collector interface {
|
||||
Build(logger *slog.Logger, wmiClient *wmi.Client) error
|
||||
Build(logger *slog.Logger, miSession *mi.Session) error
|
||||
// Close closes the collector
|
||||
Close(logger *slog.Logger) error
|
||||
// GetName get the name of the collector
|
||||
|
|
Loading…
Reference in New Issue