Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
WMICollector.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Framework_SystemPerformance_Support_WMICollector_h_
5#define _Stroika_Framework_SystemPerformance_Support_WMICollector_h_ 1
6
7#include "Stroika/Frameworks/StroikaPreComp.h"
8
9#include <memory>
10#include <optional>
11
12#if qStroika_Foundation_Common_Platform_Windows
13#include <Pdh.h>
14#else
15#error "WINDOWS REQUIRED FOR THIS MODULE"
16#endif
17
18#include "Stroika/Foundation/Containers/Mapping.h"
19#include "Stroika/Foundation/Containers/Set.h"
22
23/**
24 * \file
25 *
26 * \note Code-Status: <a href="Code-Status.md#Alpha">Alpha</a>
27 *
28 * TODO:
29 *
30 * @todo Cleanup use of AssertExternallySynchronizedMutex once we have RECURSIVE
31 * flag. (?? note AssertExternallySynchronizedMutex is recursive)
32 *
33 * @todo Support remove of counters and instances.
34 *
35 * @todo See if its possible to support other 'value' return types. Sterl thinks
36 * and there is some evidence to suppor tthis - that there should be w way to get back
37 * strings (for stuff like disk name, or process name). And the API seems to ahve some
38 * support for this, but getformattedvalue doesn't seem to support it?
39 *
40 * @todo Consider if we should support multiple objects at a time.
41 *
42 * @todo Consider use of Atom manager for tokens - as would be more efficient than strings.
43 * Would be a good place to expierment with private 'scoped' context for atom values.
44 *
45 * @todo Consider implementation based on COM calls, since Sterl believes those maybe
46 * more efficient
47 *
48 * @todo Better exception message reporting - LoadModule/FormatMEssage -
49 * see https://msdn.microsoft.com/en-us/library/windows/desktop/aa373046(v=vs.85).aspx
50 *
51 */
52
53namespace Stroika::Frameworks::SystemPerformance::Support {
54
55 using Foundation::Characters::String;
56 using Foundation::Containers::Mapping;
57 using Foundation::Containers::Set;
58 using Foundation::Time::TimePointSeconds;
59 using Foundation::Traversal::Iterable;
60
61 /**
62 * Known good WMI object names:
63 * "Processor"
64 * "PhysicalDisk"
65 * "Memory"
66 * "System"
67 * "Network Interface"
68 * "LogicalDisk"
69 *
70 * \par Example Usage
71 * WMICollector tmp { "Processor", {"_Total"}, {"% Processor Time"} };
72 * double x = tmp.GetCurrentValue ("_Total", "% Processor Time");
73 *
74 * \par Example Usage
75 * WMICollector tmp { "LogicalDisk", {"E:"}, {"% Free Space"} };
76 * double x = tmp.GetCurrentValue ("E:", "% Free Space");
77 *
78 * Use the Windows 'Performance Monitor' tool and click PerformanceMonitor and "Add Counters" to see more/list
79 */
81 public:
82 /*
83 * Special, and cannot be combined with other instances
84 */
85 static String kWildcardInstance;
86
87 public:
88 /**
89 * Instance index is not numeric.. Often value is _Total.
90 *
91 * \note the constructors may internally invoke 'collect'. (sensible for objectname/etc ctor, but less sensible
92 * for copy CTOR, but I know of know other way to clone the queries/counters). Maybe we can fix the later?
93 */
94 WMICollector (const String& objectName, const Iterable<String>& instances = {}, const Iterable<String>& counterName = {});
95 WMICollector () = delete;
96 WMICollector (const WMICollector& from);
97
98 public:
99 nonvirtual WMICollector& operator= (const WMICollector& rhs);
100
101 public:
102 /**
103 */
104 nonvirtual void Collect ();
105
106 public:
107 nonvirtual optional<TimePointSeconds> GetTimeOfLastCollection () const;
108
109 public:
110 /**
111 * Note - as a side-effect, this function also calls Collect() when its done, so that all the counters
112 * are consitent.
113 *
114 * @see AddInstancesIf
115 */
116 nonvirtual void AddInstances (const String& instance);
117 nonvirtual void AddInstances (const Iterable<String>& instances);
118
119 public:
120 /**
121 * Like AddInstancesIf, but does nothing if instance is already present, and returns true iff an addition was performed.
122 *
123 * @see AddInstances
124 */
125 nonvirtual bool AddInstancesIf (const String& instance);
126 nonvirtual bool AddInstancesIf (const Iterable<String>& instances);
127
128 public:
129 /**
130 * \note Callers may wish to call 'Collect' after adding counters, to assure all counters are collected.
131 */
132 nonvirtual void AddCounters (const String& counterName);
133 nonvirtual void AddCounters (const Iterable<String>& counterNames);
134
135 public:
136 /**
137 * Get the list of available instances for this object
138 */
140
141 public:
142 /**
143 * Get the list of available instances for this object
144 */
145 nonvirtual Set<String> GetAvailableCounters ();
146
147 public:
148 /**
149 * This will throw if there is an error capturing the given result.
150 *
151 * @see PeekCurrentValue
152 */
153 nonvirtual double GetCurrentValue (const String& instance, const String& counterName);
154
155 public:
156 /**
157 * experimental wildcard API
158 *
159 * \pre WMICollector::kWildcardInstance
160 */
161 nonvirtual Mapping<String, double> GetCurrentValues (const String& counterName);
162
163 public:
164 /**
165 * Return 'missing' if the value is not available (for any reason, including obsolete instance, or whatever)
166 *
167 * @see GetCurrentValue
168 */
169 nonvirtual optional<double> PeekCurrentValue (const String& instance, const String& counterName);
170
171 private:
172 optional<TimePointSeconds> fTimeOfLastCollection_{};
173 String fObjectName_;
174 Set<String> fCounterNames_;
175
176 private:
177 struct PerInstanceData_ {
178 String fObjectName_;
179 String fInstance_;
180 PDH_HQUERY fQuery_{}; // @todo use Synchronized<> on this as a locker
182
183 PerInstanceData_ (const String& objectName, const String& instance, const Iterable<String>& counterNames);
184 PerInstanceData_ () = delete;
185 ~PerInstanceData_ ();
186
187 void AddCounter (const String& counterName);
188 double GetCurrentValue (const String& counterName);
189 optional<double> PeekCurrentValue (const String& counterName);
190 Mapping<String, double> GetCurrentValues (const String& counterName);
191 };
192 // Note - be careful not to ever copy fInstanceData_ since uses shared_ptr and would end up with two
193 // collecters refering to the same instance handles (bad)
194 //
195 // @todo should fInstanceData use unique_ptr??
197
198 private:
199 nonvirtual void AddCounter_ (const String& counterName);
200
201 private:
202 nonvirtual void AddInstance_ (const String& instance);
203 };
204
205}
206
207/*
208 ********************************************************************************
209 ***************************** Implementation Details ***************************
210 ********************************************************************************
211 */
212#include "WMICollector.inl"
213
214#endif /*_Stroika_Framework_SystemPerformance_Support_WMICollector_h_*/
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
Definition Set.h:105
NOT a real mutex - just a debugging infrastructure support tool so in debug builds can be assured thr...
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:237
nonvirtual void AddCounters(const String &counterName)
nonvirtual optional< double > PeekCurrentValue(const String &instance, const String &counterName)
nonvirtual Mapping< String, double > GetCurrentValues(const String &counterName)
nonvirtual bool AddInstancesIf(const String &instance)
nonvirtual double GetCurrentValue(const String &instance, const String &counterName)