Skip to content

Instantly share code, notes, and snippets.

@saaj
Created April 26, 2020 20:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save saaj/d09ed8a5ab71bcc6e080a9566137484b to your computer and use it in GitHub Desktop.
Save saaj/d09ed8a5ab71bcc6e080a9566137484b to your computer and use it in GitHub Desktop.
Simple CPU and RSS monitor that pushes to statsd
#!/usr/bin/env python
import re
import time
import argparse
import logging
import psutil
import statsd
def find_process(pid, regex):
if pid:
try:
return psutil.Process(pid)
except psutil.NoSuchProcess:
pass
elif regex:
current_pid = psutil.Process().pid
for p in psutil.process_iter():
if regex.search(' '.join(p.cmdline())) and p.pid != current_pid:
return p
else:
raise ValueError('No pid or regex')
def main(host, prefix, interval, pid, regex):
client = statsd.StatsClient(host=host, prefix='.'.join(filter(bool, ['procmon', prefix])))
while True:
try:
proc = find_process(pid, regex)
if not proc:
logging.warning('No target process found')
time.sleep(interval)
continue
else:
logging.debug('Found process %s, collecting metrics', proc)
try:
pct = proc.cpu_percent(interval) # the call is blocking
mem = proc.memory_info().rss
except psutil.NoSuchProcess:
logging.warning('Target process was terminated during collection')
else:
client.gauge('cpu', pct)
client.gauge('rss', mem)
logging.debug('Sent CPU:%.0f%% RSS:%d', pct, mem)
except KeyboardInterrupt:
break
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Process monitor')
parser.add_argument('-p', '--pid', help='Target process pid', default=0)
parser.add_argument('-r', '--regex', help='Target process cmdline regex', default='')
parser.add_argument('-f', '--prefix', help='Statsd prefix', default='')
parser.add_argument('-s', '--host', help='Statsd host', default='localhost')
parser.add_argument('-i', '--interval', help='Collection interval in seconds', default=1)
parser.add_argument('-v', '--verbose', help='Be verbose', action='store_true', default=False)
args = parser.parse_args()
if not any([args.pid, args.regex]):
parser.error('Either PID or cmdline regex must be provided')
level = logging.DEBUG if args.verbose else logging.INFO
logging.basicConfig(level=level, format='%(asctime)s %(levelname)s %(name)s %(message)s')
main(args.host, args.prefix, float(args.interval), int(args.pid), re.compile(args.regex))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment