win32-pdh 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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