Skip to content

Instantly share code, notes, and snippets.

@marcobazzani
Forked from saaj/HISTORY.rst
Last active December 21, 2021 08:53
Show Gist options
  • Save marcobazzani/2ac11d1b5f71b3e99219d5d38b33d0f9 to your computer and use it in GitHub Desktop.
Save marcobazzani/2ac11d1b5f71b3e99219d5d38b33d0f9 to your computer and use it in GitHub Desktop.
Simple CPU and RSS monitor that pushes to statsd
import sys
import re
import time
import argparse
import logging
import psutil
import statsd
import requests
import os
import datetime
import json
AUTH = ""
def send_metrics(metrics, endpoint):
timestamp_now_rounded = int(int(datetime.datetime.now().strftime('%s'))/10)*10
timestamp_prev_rounded = timestamp_now_rounded - 10
headers = {
'Authorization': f"Bearer {AUTH}",
'Content-Type': 'application/json',
}
for metric in metrics:
metric['time'] = timestamp_prev_rounded
response = requests.post(endpoint, headers=headers, data=json.dumps(metrics))
if response.status_code >= 400:
print(response)
print(response.content)
def find_processes(regex):
if regex:
pids = []
current_pid = psutil.Process().pid
for p in psutil.process_iter():
try:
if regex.search(' '.join(p.cmdline())) and p.pid != current_pid:
pids.append(p)
except psutil.ZombieProcess:
logging.info(f"skipping {p.name()}")
return pids
else:
raise ValueError('No regex')
def main(prefix, interval, regex, grahite):
client = statsd.StatsClient(prefix='_'.join(filter(bool, ['procmon', prefix])))
while True:
try:
procs = find_processes(regex)
if not procs:
logging.warning('No target process found')
time.sleep(interval)
continue
else:
for proc in procs:
logging.debug('Found process %s, collecting metrics', proc)
sendme = []
for proc in procs:
try:
pct = proc.cpu_percent()
mem = proc.memory_info().rss
name = proc.name().replace('.','_').replace(' ','_').replace('(','').replace(')','')
except psutil.NoSuchProcess:
logging.warning('Target process was terminated during collection')
else:
sendme.append({'name': f'cpu.{name}', 'value':pct, "interval": int(interval)})
sendme.append({'name': f'rss.{name}', 'value':mem, "interval": int(interval)})
send_metrics(sendme, grahite)
print(f".{len(procs)}.",end="")
sys.stdout.flush()
time.sleep(interval)
except KeyboardInterrupt:
break
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Process monitor')
parser.add_argument('-r', '--regex', help='Target process cmdline regex')
parser.add_argument('-f', '--prefix', help='Statsd prefix', default='')
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)
parser.add_argument('-g', '--grahite', help='Send to graphite endpoint', default='https://graphite-prod-01-eu-west-0.grafana.net/graphite/metrics')
args = parser.parse_args()
level = logging.DEBUG if args.verbose else logging.WARN
logging.basicConfig(level=level, format='%(asctime)s %(levelname)s %(name)s %(message)s')
main(args.prefix, float(args.interval), re.compile(args.regex), args.grahite)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment