私はそれを機能させました-それは本当に簡単ではありませんでしたが。
まず第一に、以前の発言をいくつか訂正しなければなりません - ただ同じレベルになるために。
クラウド サービスには複数の仮想マシンがあり、それぞれが WebRole インスタンスまたは WorkerRole インスタンスをホストしています。したがって、単一の VM では、単一の w3wp のみが実行されるか、waworkerhost プロセス以外の w3wp がまったく実行されません。
私の特別なケースでは、単一の VM で 2 つの w3wp を実行する可能性があります。そのため、これら 2 つを区別する必要がありました。そのため、何らかのプロセスとインスタンスの関連付けを行う必要がありました。
私がログに記録したかったのは、単一の VM の合計 CPU 負荷、VM で実行されているインスタンス プロセスの CPU 負荷 (w3wp、waworkerhost) です。
合計 CPU 負荷の PerformanceCounter は簡単で、VM ごとに同じです: \Processor(_Total)\% Processortime for webrole VM w3wp (上記参照)
WebRole.cs または WorkerRole.cs の各ロール インスタンス OnStart() に対してパフォーマンス カウンター モニターを開始する必要があるため、これが必要な情報を収集できる唯一の場所であると考えました。
WorkerRole.cs で私がした:
int pc = Environment.ProcessorCount;
string instance = RoleEnvironment.CurrentRoleInstance.Id;
SomeOtherManagementClass.StartDiagnosticMonitorService(pc, instance, Process.GetCurrentProcess());
WebRole.cs では、 CurrentProcess も WaWorkerHost を返すため、上記のコードラインを WebRole の global.asax に移動する必要がありました。ここで正しいプロセスが利用可能です。
SomeOtherManagementClass に StartDiagnosticsMonitorService を配置しました。これは、StartDiagnosticsMonitorService が呼び出された CurrentProcess を受け取るようになりました。(workerrole.cs から WaWorkerHost プロセスを受信し、WebRoles から w3wp プロセスを受信します - 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) が各 VM で呼び出され、指定された process.Id の processName を取得するようになりました。これにより、返される instanceNames が w3wp、w3wp#1、w3wp# であるため、単一の VM で複数の w3wps を区別することができます。 2 など、常に w3wp である GetCurrentProcess によって提供される processName とは対照的です。このために、スタックオーバーフローで見つけたコードサンプルを変更しました-以下で見つけることができます:
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)
{
//this point is reached when a process terminates while iterating the processlist- this it cannot be found
}
}
return "";
}
最後になりましたが、SetCPUCoreData(coreCount, currentRole, processName, process.Id) は、プロセスのすべての関連データを Azure ストレージに保存するため、アプリケーションのどこからでも利用できます。
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 は StorageTable のテンプレートです。この部分に関して質問がある場合は、azure Storage API を調べるか、質問してください。