最终效果(邮件内容):
Message type: ERROR Location: /home/xxx/site-packages/flask_restful/__init__.py:292 Module: __init__ Function: handle_error Time: 2014-12-24 17:59:47,876 Message: Internal Error Traceback (most recent call last): File "/home/xxx/site-packages/flask/app.py", line 1475, in full_dispatch_request rv = self.dispatch_request() .... File "/home/xx/foo.py", line 81, in get raise Exception(u'a') Exception: a Locals: { 'self': <Bar object at 0x2ab4ed05d710>, 'data': <Foo 10, bar>, 'id': 10, } Request: { 'view_args': { 'id': 10, }, 'url_rule': <Rule '/api/foos/<id>' (HEAD, GET, PATCH, POST, OPTIONS, DELETE) -> foo.xapi>, 'cookies': { }, 'shallow': False, 'environ': { 'wsgi.multiprocess': True, 'SERVER_SOFTWARE': 'Werkzeug/0.9.6', 'SCRIPT_NAME': '', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/api/foos/10', 'SERVER_PROTOCOL': 'HTTP/1.1', 'QUERY_STRING': '', 'werkzeug.server.shutdown': <function shutdown_server at 0x2ab4ed05ea28>, 'CONTENT_LENGTH': '', 'HTTP_USER_AGENT': 'foo/0.8.0', 'HTTP_CONNECTION': 'keep-alive', 'SERVER_NAME': '0.0.0.0', 'REMOTE_PORT': 56413, 'wsgi.url_scheme': 'http', 'SERVER_PORT': '8900', 'werkzeug.request': <Request 'http://localhost:8000/api/foos/10' [GET]>, 'wsgi.input': <socket._fileobject object at 0x2ab4ed066050>, 'HTTP_HOST': 'localhost:8900', 'wsgi.multithread': False, 'HTTP_ACCEPT': '*/*', 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.errors': <open file '<stderr>', mode 'w' at 0x2ab4e6b811e0>, 'REMOTE_ADDR': '127.0.0.1', 'CONTENT_TYPE': '', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate', }, }
主要通过配置 logging SMTPHandler 来实现:
import inspect
from logging.handlers import SMTPHandler
from flask import request
mail_handler = SMTPHandler('127.0.0.1', 'foo@example.com',
'dev@bar.com', 'App exception')
mail_handler.setFormatter(NewFormatter('''
Message type: %(levelname)s
Location: %(pathname)s:%(lineno)d
Module: %(module)s
Function: %(funcName)s
Time: %(asctime)s
Message:
%(message)s
'''))
mail_handler.setLevel(logging.ERROR)
app.logger.addHandler(mail_handler)
class NewFormatter(logging.Formatter):
def format(self, record):
s = super(NewFormatter, self).format(record)
msg = '''
Locals:
%(locals)s
Request:
%(request)s
'''
s += msg % {
'locals': pretty_dict_to_string(inspect.trace()[-1][0].f_locals),
'request': pretty_dict_to_string(request.__dict__),
}
return s
pertty_dict_to_string 函数:
def pretty_dict_to_string(d, tab=1):
s = ['{\n']
for k, v in d.items():
if isinstance(v, dict):
v = pretty_dict_to_string(v, tab + 1)
else:
v = repr(v)
s.append('%s%r: %s,\n' % (' ' * tab, k, v))
s.append('%s}' % (' ' * (tab - 1)))
return ''.join(s)
Comments