banshee is under active development: collectors will keep changing, and a version you publish will likely need adjustments. For stable use, wait for version 1.0.0.

Windows

banshee/windows-collection/windows/ssh/

cpu

The usage of each logical processor of a Windows, their average and the kernel time, by SSH and PowerShell

  • windows
  • ssh
  • powershell
  • cpu

by banshee1 installation2 versions

Keen 1.0.0 · 62 lines
// The processor usage of a Windows, by SSH: each logical processor and their average, and the share of
// time spent in kernel mode (privileged time), over the interval between two runs.
// Runs one PowerShell command that only reads: the raw counters of Win32_PerfRawData_PerfOS_Processor,
// whose names are English whatever the language of Windows. The raw counters, not the formatted ones: a
// formatted percentage needs two samples taken by the same process, and each run starts a new one.
// Each counter is a time in hundreds of nanoseconds since boot; Timestamp_Sys100NS is the clock they are
// read against, so the usage over the interval is exact whatever the duration of the SSH call.
need('protocol:ssh');

per('core', 'Processors');
output('cpu-busy', 'number', array('label' => 'Average usage', 'unit' => '%'));
output('privileged', 'number', array('label' => 'Kernel time', 'unit' => '%'));
output('core-busy', 'number', array('label' => 'Processor usage', 'unit' => '%', 'per' => 'core'));
output('cores', 'number', array('label' => 'Number of processors'));

watch.above('cpu-high', 'Saturation', 'cpu-busy', array('warning' => 85, 'critical' => 95, 'for' => '3 runs'));
watch.above('core-hot', 'A processor saturated', 'core-busy', array('warning' => 95, 'for' => '3 runs', 'enabled' => false));
watch.deviate('core-neglected', 'A processor left idle', 'core-busy', array('side' => 'below', 'warning' => 30, 'enabled' => false));
watch.expect('core-count', 'Unexpected number of processors', 'cores');

// One object per logical processor, Name "0", "1"..., and one for the whole, "_Total", left out here:
// the average is computed from the processors. PercentProcessorTime counts the idle time, despite its
// name; PercentPrivilegedTime the time in kernel mode.
$read = ssh.run("powershell -NoProfile -NonInteractive -Command \""
    . "ConvertTo-Json -Compress -InputObject @(Get-CimInstance Win32_PerfRawData_PerfOS_Processor"
    . " | Select-Object Name, PercentProcessorTime, PercentPrivilegedTime, Timestamp_Sys100NS)\"");
$answer = text.trim($read['output']);
if (list.count(text.match($answer, '^\[')) == 0) {
    fail('misconfigured', 'PowerShell did not return the processor counters', $answer . $read['errors']);
}

$cores = 0;
$measured = 0;
$busy_sum = 0;
$privileged_sum = 0;
foreach (json.read($answer) as $row) {
    if ($row['Name'] == '_Total') {
        continue;
    }
    $name = 'cpu' . $row['Name'];
    $cores = $cores + 1;
    $clock = counter.rate('clock', $row['Timestamp_Sys100NS'], $name);
    $idle = counter.rate('idle', $row['PercentProcessorTime'], $name);
    $kernel = counter.rate('privileged', $row['PercentPrivilegedTime'], $name);
    if ($clock == '' || $idle == '' || $kernel == '' || $clock <= 0) {
        continue;
    }
    $busy = 100 * (1 - $idle / $clock);
    $measured = $measured + 1;
    $busy_sum = $busy_sum + $busy;
    $privileged_sum = $privileged_sum + 100 * $kernel / $clock;
    value('core-busy', number.round($busy, 1), $name);
}
if ($cores == 0) {
    fail('misconfigured', 'No processor found in Win32_PerfRawData_PerfOS_Processor', $answer);
}
if ($measured < $cores) {
    skip('First reading, or a counter went backwards: usage comes with the next run');
}
value('cpu-busy', number.round($busy_sum / $cores, 1));
value('privileged', number.round($privileged_sum / $cores, 1));
value('cores', $cores);