add possibility to trace all events of gunicorn. Run gunicorn --spew .

This commit is contained in:
benoitc 2010-04-14 19:49:26 +02:00
parent 2e40f48d05
commit 3a2e3edb3e
4 changed files with 115 additions and 2 deletions

33
NOTICE
View File

@ -4,4 +4,35 @@ Gunicorn
2009,2010 (c) Paul J. Davis <paul.joseph.davis@gmail.com>
Gunicorn is released under the MIT license. See the LICENSE
file for the complete license.
file for the complete license.
gunicorn.debug
--------------
Based on eventlet.debug module under MIT license:
Unless otherwise noted, the files in Eventlet are under the following MIT license:
Copyright (c) 2005-2006, Bob Ippolito
Copyright (c) 2007-2010, Linden Research, Inc.
Copyright (c) 2008-2010, Eventlet Contributors (see Eventlet AUTHORS)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -27,6 +27,7 @@ class Config(object):
loglevel='info',
pidfile=None,
proc_name = None,
spew=False,
timeout=30,
tmp_upload_dir=None,
umask="0",

74
gunicorn/debug.py Normal file
View File

@ -0,0 +1,74 @@
# -*- coding: utf-8 -
#
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.
"""The debug module contains utilities and functions for better
debugging Gunicorn."""
import os
import sys
import linecache
import re
import inspect
__all__ = ['spew', 'unspew']
_token_spliter = re.compile('\W+')
class Spew(object):
"""
"""
def __init__(self, trace_names=None, show_values=True):
self.trace_names = trace_names
self.show_values = show_values
def __call__(self, frame, event, arg):
if event == 'line':
lineno = frame.f_lineno
if '__file__' in frame.f_globals:
filename = frame.f_globals['__file__']
if (filename.endswith('.pyc') or
filename.endswith('.pyo')):
filename = filename[:-1]
name = frame.f_globals['__name__']
line = linecache.getline(filename, lineno)
else:
name = '[unknown]'
try:
src = inspect.getsourcelines(frame)
line = src[lineno]
except IOError:
line = 'Unknown code named [%s]. VM instruction #%d' % (
frame.f_code.co_name, frame.f_lasti)
if self.trace_names is None or name in self.trace_names:
print '%s:%s: %s' % (name, lineno, line.rstrip())
if not self.show_values:
return self
details = []
tokens = _token_spliter.split(line)
for tok in tokens:
if tok in frame.f_globals:
details.append('%s=%r' % (tok, frame.f_globals[tok]))
if tok in frame.f_locals:
details.append('%s=%r' % (tok, frame.f_locals[tok]))
if details:
print "\t%s" % ' '.join(details)
return self
def spew(trace_names=None, show_values=False):
"""Install a trace hook which writes incredibly detailed logs
about what code is being executed to stdout.
"""
sys.settrace(Spew(trace_names, show_values))
def unspew():
"""Remove the trace hook installed by spew.
"""
sys.settrace(None)

View File

@ -10,6 +10,7 @@ import pkg_resources
import sys
from gunicorn.config import Config
from gunicorn.debug import spew
from gunicorn import util, __version__
LOG_LEVELS = {
@ -51,7 +52,9 @@ def options():
op.make_option('--log-file', dest='logfile',
help='Log to a file. - equals stdout. [-]'),
op.make_option('-d', '--debug', dest='debug', action="store_true",
default=False, help='Debug mode. only 1 worker.')
default=False, help='Debug mode. only 1 worker.'),
op.make_option('--spew', dest='spew', action="store_true",
default=False, help="Install a trace hook")
]
def configure_logging(opts):
@ -114,6 +117,8 @@ def main(usage, get_app):
app = get_app(parser, opts, args)
conf = Config(opts.__dict__, opts.config)
if conf['spew']:
spew()
arbiter = conf.arbiter(conf.address, conf.workers, app, config=conf,
debug=conf['debug'], pidfile=conf['pidfile'])
if conf['daemon']:
@ -149,6 +154,8 @@ def paste_server(app, global_conf=None, host="127.0.0.1", port=None,
options['default_proc_name'] = options['__file__']
conf = Config(options)
if conf['spew']:
spew()
arbiter = conf.arbiter(conf.address, conf.workers, app, debug=conf["debug"],
pidfile=conf["pidfile"], config=conf)
if conf["daemon"] :