def _add_exception_info(self, data, record): """Adds sentry interfaces Exception and Stacktrace. See http://sentry.readthedocs.org/en/latest/developer/interfaces/index.html for more information on Sentry interfaces.""" type_, value, tb = record.exc_info data[SENTRY_INTERFACES_EXCEPTION] = {"type": str(type_), "value": str(value), "module": record.module } stack = inspect.getinnerframes(tb) # This next python statement copied pretty much verbatim from # raven-python (https://github.com/getsentry/raven-python). # # raven-python is: # # Copyright (c) 2009 David Cramer and individual contributors. # All rights reserved. frames = varmap( lambda k, v: shorten( v, string_length=self.string_max_length, list_length=self.list_max_length), get_stack_info(iter_stack_frames(stack))) # end of copied code data['sentry.interfaces.Stacktrace'] = { 'frames': frames } return data
def capture(self, exc_info=None, **kwargs): new_exc_info = False if not exc_info or exc_info is True: new_exc_info = True exc_info = sys.exc_info() if not exc_info: raise ValueError("No exception found") try: exc_type, exc_value, exc_traceback = exc_info frames = varmap( lambda k, v: shorten( v, string_length=self.client.string_max_length, list_length=self.client.list_max_length ), get_stack_info( iter_traceback_frames(exc_traceback), list_max_length=self.client.list_max_length, string_max_length=self.client.string_max_length, ), ) exc_module = getattr(exc_type, "__module__", None) if exc_module: exc_module = str(exc_module) exc_type = getattr(exc_type, "__name__", "<unknown>") finally: if new_exc_info: try: del exc_info del exc_traceback except Exception, e: self.logger.exception(e)
def capture(self, exc_info=None, **kwargs): new_exc_info = False if not exc_info or exc_info is True: new_exc_info = True exc_info = sys.exc_info() if not exc_info: raise ValueError('No exception found') try: exc_type, exc_value, exc_traceback = exc_info frames = varmap(lambda k, v: shorten(v, string_length=self.client.string_max_length, list_length=self.client.list_max_length), get_stack_info(iter_traceback_frames(exc_traceback))) culprit = get_culprit(frames, self.client.include_paths, self.client.exclude_paths) exc_module = getattr(exc_type, '__module__', None) exc_type = getattr(exc_type, '__name__', '<unknown>') finally: if new_exc_info: try: del exc_info del exc_traceback except Exception, e: self.logger.exception(e)
def capture(self, exc_info=None, **kwargs): if not exc_info or exc_info is True: exc_info = sys.exc_info() if not exc_info: raise ValueError("No exception found") exc_type, exc_value, exc_traceback = exc_info try: frames = get_stack_info(iter_traceback_frames(exc_traceback), transformer=self.transform) exc_module = getattr(exc_type, "__module__", None) if exc_module: exc_module = str(exc_module) exc_type = getattr(exc_type, "__name__", "<unknown>") return { "level": logging.ERROR, "sentry.interfaces.Exception": { "value": to_unicode(exc_value), "type": str(exc_type), "module": to_unicode(exc_module), }, "sentry.interfaces.Stacktrace": {"frames": frames}, } finally: try: del exc_type, exc_value, exc_traceback except Exception as e: self.logger.exception(e)
def capture(self, exc_info=None, **kwargs): new_exc_info = False if not exc_info or exc_info is True: new_exc_info = True exc_info = sys.exc_info() try: exc_type, exc_value, exc_traceback = exc_info frames = varmap(lambda k, v: shorten(v), get_stack_info(iter_traceback_frames(exc_traceback))) culprit = get_culprit(frames, self.client.include_paths, self.client.exclude_paths) if hasattr(exc_type, '__module__'): exc_module = exc_type.__module__ exc_type = exc_type.__name__ else: exc_module = None exc_type = exc_type.__name__ finally: if new_exc_info: try: del exc_info del exc_traceback except Exception, e: self.logger.exception(e)
def trace_exception(e): try: exc_info = sys.exc_info() frames = iter_traceback_frames(exc_info[-1]) trace(type_=EventType.exception, exc=str(e), stack=get_stack_info(frames)) except Exception: pass
def metlog_call(self, *args, **kwargs): if self.kwargs is None: self.kwargs = {} str_length = self.kwargs.pop('str_length', 200) list_length = self.kwargs.pop('list_length', 50) try: result = self._fn(*args, **kwargs) return result except Exception, e: exc_info = sys.exc_info() exc_type, exc_value, exc_traceback = exc_info frames = varmap(lambda k, v: shorten(v, string_length=str_length, list_length=list_length), get_stack_info(iter_traceback_frames(exc_traceback))) culprit = get_culprit(frames) metlog_blob = {'culprit': culprit, 'frames': frames} CLIENT_WRAPPER.client.metlog('stacktrace', logger=self._fn_fq_name, fields=metlog_blob) # re-raise the exception so that callers up the call stack # have a chance to do the right thing raise
def capture(self, exc_info=None, **kwargs): if not exc_info or exc_info is True: exc_info = sys.exc_info() if not exc_info: raise ValueError('No exception found') exc_type, exc_value, exc_traceback = exc_info try: frames = get_stack_info( iter_traceback_frames(exc_traceback), transformer=self.transform) exc_module = getattr(exc_type, '__module__', None) if exc_module: exc_module = str(exc_module) exc_type = getattr(exc_type, '__name__', '<unknown>') return { 'level': kwargs.get('level', logging.ERROR), 'sentry.interfaces.Exception': { 'value': to_unicode(exc_value), 'type': str(exc_type), 'module': to_unicode(exc_module), }, 'sentry.interfaces.Stacktrace': { 'frames': frames }, } finally: try: del exc_type, exc_value, exc_traceback except Exception as e: self.logger.exception(e)
def test_bad_locals_in_frame(self): frame = Mock() frame.f_locals = Context({ 'foo': 'bar', 'biz': 'baz', }) frame.f_lineno = 1 frame.f_globals = {} frame.f_code.co_filename = __file__ frame.f_code.co_name = __name__ frames = [(frame, 1)] results = get_stack_info(frames) self.assertEquals(len(results), 1) result = results[0] assert 'vars' in result if six.PY3: expected = { "'foo'": "'bar'", "'biz'": "'baz'", } else: expected = { "u'foo'": "u'bar'", "u'biz'": "u'baz'", } assert result['vars'] == expected
def test_bad_locals_in_frame(self): frame = Mock() frame.f_locals = Context({ 'foo': 'bar', 'biz': 'baz', }) frame.f_lineno = 1 frame.f_globals = {} frame.f_code.co_filename = __file__ frame.f_code.co_name = __name__ frames = [(frame, 1)] results = get_stack_info(frames) assert len(results['frames']) == 1 result = results['frames'][0] assert 'vars' in result if PY3: expected = { "foo": "'bar'", "biz": "'baz'", } else: expected = { "foo": "u'bar'", "biz": "u'baz'", } assert result['vars'] == expected
def create_from_exception(self, exc_info=None, **kwargs): """ Creates an event from an exception. >>> try: >>> exc_info = sys.exc_info() >>> client.create_from_exception(exc_info) >>> finally: >>> del exc_info If exc_info is not provided, or is set to True, then this method will perform the ``exc_info = sys.exc_info()`` and the requisite clean-up for you. """ new_exc = False if not exc_info or exc_info is True: new_exc = True exc_info = sys.exc_info() data = kwargs.pop('data', {}) or {} try: exc_type, exc_value, exc_traceback = exc_info frames = varmap(shorten, get_stack_info(iter_traceback_frames(exc_traceback))) if hasattr(exc_type, '__class__'): exc_module = exc_type.__class__.__module__ else: exc_module = None data['__sentry__'] = {} data['__sentry__']['frames'] = frames data['__sentry__']['exception'] = [exc_module, exc_value.args] tb_message = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_traceback)) kwargs.setdefault('message', transform(force_unicode(exc_value))) return self.process( class_name=exc_type.__name__, traceback=tb_message, data=data, **kwargs ) finally: # It's important that we cleanup the frames object (specifically exc_info[2]) # to ensure that GC can happen properly. if new_exc: try: del exc_info del exc_traceback except Exception, e: logger.exception(e)
def create_from_exception(self, exc_info=None, **kwargs): """ Creates an event from an exception. >>> try: >>> exc_info = sys.exc_info() >>> client.create_from_exception(exc_info) >>> finally: >>> del exc_info """ new_exc = bool(exc_info) if not exc_info or exc_info is True: exc_info = sys.exc_info() data = kwargs.pop('data', {}) or {} try: exc_type, exc_value, exc_traceback = exc_info frames = varmap(shorten, get_stack_info(iter_traceback_frames(exc_traceback))) if hasattr(exc_type, '__class__'): exc_module = exc_type.__class__.__module__ else: exc_module = None data['__sentry__'] = {} data['__sentry__']['frames'] = frames data['__sentry__']['exception'] = [exc_module, exc_value.args] tb_message = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_traceback)) kwargs.setdefault('message', transform(force_unicode(exc_value))) return self.process( class_name=exc_type.__name__, traceback=tb_message, data=data, **kwargs ) finally: if new_exc: try: del exc_info except Exception, e: logger.exception(e)
def test_max_frames(self): frames = [] for x in xrange(10): frame = Mock() frame.f_locals = {} frame.f_lineno = None frame.f_globals = {} frame.f_code.co_filename = str(x) frame.f_code.co_name = __name__ frames.append((frame, 1)) results = get_stack_info(frames, max_frames=4) assert results['frames_omitted'] == (3, 9) assert len(results['frames']) == 4 assert results['frames'][0]['filename'] == '0' assert results['frames'][1]['filename'] == '1' assert results['frames'][2]['filename'] == '8' assert results['frames'][3]['filename'] == '9'
def test_bad_locals_in_frame(self): frame = Mock() frame.f_locals = Context({"foo": "bar", "biz": "baz"}) frame.f_lineno = 1 frame.f_globals = {} frame.f_code.co_filename = __file__ frame.f_code.co_name = __name__ frames = [(frame, 1)] results = get_stack_info(frames) assert len(results["frames"]) == 1 result = results["frames"][0] assert "vars" in result if six.PY3: expected = {"foo": "'bar'", "biz": "'baz'"} else: expected = {"foo": "u'bar'", "biz": "u'baz'"} assert result["vars"] == expected
def __init__(self, frame): self.f_globals = { "__file__": frame.f_globals.get("__file__", "__main__"), "__name__": frame.f_globals.get("__name__"), "__loader__": None, } try: from raven.utils.stacks import get_stack_info except ImportError: pass else: self.f_locals = get_stack_info([(frame, 1)])[0]['vars'] try: fl["__traceback_hide__"] = frame.f_locals["__traceback_hide__"] except KeyError: pass self.f_code = self.Code(frame.f_code) self.f_lineno = frame.f_lineno
def test_max_frames(self): frames = [] for x in range(10): frame = Mock() frame.f_locals = {} frame.f_lineno = None frame.f_globals = {} frame.f_code.co_filename = str(x) frame.f_code.co_name = __name__ frames.append((frame, 1)) results = get_stack_info(frames, max_frames=4) assert results["frames_omitted"] == (3, 9) assert len(results["frames"]) == 4 assert results["frames"][0]["filename"] == "0" assert results["frames"][1]["filename"] == "1" assert results["frames"][2]["filename"] == "8" assert results["frames"][3]["filename"] == "9"
def test_bad_locals_in_frame(self): frame = Mock() frame.f_locals = Context({"foo": "bar", "biz": "baz"}) frame.f_lineno = 1 frame.f_globals = {} frame.f_code.co_filename = __file__ frame.f_code.co_name = __name__ frames = [frame] results = get_stack_info(frames) self.assertEquals(len(results), 1) result = results[0] self.assertTrue("vars" in result) vars = result["vars"] self.assertTrue(isinstance(vars, dict)) self.assertTrue("foo" in vars) self.assertEquals(vars["foo"], "bar") self.assertTrue("biz" in vars) self.assertEquals(vars["biz"], "baz")
def test_frame_allowance(self): frames = [] for x in range(10): frame = Mock() frame.f_locals = {"k": "v"} frame.f_lineno = None frame.f_globals = {} frame.f_code.co_filename = str(x) frame.f_code.co_name = __name__ frames.append((frame, 1)) results = get_stack_info(frames, frame_allowance=4) assert len(results["frames"]) == 10 assert results["frames"][0]["filename"] == "0" assert results["frames"][1]["filename"] == "1" for idx, frame in enumerate(results["frames"][2:8]): assert frame["filename"] == str(idx + 2) assert "vars" not in frame assert results["frames"][8]["filename"] == "8" assert results["frames"][9]["filename"] == "9"
def test_frame_allowance(self): frames = [] for x in range(10): frame = Mock() frame.f_locals = {'k': 'v'} frame.f_lineno = None frame.f_globals = {} frame.f_code.co_filename = str(x) frame.f_code.co_name = __name__ frames.append((frame, 1)) results = get_stack_info(frames, frame_allowance=4) assert len(results['frames']) == 10 assert results['frames'][0]['filename'] == '0' assert results['frames'][1]['filename'] == '1' for idx, frame in enumerate(results['frames'][2:8]): assert frame['filename'] == str(idx + 2) assert 'vars' not in frame assert results['frames'][8]['filename'] == '8' assert results['frames'][9]['filename'] == '9'
def capture(self, exc_info=None, **kwargs): new_exc_info = False if not exc_info or exc_info is True: new_exc_info = True exc_info = sys.exc_info() if not exc_info: raise ValueError('No exception found') try: exc_type, exc_value, exc_traceback = exc_info frames = varmap(lambda k, v: shorten(v, string_length=self.client.string_max_length, list_length=self.client.list_max_length), get_stack_info(iter_traceback_frames(exc_traceback), list_max_length=self.client.list_max_length, string_max_length=self.client.string_max_length)) exc_module = getattr(exc_type, '__module__', None) if exc_module: exc_module = str(exc_module) exc_type = getattr(exc_type, '__name__', '<unknown>') finally: if new_exc_info: try: del exc_info del exc_traceback except Exception as e: self.logger.exception(e) return { 'level': logging.ERROR, 'sentry.interfaces.Exception': { 'value': to_unicode(exc_value), 'type': str(exc_type), 'module': exc_module, }, 'sentry.interfaces.Stacktrace': { 'frames': frames }, }
def _get_value(self, exc_type, exc_value, exc_traceback): """ Convert exception info to a value for the values list. """ stack_info = get_stack_info( iter_traceback_frames(exc_traceback), transformer=self.transform, capture_locals=self.client.capture_locals, ) exc_module = getattr(exc_type, '__module__', None) if exc_module: exc_module = str(exc_module) exc_type = getattr(exc_type, '__name__', '<unknown>') return { 'value': to_unicode(exc_value), 'type': str(exc_type), 'module': to_unicode(exc_module), 'stacktrace': stack_info, }
def metlog_exceptor(self, logger=default_str_length, msg=default_msg, str_length=default_str_length, list_length=default_list_length, exc_info=None): if exc_info is None: exc_info = sys.exc_info() exc_type, exc_value, exc_traceback = exc_info frames = varmap(lambda k, v: shorten(v, string_length=str_length, list_length=list_length), get_stack_info(iter_traceback_frames(exc_traceback))) culprit = get_culprit(frames) metlog_blob = {'culprit': culprit, 'frames': frames} self.metlog(type='stacktrace', logger=logger, fields=metlog_blob)
def test_bad_locals_in_frame(self): frame = Mock() frame.f_locals = Context({ 'foo': 'bar', 'biz': 'baz', }) frame.f_lineno = 1 frame.f_globals = {} frame.f_code.co_filename = __file__ frame.f_code.co_name = __name__ frames = [frame] results = get_stack_info(frames) self.assertEquals(len(results), 1) result = results[0] self.assertTrue('vars' in result) vars = result['vars'] self.assertTrue(isinstance(vars, dict)) self.assertTrue('foo' in vars) self.assertEquals(vars['foo'], 'bar') self.assertTrue('biz' in vars) self.assertEquals(vars['biz'], 'baz')
def _add_exception_info(self, data, record): """Adds sentry interfaces Exception and Stacktrace. See http://sentry.readthedocs.org/en/latest/developer/interfaces/index.html for more information on Sentry interfaces.""" type_, value, _ = record.exc_info data[SENTRY_INTERFACES_EXCEPTION] = {"type": str(type_), "value": str(value), "module": record.module } # This next python statement copied pretty much verbatim from # raven-python (https://github.com/getsentry/raven-python). # # raven-python is: # # Copyright (c) 2009 David Cramer and individual contributors. # All rights reserved. frames = varmap( lambda k, v: shorten( v, string_length=self.string_max_length, list_length=self.list_max_length), get_stack_info(iter_stack_frames())) # end of copied code # filter out unwanted frames.. # don't know how to do this earlier, so we just do a # post-processing step and filter out unwanted frames frames = [frame for frame in frames if frame['module'] not in self.EXCLUDE_MODULES] data['sentry.interfaces.Stacktrace'] = { 'frames': frames } return data
def build_msg(self, event_type, data=None, date=None, time_spent=None, extra=None, stack=None, public_key=None, tags=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 if data is None: data = {} if extra is None: extra = {} if not date: date = datetime.datetime.utcnow() if stack is None: stack = self.auto_log_stacks 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, v in result.iteritems(): if k not in data: data[k] = v if stack and 'sentry.interfaces.Stacktrace' not in data: if stack is True: frames = iter_stack_frames() else: frames = stack data.update({ 'sentry.interfaces.Stacktrace': { 'frames': get_stack_info(frames, list_max_length=self.list_max_length, string_max_length=self.string_max_length) }, }) if 'sentry.interfaces.Stacktrace' in data: if self.include_paths: for frame in data['sentry.interfaces.Stacktrace']['frames']: if frame.get('in_app') is not None: continue if frame.get('module') and frame.get('function'): func_name = '%s.%s' % (frame['module'], frame['module']) elif frame.get('module'): func_name = frame['module'] elif frame.get('function'): func_name = frame['function'] else: func_name = '' func_name = '%s.%s' % (frame.get('module') or '<unknown>', frame.get('function') or '<unknown>') frame['in_app'] = (any( func_name.startswith(x) for x in self.include_paths) and not any( func_name.startswith(x) for x in self.exclude_paths)) if not culprit: culprit = get_culprit( data['sentry.interfaces.Stacktrace']['frames']) 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() data['tags'] = tags or {} data.setdefault('extra', {}) data.setdefault('level', logging.ERROR) # Add extra context if self.extra: for k, v in self.extra.iteritems(): data['extra'].setdefault(k, v) for k, v in extra.iteritems(): data['extra'][k] = v if culprit: data['culprit'] = culprit if not data.get('checksum'): checksum_bits = handler.get_hash(data) else: checksum_bits = data['checksum'] if isinstance(checksum_bits, (list, tuple)): checksum = hashlib.md5() for bit in checksum_bits: checksum.update(to_string(bit)) checksum = checksum.hexdigest() else: checksum = checksum_bits data['checksum'] = checksum # Run the data through processors for processor in self.get_processors(): data.update(processor.process(data)) if 'message' not in data: data['message'] = handler.to_string(data) data.setdefault('project', self.project) # Legacy support for site attribute site = data.pop('site', None) or self.site if site: data['tags'].setdefault('site', site) # Make sure all data is coerced data = self.transform(data) # It's important date is added **after** we serialize data.update({ 'timestamp': date, 'time_spent': time_spent, 'event_id': event_id, 'platform': PLATFORM_NAME, }) return data
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, v in iteritems(result): if k not 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 stack is None and 'exception' not in data: stack = self.auto_log_stacks if stack and 'stacktrace' not in data: if stack is 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 frame in 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 x in self.include_paths) and not any(path.startswith(x) for x in self.exclude_paths) ) if not culprit: if 'stacktrace' in data: culprit = get_culprit(data['stacktrace']['frames']) elif 'exception' in data: stacktrace = data['exception']['values'][0].get('stacktrace') if stacktrace: culprit = get_culprit(stacktrace['frames']) 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.release is not None: data['release'] = self.release if self.environment is 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 processor in 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, value in iteritems(data['tags']): data['tags'][key] = to_unicode(value) # extra data can be any arbitrary value for k, v in 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', date or datetime.utcnow()) data.setdefault('time_spent', time_spent) data.setdefault('event_id', event_id) data.setdefault('platform', PLATFORM_NAME) return data
def build_msg(self, event_type, data=None, date=None, time_spent=None, extra=None, stack=None, public_key=None, tags=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 if data is None: data = {} if extra is None: extra = {} if not date: date = datetime.datetime.utcnow() if stack is None: stack = self.auto_log_stacks 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, v in result.iteritems(): if k not in data: data[k] = v if stack and 'sentry.interfaces.Stacktrace' not in data: if stack is True: frames = iter_stack_frames() else: frames = stack data.update({ 'sentry.interfaces.Stacktrace': { 'frames': get_stack_info(frames, list_max_length=self.list_max_length, string_max_length=self.string_max_length) }, }) if 'sentry.interfaces.Stacktrace' in data: if self.include_paths: for frame in data['sentry.interfaces.Stacktrace']['frames']: 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 x in self.include_paths) and not any(path.startswith(x) for x in self.exclude_paths)) if not culprit: culprit = get_culprit(data['sentry.interfaces.Stacktrace']['frames']) 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() data['tags'] = tags or {} data.setdefault('extra', {}) data.setdefault('level', logging.ERROR) # Add extra context if self.extra: for k, v in self.extra.iteritems(): data['extra'].setdefault(k, v) for k, v in extra.iteritems(): data['extra'][k] = v if culprit: data['culprit'] = culprit if not data.get('checksum'): checksum_bits = handler.get_hash(data) else: checksum_bits = data['checksum'] if isinstance(checksum_bits, (list, tuple)): checksum = hashlib.md5() for bit in checksum_bits: checksum.update(to_string(bit)) checksum = checksum.hexdigest() else: checksum = checksum_bits data['checksum'] = checksum # Run the data through processors for processor in self.get_processors(): data.update(processor.process(data)) if 'message' not in data: data['message'] = handler.to_string(data) data.setdefault('project', self.project) # Legacy support for site attribute site = data.pop('site', None) or self.site if site: data['tags'].setdefault('site', site) # Make sure all data is coerced data = self.transform(data) # It's important date is added **after** we serialize data.update({ 'timestamp': date, 'time_spent': time_spent, 'event_id': event_id, 'platform': PLATFORM_NAME, }) return data
def capture(self, event_type, data=None, date=None, time_spent=None, event_id=None, extra=None, stack=None, **kwargs): """ Captures and processes an event and pipes it off to SentryClient.send. To use structured data (interfaces) with capture: >>> capture('Message', message='foo', data={ >>> 'sentry.interfaces.Http': { >>> 'url': '...', >>> 'data': {}, >>> 'query_string': '...', >>> 'method': 'POST', >>> }, >>> 'logger': 'logger.name', >>> 'site': 'site.name', >>> }, extra={ >>> 'key': 'value', >>> }) The finalized ``data`` structure contains the following (some optional) builtin values: >>> { >>> # the culprit and version information >>> 'culprit': 'full.module.name', # or /arbitrary/path >>> >>> # all detectable installed modules >>> 'modules': { >>> 'full.module.name': 'version string', >>> }, >>> >>> # arbitrary data provided by user >>> 'extra': { >>> 'key': 'value', >>> } >>> } :param event_type: the module path to the Event class. Builtins can use shorthand class notation and exclude the full module path. :param tags: a list of tuples (key, value) specifying additional tags for event :param data: the data base, useful for specifying structured data interfaces. Any key which contains a '.' will be assumed to be a data interface. :param date: the datetime of this event :param time_spent: a float value representing the duration of the event :param event_id: a 32-length unique string identifying this event :param extra: a dictionary of additional standard metadata :param culprit: a string representing the cause of this event (generally a path to a function) :return: a 32-length string identifying this event """ if data is None: data = {} if extra is None: extra = {} if date is None: date = datetime.datetime.utcnow() if stack is None: stack = self.auto_log_stacks 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, v in result.iteritems(): if k not in data: data[k] = v else: data[k].update(v) if stack and 'sentry.interfaces.Stacktrace' not in data: if stack is True: frames = iter_stack_frames() else: frames = stack data.update({ 'sentry.interfaces.Stacktrace': { 'frames': varmap(lambda k, v: shorten(v), get_stack_info(frames)) }, }) if 'sentry.interfaces.Stacktrace' in data and not culprit: culprit = get_culprit(data['sentry.interfaces.Stacktrace']['frames'], self.include_paths, self.exclude_paths) if not data.get('level'): data['level'] = logging.ERROR data['modules'] = get_versions(self.include_paths) data['server_name'] = self.name data.setdefault('extra', {}) data.setdefault('level', logging.ERROR) # Shorten lists/strings for k, v in extra.iteritems(): data['extra'][k] = shorten(v, string_length=self.string_max_length, list_length=self.list_max_length) if culprit: data['culprit'] = culprit checksum = hashlib.md5() for bit in handler.get_hash(data): checksum.update(to_unicode(bit) or '') data['checksum'] = checksum = checksum.hexdigest() # create ID client-side so that it can be passed to application event_id = uuid.uuid4().hex data['event_id'] = event_id # Run the data through processors for processor in self.get_processors(): data.update(processor.process(data)) # Make sure all data is coerced data = transform(data) if not date: date = datetime.datetime.utcnow() data['message'] = handler.to_string(data) data.update({ 'timestamp': date, 'time_spent': time_spent, 'event_id': event_id, 'project': self.project, }) self.send(**data) return (event_id, checksum)
def capture(self, event_type, data=None, date=None, time_spent=None, event_id=None, extra=None, stack=None, **kwargs): """ Captures and processes an event and pipes it off to SentryClient.send. To use structured data (interfaces) with capture: >>> capture('Message', message='foo', data={ >>> 'sentry.interfaces.Http': { >>> 'url': '...', >>> 'data': {}, >>> 'query_string': '...', >>> 'method': 'POST', >>> }, >>> 'logger': 'logger.name', >>> 'site': 'site.name', >>> }, extra={ >>> 'key': 'value', >>> }) The finalized ``data`` structure contains the following (some optional) builtin values: >>> { >>> # the culprit and version information >>> 'culprit': 'full.module.name', # or /arbitrary/path >>> >>> # all detectable installed modules >>> 'modules': { >>> 'full.module.name': 'version string', >>> }, >>> >>> # arbitrary data provided by user >>> 'extra': { >>> 'key': 'value', >>> } >>> } :param event_type: the module path to the Event class. Builtins can use shorthand class notation and exclude the full module path. :param data: the data base, useful for specifying structured data interfaces. Any key which contains a '.' will be assumed to be a data interface. :param date: the datetime of this event :param time_spent: a float value representing the duration of the event :param event_id: a 32-length unique string identifying this event :param extra: a dictionary of additional standard metadata :param culprit: a string representing the cause of this event (generally a path to a function) :return: a 32-length string identifying this event """ if data is None: data = {} if extra is None: extra = {} if not date: date = datetime.datetime.utcnow() if stack is None: stack = self.auto_log_stacks 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, v in result.iteritems(): if k not in data: data[k] = v if stack and 'sentry.interfaces.Stacktrace' not in data: if stack is True: frames = iter_stack_frames() else: frames = stack data.update({ 'sentry.interfaces.Stacktrace': { 'frames': varmap(lambda k, v: shorten(v, string_length=self.string_max_length, list_length=self.list_max_length), get_stack_info(frames)) }, }) if 'sentry.interfaces.Stacktrace' in data and not culprit: culprit = get_culprit(data['sentry.interfaces.Stacktrace']['frames'], self.include_paths, self.exclude_paths) if not data.get('level'): data['level'] = logging.ERROR data['modules'] = get_versions(self.include_paths) data['server_name'] = self.name data.setdefault('extra', {}) data.setdefault('level', logging.ERROR) # Shorten lists/strings for k, v in extra.iteritems(): data['extra'][k] = shorten(v, string_length=self.string_max_length, list_length=self.list_max_length) if culprit: data['culprit'] = culprit if 'checksum' not in data: checksum_bits = handler.get_hash(data) else: checksum_bits = data['checksum'] if isinstance(checksum_bits, (list, tuple)): checksum = hashlib.md5() for bit in checksum_bits: checksum.update(to_string(bit)) checksum = checksum.hexdigest() else: checksum = checksum_bits data['checksum'] = checksum # create ID client-side so that it can be passed to application event_id = uuid.uuid4().hex # Run the data through processors for processor in self.get_processors(): data.update(processor.process(data)) # Make sure all data is coerced data = transform(data) if 'message' not in data: data['message'] = handler.to_string(data) data.update({ 'timestamp': date, 'time_spent': time_spent, 'event_id': event_id, }) data.setdefault('project', self.project) data.setdefault('site', self.site) self.send(**data) return (event_id, checksum)
def build_msg(self, event_type, data=None, date=None, time_spent=None, extra=None, stack=None, public_key=None, tags=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, v in six.iteritems(result): if k not 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 stack is None and 'exception' not in data: stack = self.auto_log_stacks if stack and 'stacktrace' not in data: if stack is 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 'stacktrace' in data: self._mark_stacktrace_frames(data['stacktrace']) if 'exception' in data: self._mark_stacktrace_frames(data['exception']['values'][0].get('stacktrace')) if not culprit: if 'stacktrace' in data: culprit = get_culprit(data['stacktrace']['frames']) elif 'exception' in data: stacktrace = data['exception']['values'][0].get('stacktrace') if stacktrace: culprit = get_culprit(stacktrace['frames']) 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.release is not None: data['release'] = self.release 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 # Run the data through processors for processor in 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, value in six.iteritems(data['tags']): data['tags'][key] = to_unicode(value) # extra data can be any arbitrary value for k, v in six.iteritems(data['extra']): data['extra'][k] = self.transform(v) # It's important date is added **after** we serialize data.setdefault('project', self.project) data.setdefault('timestamp', date or datetime.utcnow()) data.setdefault('time_spent', time_spent) data.setdefault('event_id', event_id) data.setdefault('platform', PLATFORM_NAME) return data
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, v in iteritems(result): if k not 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 stack is None and 'exception' not in data: stack = self.auto_log_stacks if stack and 'stacktrace' not in data: if stack is 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 frame in 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 x in self.include_paths) and not any(path.startswith(x) for x in 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.release is not None: data['release'] = self.release if self.environment is 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 processor in 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, value in iteritems(data['tags']): data['tags'][key] = to_unicode(value) # extra data can be any arbitrary value for k, v in 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', date or datetime.utcnow()) data.setdefault('time_spent', time_spent) data.setdefault('event_id', event_id) data.setdefault('platform', PLATFORM_NAME) data.setdefault('sdk', SDK_VALUE) # 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
def process(self, **kwargs): """ Processes the message before passing it on to the server. This includes: - extracting stack frames (for non exceptions) - identifying module versions - coercing data - generating message identifiers You may pass the ``stack`` parameter to specify an explicit stack, or simply to tell Raven that you want to capture the stacktrace. To automatically grab the stack from a non-exception: >>> client.process(message='test', stack=True) To capture an explicit stack (e.g. something from a different threadframe?): >>> import inspect >>> from raven.utils import iter_stack_frames >>> client.process(message='test', stack=iter_stack_frames(inspect.stack())) """ if kwargs.get('data'): # Ensure we're not changing the original data which was passed # to Sentry data = kwargs.get('data').copy() else: data = {} if '__sentry__' not in data: data['__sentry__'] = {} get_stack = kwargs.pop('stack', self.auto_log_stacks) if get_stack and not data['__sentry__'].get('frames'): if get_stack is True: stack = [] found = None for frame in iter_stack_frames(): # There are initial frames from Sentry that need skipped name = frame.f_globals.get('__name__') if found is None: if name == 'logging': found = False continue elif not found: if name != 'logging': found = True else: continue stack.append(frame) stack.reverse() else: # assume stack was a list of frames stack = get_stack or [] data['__sentry__']['frames'] = varmap(shorten, get_stack_info(stack)) kwargs.setdefault('level', logging.ERROR) kwargs.setdefault('server_name', self.name) kwargs.setdefault('site', self.site) versions = get_versions(self.include_paths) data['__sentry__']['versions'] = versions # Shorten lists/strings for k, v in data.iteritems(): if k == '__sentry__': continue data[k] = shorten(v, string_length=self.string_max_length, list_length=self.list_max_length) # if we've passed frames, lets try to fetch the culprit if not kwargs.get('view') and data['__sentry__'].get('frames'): # We iterate through each frame looking for an app in INSTALLED_APPS # When one is found, we mark it as last "best guess" (best_guess) and then # check it against SENTRY_EXCLUDE_PATHS. If it isnt listed, then we # use this option. If nothing is found, we use the "best guess". view = get_culprit(data['__sentry__']['frames'], self.include_paths, self.exclude_paths) if view: kwargs['view'] = view # try to fetch the current version if kwargs.get('view'): # get list of modules from right to left parts = kwargs['view'].split('.') module_list = ['.'.join(parts[:idx]) for idx in xrange(1, len(parts) + 1)][::-1] version = None module = None for m in module_list: if m in versions: module = m version = versions[m] # store our "best guess" for application version if version: data['__sentry__'].update({ 'version': version, 'module': module, }) if 'checksum' not in kwargs: kwargs['checksum'] = checksum = construct_checksum(**kwargs) else: checksum = kwargs['checksum'] # create ID client-side so that it can be passed to application message_id = uuid.uuid4().hex kwargs['message_id'] = message_id # Make sure all data is coerced kwargs['data'] = transform(data) if 'timestamp' not in kwargs: kwargs['timestamp'] = datetime.datetime.utcnow() self.send(**kwargs) return (message_id, checksum)
def build_msg(self, event_type, data=None, date=None, time_spent=None, extra=None, stack=None, public_key=None, **kwargs): """ Captures, processes and serializes an event into a dict object """ # create ID client-side so that it can be passed to application event_id = uuid.uuid4().hex if data is None: data = {} if extra is None: extra = {} if not date: date = datetime.datetime.utcnow() if stack is None: stack = self.auto_log_stacks 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, v in result.iteritems(): if k not in data: data[k] = v if stack and 'sentry.interfaces.Stacktrace' not in data: if stack is True: frames = iter_stack_frames() else: frames = stack data.update({ 'sentry.interfaces.Stacktrace': { 'frames': varmap( lambda k, v: shorten(v, string_length=self. string_max_length, list_length=self.list_max_length), get_stack_info(frames)) }, }) if 'sentry.interfaces.Stacktrace' in data and not culprit: culprit = get_culprit( data['sentry.interfaces.Stacktrace']['frames'], self.include_paths, self.exclude_paths) if not data.get('level'): data['level'] = logging.ERROR data['modules'] = get_versions(self.include_paths) data['server_name'] = self.name data.setdefault('extra', {}) data.setdefault('level', logging.ERROR) # Shorten lists/strings for k, v in extra.iteritems(): data['extra'][k] = shorten(v, string_length=self.string_max_length, list_length=self.list_max_length) if culprit: data['culprit'] = culprit if 'checksum' not in data: checksum_bits = handler.get_hash(data) else: checksum_bits = data['checksum'] if isinstance(checksum_bits, (list, tuple)): checksum = hashlib.md5() for bit in checksum_bits: checksum.update(to_string(bit)) checksum = checksum.hexdigest() else: checksum = checksum_bits data['checksum'] = checksum # Run the data through processors for processor in self.get_processors(): data.update(processor.process(data)) # Make sure all data is coerced data = transform(data) if 'message' not in data: data['message'] = handler.to_string(data) data.update({ 'timestamp': date, 'time_spent': time_spent, 'event_id': event_id, }) data.setdefault('project', self.project) data.setdefault('site', self.site) data.setdefault('public_key', self.public_key) return data
def build_msg(self, event_type, data=None, date=None, time_spent=None, extra=None, stack=None, public_key=None, tags=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 if data is None: data = {} if extra is None: extra = {} if not date: date = datetime.datetime.utcnow() if stack is None: stack = self.auto_log_stacks 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, v in six.iteritems(result): if k not in data: data[k] = v if stack and 'sentry.interfaces.Stacktrace' not in data: if stack is True: frames = iter_stack_frames() else: frames = stack data.update({ 'sentry.interfaces.Stacktrace': { 'frames': get_stack_info(frames, transformer=self.transform) }, }) if 'sentry.interfaces.Stacktrace' in data: if self.include_paths: for frame in data['sentry.interfaces.Stacktrace']['frames']: 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 x in self.include_paths) and not any( path.startswith(x) for x in self.exclude_paths)) if not culprit: culprit = get_culprit( data['sentry.interfaces.Stacktrace']['frames']) 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() data['tags'] = tags or {} data.setdefault('extra', {}) data.setdefault('level', logging.ERROR) # Add default extra context if self.extra: for k, v in six.iteritems(self.extra): data['extra'].setdefault(k, v) # Add default tag context if self.tags: for k, v in six.iteritems(self.tags): data['tags'].setdefault(k, v) for k, v in six.iteritems(extra): data['extra'][k] = v if culprit: data['culprit'] = culprit # Run the data through processors for processor in self.get_processors(): data.update(processor.process(data)) if 'message' not in data: data['message'] = handler.to_string(data) data.setdefault('project', self.project) # Legacy support for site attribute site = data.pop('site', None) or self.site if site: data['tags'].setdefault('site', site) for key, value in six.iteritems(data['tags']): data['tags'][key] = to_unicode(value) # Make sure custom data is coerced for k, v in six.iteritems(data['extra']): data['extra'][k] = self.transform(v) # It's important date is added **after** we serialize data.update({ 'timestamp': date, 'time_spent': time_spent, 'event_id': event_id, 'platform': PLATFORM_NAME, }) return data
def build_msg( self, event_type, data=None, date=None, time_spent=None, extra=None, stack=None, public_key=None, **kwargs ): """ Captures, processes and serializes an event into a dict object """ # create ID client-side so that it can be passed to application event_id = uuid.uuid4().hex if data is None: data = {} if extra is None: extra = {} if not date: date = datetime.datetime.utcnow() if stack is None: stack = self.auto_log_stacks 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, v in result.iteritems(): if k not in data: data[k] = v if stack and "sentry.interfaces.Stacktrace" not in data: if stack is True: frames = iter_stack_frames() else: frames = stack data.update( { "sentry.interfaces.Stacktrace": { "frames": varmap( lambda k, v: shorten( v, string_length=self.string_max_length, list_length=self.list_max_length ), get_stack_info(frames), ) } } ) if "sentry.interfaces.Stacktrace" in data and not culprit: culprit = get_culprit( data["sentry.interfaces.Stacktrace"]["frames"], self.include_paths, self.exclude_paths ) if not data.get("level"): data["level"] = logging.ERROR data["modules"] = get_versions(self.include_paths) data["server_name"] = self.name data.setdefault("extra", {}) data.setdefault("level", logging.ERROR) # Shorten lists/strings for k, v in extra.iteritems(): data["extra"][k] = shorten(v, string_length=self.string_max_length, list_length=self.list_max_length) if culprit: data["culprit"] = culprit if "checksum" not in data: checksum_bits = handler.get_hash(data) else: checksum_bits = data["checksum"] if isinstance(checksum_bits, (list, tuple)): checksum = hashlib.md5() for bit in checksum_bits: checksum.update(to_string(bit)) checksum = checksum.hexdigest() else: checksum = checksum_bits data["checksum"] = checksum # Run the data through processors for processor in self.get_processors(): data.update(processor.process(data)) # Make sure all data is coerced data = transform(data) if "message" not in data: data["message"] = handler.to_string(data) data.update({"timestamp": date, "time_spent": time_spent, "event_id": event_id}) data.setdefault("project", self.project) data.setdefault("site", self.site) data.setdefault("public_key", self.public_key) return data
def build_msg(self, event_type, data=None, date=None, time_spent=None, extra=None, stack=None, public_key=None, tags=None, **kwargs): """ Captures, processes and serializes an event into a dict object """ # create ID client-side so that it can be passed to application event_id = uuid.uuid4().hex if data is None: data = {} if extra is None: extra = {} if not date: date = datetime.datetime.utcnow() if stack is None: stack = self.auto_log_stacks 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, v in result.iteritems(): if k not in data: data[k] = v if stack and 'sentry.interfaces.Stacktrace' not in data: if stack is True: frames = iter_stack_frames() else: frames = stack data.update({ 'sentry.interfaces.Stacktrace': { 'frames': varmap(lambda k, v: shorten(v, string_length=self.string_max_length, list_length=self.list_max_length), get_stack_info(frames)) }, }) if 'sentry.interfaces.Stacktrace' in data and not culprit: culprit = get_culprit( data['sentry.interfaces.Stacktrace']['frames'], self.include_paths, self.exclude_paths ) if not data.get('level'): data['level'] = kwargs.get('level') or logging.ERROR data['modules'] = get_versions(self.include_paths) data['server_name'] = self.name data['tags'] = tags data.setdefault('extra', {}) data.setdefault('level', logging.ERROR) # Shorten lists/strings for k, v in extra.iteritems(): data['extra'][k] = shorten(v, string_length=self.string_max_length, list_length=self.list_max_length) if culprit: data['culprit'] = culprit if 'checksum' not in data: checksum_bits = handler.get_hash(data) else: checksum_bits = data['checksum'] if isinstance(checksum_bits, (list, tuple)): checksum = hashlib.md5() for bit in checksum_bits: checksum.update(to_string(bit)) checksum = checksum.hexdigest() else: checksum = checksum_bits data['checksum'] = checksum # Run the data through processors for processor in self.get_processors(): data.update(processor.process(data)) if 'message' not in data: data['message'] = handler.to_string(data) data.setdefault('project', self.project) data.setdefault('site', self.site) data.setdefault('public_key', self.public_key) # Make sure all data is coerced data = self.transform(data) # It's important date is added **after** we serialize data.update({ 'timestamp': date, 'time_spent': time_spent, 'event_id': event_id, }) return data
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): event_id = uuid.uuid4().hex data = merge_dicts(self.context.data, data) data.setdefault('tags', {}) data.setdefault('extra', {}) if '.' not in event_type: event_type = 'raven.events.%s' % event_type handler = self.get_handler(event_type) result = handler.capture(**kwargs) culprit = result.pop('culprit', None) if data.get('culprit'): culprit = data['culprit'] for k, v in iteritems(result): if k not in data: data[k] = v if stack is None and 'exception' not in data: stack = self.auto_log_stacks if stack and 'stacktrace' not in data: if stack is 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 frame in 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 x in self.include_paths)) and not any((path.startswith(x) for x in self.exclude_paths)) if not culprit: if 'stacktrace' in data: culprit = get_culprit(data['stacktrace']['frames']) elif 'exception' in data: stacktrace = data['exception']['values'][0].get('stacktrace') if stacktrace: culprit = get_culprit(stacktrace['frames']) 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.release is not None: data['release'] = self.release if self.environment is not None: data['environment'] = self.environment data['tags'] = merge_dicts(self.tags, data['tags'], tags) data['extra'] = merge_dicts(self.extra, data['extra'], extra) 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 for processor in self.get_processors(): data.update(processor.process(data)) if 'message' not in data: data['message'] = kwargs.get('message', handler.to_string(data)) for key, value in iteritems(data['tags']): data['tags'][key] = to_unicode(value) for k, v in iteritems(data['extra']): data['extra'][k] = self.transform(v) data.setdefault('project', self.remote.project) data.setdefault('timestamp', date or datetime.utcnow()) data.setdefault('time_spent', time_spent) data.setdefault('event_id', event_id) data.setdefault('platform', PLATFORM_NAME) data.setdefault('sdk', SDK_VALUE) if self.enable_breadcrumbs: crumbs = self.context.breadcrumbs.get_buffer() if crumbs: data.setdefault('breadcrumbs', {'values': crumbs}) return data
def process(self, **kwargs): """ Processes the message before passing it on to the server. This includes: - extracting stack frames (for non exceptions) - identifying module versions - coercing data - generating message identifiers You may pass the ``stack`` parameter to specify an explicit stack, or simply to tell Raven that you want to capture the stacktrace. To automatically grab the stack from a non-exception: >>> client.process(message='test', stack=True) To capture an explicit stack (e.g. something from a different threadframe?): >>> import inspect >>> from raven.utils import iter_stack_frames >>> client.process(message='test', stack=iter_stack_frames(inspect.stack())) """ if kwargs.get('data'): # Ensure we're not changing the original data which was passed # to Sentry data = kwargs.get('data').copy() else: data = {} if '__sentry__' not in data: data['__sentry__'] = {} get_stack = kwargs.pop('stack', self.auto_log_stacks) if get_stack and not data['__sentry__'].get('frames'): if get_stack is True: stack = [] found = None for frame in iter_stack_frames(): # There are initial frames from Sentry that need skipped name = frame.f_globals.get('__name__') if found is None: if name == 'logging': found = False continue elif not found: if name != 'logging': found = True else: continue stack.append(frame) stack.reverse() else: # assume stack was a list of frames stack = get_stack or [] data['__sentry__']['frames'] = varmap(shorten, get_stack_info(stack)) kwargs.setdefault('level', logging.ERROR) kwargs.setdefault('server_name', self.name) kwargs.setdefault('site', self.site) versions = get_versions(self.include_paths) data['__sentry__']['versions'] = versions # Shorten lists/strings for k, v in data.iteritems(): if k == '__sentry__': continue data[k] = shorten(v, string_length=self.string_max_length, list_length=self.list_max_length) # if we've passed frames, lets try to fetch the culprit if not kwargs.get('view') and data['__sentry__'].get('frames'): # We iterate through each frame looking for an app in INSTALLED_APPS # When one is found, we mark it as last "best guess" (best_guess) and then # check it against SENTRY_EXCLUDE_PATHS. If it isnt listed, then we # use this option. If nothing is found, we use the "best guess". view = get_culprit(data['__sentry__']['frames'], self.include_paths, self.exclude_paths) if view: kwargs['view'] = view # try to fetch the current version if kwargs.get('view'): # get list of modules from right to left parts = kwargs['view'].split('.') module_list = [ '.'.join(parts[:idx]) for idx in xrange(1, len(parts) + 1) ][::-1] version = None module = None for m in module_list: if m in versions: module = m version = versions[m] # store our "best guess" for application version if version: data['__sentry__'].update({ 'version': version, 'module': module, }) if 'checksum' not in kwargs: kwargs['checksum'] = checksum = construct_checksum(**kwargs) else: checksum = kwargs['checksum'] # create ID client-side so that it can be passed to application message_id = uuid.uuid4().hex kwargs['message_id'] = message_id # Make sure all data is coerced kwargs['data'] = transform(data) if 'timestamp' not in kwargs: kwargs['timestamp'] = datetime.datetime.utcnow() self.send(**kwargs) return (message_id, checksum)