win32-pdh 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5243c26326dadf2f4c5f3cbdb3bfab9a531a1992bbc3b3bc438c8169add75603
4
- data.tar.gz: 599302bb34ec10951fdc9c2f260378298dff79b745575b8ac28325cbc2892997
3
+ metadata.gz: d9f57c2db43f6412bceab31740be7f3131752334ff5b9c5f1f41f634519477bd
4
+ data.tar.gz: 74ea0ab008113496543dc001d947cbe93b3751eef9fb65be219887eb88921b36
5
5
  SHA512:
6
- metadata.gz: ecd4510ff8a655d541b6af78b2a6a2b7f0d9487b1916b232479434de13fd31dbe3881b766b0f3a1e681a054decfe9aa4f1b18e5760b1c852926acbb14a59f941
7
- data.tar.gz: 0307ddac4aebe77742b783066afb96064dd7c462637136ae27159efc968be98da0ca65bc2fcdd2f454665961d269597780cbd961b6c1f7c39fde027da1e5fa97
6
+ metadata.gz: 3b569a0bf0cfe35093c065cb527dc521fc503ff40dc882e35afdbfa8ec4036da16cf5cd7ef7003609406a640f77ae97ca93367119b2105a1b890212493a7edbd
7
+ data.tar.gz: 14e6def409243a45b3e3a51dbf544f9e5df224cbb32252bd9c13920702ccd05f6029e690932eb07618f970977579b694c58cb7539a78f111ccf7482ed2a85077
@@ -104,6 +104,7 @@ module Win32
104
104
  PERF_DETAIL_WIZARD = 400
105
105
  ERROR_SUCCESS = 0x00000000
106
106
 
107
+ # Value-to-name map, for reverse lookup.
107
108
  NAMES = {
108
109
  0x00000000 => 'PDH_CSTATUS_VALID_DATA'.freeze,
109
110
  0x00000001 => 'PDH_CSTATUS_NEW_DATA'.freeze,
@@ -193,6 +194,7 @@ module Win32
193
194
  0xC0000BFE => 'PDH_QUERY_PERF_DATA_TIMEOUT'.freeze,
194
195
  }.freeze
195
196
 
