raven.contrib.flask.Sentry的base.py函数build_msg分析

Flask中使用Sentry来捕获异常,通常只需要在flask的init.py最后加入如下代码即可


if config.SENTRY_ENABLED:

   from raven.contrib.flaskimport Sentry

   sentry = Sentry(app, dsn='https://xxxx')


我想看下每个event的数据是怎么封装的,于是找到了build_msg这个函数

raven的base.py中函数build_msg


def build_msg(self, event_type, data=None, date=None,

time_spent=None, extra=None, stack=None, public_key=None,

tags=None, fingerprint=None,**kwargs):

    """

Captures, processes and serializes an event into a dict object

The result of ``build_msg`` should be a standardized dict, with

all default values available.

"""

# create ID client-side so that it can be passed to application

    event_id= uuid.uuid4().hex

data= merge_dicts(self.context.data, data)

data.setdefault('tags', {})

data.setdefault('extra', {})

if '.' not in event_type:

        # Assume it's a builtin

        event_type= 'raven.events.%s' % event_type

handler= self.get_handler(event_type)

result= handler.capture(**kwargs)

# data (explicit) culprit takes over auto event detection

    culprit= result.pop('culprit', None)

if data.get('culprit'):

        culprit= data['culprit']

for k, vin iteritems(result):

        if knot in data:

            data[k]= v

# auto_log_stacks only applies to events that are not exceptions

# due to confusion about which stack is which and the automatic

# application of stacktrace to exception objects by Sentry

    if stackis Noneand 'exception' not in data:

        stack= self.auto_log_stacks

if stackand 'stacktrace' not in data:

        if stackis True:

            frames= iter_stack_frames()

else:

            frames= stack

stack_info= get_stack_info(

frames,

transformer=self.transform,

capture_locals=self.capture_locals,

)

data.update({

'stacktrace': stack_info,

})

if self.include_paths:

        for framein self._iter_frames(data):

            if frame.get('in_app')is not None:

                continue

            path= frame.get('module')

if not path:

                continue

            if path.startswith('raven.'):

                frame['in_app']= False

else:

                frame['in_app']= (

any(path.startswith(x)for xin self.include_paths)and

                    not any(path.startswith(x)for xin self.exclude_paths)

)

if not culprit:

        culprit= self.transaction.peek()

if not data.get('level'):

        data['level']= kwargs.get('level')or logging.ERROR

if not data.get('server_name'):

        data['server_name']= self.name

if not data.get('modules'):

        data['modules']= self.get_module_versions()

if self.releaseis not None:

        data['release']= self.release

if self.environmentis not None:

        data['environment']= self.environment

data['tags']= merge_dicts(self.tags, data['tags'], tags)

data['extra']= merge_dicts(self.extra, data['extra'], extra)

# Legacy support for site attribute

    site= data.pop('site', None)or self.site

if site:

        data['tags'].setdefault('site', site)

if culprit:

        data['culprit']= culprit

if fingerprint:

        data['fingerprint']= fingerprint

# Run the data through processors

    for processorin self.get_processors():

        data.update(processor.process(data))

if 'message' not in data:

        data['message']= kwargs.get('message', handler.to_string(data))

# tags should only be key=>u'value'

    for key, valuein iteritems(data['tags']):

        data['tags'][key]= to_unicode(value)

# print "KV", key, value, data['tags'][key]

# extra data can be any arbitrary value

    for k, vin iteritems(data['extra']):

        data['extra'][k]= self.transform(v)

# It's important date is added **after** we serialize

    data.setdefault('project', self.remote.project)

data.setdefault('timestamp', dateor datetime.utcnow())

data.setdefault('time_spent', time_spent)

data.setdefault('event_id', event_id)

data.setdefault('platform', PLATFORM_NAME)

data.setdefault('sdk', SDK_VALUE)

data.setdefault('repos', self.repos)

print "[TAGS]", data['tags'], data.keys()

print "[VALUES]", data.values()

# insert breadcrumbs

    if self.enable_breadcrumbs:

        crumbs= self.context.breadcrumbs.get_buffer()

if crumbs:

            # Make sure we send the crumbs here as "values" as we use the

# raven client internally in sentry and the alternative

# submission option of a list here is not supported by the

# internal sender.

            data.setdefault('breadcrumbs', {'values': crumbs})

return data

在代码中随便写了一个print来打印一个不存在的key来引发异常,每个event的data.values()结构有点复杂,结果如下


