sensu-plugins-process-checks 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e4c1e16b051ae71d9479b95387e22c504ab7a7f0
4
- data.tar.gz: 43d7d36c527666e51220a43a05c26793ea420397
3
+ metadata.gz: 2d2298603cc93f7fa246cfae47fe4abf183fbe12
4
+ data.tar.gz: 0df7445dde46ef1df869d6f35470c78b3cf00859
5
5
  SHA512:
6
- metadata.gz: 4d4cca0b109f96d84089aa5855841a9bc50e8214949c883092850c16d43ada5af4912ec5da7f7cac1915ee81fe2c9e34e46e9731f0b379d5f61c6836ed621829
7
- data.tar.gz: 512a08cd43764730059955e144f7dd3772ae9944b517a7bc5ac969ad5b07be2d6b7a8e136a73ff8693436b6e442638a34a17c758209cff2c1dd62be80164b791
6
+ metadata.gz: 19dc7d11cd249a108ef10e6e52001754f1d560d5dbdcd85566107b6d2a2479982a08b81daeec8870c3fb125f4da9f3e5f5cf1b28ab70ce657909339e26c3d480
7
+ data.tar.gz: 02e090d85944b1dda4eadb8e500f838c0ca42a84e479127632571c45666a10be5d5d253549b9cdaa613c71b9c5d1ed42c0c3e37c02852685a627fc6a18ee0040
@@ -1,11 +1,21 @@
1
1
  # Change Log
2
2
  This project adheres to [Semantic Versioning](http://semver.org/).
3
3
 
4
- This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachangelog.com/)
4
+ This CHANGELOG follows the format listed [here](https://github.com/sensu-plugins/community/blob/master/HOW_WE_CHANGELOG.md)
5
5
 
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.5.0] - 2017-10-04
10
+ ### Added
11
+ - metric-per-processes.py: Add metrics filter (@rthouvenin)
12
+
13
+ ### Changed
14
+ - updated changelog guidelines (@majormoses)
15
+
16
+ ### Fixed
17
+ - spelling in PR template (@majormoses)
18
+
9
19
  ## [2.4.0] - 2017-07-18
10
20
  ### Added
11
21
  - ruby 2.4 testing (@majormoses)
@@ -139,8 +149,9 @@ This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachang
139
149
  - built against 1.9.3, 2.0, 2.1
140
150
  - cryptographically signed
141
151
 
142
- [Unreleased]: https://github.com/sensu-plugins/sensu-plugins-process-checks/compare/2.3.0...HEAD
143
- [2.4.0]: https://github.com/sensu-plugins/sensu-plugins-process-checks/compare/2.3.0...
152
+ [Unreleased]: https://github.com/sensu-plugins/sensu-plugins-process-checks/compare/2.5.0...HEAD
153
+ [2.5.0]: https://github.com/sensu-plugins/sensu-plugins-process-checks/compare/2.4.0...2.5.0
154
+ [2.4.0]: https://github.com/sensu-plugins/sensu-plugins-process-checks/compare/2.3.0...2.4.0
144
155
  [2.3.0]: https://github.com/sensu-plugins/sensu-plugins-process-checks/compare/2.2.0...2.3.0
145
156
  [2.2.0]: https://github.com/sensu-plugins/sensu-plugins-process-checks/compare/2.1.0...2.2.0
146
157
  [2.1.0]: https://github.com/sensu-plugins/sensu-plugins-process-checks/compare/2.0.0...2.1.0
data/README.md CHANGED
@@ -26,8 +26,40 @@
26
26
 
27
27
  ## Usage
28
28
 
