MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Concurrent;5using System.Collections.Generic;6using System.Diagnostics;7using System.Diagnostics.CodeAnalysis;8using System.Globalization;9using System.Management.Automation.Tracing;10 11namespace System.Management.Automation.PerformanceData12{13 /// <summary>14 /// Powershell Performance Counters Manager class shall provide a mechanism15 /// for components using SYstem.Management.Automation assembly to register16 /// performance counters with Performance Counters subsystem.17 /// </summary>18 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]19 public class PSPerfCountersMgr20 {21 #region Private Members22 private static PSPerfCountersMgr s_PSPerfCountersMgrInstance;23 private ConcurrentDictionary<Guid, CounterSetInstanceBase> _CounterSetIdToInstanceMapping;24 private ConcurrentDictionary<string, Guid> _CounterSetNameToIdMapping;25 private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource();26 27 #region Constructors28 29 private PSPerfCountersMgr()30 {31 _CounterSetIdToInstanceMapping = new ConcurrentDictionary<Guid, CounterSetInstanceBase>();32 _CounterSetNameToIdMapping = new ConcurrentDictionary<string, Guid>();33 }34 35 #endregion36 37 #endregion38 39 #region Destructor40 41 /// <summary>42 /// Destructor which will trigger the cleanup of internal data structures and43 /// disposal of counter set instances.44 /// </summary>45 ~PSPerfCountersMgr()46 {47 RemoveAllCounterSets();48 }49 50 #endregion51 52 #region Public Methods53 54 /// <summary>55 /// Getter method to retrieve the singleton instance of the PSPerfCountersMgr.56 /// </summary>57 public static PSPerfCountersMgr Instance58 {59 get { return s_PSPerfCountersMgrInstance ?? (s_PSPerfCountersMgrInstance = new PSPerfCountersMgr()); }60 }61 62 /// <summary>63 /// Helper method to generate an instance name for a counter set.64 /// </summary>65 public string GetCounterSetInstanceName()66 {67 Process currentProcess = Process.GetCurrentProcess();68 string pid = string.Create(CultureInfo.InvariantCulture, $"{currentProcess.Id}");69 return pid;70 }71 72 /// <summary>73 /// Method to determine whether the counter set given by 'counterSetName' is74 /// registered with the system. If true, then counterSetId is populated.75 /// </summary>76 public bool IsCounterSetRegistered(string counterSetName, out Guid counterSetId)77 {78 counterSetId = new Guid();79 if (counterSetName == null)80 {81 ArgumentNullException argNullException = new ArgumentNullException(nameof(counterSetName));82 _tracer.TraceException(argNullException);83 return false;84 }85 86 return _CounterSetNameToIdMapping.TryGetValue(counterSetName, out counterSetId);87 }88 89 /// <summary>90 /// Method to determine whether the counter set given by 'counterSetId' is91 /// registered with the system. If true, then CounterSetInstance is populated.92 /// </summary>93 public bool IsCounterSetRegistered(Guid counterSetId, out CounterSetInstanceBase counterSetInst)94 {95 return _CounterSetIdToInstanceMapping.TryGetValue(counterSetId, out counterSetInst);96 }97 98 /// <summary>99 /// Method to register a counter set with the Performance Counters Manager.100 /// </summary>101 public bool AddCounterSetInstance(CounterSetRegistrarBase counterSetRegistrarInstance)102 {103 if (counterSetRegistrarInstance == null)104 {105 ArgumentNullException argNullException = new ArgumentNullException("counterSetRegistrarInstance");106 _tracer.TraceException(argNullException);107 return false;108 }109 110 Guid counterSetId = counterSetRegistrarInstance.CounterSetId;111 string counterSetName = counterSetRegistrarInstance.CounterSetName;112 CounterSetInstanceBase counterSetInst = null;113 114 if (this.IsCounterSetRegistered(counterSetId, out counterSetInst))115 {116 InvalidOperationException invalidOperationException = new InvalidOperationException(117 string.Format(118 CultureInfo.InvariantCulture,119 "A Counter Set Instance with id '{0}' is already registered",120 counterSetId));121 _tracer.TraceException(invalidOperationException);122 return false;123 }124 125 try126 {127 if (!string.IsNullOrWhiteSpace(counterSetName))128 {129 Guid retrievedCounterSetId;130 // verify that there doesn't exist another counter set with the same name131 if (this.IsCounterSetRegistered(counterSetName, out retrievedCounterSetId))132 {133 InvalidOperationException invalidOperationException =134 new InvalidOperationException(135 string.Format(136 CultureInfo.InvariantCulture,137 "A Counter Set Instance with name '{0}' is already registered",138 counterSetName));139 _tracer.TraceException(invalidOperationException);140 return false;141 }142 143 _CounterSetNameToIdMapping.TryAdd(counterSetName, counterSetId);144 }145 146 _CounterSetIdToInstanceMapping.TryAdd(147 counterSetId,148 counterSetRegistrarInstance.CounterSetInstance);149 }150 catch (OverflowException overflowException)151 {152 _tracer.TraceException(overflowException);153 return false;154 }155 156 return true;157 }158 159 /// <summary>160 /// If IsNumerator is true, then updates the numerator component161 /// of target counter 'counterId' in Counter Set 'counterSetId'162 /// by 'stepAmount'.163 /// Otherwise, updates the denominator component by 'stepAmount'.164 /// </summary>165 public bool UpdateCounterByValue(166 Guid counterSetId,167 int counterId,168 long stepAmount = 1,169 bool isNumerator = true)170 {171 CounterSetInstanceBase counterSetInst = null;172 if (this.IsCounterSetRegistered(counterSetId, out counterSetInst))173 {174 return counterSetInst.UpdateCounterByValue(counterId, stepAmount, isNumerator);175 }176 else177 {178 InvalidOperationException invalidOperationException =179 new InvalidOperationException(180 string.Format(181 CultureInfo.InvariantCulture,182 "No Counter Set Instance with id '{0}' is registered",183 counterSetId));184 _tracer.TraceException(invalidOperationException);185 return false;186 }187 }188 189 /// <summary>190 /// If IsNumerator is true, then updates the numerator component191 /// of target counter 'counterName' in Counter Set 'counterSetId'192 /// by 'stepAmount'.193 /// Otherwise, updates the denominator component by 'stepAmount'.194 /// </summary>195 public bool UpdateCounterByValue(196 Guid counterSetId,197 string counterName,198 long stepAmount = 1,199 bool isNumerator = true)200 {201 CounterSetInstanceBase counterSetInst = null;202 if (this.IsCounterSetRegistered(counterSetId, out counterSetInst))203 {204 return counterSetInst.UpdateCounterByValue(counterName, stepAmount, isNumerator);205 }206 else207 {208 InvalidOperationException invalidOperationException =209 new InvalidOperationException(210 string.Format(211 CultureInfo.InvariantCulture,212 "No Counter Set Instance with id '{0}' is registered",213 counterSetId));214 _tracer.TraceException(invalidOperationException);215 return false;216 }217 }218 219 /// <summary>220 /// If IsNumerator is true, then updates the numerator component221 /// of target counter 'counterId' in Counter Set 'counterSetName'222 /// by 'stepAmount'.223 /// Otherwise, updates the denominator component by 'stepAmount'.224 /// </summary>225 public bool UpdateCounterByValue(226 string counterSetName,227 int counterId,228 long stepAmount = 1,229 bool isNumerator = true)230 {231 if (counterSetName == null)232 {233 ArgumentNullException argNullException = new ArgumentNullException(nameof(counterSetName));234 _tracer.TraceException(argNullException);235 return false;236 }237 238 Guid counterSetId;239 if (this.IsCounterSetRegistered(counterSetName, out counterSetId))240 {241 CounterSetInstanceBase counterSetInst = _CounterSetIdToInstanceMapping[counterSetId];242 return counterSetInst.UpdateCounterByValue(counterId, stepAmount, isNumerator);243 }244 else245 {246 InvalidOperationException invalidOperationException =247 new InvalidOperationException(248 string.Format(249 CultureInfo.InvariantCulture,250 "No Counter Set Instance with id '{0}' is registered",251 counterSetId));252 _tracer.TraceException(invalidOperationException);253 254 return false;255 }256 }257 258 /// <summary>259 /// If IsNumerator is true, then updates the numerator component260 /// of target counter 'counterName' in Counter Set 'counterSetName'261 /// by 'stepAmount'.262 /// Otherwise, updates the denominator component by 'stepAmount'.263 /// </summary>264 public bool UpdateCounterByValue(265 string counterSetName,266 string counterName,267 long stepAmount = 1,268 bool isNumerator = true)269 {270 Guid counterSetId;271 if (counterSetName == null)272 {273 ArgumentNullException argNullException = new ArgumentNullException(nameof(counterSetName));274 _tracer.TraceException(argNullException);275 return false;276 }277 278 if (this.IsCounterSetRegistered(counterSetName, out counterSetId))279 {280 CounterSetInstanceBase counterSetInst = _CounterSetIdToInstanceMapping[counterSetId];281 return counterSetInst.UpdateCounterByValue(counterName, stepAmount, isNumerator);282 }283 else284 {285 InvalidOperationException invalidOperationException =286 new InvalidOperationException(287 string.Format(288 CultureInfo.InvariantCulture,289 "No Counter Set Instance with name {0} is registered",290 counterSetName));291 _tracer.TraceException(invalidOperationException);292 return false;293 }294 }295 296 /// <summary>297 /// If IsNumerator is true, then sets the numerator component298 /// of target counter 'counterId' in Counter Set 'counterSetId'299 /// to 'counterValue'.300 /// Otherwise, updates the denominator component to 'counterValue'.301 /// </summary>302 public bool SetCounterValue(303 Guid counterSetId,304 int counterId,305 long counterValue = 1,306 bool isNumerator = true)307 {308 CounterSetInstanceBase counterSetInst = null;309 if (this.IsCounterSetRegistered(counterSetId, out counterSetInst))310 {311 return counterSetInst.SetCounterValue(counterId, counterValue, isNumerator);312 }313 else314 {315 InvalidOperationException invalidOperationException =316 new InvalidOperationException(317 string.Format(318 CultureInfo.InvariantCulture,319 "No Counter Set Instance with id '{0}' is registered",320 counterSetId));321 _tracer.TraceException(invalidOperationException);322 return false;323 }324 }325 326 /// <summary>327 /// If IsNumerator is true, then sets the numerator component328 /// of target counter 'counterName' in Counter Set 'counterSetId'329 /// to 'counterValue'.330 /// Otherwise, updates the denominator component to 'counterValue'.331 /// </summary>332 public bool SetCounterValue(333 Guid counterSetId,334 string counterName,335 long counterValue = 1,336 bool isNumerator = true)337 {338 CounterSetInstanceBase counterSetInst = null;339 if (this.IsCounterSetRegistered(counterSetId, out counterSetInst))340 {341 return counterSetInst.SetCounterValue(counterName, counterValue, isNumerator);342 }343 else344 {345 InvalidOperationException invalidOperationException =346 new InvalidOperationException(347 string.Format(348 CultureInfo.InvariantCulture,349 "No Counter Set Instance with id '{0}' is registered",350 counterSetId));351 _tracer.TraceException(invalidOperationException);352 return false;353 }354 }355 356 /// <summary>357 /// If IsNumerator is true, then sets the numerator component358 /// of target counter 'counterId' in Counter Set 'counterSetName'359 /// to 'counterValue'.360 /// Otherwise, updates the denominator component to 'counterValue'.361 /// </summary>362 public bool SetCounterValue(363 string counterSetName,364 int counterId,365 long counterValue = 1,366 bool isNumerator = true)367 {368 if (counterSetName == null)369 {370 ArgumentNullException argNullException = new ArgumentNullException(nameof(counterSetName));371 _tracer.TraceException(argNullException);372 return false;373 }374 375 Guid counterSetId;376 if (this.IsCounterSetRegistered(counterSetName, out counterSetId))377 {378 CounterSetInstanceBase counterSetInst = _CounterSetIdToInstanceMapping[counterSetId];379 return counterSetInst.SetCounterValue(counterId, counterValue, isNumerator);380 }381 else382 {383 InvalidOperationException invalidOperationException =384 new InvalidOperationException(385 string.Format(386 CultureInfo.InvariantCulture,387 "No Counter Set Instance with name '{0}' is registered",388 counterSetName));389 _tracer.TraceException(invalidOperationException);390 return false;391 }392 }393 394 /// <summary>395 /// If IsNumerator is true, then sets the numerator component396 /// of target counter 'counterName' in Counter Set 'counterSetName'397 /// to 'counterValue'.398 /// Otherwise, updates the denominator component to 'counterValue'.399 /// </summary>400 public bool SetCounterValue(401 string counterSetName,402 string counterName,403 long counterValue = 1,404 bool isNumerator = true)405 {406 if (counterSetName == null)407 {408 ArgumentNullException argNullException = new ArgumentNullException(nameof(counterSetName));409 _tracer.TraceException(argNullException);410 return false;411 }412 413 Guid counterSetId;414 if (this.IsCounterSetRegistered(counterSetName, out counterSetId))415 {416 CounterSetInstanceBase counterSetInst = _CounterSetIdToInstanceMapping[counterSetId];417 return counterSetInst.SetCounterValue(counterName, counterValue, isNumerator);418 }419 else420 {421 InvalidOperationException invalidOperationException =422 new InvalidOperationException(423 string.Format(424 CultureInfo.InvariantCulture,425 "No Counter Set Instance with name '{0}' is registered",426 counterSetName));427 _tracer.TraceException(invalidOperationException);428 return false;429 }430 }431 432 #endregion433 434 #region Internal Methods435 436 /// <summary>437 /// NOTE: This method is provided solely for testing purposes.438 /// </summary>439 internal void RemoveAllCounterSets()440 {441 ICollection<Guid> counterSetIdKeys = _CounterSetIdToInstanceMapping.Keys;442 foreach (Guid counterSetId in counterSetIdKeys)443 {444 CounterSetInstanceBase currentCounterSetInstance = _CounterSetIdToInstanceMapping[counterSetId];445 currentCounterSetInstance.Dispose();446 }447 448 _CounterSetIdToInstanceMapping.Clear();449 _CounterSetNameToIdMapping.Clear();450 }451 452 #endregion453 }454}455 