diff --git a/awx/main/middleware.py b/awx/main/middleware.py index b1a03c9a38..d79eb06af9 100644 --- a/awx/main/middleware.py +++ b/awx/main/middleware.py @@ -62,6 +62,17 @@ class TimingMiddleware(threading.local, MiddlewareMixin): with open(filepath, 'w') as f: f.write('%s %s\n' % (request.method, request.get_full_path())) pstats.Stats(self.prof, stream=f).sort_stats('cumulative').print_stats() + + if settings.AWX_REQUEST_PROFILE_WITH_DOT: + from gprof2dot import main as generate_dot + raw = os.path.join(self.dest, filename) + '.raw' + pstats.Stats(self.prof).dump_stats(raw) + generate_dot([ + '-n', '2.5', '-f', 'pstats', '-o', + os.path.join( self.dest, filename).replace('.pstats', '.dot'), + raw + ]) + os.remove(raw) return filepath diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 180a447030..e86208e051 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -1208,6 +1208,19 @@ SILENCED_SYSTEM_CHECKS = ['models.E006'] # Use middleware to get request statistics AWX_REQUEST_PROFILE = False +# +# Optionally, AWX can generate DOT graphs +# (http://www.graphviz.org/doc/info/lang.html) for per-request profiling +# via gprof2dot (https://github.com/jrfonseca/gprof2dot) +# +# If you set this to True, you must `/var/lib/awx/venv/awx/bin/pip install gprof2dot` +# .dot files will be saved in `/var/log/tower/profile/` and can be converted e.g., +# +# ~ yum install graphviz +# ~ dot -o profile.png -Tpng /var/log/tower/profile/some-profile-data.dot +# +AWX_REQUEST_PROFILE_WITH_DOT = False + # Delete temporary directories created to store playbook run-time AWX_CLEANUP_PATHS = True diff --git a/requirements/requirements_dev.txt b/requirements/requirements_dev.txt index 635862432c..fa73f78c78 100644 --- a/requirements/requirements_dev.txt +++ b/requirements/requirements_dev.txt @@ -21,4 +21,5 @@ matplotlib backports.tempfile # support in unit tests for py32+ tempfile.TemporaryDirectory mockldap sdb +gprof2dot atomicwrites==1.1.5