[None, {'values': [{ 'stacktrace': {'frames': [ {'function': 'wsgi_app', 'abs_path': '/Users/charles/workspace/jiayincloud/titans/.venv/lib/python2.7/site-packages/flask/app.py', 'pre_context': [' ctx = self.request_context(environ)', ' ctx.push()', ' error = None', ' try:', ' try:' ], 'post_context': [ ' except Exception as e:', ' error = e', ' response = self.handle_exception(e)', ' except:',                                                                         ' error = sys.exc_info()[1]' ], 'vars': {'e': "KeyError('name',)", 'start_response': '', 'self': "", 'ctx': "", 'environ': {"'HTTP_CACHE_CONTROL'": "'max-age=0'", "'HTTP_UPGRADE_INSECURE_REQUESTS'": "'1'", "'wsgi.multiprocess'": True, "'HTTP_ACCEPT_ENCODING'": "'gzip, deflate, br'", "'HTTP_ACCEPT_LANGUAGE'": "'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7'", "'HTTP_ACCEPT'": "'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8'", "'wsgi.multithread'": False, "'SCRIPT_NAME'": "''", "'QUERY_STRING'": "'code=2109d42687cc00d85129d795d5ad8ad905be5bc19533215be817f6b8c5783f31'", "'wsgi.input'": '<_io.BytesIO object at 0x10b4f20b0>', "'PATH_INFO'": "'/oauth/callback'", "'REQUEST_METHOD'": "'GET'", "'HTTP_USER_AGENT'": "'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36'", "'SERVER_PORT'": "'5000'", "'wsgi.url_scheme'": "'http'", "'REMOTE_ADDR'": "'127.0.0.1'", "'SERVER_PROTOCOL'": "'HTTP/1.1'", "'wsgi.version'": [1, 0], "'wsgi.errors'": "', mode 'w' at 0x10787f1e0>", "'SERVER_NAME'": "'127.0.0.1'", "'werkzeug.request'": "", "'wsgi.run_once'": False, "'HTTP_HOST'": "'127.0.0.1:5000'", "'HTTP_CONNECTION'": "'keep-alive'", "'HTTP_COOKIE'": "'session=eyJPQVVUSF9BRlRFUl9MT0dJTl9TRVNTSU9OX1VSTCI6Ii8ifQ.DTDDRg.oW8B4bGCRz1RWWo36GwLKctcHlw'"}, 'error': "KeyError('name',)"}, 'module': 'flask.app', 'filename': 'flask/app.py', 'lineno': 1982, 'in_app': False, 'context_line': ' response = self.full_dispatch_request()' }, {'function': 'full_dispatch_request', 'abs_path': '/Users/charles/workspace/jiayincloud/titans/.venv/lib/python2.7/site-packages/flask/app.py', 'pre_context': [' request_started.send(self)', ' rv = self.preprocess_request()', ' if rv is None:', ' rv = self.dispatch_request()', ' except Exception as e:'], 'post_context': [' return self.finalize_request(rv)', '', ' def finalize_request(self, rv, from_error_handler=False):', ' """Given the return value from a view function this finalizes', ' the request by converting it into a response and invoking the'], 'vars': {'rv': None, 'e': "KeyError('name',)", 'self': ""}, 'module': 'flask.app', 'filename': 'flask/app.py', 'lineno': 1614, 'in_app': False, 'context_line': ' rv = self.handle_user_exception(e)' }, {'function': 'handle_user_exception', 'abs_path': '/Users/charles/workspace/jiayincloud/titans/.venv/lib/python2.7/site-packages/flask/app.py', 'pre_context': [' return self.handle_http_exception(e)', '', ' handler = self._find_error_handler(e)', '', ' if handler is None:'], 'post_context': [' return handler(e)', '', ' def handle_exception(self, e):', ' """Default exception handling that kicks in when an exception', ' occurs that is not caught. In debug mode the exception will'], 'vars': {'e': "KeyError('name',)", 'self': "", 'exc_type': "", 'handler': None, 'tb': '', 'exc_value': "KeyError('name',)"}, 'module': 'flask.app', 'filename': 'flask/app.py', 'lineno': 1517, 'in_app': False, 'context_line': ' reraise(exc_type, exc_value, tb)' }, {'function': 'full_dispatch_request', 'abs_path': '/Users/charles/workspace/jiayincloud/titans/.venv/lib/python2.7/site-packages/flask/app.py', 'pre_context': [' self.try_trigger_before_first_request_functions()', ' try:', ' request_started.send(self)', ' rv = self.preprocess_request()', ' if rv is None:'], 'post_context': [' except Exception as e:', ' rv = self.handle_user_exception(e)', ' return self.finalize_request(rv)', '', ' def finalize_request(self, rv, from_error_handler=False):'], 'vars': {'rv': None, 'e': "KeyError('name',)", 'self': ""}, 'module': 'flask.app', 'filename': 'flask/app.py', 'lineno': 1612, 'in_app': False, 'context_line': ' rv = self.dispatch_request()' }, {'function': 'dispatch_request', 'abs_path': '/Users/charles/workspace/jiayincloud/titans/.venv/lib/python2.7/site-packages/flask/app.py', 'pre_context': [' # request came with the OPTIONS method, reply automatically', " if getattr(rule, 'provide_automatic_options', False) \\", " and req.method == 'OPTIONS':", ' return self.make_default_options_response()', ' # otherwise dispatch to the handler for that endpoint'], 'post_context': ['', ' def full_dispatch_request(self):', ' """Dispatches the request and on top of that performs request', ' pre and postprocessing as well as HTTP exception catching and', ' error handling.'], 'vars': {'self': "", 'req': "", 'rule': "gitlab.authorized>"}, 'module': 'flask.app', 'filename': 'flask/app.py', 'lineno': 1598, 'in_app': False, 'context_line': ' return self.view_functions[rule.endpoint](**req.view_args)' }, {'function': 'authorized', 'abs_path': '/Users/charles/workspace/jiayincloud/titans/titans/lib/oauth/gitlab.py', 'pre_context': ['', ' # 1. using requests method', ' s = requests.session()', " res = s.request('POST', config.GITLAB_OAUTH_ACCESS_TOKEN_URL, **payload)", ' auth = res.json()'], 'post_context': [' """', ' For Gitlab 8.14.5', " res: {u'access_token': u'ed1471bf5f6e3b7caae9f33f7c73a36d5d20b392c483adab7ca0161a496f8dd9', ", " u'token_type': u'bearer', ", " u'created_at': 1512534693, "], 'vars': {'res': '', 's': '',

                                                                'payload': {"'data'": {"'client_id'": "'0e96e89b7e4c84fb066039e85aa59731e7a0dae72912f25a9af5935cdfd02d95'",

                                                                                        "'scope'": "'read_user'",

                                                                                        "'redirect_uri'": "'http://127.0.0.1:5000/oauth/callback'",

                                                                                        "'grant_type'": "'authorization_code'",

                                                                                        "'client_secret'": '********',

                                                                                        "'code'": u"u'2109d42687cc00d85129d795d5ad8ad905be5bc19533215be817f6b8c5783f31'"

                                                                                      }

                                                                            },

                                                                'auth': {u"u'error'": u"u'invalid_grant'",

                                                                        u"u'error_description'": u"u'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.'"

                                                                        }

                                                                },

                                                        'module': 'titans.lib.oauth.gitlab',

                                                        'filename': 'titans/lib/oauth/gitlab.py',

                                                        'lineno': 63,

                                                        'in_app': True,

                                                        'context_line': '    print auth["name"]'

                                                        }

                                                      ]

                                          },

                            'type': 'KeyError',

                            'module': u'exceptions',

                            'value': u"'name'"

                            }

                          ]

                },

            '/oauth/callback',

            u'nuaaysdeMacBook-Pro.local',

            {'sys.argv': ("'.venv/bin/gunicorn'", "'--name=gcloud'", "'--preload'", "'--workers=4'", "'--worker-class=tornado'", "'--bind=0.0.0.0:5000'", "'--log-level=DEBUG'", "'--access-logfile=access.log'", "'--error-logfile=error.log'", "'titans:app'")

            },

            'd8516b6a7cff4261a904a816504dd0eb',

            {'python': '2.7.10'},

            {},

            40,

            {'url': u'http://127.0.0.1:5000/oauth/callback',

              'headers': {'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7', 'Accept-Encoding': 'gzip, deflate, br', 'Host': '127.0.0.1:5000', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36', 'Connection': 'keep-alive', 'Cookie': 'session=eyJPQVVUSF9BRlRFUl9MT0dJTl9TRVNTSU9OX1VSTCI6Ii8ifQ.DTDDRg.oW8B4bGCRz1RWWo36GwLKctcHlw', 'Cache-Control': 'max-age=0', 'Upgrade-Insecure-Requests': '1'},

              'env': {'SERVER_NAME': '127.0.0.1', 'SERVER_PORT': '5000', 'REMOTE_ADDR': '127.0.0.1'},

              'query_string': u'code=2109d42687cc00d85129d795d5ad8ad905be5bc19533215be817f6b8c5783f31', 'data': {}, 'method': 'GET'

            },

            '2',

            'python',

            {'ip_address': '127.0.0.1'},

            datetime.datetime(2018, 1, 5, 8, 5, 29, 750664),

            u"KeyError: 'name'",

            {},

            {'version': '6.4.0', 'name': 'raven-python'}

        ]

你可能感兴趣的:(raven.contrib.flask.Sentry的base.py函数build_msg分析)