29
+ Check if an arbitrary process seems to be running or not. Our arbitrary process in this example is called `gutrot`.
30
+ Usage of `check-process.rb` would look something similar to the following:
31
+
32
+ $ /opt/sensu/embedded/bin/ruby /opt/sensu/embedded/bin/check-process.rb -p gutrot
33
+ CheckProcess OK: Found 3 matching processes; cmd /gutrot/
34
+
35
+ The `-p` argument is for a pattern to match against the list of running processes reported by `ps`.
36
+
37
+ Example configuration at `/etc/sensu/conf.d/check_gutrot_running.json`:
38
+
39
+ {
40
+ "checks": {
41
+ "check_gutrot_running": {
42
+ "command": "check-process.rb -p gutrot",
43
+ "standalone": true,
44
+ "interval": 60,
45
+ "handlers": ["default"]
46
+ }
47
+ }
48
+ }
49
+
50
+ The check is named `check_gutrot_running` and it runs `check-process.rb -p gutrot` every `60` seconds (interval)
51
+ then lets the `default` handler handle the result.
52
+
29
53
  ## Installation
30
54
 
31
55
  [Installation and Setup](http://sensu-plugins.io/docs/installation_instructions.html)
32
56
 
57
+ Quick install after following the steps above:
58
+
59
+ $ sensu-install process-checks
60
+
61
+ The checks will be installed at:
62
+
63
+ /opt/sensu/embedded/bin/
64
+
33
65
  ## Notes
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # USAGE:
18
18
  #
19
- # metrics-per-process.py -n <process_name> | -p <path_to_process_pid_file> [-s <graphite_scheme>]
19
+ # metrics-per-process.py -n <process_name> | -p <path_to_process_pid_file> [-s <graphite_scheme>] [-m <metrics_regexes>]
20
20
  #
21
21
  # NOTES:
22
22
  # The plugin requires to read files in the /proc file system, make sure the owner
@@ -66,6 +66,7 @@
66
66
  import os
67
67
  import optparse
68
68
  import psutil
69
+ import re
69
70
  import sys
70
71
  import time
71
72
 
@@ -89,6 +90,7 @@ TCP_CONN_STATUSES = [
89
90
  'CLOSING',
90
91
  'NONE'
91
92
  ]
93
+ MEMORY_STATS = ['rss', 'vms', 'shared', 'text', 'lib', 'data', 'dirty']
92
94
 
93
95
  def find_pids_from_name(process_name):
94
96
  '''Find process PID from name using /proc/<pids>/comm'''
@@ -107,60 +109,115 @@ def find_pids_from_name(process_name):
107
109
  pass
108
110
  return pids
109
111
 
110
- def stats_per_pid(pid):
111
- '''Gets process stats using psutil module
112
+ def additional_stats(process_handler, metrics_regexp):
113
+ stats = {}
112
114
 
113
- details at http://pythonhosted.org/psutil/#process-class'''
115
+ if metrics_regexp.match('cpu.user'):
116
+ stats['cpu.user'] = process_handler.cpu_times().user
114
117
 
115
- stats = {}
116
- process_handler = psutil.Process(pid)
118
+ if metrics_regexp.match('cpu.system'):
119
+ stats['cpu.system'] = process_handler.cpu_times().system
120
+
121
+ if metrics_regexp.match('cpu.percent'):
122
+ stats['cpu.percent'] = process_handler.cpu_percent()
123
+
124
+ if metrics_regexp.match('threads'):
125
+ stats['threads'] = process_handler.num_threads()
126
+
127
+ if metrics_regexp.match('memory.percent'):
128
+ stats['memory.percent'] = process_handler.memory_percent()
129
+
130
+ if metrics_regexp.match('fds'):
131
+ stats['fds'] = process_handler.num_fds()
132
+
133
+ if metrics_regexp.match('ctx_switches.voluntary'):
134
+ stats['ctx_switches.voluntary'] = process_handler.num_ctx_switches().voluntary
135
+
136
+ if metrics_regexp.match('ctx_switches.involuntary'):
137
+ stats['ctx_switches.involuntary'] = process_handler.num_ctx_switches().involuntary
138
+
139
+ if metrics_regexp.match('io_counters.read_count'):
140
+ stats['io_counters.read_count'] = process_handler.io_counters().read_count
141
+
142
+ if metrics_regexp.match('io_counters.write_count'):
143
+ stats['io_counters.write_count'] = process_handler.io_counters().write_count
144
+
145
+ if metrics_regexp.match('io_counters.read_bytes'):
146
+ stats['io_counters.read_bytes'] = process_handler.io_counters().read_bytes
147
+
148
+ if metrics_regexp.match('io_counters.write_bytes'):
149
+ stats['io_counters.write_bytes'] = process_handler.io_counters().write_bytes
150
+
151
+ return stats
152
+
153
+ # Memory info
154
+ def memory_stats(process_handler, metrics_regexp):
117
155
  if psutil.version_info < (4,0,0):
118
156
  process_memory_info = process_handler.memory_info_ex()
119
157
  else:
120
158
  process_memory_info = process_handler.memory_info()
121
- stats['cpu.user'] = process_handler.cpu_times().user
122
- stats['cpu.system'] = process_handler.cpu_times().system
123
- stats['cpu.percent'] = process_handler.cpu_percent()
124
- stats['threads'] = process_handler.num_threads()
125
- stats['memory.rss'] = process_memory_info.rss
126
- stats['memory.vms'] = process_memory_info.vms
127
- stats['memory.shared'] = process_memory_info.shared
128
- stats['memory.text'] = process_memory_info.text
129
- stats['memory.lib'] = process_memory_info.lib
130
- stats['memory.data'] = process_memory_info.data
131
- stats['memory.dirty'] = process_memory_info.dirty
132
- stats['memory.percent'] = process_handler.memory_percent()
133
- stats['fds'] = process_handler.num_fds()
134
- stats['ctx_switches.voluntary'] = process_handler.num_ctx_switches().voluntary
135
- stats['ctx_switches.involuntary'] = process_handler.num_ctx_switches().involuntary
136
- stats['io_counters.read_count'] = process_handler.io_counters().read_count
137
- stats['io_counters.write_count'] = process_handler.io_counters().write_count
138
- stats['io_counters.read_bytes'] = process_handler.io_counters().read_bytes
139
- stats['io_counters.write_bytes'] = process_handler.io_counters().write_bytes
140
- # TCP/UDP/Unix Socket Connections
141
- tcp_conns = process_handler.connections(kind='tcp')
159
+
160
+ stats = {}
161
+ for stat in MEMORY_STATS:
162
+ if metrics_regexp.match('memory.' + stat):
163
+ stats['memory.' + stat] = getattr(process_memory_info, stat)
164
+
165
+ return stats
166
+
167
+ # TCP/UDP/Unix Socket Connections
168
+ def connection_stats(process_handler, metrics_regexp):
169
+ tcp_stats = ['total'] + [s.lower() for s in TCP_CONN_STATUSES]
170
+ tcp_conns = None
171
+ tcp_conns_count = {}
172
+ for stat in tcp_stats:
173
+ if metrics_regexp.match('conns.tcp.' + stat):
174
+ if tcp_conns is None:
175
+ tcp_conns = process_handler.connections(kind='tcp')
176
+
177
+ stats = {}
142
178
  if tcp_conns:
143
179
  stats['conns.tcp.total'] = len(tcp_conns)
144
- tcp_conns_count = {}
145
180
  for tcp_status in TCP_CONN_STATUSES:
146
- tcp_conns_count['conns.tcp.' + tcp_status.lower()] = 0
147
- for conn in tcp_conns:
148
- if conn.status == tcp_status:
149
- tcp_conns_count['conns.tcp.' + tcp_status.lower()] = tcp_conns_count[
150
- 'conns.tcp.' + tcp_status.lower()] + 1
181
+ stat = 'conns.tcp.' + tcp_status.lower()
182
+ if metrics_regexp.match(stat):
183
+ tcp_conns_count[stat] = 0
184
+ for conn in tcp_conns:
185
+ if conn.status == tcp_status:
186
+ tcp_conns_count[stat] = tcp_conns_count[stat] + 1
151
187
  stats.update(tcp_conns_count)
152
- udp_conns = process_handler.connections(kind='udp')
153
- if udp_conns:
154
- stats['conns.udp.total'] = len(udp_conns)
155
- unix_conns = process_handler.connections(kind='unix')
156
- if unix_conns:
157
- stats['conns.unix_sockets.total'] = len(unix_conns)
188
+
189
+ if metrics_regexp.match('conns.udp.total'):
190
+ udp_conns = process_handler.connections(kind='udp')
191
+ if udp_conns:
192
+ stats['conns.udp.total'] = len(udp_conns)
193
+
194
+ if metrics_regexp.match('conns.unix_sockets.total'):
195
+ unix_conns = process_handler.connections(kind='unix')
196
+ if unix_conns:
197
+ stats['conns.unix_sockets.total'] = len(unix_conns)
198
+
199
+ return stats
200
+
201
+ def stats_per_pid(pid, metrics_regexes):
202
+ '''Gets process stats using psutil module
203
+
204
+ Returns only the stats with a name that matches one of the metrics_regexes
205
+ details at http://pythonhosted.org/psutil/#process-class'''
206
+
207
+ stats = {}
208
+ process_handler = psutil.Process(pid)
209
+
210
+ for metrics_regexp in metrics_regexes:
211
+ stats.update(memory_stats(process_handler, metrics_regexp))
212
+ stats.update(connection_stats(process_handler, metrics_regexp))
213
+ stats.update(additional_stats(process_handler, metrics_regexp))
214
+
158
215
  return stats
159
216
 
160
- def multi_pid_process_stats(pids):
217
+ def multi_pid_process_stats(pids, metrics_regexes):
161
218
  stats = {'total_processes': len(pids)}
162
219
  for pid in pids:
163
- stats = Counter(stats) + Counter(stats_per_pid(pid))
220
+ stats = Counter(stats) + Counter(stats_per_pid(pid, metrics_regexes))
164
221
  return stats
165
222
 
166
223
  def recursive_dict_sum(dictionnary):
@@ -208,6 +265,12 @@ def main():
208
265
  dest = 'graphite_scheme',
209
266
  metavar = 'GRAPHITE_SCHEME')
