From 745000b108656e2f681eba0e83226457d3af5e88 Mon Sep 17 00:00:00 2001 From: Andy Wang Date: Wed, 2 May 2018 14:46:44 -0500 Subject: [PATCH] Support 'I' (TASK_IDLE) process state introduced by Linux kernel 4.14 - default behavior counts I in the same bucket as D (uninterruptible) Add --idle-state, -I option to split out TASK_IDLE processes into a .idle metric --- CHANGELOG.md | 6 +++++ bin/metrics-processes-threads-count.rb | 16 ++++++++++++- test/metrics-processes-threads-count_spec.rb | 24 ++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db6b51c..2ae4c42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ This CHANGELOG follows the format listed [here](https://github.com/sensu-plugins ## [Unreleased] +### Fixed +- metrics-processes-threads-count.rb: Backward compatible support for TASK_IDLE process state in Linux 4.14+ (@awangptc) + +### Added +- metrics-processes-threads-count.rb: Add option to separate out TASK_IDLE process into it's own metric (@awangptc) + ## [3.1.0] - 2018-05-02 ### Added diff --git a/bin/metrics-processes-threads-count.rb b/bin/metrics-processes-threads-count.rb index 01b0896..6c84797 100755 --- a/bin/metrics-processes-threads-count.rb +++ b/bin/metrics-processes-threads-count.rb @@ -58,6 +58,13 @@ class ProcessesThreadsCount < Sensu::Plugin::Metric::CLI::Graphite boolean: true, default: false + option :idle_state, + description: 'If specified, count TASK_IDLE (I) state in separate .idle metric. Note: TASK_IDLE is only available on Linux Kernels 4.14 and higher', + short: '-I', + long: '--idle-state', + boolean: true, + default: false + # Takes a value to be tested as an integer. If a new Integer instance cannot be created from it, return 1. # See the comments on get_process_threads() for why 1 is returned. def test_int(i) @@ -95,9 +102,14 @@ def count_processes_by_status(ps_table) %w[S R D T t X Z].each do |v| list_proc[v] = 0 end + list_proc['I'] = 0 if config[:idle_state] if ps_table.first.respond_to?(:state) ps_table.each do |pr| - list_proc[pr[:state]] += 1 + state = pr[:state] + if state == 'I' + state = 'D' unless config[:idle_state] + end + list_proc[state] += 1 end end list_proc @@ -131,6 +143,8 @@ def run output "#{[config[:scheme], 'dead'].join('.')} #{proc_count} #{timestamp}" when 'Z' output "#{[config[:scheme], 'zombie'].join('.')} #{proc_count} #{timestamp}" + when 'I' + output "#{[config[:scheme], 'idle'].join('.')} #{proc_count} #{timestamp}" end end end diff --git a/test/metrics-processes-threads-count_spec.rb b/test/metrics-processes-threads-count_spec.rb index c7a8eee..eb06a1d 100755 --- a/test/metrics-processes-threads-count_spec.rb +++ b/test/metrics-processes-threads-count_spec.rb @@ -45,6 +45,30 @@ ptcount = ProcessesThreadsCount.new expect(ptcount.count_threads(table)).to eq(10) end + + it 'should be able to count processes in each state - count I toward D for 4.14+ kernels' do + states = %w[S R D T t X Z I] + ps_entry = Struct.new(:state) + table = states.map { |state| ps_entry.new(state) } + ptcount = ProcessesThreadsCount.new + counts = ptcount.count_processes_by_status(table) + states.each do |state| + expect(counts[state]).to eq(2) if state == 'D' + expect(counts[state]).to be_nil if state == 'I' + end + end + + it 'should be able to count processes in each state with :idle_state enabled - count I separate' do + states = %w[S R D T t X Z I] + ps_entry = Struct.new(:state) + table = states.map { |state| ps_entry.new(state) } + ptcount = ProcessesThreadsCount.new + ptcount.config[:idle_state] = true + counts = ptcount.count_processes_by_status(table) + states.each do |state| + expect(counts[state]).to eq(1) + end + end end describe ThreadsCount, 'run' do