0

I'm trying to write small IIS process monitor (CPU and memory usage) which should be as light for the system as possible. All I need is IIS App Pool Name, current Memory Usage and current CPU Usage.

I've managed to do it without bigger problems using these two commands:

using (var srvman = new ServerManager())
{
    workerProcesses = srvman.WorkerProcesses;
}

and

processes = Process.GetProcesses().Where(processItem => processItem.ProcessName.Contains("w3wp") || processItem.ProcessName.Contains("php-cgi"))

The first one returns running app pools with process ID's and second one is returning process information from system (so here is where I'm getting CPU and Memory usage). Joining this two informations gives me almost what I want. The one exception is PHP apps which are running on IIS.

For PHP apps, php-cgi.exe processes are being spawned which I need to correlate to the IIS App Pool worker process. Do you have any idea how to connect php-cgi.exe processes to their w3wp.exe parents?

Here is an example of the output I would like to produce:

1x w3wp.exe for site.com is using 15MB memory
4x php-cgi.exe is using 4x 15MB = 60MB memory

I'm planning to sum this information (which in this scenario would be 75 MB of memory usage for site.com).

Mitch
  • 21,223
  • 6
  • 63
  • 86
GrZeCh
  • 2,332
  • 8
  • 29
  • 38
  • I edited your post to remove tags from the title, which is avoided in StackExchange. See http://meta.stackexchange.com/questions/19190/should-questions-include-tags-in-their-titles – Mitch Jan 12 '15 at 07:30
  • Ok. I will remember that. – GrZeCh Jan 12 '15 at 09:48

1 Answers1

1

You can get the parent process PID using a bit of P/Invoke as described by Simon Mourier. Doing so is a low cost operation and will tie the list of all php-cgi process back to their creators.

using (var srvman = new ServerManager())
{
    var procs = from worker in srvman.WorkerProcesses
                let workerProcess = Process.GetProcessById(worker.ProcessId)
                join cgi in Process.GetProcessesByName("php-cgi")
                    on workerProcess.Id equals ParentProcessUtilities.GetParentProcess(cgi.Handle).Id
                    into childProcesses
                select new
                {
                    Worker = worker,
                    WorkerProcess = workerProcess,
                    Children = childProcesses,
                    TotalMemoryUse = workerProcess.PrivateMemorySize64
                        + childProcesses.Sum(p => p.PrivateMemorySize64)
                };

    foreach (var proc in procs)
    {
        Console.WriteLine("Worker {0}:{1} using {2} total bytes", proc.Worker.AppPoolName,
            proc.Worker.ProcessId, proc.TotalMemoryUse);

        foreach (var child in proc.Children)
        {
            Console.WriteLine("\tphp-cgi process {0} using {1} bytes", child.Id, child.PrivateMemorySize64);
        }
    }
}

Output

C:\drop> phpProcessTest.exe
Worker DefaultAppPool:4396 using 61530112 total bytes
    php-cgi process 3540 using 7024640 bytes
    php-cgi process 3144 using 6389760 bytes
Community
  • 1
  • 1
Mitch
  • 21,223
  • 6
  • 63
  • 86
  • wow. That was quick. I will check it today. Can you also help me with monitoring CPU (current) usage in X (default 60) seconds interval for w3wp and their sub php-cgi processes? I was wondering if in scenario where we are checking CPU usage in 60 seconds intervals 60 seconds is 100% CPU usage and difference between TotalProcessorTime in 0 and 60 second is real application CPU usage in this time. – GrZeCh Jan 12 '15 at 09:29
  • It works but it looks like it is a little too resource consuming. I'll try to make it lighter if it is possible. Keep in mind that I'm trying to run it on system where is running about 600 w3wp processes and querying all of them is using CPU resources. – GrZeCh Jan 12 '15 at 12:34
  • I think that using one process list variable (public static Process[] processes = null;) refreshed every checking and accessing it from all parts of code has solved high usage. I'm accessing this variable from LINQ provided by you and also from ParentProcessUtilities class. – GrZeCh Jan 12 '15 at 12:46
  • @GrZeCh, Re: CPU, that will give you a CPU usage, but it will not match the one you see in Task Manager since the sampling period is so much longer. Not incorrect, just different. – Mitch Jan 12 '15 at 17:52