197
+ # Value-to-message hash, for generating messages.
196
198
  MESSAGES = {
197
199
  0x00000000 => 'The returned data is valid.'.freeze,
198
200
  0x00000001 => 'The return data value is valid and different from the last sample.'.freeze,
@@ -5,7 +5,12 @@ require 'win32/pdh/constants'
5
5
 
6
6
  module Win32
7
7
  module Pdh
8
+ ##
9
+ # Class representing an individual counter.
10
+ #
11
+ # This won't usually be created directly, but built using Query#add_counter.
8
12
  class Counter
13
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/aa373041(v=vs.85).aspx
9
14
  class PDH_COUNTER_PATH_ELEMENTS < FFI::Struct
10
15
  layout(
11
16
  :szMachineName, :pointer,
@@ -16,6 +21,7 @@ module Win32
16
21
  :szCounterName, :pointer,
17
22
  )
18
23
  end
24
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/aa373038(v=vs.85).aspx
19
25
  class PDH_COUNTER_INFO < FFI::Struct
20
26
  layout(
21
27
  :dwLength, :uint,
@@ -33,6 +39,7 @@ module Win32
33
39
  )
34
40
  end
35
41
 
42
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/aa373050(v=vs.85).aspx
36
43
  class PDH_FMT_COUNTERVALUE_VALUE < FFI::Union
37
44
  layout(
38
45
  :longValue, :int32,
@@ -43,6 +50,7 @@ module Win32
43
50
  )
44
51
  end
45
52
 
53
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/aa373050(v=vs.85).aspx
46
54
  class PDH_FMT_COUNTERVALUE < FFI::Struct
47
55
  layout(
48
56
  :CStatus, :uint32,
@@ -52,6 +60,9 @@ module Win32
52
60
 
53
61
  attr_accessor :type, :version, :status, :scale, :default_scale, :full_path, :machine_name, :object_name, :instance_name, :instance_index, :counter_name, :explain_text
54
62
 
63
+ ##
64
+ # Initializes the counter from a query and a path. This usually won't be
65
+ # called directly, but generated from Query#add_counter
55
66
  def initialize(query:, path:)
56
67
  path = (path + "\0").encode('UTF-16LE')
57
68
  handle_pointer = FFI::MemoryPointer.new(:pointer)
@@ -66,6 +77,16 @@ module Win32
66
77
  load_info
67
78
  end
68
79
 
80
+ ##
81
+ # Remove the counter from its Query.
82
+ #
83
+ # This isn't necessary as a part of general cleanup, as closing a Query
84
+ # will also clean up all counters. This is necessary if you are doing
85
+ # long-term management that may need counters added and removed while
86
+ # running. So if you're using a Query as a one-off and it is being closed
87
+ # after use, don't bother with this. If you are keeping a single query
88
+ # open long-term, make sure you use this when necessary, otherwise you
89
+ # will leak memory.
69
90
  def remove
70
91
  # Only allow removing once
71
92
  unless @handle.nil?
@@ -105,12 +126,20 @@ module Win32
105
126
  Pdh.check_status @status
106
127
  end
107
128
 
108
- def good?
109
- @status == Constants::ERROR_SUCCESS
110
- end
129
+ private :load_info
111
130
 
131
+ ##
112
132
  # Get the PDH_FMT_COUNTERVALUE_VALUE given the format, checking status and
113
- # raising an exception if necessary
133
+ # raising an exception if necessary.
134
+ #
135
+ # Usually, you won't use this directly; you'd use #get_double, #get_long,
136
+ # or #get_large to get the formatted value without any hassle.
137
+ #
138
+ # Will raise a PdhError if the value is bad (if you've only run
139
+ # Query#collect_query_data once, but this counter requires a history to
140
+ # calculate a rate, this will raise an exception. Be careful, and
141
+ # probably wrap all calls to this in an exception block that takes into
142
+ # account the possibility of a counter failing to get a value)
114
143
  def get(format)
115
144
  value = PDH_FMT_COUNTERVALUE.new
116
145
  status = PdhFFI.PdhGetFormattedCounterValue(
@@ -125,19 +154,25 @@ module Win32
125
154
  end
126
155
 
127
156
  ##
128
- # Get value as a double
157
+ # Get value as a double.
158
+ #
159
+ # This uses #get, so read the notes in there about exception raising.
129
160
  def get_double
130
161
  get(Constants::PDH_FMT_DOUBLE)[:doubleValue]
131
162
  end
132
163
 
133
164
  ##
134
- # Get value as a 64-bit integer
165
+ # Get value as a 64-bit integer.
166
+ #
167
+ # This uses #get, so read the notes in there about exception raising.
135
168
  def get_large
136
169
  get(Constants::PDH_FMT_LARGE)[:largeValue]
137
170
  end
138
171
 
139
172
  ##
140
173
  # Get value as a 32-bit integer
174
+ #
175
+ # This uses #get, so read the notes in there about exception raising.
141
176
  def get_long
142
177
  get(Constants::PDH_FMT_LONG)[:longValue]
143
178
  end
@@ -3,6 +3,8 @@ require 'win32/pdh/counter'
3
3
 
4
4
  module Win32
5
5
  module Pdh
6
+ ##
7
+ # Class representing a Query, and holding a query handle.
6
8
  class Query
7
9
  def initialize(source=nil)
8
10
  source =
@@ -13,7 +15,7 @@ module Win32
13
15
  end
14
16
  handle_pointer = FFI::MemoryPointer.new(:pointer)
15
17
  status = PdhFFI.PdhOpenQueryW(source, FFI::Pointer::NULL, handle_pointer)
16
- raise PdhError, status unless status == Constants::ERROR_SUCCESS
18
+ Pdh.check_status status
17
19
  @handle = handle_pointer.read_pointer
18
20
  end
19
21
 
@@ -21,18 +23,20 @@ module Win32
21
23
  # Only allow closing once
22
24
  unless @handle.nil?
23
25
  status = PdhFFI.PdhCloseQuery(@handle)
24
- raise PdhError, status unless status == Constants::ERROR_SUCCESS
26
+ Pdh.check_status status
25
27
  @handle = nil
26
28
  end
27
29
  end
28
30
 
29
31
  ##
30
- # Simple query opening function. Uses the OpenQuery function and gets a
31
- # query, passes it into the block, and then closes it afterward. If no
32
- # block is given, it just returns the query, and you are responsible for
33
- # closing it. The GC will not close this for you, so you can easily leak
34
- # resources. It's strongly recommended to use the block style if at all
35
- # possible to ensure resource cleanup.
32
+ # Simple query opening function.
33
+ #
34
+ # Uses the OpenQuery function and gets a query, passes it into the block,
35
+ # and then closes it afterward. If no block is given, it just returns the
36
+ # query, and you are responsible for closing it. The GC will not close
37
+ # this for you, so you can easily leak resources. It's strongly
38
+ # recommended to use the block style if at all possible to ensure resource
39
+ # cleanup.
36
40
  def self.open(source=nil)
37
41
  query = new source
38
42
  if block_given?
@@ -46,12 +50,18 @@ module Win32
46
50
  end
47
51
  end
48
52
 
53
+ ##
54
+ # Simple wrapper around PdhIsRealTimeQuery.
55
+ #
56
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/aa372646(v=vs.85).aspx
49
57
  def real_time?
50
58
  PdhFFI.PdhIsRealTimeQuery(@handle) == :true
51
59
  end
52
60
 
53
61
  ##
54
62
  # Adds a counter to this query and return it as a Counter object.
63
+ #
64
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/aa372204(v=vs.85).aspx
55
65
  def add_counter(path)
56
66
  Counter.new(
57
67
  query: @handle,
@@ -59,6 +69,12 @@ module Win32
59
69
  )
60
70
  end
61
71
 
72
+ ##
73
+ # Calls PdhCollectQueryData. This is necessary to load counters with data
74
+ # before retreiving it.
75
+ #
76
+ # Some counters may need this called twice before they can retreive the
77
+ # data. CPU counters are obvious examples.
62
78
  def collect_query_data
63
79
  status = PdhFFI.PdhCollectQueryData(@handle)
64
80
  Pdh.check_status status
data/lib/win32/pdh.rb CHANGED
@@ -4,6 +4,9 @@ require 'ffi'
4
4
 
5
5
  module Win32
6
6
  module Pdh
7
+ ##
8
+ # Simple error subclass. Currently, this is what type all exceptions
9
+ # directly raised by this library are.
7
10
  class PdhError < StandardError
8
11
  def initialize(status)
9
12
  super("PDH error #{Constants::NAMES[status]}: #{Constants::MESSAGES[status]}")
@@ -36,6 +39,8 @@ module Win32
36
39
  array.pack('n*').force_encoding('UTF-16BE').encode('UTF-8')
37
40
  end
38
41
 
42
+ ##
43
+ # Container namespace for all Pdh functions.
39
44
  module PdhFFI
40
45
  extend FFI::Library
41
46
  ffi_lib 'Pdh.dll'
@@ -69,12 +74,14 @@ module Win32
69
74
 
70
75
  ##
71
76
  # Uses PdhEnumObjects to enumerate objects at the given target. Returns the
72
- # objects as a list.
77
+ # objects as an array of strings.
78
+ #
79
+ # PdhEnumObjects: https://msdn.microsoft.com/en-us/library/windows/desktop/aa372600(v=vs.85).aspx
73
80
  #
74
81
  # Params:
75
- # +source+:: The same as szDataSource
76
- # +machine+:: The same as szMachineName
77
- # +detail+:: Alias for dwDetailLevel, as a symbol. May be :novice, :advanced, :expert, or :wizard. Defaults to :novice.
82
+ # source:: The same as szDataSource
83
+ # machine:: The same as szMachineName
84
+ # detail:: Alias for dwDetailLevel, as a symbol. May be :novice, :advanced, :expert, or :wizard. Defaults to :novice.
78
85
  def self.enum_objects(source: nil, machine: nil, detail: :novice)
79
86
  source =
80
87
  if source.nil?
@@ -125,11 +132,15 @@ module Win32
125
132
  string.split("\0")
126
133
  end
127
134
 
135
+ ##
136
+ # Structure of instances and counters, for ::enum_object_items
128
137
  ItemEnum = Struct.new('ItemEnum', :instances, :counters)
129
138
 
130
139
  ##
131
140
  # Enumerates an object's counter and instance names. Returns an ItemEnum
132
141
  # with the results.
142
+ #
143
+ # Uses PdhEnumObjectItems: https://msdn.microsoft.com/en-us/library/windows/desktop/aa372595(v=vs.85).aspx
133
144
  def self.enum_object_items(object:, source: nil, machine: nil, detail: :novice)
134
145
  object = (object + "\0").encode('UTF-16LE')
135
146
  source =
@@ -194,6 +205,10 @@ module Win32
194
205
 
195
206
  ##
196
207
  # Expands a wildcard path into all matching counter paths.
208
+ #
209
+ # Returns a frozen array of frozen strings.
210
+ #
211
+ # Uses PdhExpandWildCardPath: https://msdn.microsoft.com/en-us/library/windows/desktop/aa372606(v=vs.85).aspx
197
212
  def self.expand_wildcards(path:, source: nil, expand_counters: true, expand_instances: true)
198
213
  path = (path + "\0").encode('UTF-16LE')
199
214
  source =
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: win32-pdh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Taylor C. Richberger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-16 00:00:00.000000000 Z
11
+ date: 2018-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi