2019-07-29 18:31:45 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- mode: python; indent-tabs-mode: nil; -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
|
|
diagnostics.py
|
|
|
|
|
|
|
|
Copyright 2019 by Eric Hellman
|
|
|
|
|
|
|
|
Distributable under the GNU General Public License Version 3 or newer.
|
|
|
|
|
|
|
|
"""
|
|
|
|
import json
|
|
|
|
import resource
|
|
|
|
import sys
|
2019-07-29 21:45:12 +00:00
|
|
|
from collections import Mapping, Container
|
|
|
|
from sys import getsizeof
|
2019-08-05 16:17:01 +00:00
|
|
|
import threading
|
|
|
|
|
2019-07-29 21:52:17 +00:00
|
|
|
import cherrypy
|
2019-07-29 18:31:45 +00:00
|
|
|
from cherrypy.lib.sessions import RamSession
|
2019-07-29 21:52:17 +00:00
|
|
|
from Page import Page
|
2019-07-29 18:31:45 +00:00
|
|
|
|
2019-08-05 16:17:01 +00:00
|
|
|
def thread_info():
|
|
|
|
return [t.name for t in threading.enumerate()]
|
|
|
|
|
2019-07-29 21:45:12 +00:00
|
|
|
def deep_getsizeof(o, ids):
|
|
|
|
"""Find the memory footprint of a Python object
|
|
|
|
|
|
|
|
This is a recursive function that rills down a Python object graph
|
|
|
|
like a dictionary holding nested ditionaries with lists of lists
|
|
|
|
and tuples and sets.
|
|
|
|
|
|
|
|
The sys.getsizeof function does a shallow size of only. It counts each
|
|
|
|
object inside a container as pointer only regardless of how big it
|
|
|
|
really is.
|
|
|
|
|
|
|
|
:param o: the object
|
|
|
|
:param ids:
|
|
|
|
:return:
|
|
|
|
https://github.com/the-gigi/deep/blob/master/deeper.py
|
|
|
|
"""
|
|
|
|
d = deep_getsizeof
|
|
|
|
if id(o) in ids:
|
|
|
|
return 0
|
|
|
|
|
|
|
|
r = getsizeof(o)
|
|
|
|
ids.add(id(o))
|
|
|
|
|
|
|
|
if isinstance(o, str):
|
|
|
|
return r
|
|
|
|
|
|
|
|
if isinstance(o, Mapping):
|
2019-07-31 18:48:49 +00:00
|
|
|
try:
|
|
|
|
return r + sum(d(k, ids) + d(v, ids) for k, v in list(o.items()))
|
|
|
|
except RuntimeError:
|
|
|
|
return 'error'
|
2019-07-29 21:45:12 +00:00
|
|
|
|
|
|
|
if isinstance(o, Container):
|
|
|
|
return r + sum(d(x, ids) for x in o)
|
|
|
|
|
|
|
|
return r
|
|
|
|
|
2019-07-29 18:31:45 +00:00
|
|
|
class DiagnosticsPage (Page):
|
|
|
|
""" Python health. """
|
2019-07-29 21:52:17 +00:00
|
|
|
|
|
|
|
@cherrypy.tools.json_out()
|
2019-07-29 18:31:45 +00:00
|
|
|
def index (self, **dummy_kwargs):
|
|
|
|
""" return stats. """
|
|
|
|
stats = {}
|
|
|
|
stats['sessions'] = len(RamSession.cache)
|
2019-07-29 21:45:12 +00:00
|
|
|
stats['sessions_storage'] = deep_getsizeof(RamSession.cache, set())
|
2019-07-29 18:31:45 +00:00
|
|
|
stats['allocated_blocks'] = sys.getallocatedblocks()
|
2019-07-29 21:45:12 +00:00
|
|
|
stats['rusage_self'] = resource.getrusage(resource.RUSAGE_SELF)
|
|
|
|
stats['rusage_children'] = resource.getrusage(resource.RUSAGE_CHILDREN)
|
2019-08-05 16:17:01 +00:00
|
|
|
stats['thread_info'] = thread_info()
|
2019-07-29 21:52:17 +00:00
|
|
|
return stats
|
2019-07-29 21:45:12 +00:00
|
|
|
|