munin-contrib/plugins/gunicorn/gunicorn_memory_status

108 lines
3.3 KiB
Python
Executable File

#!/usr/bin/env python
"""
gunicorn_status - A munin plugin for Linux to monitor the memory
usage of gunicorn processes
Copyright (C) 2012 Azavea, Inc.
Author: Andrew Jennings
Like Munin, this plugin is licensed under the GNU GPL v2 license
http://www.opensource.org/licenses/GPL-2.0
If you've put your gunicorn pid somewhere other than the
default /var/run/gunicorn.pid, you can add a section like
this to your munin-node's plugin configuration:
[gunicorn_*]
env.gunicorn_pid_path [path to your gunicorn pid]
This plugin supports the following munin configuration parameters:
#%# family=auto contrib
#%# capabilities=autoconf
"""
import sys, os, re
from subprocess import check_output
# set path to your gunicorn pid
try:
GUNICORN_PID_PATH = os.environ['gunicorn_pid_path']
except:
GUNICORN_PID_PATH = "/var/run/gunicorn.pid"
class GunicornMemoryStatus():
master_pid = ''
"""
The Gunicorn master process pid, as a string
"""
def __init__(self):
try:
self._get_master_pid()
except:
raise Exception("Couldn't read gunicorn pid information")
def print_total_memory(self):
print('total_memory.value %d' % self._get_total_memory())
def _get_master_pid(self):
master_pid_file = open(GUNICORN_PID_PATH)
self.master_pid = master_pid_file.read().rstrip()
master_pid_file.close()
return True
def _get_total_memory(self):
master = self._get_master_memory()
total = master +self. _get_worker_memory()
total_in_mb = total / 1024
return total_in_mb
def _get_master_memory(self):
master = int(check_output(
['ps', '--pid', self.master_pid, '-o', 'rss', '--no-headers']))
return master
def _get_worker_memory(self):
worker_processes = check_output(
['ps', '--ppid', self.master_pid, '-o', 'rss', '--no-headers'])
process_memory_usage = [int(rss) for rss in worker_processes.splitlines()]
worker_memory_usage = sum(process_memory_usage)
return worker_memory_usage
def print_config():
instance = None
name = os.path.basename(sys.argv[0])
if name != "gunicorn_memory_status":
for r in ("^gunicorn_(.*?)_memory_status$", "^gunicorn_memory_status_(.*?)$"):
m = re.match(r, name, re.IGNORECASE)
if m:
instance = m.group(1)
break
graph_title = "graph_title Gunicorn - Memory Usage"
if instance:
graph_title = "%s - %s" % (graph_title, instance)
print(graph_title)
print("graph_args --base 1024 -l 0")
print("graph_vlabel Megabytes")
print("graph_category appserver")
print("total_memory.label Total Memory")
if __name__ == "__main__":
if len(sys.argv) == 2 and sys.argv[1] == 'config':
print_config()
elif len(sys.argv) == 2 and sys.argv[1] == 'autoconf':
try:
open(GUNICORN_PID_PATH).close()
print("yes")
except:
print("no")
# Some docs say it'll be called with fetch, some say no arg at all
elif len(sys.argv) == 1 or (len(sys.argv) == 2 and sys.argv[1] == 'fetch'):
try:
status = GunicornMemoryStatus()
status.print_total_memory()
except:
sys.exit("Couldn't retrieve gunicorn memory usage information")