210
267
 
268
+ parser.add_option('-m', '--metrics-regexes',
269
+ help = 'comma-separated list of regexes used to match the metric names to collect, default to .*',
270
+ default = '.*',
271
+ dest = 'metrics_regexes',
272
+ metavar = 'METRICS_REGEXES')
273
+
211
274
  (options, args) = parser.parse_args()
212
275
 
213
276
  if options.process_name and options.process_pid_file:
@@ -218,13 +281,15 @@ def main():
218
281
  print 'A process name or a process pid file path is needed'
219
282
  sys.exit(1)
220
283
 
284
+ options.metrics_regexes = [re.compile(regex) for regex in options.metrics_regexes.split(',')]
285
+
221
286
  if options.process_name:
222
287
  pids = find_pids_from_name(options.process_name)
223
- graphite_printer(multi_pid_process_stats(pids), options.graphite_scheme)
288
+ graphite_printer(multi_pid_process_stats(pids, options.metrics_regexes), options.graphite_scheme)
224
289
 
225
290
  if options.process_pid_file:
226
291
  pid = get_pid_from_pid_file(options.process_pid_file)
227
- graphite_printer(stats_per_pid(pid), options.graphite_scheme)
292
+ graphite_printer(stats_per_pid(pid, options.metrics_regexes), options.graphite_scheme)
228
293
  #
229
294
  if __name__ == '__main__':
230
295
  main()
@@ -1,7 +1,7 @@
1
1
  module SensuPluginsProcessChecks
2
2
  module Version
3
3
  MAJOR = 2
4
- MINOR = 4
4
+ MINOR = 5
5
5
  PATCH = 0
6
6
 
7
7
  VER_STRING = [MAJOR, MINOR, PATCH].compact.join('.')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sensu-plugins-process-checks
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sensu-Plugins and contributors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-18 00:00:00.000000000 Z
11
+ date: 2017-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: english
@@ -236,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
236
236
  version: '0'
237
237
  requirements: []
238
238
  rubyforge_project:
239
- rubygems_version: 2.4.5
239
+ rubygems_version: 2.6.13
240
240
  signing_key:
241
241
  specification_version: 4
242
242
  summary: Sensu plugins for checking running processes