def test_int_subclass(self): class X(int): pass result = transform(X()) self.assertEquals(type(result), int) self.assertEquals(result, 0)
def test_dict_keys_utf8_as_unicode(self): x = {u'רונית מגן': 'bar'} result = transform(x) keys = result.keys() self.assertEquals(len(keys), 1) self.assertTrue(type(keys[0]), str) self.assertEquals(keys[0], 'רונית מגן')
def test_correct_unicode(self): x = 'רונית מגן' if six.PY2: x = x.decode('utf-8') result = transform(x) self.assertEquals(type(result), six.text_type) self.assertEquals(result, x)
def test_dict_keys(self): x = {u'foo': 'bar'} result = transform(x) self.assertEquals(type(result), dict) keys = result.keys() self.assertEquals(len(keys), 1) self.assertTrue(type(keys[0]), str) self.assertEquals(keys[0], 'foo')
def test_custom_repr(self): class Foo(object): def __opbeat__(self): return 'example' x = Foo() result = transform(x) self.assertEquals(result, 'example')
def test_dict_keys(self): x = {'foo': 'bar'} result = transform(x) self.assertEquals(type(result), dict) keys = list(result.keys()) self.assertEquals(len(keys), 1) self.assertTrue(type(keys[0]), str) self.assertEquals(keys[0], 'foo')
def test_custom_repr(self): class Foo(object): def __sentry__(self): return 'example' x = Foo() result = transform(x) self.assertEquals(result, 'example')
def test_broken_repr(self): class Foo(object): def __repr__(self): raise ValueError x = Foo() result = transform(x) self.assertEquals(result, u"<BadRepr: <class 'tests.utils.encoding.tests.Foo'>>")
def test_dict_keys_utf8_as_unicode(self): x = { six.text_type('\u05e8\u05d5\u05e0\u05d9\u05ea \u05de\u05d2\u05df'): 'bar' } result = transform(x) keys = list(result.keys()) self.assertEquals(len(keys), 1) self.assertTrue(type(keys[0]), str) self.assertEquals(keys[0], '\u05e8\u05d5\u05e0\u05d9\u05ea \u05de\u05d2\u05df')
def test_broken_repr(self): class Foo(object): def __repr__(self): raise ValueError x = Foo() result = transform(x) self.assertEquals( result, u"<BadRepr: <class 'tests.utils.encoding.tests.Foo'>>")
def test_dict_keys_utf8_as_str(self): x = {'רונית מגן': 'bar'} result = transform(x) self.assertEquals(type(result), dict) keys = list(result.keys()) self.assertEquals(len(keys), 1) self.assertTrue(type(keys[0]), six.binary_type) if six.PY3: self.assertEquals(keys[0], 'רונית מגן') else: self.assertEquals(keys[0], u'רונית מגן')
def test_broken_repr(self): class Foo(object): def __repr__(self): raise ValueError x = Foo() result = transform(x) if six.PY2: expected = u"<BadRepr: <class 'tests.utils.encoding.tests.Foo'>>" else: expected = "<BadRepr: <class 'tests.utils.encoding.tests.TransformTest.test_broken_repr.<locals>.Foo'>>" self.assertEquals(result, expected)
def build_msg_for_logging(self, event_type, data=None, date=None, extra=None, stack=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 self.build_msg(data=data) # if '.' not in event_type: # Assume it's a builtin event_type = 'opbeat.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 'stacktrace' not in data: if stack is True: frames = iter_stack_frames() else: frames = stack data.update({ '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 'stacktrace' in data and not culprit: culprit = get_culprit( data['stacktrace']['frames'], self.include_paths, self.exclude_paths ) if not data.get('level'): data['level'] = 'error' if isinstance( data['level'], ( int, long ) ): data['level'] = logging.getLevelName(data['level']).lower() data.setdefault('extra', {}) # 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 # 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) # Make sure certain values are not too long for v in defaults.MAX_LENGTH_VALUES: if v in data: data[v] = shorten(data[v], string_length=defaults.MAX_LENGTH_VALUES[v] ) data.update({ 'timestamp': date, # 'time_spent': time_spent, 'client_supplied_id': event_id, }) return data
def test_recursive(self): x = [] x.append(x) result = transform(x) self.assertEquals(result, ['<...>'])
def test_uuid(self): x = uuid.uuid4() result = transform(x) self.assertEquals(result, repr(x)) self.assertTrue(type(result), str)
def get_frame_info(frame, lineno, extended=True): # Support hidden frames f_locals = getattr(frame, 'f_locals', {}) if _getitem_from_frame(f_locals, '__traceback_hide__'): return None f_globals = getattr(frame, 'f_globals', {}) loader = f_globals.get('__loader__') module_name = f_globals.get('__name__') f_code = getattr(frame, 'f_code', None) if f_code: abs_path = frame.f_code.co_filename function = frame.f_code.co_name else: abs_path = None function = None if lineno: lineno -= 1 # Try to pull a relative file path # This changes /foo/site-packages/baz/bar.py into baz/bar.py try: base_filename = sys.modules[module_name.split('.', 1)[0]].__file__ filename = abs_path.split(base_filename.rsplit('/', 2)[0], 1)[-1][1:] except: filename = abs_path if not filename: filename = abs_path frame_result = { 'abs_path': abs_path, 'filename': filename, 'module': module_name, 'function': function, 'lineno': lineno + 1, } if extended: if lineno is not None and abs_path: pre_context, context_line, post_context = get_lines_from_file( abs_path, lineno, 3, loader, module_name) else: pre_context, context_line, post_context = [], None, [] if f_locals is not None and not isinstance(f_locals, dict): # XXX: Genshi (and maybe others) have broken implementations of # f_locals that are not actually dictionaries try: f_locals = to_dict(f_locals) except Exception: f_locals = '<invalid local scope>' if context_line: frame_result.update({ 'pre_context': pre_context, 'context_line': context_line, 'post_context': post_context, 'vars': transform(f_locals), }) return frame_result
def test_float(self): result = transform(13.0) self.assertEquals(type(result), float) self.assertEquals(result, 13.0)
def test_bad_string(self): x = six.b('The following character causes problems: \xd4') result = transform(x) self.assertEquals(type(result), six.binary_type) self.assertEquals(result, six.b('(Error decoding value)'))
def test_correct_unicode(self): x = 'רונית מגן'.decode('utf-8') result = transform(x) self.assertEquals(type(result), unicode) self.assertEquals(result, x)
def get_stack_info(frames): """ Given a list of frames, returns a list of stack information dictionary objects that are JSON-ready. We have to be careful here as certain implementations of the _Frame class do not contain the nescesary data to lookup all of the information we want. """ results = [] # print list(frames)[0] for frame, lineno in frames: # Support hidden frames f_locals = getattr(frame, 'f_locals', {}) if _getitem_from_frame(f_locals, '__traceback_hide__'): continue f_globals = getattr(frame, 'f_globals', {}) loader = f_globals.get('__loader__') module_name = f_globals.get('__name__') f_code = getattr(frame, 'f_code', None) if f_code: abs_path = frame.f_code.co_filename function = frame.f_code.co_name else: abs_path = None function = None if lineno: lineno -= 1 if lineno is not None and abs_path: pre_context, context_line, post_context = get_lines_from_file(abs_path, lineno, 3, loader, module_name) else: pre_context, context_line, post_context = [], None, [] # Try to pull a relative file path # This changes /foo/site-packages/baz/bar.py into baz/bar.py try: base_filename = sys.modules[module_name.split('.', 1)[0]].__file__ filename = abs_path.split(base_filename.rsplit('/', 2)[0], 1)[-1][1:] except: filename = abs_path if not filename: filename = abs_path if f_locals is not None and not isinstance(f_locals, dict): # XXX: Genshi (and maybe others) have broken implementations of # f_locals that are not actually dictionaries try: f_locals = to_dict(f_locals) except Exception: f_locals = '<invalid local scope>' frame_result = { 'abs_path': abs_path, 'filename': filename, 'module': module_name, 'function': function, 'lineno': lineno + 1, 'vars': transform(f_locals), } if context_line: frame_result.update({ 'pre_context': pre_context, 'context_line': context_line, 'post_context': post_context, }) results.append(frame_result) return results
def test_bad_string(self): x = 'The following character causes problems: \xd4' result = transform(x) self.assertEquals(type(result), str) self.assertEquals(result, '<type \'str\'>')
def build_msg_for_logging(self, event_type, data=None, date=None, extra=None, stack=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 self.build_msg(data=data) # if '.' not in event_type: # Assume it's a builtin event_type = 'opbeat.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 'stacktrace' not in data: if stack is True: frames = iter_stack_frames() else: frames = stack data.update({ '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 'stacktrace' in data and not culprit: culprit = get_culprit(data['stacktrace']['frames'], self.include_paths, self.exclude_paths) if not data.get('level'): data['level'] = 'error' if isinstance(data['level'], (int, long)): data['level'] = logging.getLevelName(data['level']).lower() data.setdefault('extra', {}) # 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 # 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) # Make sure certain values are not too long for v in defaults.MAX_LENGTH_VALUES: if v in data: data[v] = shorten(data[v], string_length=defaults.MAX_LENGTH_VALUES[v]) data.update({ 'timestamp': date, # 'time_spent': time_spent, 'client_supplied_id': event_id, }) return data
def test_bool(self): result = transform(True) self.assertEquals(type(result), bool) self.assertEquals(result, True)
def get_stack_info(frames): """ Given a list of frames, returns a list of stack information dictionary objects that are JSON-ready. We have to be careful here as certain implementations of the _Frame class do not contain the nescesary data to lookup all of the information we want. """ results = [] # print list(frames)[0] for frame, lineno in frames: # Support hidden frames f_locals = getattr(frame, 'f_locals', {}) if _getitem_from_frame(f_locals, '__traceback_hide__'): continue f_globals = getattr(frame, 'f_globals', {}) loader = f_globals.get('__loader__') module_name = f_globals.get('__name__') f_code = getattr(frame, 'f_code', None) if f_code: abs_path = frame.f_code.co_filename function = frame.f_code.co_name else: abs_path = None function = None if lineno: lineno -= 1 if lineno is not None and abs_path: pre_context, context_line, post_context = get_lines_from_file( abs_path, lineno, 3, loader, module_name) else: pre_context, context_line, post_context = [], None, [] # Try to pull a relative file path # This changes /foo/site-packages/baz/bar.py into baz/bar.py try: base_filename = sys.modules[module_name.split('.', 1)[0]].__file__ filename = abs_path.split(base_filename.rsplit('/', 2)[0], 1)[-1][1:] except: filename = abs_path if not filename: filename = abs_path if f_locals is not None and not isinstance(f_locals, dict): # XXX: Genshi (and maybe others) have broken implementations of # f_locals that are not actually dictionaries try: f_locals = to_dict(f_locals) except Exception: f_locals = '<invalid local scope>' frame_result = { 'abs_path': abs_path, 'filename': filename, 'module': module_name, 'function': function, 'lineno': lineno + 1, 'vars': transform(f_locals), } if context_line: frame_result.update({ 'pre_context': pre_context, 'context_line': context_line, 'post_context': post_context, }) results.append(frame_result) return results
def test_incorrect_unicode(self): x = 'רונית מגן' result = transform(x) self.assertEquals(type(result), str) self.assertEquals(result, 'רונית מגן')