Repository: DataDog/dd-agent

Issue:
Windows CPU times can add up to > 100%
We're collecting PercentUserTime and PercentIdleTime from [Win32_PerfFormattedData_PerfOS_Processor](http://msdn.microsoft.com/en-us/library/windows/desktop/aa394271%28v=vs.85%29.aspx) which shouldn't ever add up to more than 100%, but it seems like it does.

Maybe we need to use a different metric other than PercentIdleTime?



Discussion:
![screen shot 2013-09-04 at 1 40 43 pm](https://f.cloud.github.com/assets/1970694/1084331/275e0e7a-15ac-11e3-9e70-3d4b29fddcc5.png)

We should try if this can be reproduced with psutil, and maybe use psutil to solve that issue.

At first I thought that it could be related to this issue that was on [psutil](https://code.google.com/p/psutil/issues/detail?id=392&can=1&q=windows&colspec=ID%20Summa...): (broken windows api where cpu times is sometimes decreasing) but I think that maybe we're not getting PercentUserTime correctly:

From [msdn doc](http://msdn.microsoft.com/en-us/library/windows/desktop/aa394271%28v=vs.85%29.aspx),
PercentUserTime and PercentPrivilegedTime are Percentage of non-idle processor time and we report then directly so we may have been over-reporting them ( not dividing them by PercentProcessorTime ) 

I'm a bit worried that on the docs linked PercentIdleTime is described as the 'sample interval that the **disk** was idle' but it's probably just a typo, given that the basis of the data [here](http://msdn.microsoft.com/en-us/library/windows/desktop/aa394317%28v=vs.85%29.aspx) report it as the processor Idle time.

I'll try correcting the values and see if we get better results

After checking, it seems that we're getting the points correctly because PercentUserTime and PercentPrivilegedTime always sum up to roughly PercentProcessorTime so they must be a percentage of the total time and there is no need for correction.

Reporting system.cpu.idle as `100 - PercentProcessorTime` should give better results (I build one check reporting this way and haven't seen any value getting over 100) but it still feels like it isn't a proper solution. I'll try deducing the values from PerfRawData instead to see if we can get saner results

Should we just switch to psutil to get these metrics on Windows ? How does psutil get them ?

Psutil calls another system function GetSystemTimes with which it gets kerneltime, usertime and idletime, waits, and then call this function again, which allows him to deduce the percentages of time spent in user mode, system mode and idle mode.
An issue is that we also get system.cpu.interrupt that is not available with psutil.

Update on using `100-PercentProcessorTime` instead of `PercentIdleTime`: it also gets >100 spikes

I'll check collecting the value we can with psutils and keeping the wmi solution for system.cpu.interrupt


Resolving patch:
diff --git a/checks/system/win32.py b/checks/system/win32.py
--- a/checks/system/win32.py
+++ b/checks/system/win32.py
@@ -1,5 +1,9 @@
+# project
 from checks import Check
 
+# 3rd party
+import psutil
+
 try:
     import wmi
     w = wmi.WMI()
@@ -85,10 +89,10 @@ class Cpu(Check):
     def __init__(self, logger):
         Check.__init__(self, logger)
         self.logger = logger
-        self.gauge('system.cpu.user')
-        self.gauge('system.cpu.idle')
+        self.counter('system.cpu.user')
+        self.counter('system.cpu.idle')
         self.gauge('system.cpu.interrupt')
-        self.gauge('system.cpu.system')
+        self.counter('system.cpu.system')
 
     def check(self, agentConfig):
         try:
@@ -98,21 +102,15 @@ def check(self, agentConfig):
                              ' No CPU metrics will be returned.')
             return
 
-        cpu_user = self._average_metric(cpu, 'PercentUserTime')
-        if cpu_user:
-            self.save_sample('system.cpu.user', cpu_user)
-
-        cpu_idle = self._average_metric(cpu, 'PercentIdleTime')
-        if cpu_idle:
-            self.save_sample('system.cpu.idle', cpu_idle)
-
         cpu_interrupt = self._average_metric(cpu, 'PercentInterruptTime')
         if cpu_interrupt is not None:
             self.save_sample('system.cpu.interrupt', cpu_interrupt)
 
-        cpu_privileged = self._average_metric(cpu, 'PercentPrivilegedTime')
-        if cpu_privileged is not None:
-            self.save_sample('system.cpu.system', cpu_privileged)
+        cpu_percent = psutil.cpu_times()
+
+        self.save_sample('system.cpu.user', 100 * cpu_percent.user / psutil.NUM_CPUS)
+        self.save_sample('system.cpu.idle', 100 * cpu_percent.idle / psutil.NUM_CPUS)
+        self.save_sample('system.cpu.system', 100 * cpu_percent.system/ psutil.NUM_CPUS)
 
         return self.get_metrics()
 


Test patch: