It worked for me - although it was not so simple.
First of all, I have to make some corrections to my previous statements - just to be on the same level.
There are several virtual machines in the cloud service, each of which has either a WebRole instance or a WorkerRole instance. Thus, on one virtual machine, only one w3wp is launched or does not have w3wp at all, except for the waworkerhost process.
In my special case, it is possible to have two w3wp running on the same virtual machine. so I needed to distinguish between the two - so I demanded that I make some kind of association of instance processes.
What I wanted to register was: general CPU utilization of one VM, processor load of an instance process running on a virtual machine (w3wp, waworkerhost).
PerformanceCounter to fully load the CPU is easy and equal for each virtual machine: \ Processor (_Total) \% Processortime for webrole VM I just could not use the counter \ process (w3wp) \% processortime, because I can not be sure that it is correct w3wp (see above)
Now here's what I did: Since you have to run the performance counter monitor for each instance of the OnStart () role in WebRole.cs or WorkerRole.cs, I decided that this is the only place where I can somehow collect the necessary information.
In WorkerRole.cs, I did:
int pc = Environment.ProcessorCount; string instance = RoleEnvironment.CurrentRoleInstance.Id; SomeOtherManagementClass.StartDiagnosticMonitorService(pc, instance, Process.GetCurrentProcess());
In WebRole.cs, CurrentProcess also returns WaWorkerHost, so I had to move the above codes to global.asax WebRole. The correct process is available here.
In SomeOtherManagementClass, I put the StartDiagnosticsMonitorService, which now receives the CurrentProcess from which StartDiagnosticsMonitorService was called. (from workerrole.cs he will receive the WaWorkerHost Process and WebRoles - the w3wp process - including the PID)
public static void StartDiagnosticMonitorService(int coreCount, string currentRole, Process process) { string processName = GetProcessInstanceName(process.Id); SetCPUCoreData(coreCount, currentRole, processName, process.Id); ... instanceProcessLoadCounterName = String.Format(@"\Process({0})\% Processor Time", processName); }
GetProcessInstanceName (process.Id) is now called in each virtual machine and gets the process name for the provided process. Id This allows you to differentiate between multiple w3wps on the same virtual machine, because the returned instances are returned by w3wp, w3wp # 1, w3wp # 2, etc., unlike the processName provided by GetCurrentProcess, which is always w3wp. To do this, I changed the code I found here in stackoverflow - you can find it below:
private static string GetProcessInstanceName(int pid) { PerformanceCounterCategory cat = new PerformanceCounterCategory("Process"); string[] instances = cat.GetInstanceNames(); foreach (string instance in instances) { try { using (PerformanceCounter cnt = new PerformanceCounter("Process", "ID Process", instance, true)) { int val = (int)cnt.RawValue; if (val == pid) { return instance; } } } catch (InvalidOperationException) {
And last but not least: SetCPUCoreData (coreCount, currentRole, processName, process.Id) saves all the relevant process data in the azure storage, so it is available anywhere in the application:
private static void SetCPUCoreData(int count, string roleinstance, string processName, int processID) { string[] instances = roleinstance.Split('.'); CloudStorageAccount storageAccount = CloudStorageAccount.Parse(GetSettingValue("LoadMonitor.Connection.String")); CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient(); const string tableName = "PerformanceMonitorCoreCount"; cloudTableClient.CreateTableIfNotExist(tableName); TableServiceContext serviceContext = cloudTableClient.GetDataServiceContext(); PerformanceCounterCPUCoreEntity ent = new PerformanceCounterCPUCoreEntity(count, instances[instances.Count() - 1],processName, processID); serviceContext.AttachTo(tableName, ent); serviceContext.UpdateObject(ent); serviceContext.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate); }
PerformanceCounterCPUCoreEntity is a template for StorageTable - take a look at the azure storage API if you have any questions about this part or just ask.