Ejemplo n.º 1
0
    def _emit(self, record, **kwargs):
        data = {}

        for k, v in record.__dict__.iteritems():
            if '.' not in k and k not in ('culprit',):
                continue
            data[k] = v

        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            frames = []
            started = False
            last_mod = ''
            for frame in iter_stack_frames():
                if not started:
                    f_globals = getattr(frame, 'f_globals', {})
                    module_name = f_globals.get('__name__', '')
                    if last_mod.startswith('logging') and not module_name.startswith('logging'):
                        started = True
                    else:
                        last_mod = module_name
                        continue
                frames.append(frame)
            stack = frames

        extra = getattr(record, 'data', {})
        # Add in all of the data from the record that we aren't already capturing
        for k in record.__dict__.keys():
            if k in ('stack', 'name', 'args', 'msg', 'levelno', 'exc_text', 'exc_info', 'data', 'created', 'levelname', 'msecs', 'relativeCreated'):
                continue
            extra[k] = record.__dict__[k]

        date = datetime.datetime.utcfromtimestamp(record.created)

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if record.exc_info and all(record.exc_info):
            handler = self.client.get_handler('raven.events.Exception')

            data.update(handler.capture(exc_info=record.exc_info))
            data['checksum'] = handler.get_hash(data)

        data['level'] = record.levelno
        data['logger'] = record.name

        return self.client.capture('Message', message=record.msg, params=record.args,
                            stack=stack, data=data, extra=extra,
                            date=date, **kwargs)
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    def _emit(self, record, **kwargs):
        data = {}

        for k, v in record.__dict__.iteritems():
            if '.' not in k and k not in ('culprit',):
                continue
            data[k] = v

        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            frames = []
            started = False
            last_mod = ''
            for item in stack:
                if isinstance(item, (list, tuple)):
                    frame, lineno = item
                else:
                    frame, lineno = item, item.f_lineno

                if not started:
                    f_globals = getattr(frame, 'f_globals', {})
                    module_name = f_globals.get('__name__', '')
                    if (last_mod and last_mod.startswith('logging')) \
                        and not module_name.startswith('logging'):
                        started = True
                    else:
                        last_mod = module_name
                        continue
                frames.append((frame, lineno))
            stack = frames

        extra = getattr(record, 'data', {})
        # Add in all of the data from the record that we aren't already capturing
        for k in record.__dict__.keys():
            if k in ('stack', 'name', 'args', 'msg', 'levelno', 'exc_text', 'exc_info', 'data', 'created', 'levelname', 'msecs', 'relativeCreated'):
                continue
            if k.startswith('_'):
                continue
            extra[k] = record.__dict__[k]

        date = datetime.datetime.utcfromtimestamp(record.created)

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if record.exc_info and all(record.exc_info):
            handler = self.client.get_handler('raven.events.Exception')

            data.update(handler.capture(exc_info=record.exc_info))
            data['checksum'] = handler.get_hash(data)

        data['level'] = record.levelno
        data['logger'] = record.name

        return self.client.capture('Message', message=record.msg, params=record.args,
                            stack=stack, data=data, extra=extra,
                            date=date, **kwargs)
Ejemplo n.º 4
0
    def _emit(self, record, **kwargs):
        data = {}

        for k, v in record.__dict__.iteritems():
            if '.' not in k:
                continue
            data[k] = v

        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            frames = []
            started = False
            last_mod = ''
            for frame in iter_stack_frames():
                if not started:
                    f_globals = getattr(frame, 'f_globals', {})
                    module_name = f_globals.get('__name__', '')
                    if last_mod.startswith('logging') and not module_name.startswith('logging'):
                        started = True
                    else:
                        last_mod = module_name
                        continue
                frames.append(frame)
            stack = frames

        extra = getattr(record, 'data', {})

        date = datetime.datetime.utcfromtimestamp(record.created)

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if record.exc_info and all(record.exc_info):
            handler = self.client.get_handler('raven.events.Exception')

            data.update(handler.capture(exc_info=record.exc_info))

        data['level'] = record.levelno
        data['logger'] = record.name

        return self.client.capture('Message', message=record.msg, params=record.args,
                            stack=stack, data=data, extra=extra,
                            date=date, **kwargs)
Ejemplo n.º 5
0
    def _emit(self, record, **kwargs):
        data, extra = extract_extra(record)

        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            stack = self._get_targetted_stack(stack, record)

        date = datetime.datetime.utcfromtimestamp(record.created)
        event_type = 'raven.events.Message'
        handler_kwargs = {
            'params': record.args,
        }
        try:
            handler_kwargs['message'] = text_type(record.msg)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs['message'] = repr(record.msg)[1:-1]

        try:
            handler_kwargs['formatted'] = text_type(record.message)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs['formatted'] = repr(record.message)[1:-1]

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if record.exc_info and all(record.exc_info):
            # capture the standard message first so that we ensure
            # the event is recorded as an exception, in addition to having our
            # message interface attached
            handler = self.client.get_handler(event_type)
            data.update(handler.capture(**handler_kwargs))

            event_type = 'raven.events.Exception'
            handler_kwargs = {'exc_info': record.exc_info}

        data['level'] = record.levelno
        data['logger'] = record.name

        kwargs['tags'] = tags = {}
        if self.tags:
            tags.update(self.tags)
        tags.update(getattr(record, 'tags', {}))

        kwargs.update(handler_kwargs)
        sample_rate = extra.pop('sample_rate', None)

        return self.client.capture(event_type,
                                   stack=stack,
                                   data=data,
                                   extra=extra,
                                   date=date,
                                   sample_rate=sample_rate,
                                   **kwargs)
Ejemplo n.º 6
0
    def emit(self, record):
        if record.levelno <= logging.ERROR and self.can_record(record):
            request = None
            exc_info = None
            for frame_info in getouterframes(currentframe()):
                frame = frame_info[0]
                if not request:
                    request = frame.f_locals.get('request', None)
                    if not request:
                        view = frame.f_locals.get('self', None)
                        try:
                            request = getattr(view, 'request', None)
                        except RuntimeError:
                            request = None

                if not exc_info:
                    exc_info = frame.f_locals.get('exc_info', None)
                    if not hasattr(exc_info, '__getitem__'):
                        exc_info = None
                if request and exc_info:
                    break

            if exc_info:
                record.exc_info = exc_info
                record.stack = iter_stack_frames(getinnerframes(exc_info[2]))
            if request:
                try:
                    body_pos = request.stdin.tell()
                    request.stdin.seek(0)
                    body = request.stdin.read()
                    request.stdin.seek(body_pos)
                    http = dict(headers=request.environ,
                                url=request.getURL(),
                                method=request.method,
                                host=request.environ.get('REMOTE_ADDR', ''),
                                data=body)
                    if 'HTTP_USER_AGENT' in http['headers']:
                        if 'User-Agent' not in http['headers']:
                            http['headers']['User-Agent'] = http['headers'][
                                'HTTP_USER_AGENT']
                    if 'QUERY_STRING' in http['headers']:
                        http['query_string'] = http['headers']['QUERY_STRING']
                    setattr(record, 'request', http)
                    user = request.get('AUTHENTICATED_USER', None)
                    if user is not None and user != nobody:
                        user_dict = {
                            'id': user.getId(),
                            'email': user.getProperty('email') or ''
                        }
                    else:
                        user_dict = {}
                    setattr(record, 'user', user_dict)
                except (AttributeError, KeyError):
                    logger.warning('Could not extract data from request',
                                   exc_info=True)

        return super(ZopeSentryHandler, self).emit(record)
Ejemplo n.º 7
0
    def emit(self, record):
        if record.levelno <= logging.ERROR and self.can_record(record):
            request = None
            exc_info = None
            for frame_info in getouterframes(currentframe()):
                frame = frame_info[0]
                if not request:
                    request = frame.f_locals.get('request', None)
                    if not request:
                        view = frame.f_locals.get('self', None)
                        try:
                            request = getattr(view, 'request', None)
                        except RuntimeError:
                            request = None
                if not exc_info:
                    exc_info = frame.f_locals.get('exc_info', None)
                    if not hasattr(exc_info, '__getitem__'):
                        exc_info = None
                if request and exc_info:
                    break

            if exc_info:
                record.exc_info = exc_info
                record.stack = \
                    iter_stack_frames(getinnerframes(exc_info[2]))
            if request:
                try:
                    body_pos = request.stdin.tell()
                    request.stdin.seek(0)
                    body = request.stdin.read()
                    request.stdin.seek(body_pos)
                    http = dict(headers=request.environ,
                                url=request.getURL(),
                                method=request.method,
                                host=request.environ.get('REMOTE_ADDR',
                                ''), data=body)
                    if 'HTTP_USER_AGENT' in http['headers']:
                        if 'User-Agent' not in http['headers']:
                            http['headers']['User-Agent'] = \
                                http['headers']['HTTP_USER_AGENT']
                    if 'QUERY_STRING' in http['headers']:
                        http['query_string'] = http['headers']['QUERY_STRING']
                    setattr(record, 'request', http)
                    user = request.get('AUTHENTICATED_USER', None)
                    if user is not None and user != nobody:
                        user_dict = {
                            'id': user.getId(),
                            'email': user.getProperty('email') or '',
                        }
                    else:
                        user_dict = {}
                    setattr(record, 'user', user_dict)
                except (AttributeError, KeyError):
                    logger.warning('Could not extract data from request', exc_info=True)
        return super(ZopeSentryHandler, self).emit(record)
Ejemplo n.º 8
0
    def _emit(self, record, **kwargs):
        data, extra = extract_extra(record)

        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            stack = self._get_targetted_stack(stack, record)

        date = datetime.datetime.utcfromtimestamp(record.created)
        event_type = 'raven.events.Message'
        handler_kwargs = {
            'params': record.args,
        }
        try:
            handler_kwargs['message'] = text_type(record.msg)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs['message'] = repr(record.msg)[1:-1]

        try:
            handler_kwargs['formatted'] = text_type(record.message)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs['formatted'] = repr(record.message)[1:-1]

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if record.exc_info and all(record.exc_info):
            # capture the standard message first so that we ensure
            # the event is recorded as an exception, in addition to having our
            # message interface attached
            handler = self.client.get_handler(event_type)
            data.update(handler.capture(**handler_kwargs))

            event_type = 'raven.events.Exception'
            handler_kwargs = {'exc_info': record.exc_info}

        data['level'] = record.levelno
        data['logger'] = record.name

        kwargs['tags'] = tags = {}
        if self.tags:
            tags.update(self.tags)
        tags.update(getattr(record, 'tags', {}))

        kwargs.update(handler_kwargs)
        sample_rate = extra.pop('sample_rate', None)

        return self.client.capture(
            event_type, stack=stack, data=data,
            extra=extra, date=date, sample_rate=sample_rate,
            **kwargs)
Ejemplo n.º 9
0
 def test_explicit_stack(self):
     self.logger.info('This is a test of stacks', extra={'stack': iter_stack_frames()})
     self.assertEquals(len(self.client.events), 1)
     event = self.client.events.pop(0)
     self.assertEquals(event['culprit'], 'tests.handlers.logging.tests.test_explicit_stack')
     self.assertEquals(event['message'], 'This is a test of stacks')
     self.assertFalse('sentry.interfaces.Exception' in event)
     self.assertTrue('sentry.interfaces.Message' in event)
     msg = event['sentry.interfaces.Message']
     self.assertEquals(msg['message'], 'This is a test of stacks')
     self.assertEquals(msg['params'], ())
     self.assertTrue('sentry.interfaces.Stacktrace' in event)
Ejemplo n.º 10
0
    def _emit(self, record, **kwargs):
        data = {
            'user': {'id': self.client.name}
        }

        extra = getattr(record, 'data', None)
        if not isinstance(extra, dict):
            if extra:
                extra = {'data': extra}
            else:
                extra = {}

        for k, v in six.iteritems(vars(record)):
            if k in RESERVED:
                continue
            if k.startswith('_'):
                continue
            if '.' not in k and k not in ('culprit', 'server_name'):
                extra[k] = v
            else:
                data[k] = v

        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            stack = self._get_targetted_stack(stack, record)

        date = datetime.datetime.utcfromtimestamp(record.created)
        event_type = 'raven.events.Message'
        handler_kwargs = {
            'params': record.args,
        }
        try:
            handler_kwargs['message'] = six.text_type(record.msg)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs['message'] = repr(record.msg)[1:-1]

        try:
            handler_kwargs['formatted'] = six.text_type(record.message)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs['formatted'] = repr(record.message)[1:-1]

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        try:
            exc_info = self._exc_info(record)
        except Exception, ex:
            log.info('Unable to retrieve exception info - %s', ex, exc_info=True)
            exc_info = None
Ejemplo n.º 11
0
    def test_explicit_stack(self):
        record = self.make_record('This is a test of stacks', extra={'stack': iter_stack_frames()})
        self.handler.emit(record)

        self.assertEqual(len(self.client.events), 1)
        event = self.client.events.pop(0)
        assert 'stacktrace' in event
        self.assertTrue('message' in event, event)
        self.assertEqual(event['message'], 'This is a test of stacks')
        assert 'exception' not in event
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEqual(msg['message'], 'This is a test of stacks')
        self.assertEqual(msg['params'], ())
Ejemplo n.º 12
0
    def test_explicit_stack(self):
        record = self.make_record('This is a test of stacks', extra={'stack': iter_stack_frames()})
        self.handler.emit(record)

        self.assertEqual(len(self.client.events), 1)
        event = self.client.events.pop(0)
        assert 'stacktrace' in event
        self.assertTrue('message' in event, event)
        self.assertEqual(event['message'], 'This is a test of stacks')
        assert 'exception' not in event
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEqual(msg['message'], 'This is a test of stacks')
        self.assertEqual(msg['params'], ())
Ejemplo n.º 13
0
    def test_stack_explicit_frames(self):
        frames = inspect.stack()

        self.client.create_from_text('test', stack=iter_stack_frames(frames))

        self.assertEquals(len(self.client.events), 1)
        event = self.client.events.pop(0)
        self.assertEquals(event['message'], 'test')
        data = event['data']['__sentry__']
        self.assertTrue('frames' in data)
        self.assertEquals(len(frames), len(data['frames']))
        for frame, frame_i in zip(frames, data['frames']):
            self.assertEquals(frame[0].f_code.co_filename, frame_i['filename'])
            self.assertEquals(frame[0].f_code.co_name, frame_i['function'])
Ejemplo n.º 14
0
 def test_explicit_stack(self):
     self.logger.info("This is a test of stacks", extra={"stack": iter_stack_frames()})
     self.assertEquals(len(self.client.events), 1)
     event = self.client.events.pop(0)
     self.assertTrue("culprit" in event, event)
     self.assertEquals(event["culprit"], "tests.handlers.logging.tests.test_explicit_stack")
     self.assertTrue("message" in event, event)
     self.assertEquals(event["message"], "This is a test of stacks")
     self.assertFalse("sentry.interfaces.Exception" in event)
     self.assertTrue("sentry.interfaces.Message" in event)
     msg = event["sentry.interfaces.Message"]
     self.assertEquals(msg["message"], "This is a test of stacks")
     self.assertEquals(msg["params"], ())
     self.assertTrue("sentry.interfaces.Stacktrace" in event)
Ejemplo n.º 15
0
 def test_explicit_stack(self):
     self.logger.info('This is a test of stacks', extra={'stack': iter_stack_frames()})
     self.assertEquals(len(self.client.events), 1)
     event = self.client.events.pop(0)
     self.assertTrue('culprit' in event, event)
     self.assertEquals(event['culprit'], 'tests.handlers.logging.tests.test_explicit_stack')
     self.assertTrue('message' in event, event)
     self.assertEquals(event['message'], 'This is a test of stacks')
     self.assertFalse('sentry.interfaces.Exception' in event)
     self.assertTrue('sentry.interfaces.Message' in event)
     msg = event['sentry.interfaces.Message']
     self.assertEquals(msg['message'], 'This is a test of stacks')
     self.assertEquals(msg['params'], ())
     self.assertTrue('sentry.interfaces.Stacktrace' in event)
Ejemplo n.º 16
0
    def test_stack_explicit_frames(self):
        def bar():
            return inspect.stack()

        frames = bar()

        self.client.captureMessage("test", stack=iter_stack_frames(frames))

        self.assertEquals(len(self.client.events), 1)
        event = self.client.events.pop(0)
        self.assertEquals(event["message"], "test")
        self.assertTrue("sentry.interfaces.Stacktrace" in event)
        self.assertEquals(len(frames), len(event["sentry.interfaces.Stacktrace"]["frames"]))
        for frame, frame_i in zip(frames, event["sentry.interfaces.Stacktrace"]["frames"]):
            self.assertEquals(frame[0].f_code.co_filename, frame_i["abs_path"])
            self.assertEquals(frame[0].f_code.co_name, frame_i["function"])
Ejemplo n.º 17
0
    def test_stack_explicit_frames(self):
        def bar():
            return inspect.stack()

        frames = bar()

        self.client.captureMessage('test', stack=iter_stack_frames(frames))

        self.assertEquals(len(self.client.events), 1)
        event = self.client.events.pop(0)
        self.assertEquals(event['message'], 'test')
        assert 'stacktrace' in event
        self.assertEquals(len(frames), len(event['stacktrace']['frames']))
        for frame, frame_i in zip(frames, event['stacktrace']['frames']):
            self.assertEquals(frame[0].f_code.co_filename, frame_i['abs_path'])
            self.assertEquals(frame[0].f_code.co_name, frame_i['function'])
Ejemplo n.º 18
0
    def test_stack_explicit_frames(self):
        def bar():
            return inspect.stack()

        frames = bar()

        self.client.captureMessage('test', stack=iter_stack_frames(frames))

        self.assertEquals(len(self.client.events), 1)
        event = self.client.events.pop(0)
        self.assertEquals(event['message'], 'test')
        assert 'stacktrace' in event
        self.assertEquals(len(frames), len(event['stacktrace']['frames']))
        for frame, frame_i in zip(frames, event['stacktrace']['frames']):
            self.assertEquals(frame[0].f_code.co_filename, frame_i['abs_path'])
            self.assertEquals(frame[0].f_code.co_name, frame_i['function'])
Ejemplo n.º 19
0
    def test_stack_explicit_frames(self):
        def bar():
            return inspect.stack()

        frames = bar()

        self.client.create_from_text('test', stack=iter_stack_frames(frames))

        self.assertEquals(len(self.client.events), 1)
        event = self.client.events.pop(0)
        self.assertEquals(event['message'], 'test')
        data = event['data']['__sentry__']
        self.assertTrue('frames' in data)
        self.assertEquals(len(frames), len(data['frames']))

        for frame, frame_i in zip(frames, data['frames']):
            self.assertEquals(frame[0].f_code.co_filename, frame_i['filename'])
            self.assertEquals(frame[0].f_code.co_name, frame_i['function'])
Ejemplo n.º 20
0
 def raven_log(self, event):
     f = event["log_failure"]
     stack = None
     extra = dict()
     tb = f.getTracebackObject()
     if not tb:
         # include the current stack for at least some context
         stack = list(iter_stack_frames())[4:]  # approx.
         extra = dict(no_failure_tb=True)
     extra.update(
         log_format=event.get('log_format'),
         log_namespace=event.get('log_namespace'),
         client_info=event.get('client_info'),
         )
     reactor.callFromThread(
         self.raven_client.captureException,
         exc_info=(f.type, f.value, tb),
         stack=stack,
         extra=extra,
     )
     # just in case
     del tb
Ejemplo n.º 21
0
    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
Ejemplo n.º 22
0
 def raven_log(self, event):
     f = event["log_failure"]
     stack = None
     extra = dict()
     tb = f.getTracebackObject()
     if not tb:
         # include the current stack for at least some
         # context. sentry's expecting that "Frames should be
         # sorted from oldest to newest."
         stack = reversed(list(iter_stack_frames())[5:])  # approx.
         extra = dict(no_failure_tb=True)
     extra.update(
         log_format=event.get('log_format'),
         log_namespace=event.get('log_namespace'),
         client_info=event.get('client_info'),
     )
     reactor.callFromThread(
         self.raven_client.captureException,
         exc_info=(f.type, f.value, tb),
         stack=stack,
         extra=extra,
     )
     # just in case
     del tb
Ejemplo n.º 23
0
    def test_logger(self):
        client = TempStoreClient(include_paths=['tests', 'raven'])
        handler = SentryHandler(client)

        logger = self.logger
        logger.handlers = []
        logger.addHandler(handler)

        logger.error('This is a test error')

        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['logger'], __name__)
        self.assertEquals(event['level'], logging.ERROR)
        self.assertEquals(event['message'], 'This is a test error')
        self.assertFalse('sentry.interfaces.Stacktrace' in event)
        self.assertFalse('sentry.interfaces.Exception' in event)
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test error')
        self.assertEquals(msg['params'], ())

        logger.warning('This is a test warning')
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['logger'], __name__)
        self.assertEquals(event['level'], logging.WARNING)
        self.assertEquals(event['message'], 'This is a test warning')
        self.assertFalse('sentry.interfaces.Stacktrace' in event)
        self.assertFalse('sentry.interfaces.Exception' in event)
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test warning')
        self.assertEquals(msg['params'], ())

        logger.info('This is a test info with a url',
                    extra=dict(data=dict(url='http://example.com', ), ))
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['extra']['url'], 'http://example.com')
        self.assertFalse('sentry.interfaces.Stacktrace' in event)
        self.assertFalse('sentry.interfaces.Exception' in event)
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test info with a url')
        self.assertEquals(msg['params'], ())

        try:
            raise ValueError('This is a test ValueError')
        except ValueError:
            logger.info('This is a test info with an exception', exc_info=True)

        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)

        self.assertEquals(event['message'],
                          'This is a test info with an exception')
        self.assertTrue('sentry.interfaces.Stacktrace' in event)
        self.assertTrue('sentry.interfaces.Exception' in event)
        exc = event['sentry.interfaces.Exception']
        self.assertEquals(exc['type'], 'ValueError')
        self.assertEquals(exc['value'], 'This is a test ValueError')
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'],
                          'This is a test info with an exception')
        self.assertEquals(msg['params'], ())

        # test stacks
        logger.info('This is a test of stacks', extra={'stack': True})
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertTrue('sentry.interfaces.Stacktrace' in event)
        frames = event['sentry.interfaces.Stacktrace']['frames']
        self.assertNotEquals(len(frames), 1)
        frame = frames[0]
        self.assertEquals(frame['module'], __name__)
        self.assertFalse('sentry.interfaces.Exception' in event)
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test of stacks')
        self.assertEquals(msg['params'], ())
        self.assertEquals(event['culprit'],
                          'tests.handlers.logging.tests.test_logger')
        self.assertEquals(event['message'], 'This is a test of stacks')

        # test no stacks
        logger.info('This is a test of no stacks', extra={'stack': False})
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event.get('culprit'), None)
        self.assertEquals(event['message'], 'This is a test of no stacks')
        self.assertFalse('sentry.interfaces.Stacktrace' in event)
        self.assertFalse('sentry.interfaces.Exception' in event)
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test of no stacks')
        self.assertEquals(msg['params'], ())

        # test args
        logger.info('This is a test of %s', 'args')
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['message'], 'This is a test of args')
        self.assertFalse('sentry.interfaces.Stacktrace' in event)
        self.assertFalse('sentry.interfaces.Exception' in event)
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test of %s')
        self.assertEquals(msg['params'], ('args', ))

        # test explicit stack
        logger.info('This is a test of stacks',
                    extra={'stack': iter_stack_frames()})
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['culprit'],
                          'tests.handlers.logging.tests.test_logger')
        self.assertEquals(event['message'], 'This is a test of stacks')
        self.assertFalse('sentry.interfaces.Exception' in event)
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test of stacks')
        self.assertEquals(msg['params'], ())
        self.assertTrue('sentry.interfaces.Stacktrace' in event)
Ejemplo n.º 24
0
    def _emit(self, record, **kwargs):
        data = {}

        extra = getattr(record, 'data', None)
        if not isinstance(extra, dict):
            if extra:
                extra = {'data': extra}
            else:
                extra = {}

        for k, v in six.iteritems(vars(record)):
            if k in RESERVED:
                continue
            if k.startswith('_'):
                continue
            if '.' not in k and k not in ('culprit', 'server_name', 'fingerprint'):
                extra[k] = v
            else:
                data[k] = v

        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            stack = self._get_targetted_stack(stack, record)

        date = datetime.datetime.utcfromtimestamp(record.created)
        event_type = 'raven.events.Message'
        handler_kwargs = {
            'params': record.args,
        }
        try:
            handler_kwargs['message'] = six.text_type(record.msg)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs['message'] = repr(record.msg)[1:-1]

        try:
            handler_kwargs['formatted'] = six.text_type(record.message)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs['formatted'] = repr(record.message)[1:-1]

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if record.exc_info and all(record.exc_info):
            # capture the standard message first so that we ensure
            # the event is recorded as an exception, in addition to having our
            # message interface attached
            handler = self.client.get_handler(event_type)
            data.update(handler.capture(**handler_kwargs))

            event_type = 'raven.events.Exception'
            handler_kwargs = {'exc_info': record.exc_info}

        # HACK: discover a culprit when we normally couldn't
        elif not (data.get('stacktrace') or data.get('culprit')) and (record.name or record.funcName):
            culprit = label_from_frame({'module': record.name, 'function': record.funcName})
            if culprit:
                data['culprit'] = culprit

        data['level'] = record.levelno
        data['logger'] = record.name

        if hasattr(record, 'tags'):
            kwargs['tags'] = record.tags
        elif self.tags:
            kwargs['tags'] = self.tags

        kwargs.update(handler_kwargs)

        return self.client.capture(
            event_type, stack=stack, data=data,
            extra=extra, date=date, **kwargs)
Ejemplo n.º 25
0
def base_kwargs(extra=None):
    kwargs = {'stack': iter_stack_frames(get_stacks())}
    if extra is not None:
        kwargs['extra'] = extra
    return kwargs
Ejemplo n.º 26
0
    def _emit(self, record, **kwargs):
        data, extra = extract_extra(record)

        # Use client name as default user id
        data.setdefault('user', {'id': self.client.name})

        # Retrieve stack
        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            stack = self._get_targetted_stack(stack, record)

        # Build message
        date = datetime.datetime.utcfromtimestamp(record.created)
        event_type = 'raven.events.Message'
        handler_kwargs = {
            'params': record.args,
        }

        try:
            handler_kwargs['message'] = text_type(record.msg)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs['message'] = repr(record.msg)[1:-1]

        try:
            handler_kwargs['formatted'] = text_type(record.message)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs['formatted'] = repr(record.message)[1:-1]

        # Retrieve exception information from record
        try:
            exc_info = self._exc_info(record)
        except Exception as ex:
            log.info('Unable to retrieve exception info - %s', ex, exc_info=True)
            exc_info = None

        # Parse exception information
        exception_hash = None

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if exc_info and len(exc_info) == 3 and all(exc_info):
            message = handler_kwargs.get('formatted')

            # Replace exception messages with more helpful details
            if not record.exc_info and message and RE_TRACEBACK_HEADER.match(message):
                # Generate new record title
                handler_kwargs['formatted'] = '%s\n\n%s' % (
                    self._generate_title(record, exc_info),
                    message
                )
            elif not record.exc_info:
                log.debug("Message %r doesn't match traceback header", message)

            # capture the standard message first so that we ensure
            # the event is recorded as an exception, in addition to having our
            # message interface attached
            handler = self.client.get_handler(event_type)
            data.update(handler.capture(**handler_kwargs))

            event_type = 'raven.events.Exception'
            handler_kwargs = {'exc_info': exc_info}

            # Calculate exception hash
            exception_hash = ErrorHasher.hash(exc_info=exc_info)

        # HACK: discover a culprit when we normally couldn't
        elif not (data.get('stacktrace') or data.get('culprit')) and (record.name or record.funcName):
            culprit = self._label_from_frame({'module': record.name, 'function': record.funcName})

            if culprit:
                data['culprit'] = culprit

        data['level'] = record.levelno
        data['logger'] = record.name

        # Store record `tags` in message
        if hasattr(record, 'tags'):
            kwargs['tags'] = record.tags
        elif self.tags:
            kwargs['tags'] = self.tags

        # Store `exception_hash` in message (if defined)
        if exception_hash:
            if 'tags' not in kwargs:
                kwargs['tags'] = {}

            kwargs['tags']['exception.hash'] = exception_hash

        kwargs.update(handler_kwargs)

        return self.client.capture(
            event_type, stack=stack, data=data,
            extra=extra, date=date, **kwargs
        )
Ejemplo n.º 27
0
    def _emit(self, record, **kwargs):
        data = {}
        extra = getattr(record, 'data', None)
        if not isinstance(extra, dict):
            if extra:
                extra = {'data': extra}
            else:
                extra = {}
        for k, v in iteritems(vars(record)):
            if k in RESERVED:
                continue
            if k.startswith('_'):
                continue
            if '.' not in k and k not in ('culprit', 'server_name',
                                          'fingerprint'):
                extra[k] = v
            else:
                data[k] = v

        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()
        if stack:
            stack = self._get_targetted_stack(stack, record)
        date = datetime.datetime.utcfromtimestamp(record.created)
        event_type = 'raven.events.Message'
        handler_kwargs = {'params': record.args}
        try:
            handler_kwargs['message'] = text_type(record.msg)
        except UnicodeDecodeError:
            handler_kwargs['message'] = repr(record.msg)[1:-1]

        try:
            handler_kwargs['formatted'] = text_type(record.message)
        except UnicodeDecodeError:
            handler_kwargs['formatted'] = repr(record.message)[1:-1]

        if record.exc_info and all(record.exc_info):
            handler = self.client.get_handler(event_type)
            data.update(handler.capture(**handler_kwargs))
            event_type = 'raven.events.Exception'
            handler_kwargs = {'exc_info': record.exc_info}
        elif not (data.get('stacktrace')
                  or data.get('culprit')) and (record.name or record.funcName):
            culprit = label_from_frame({
                'module': record.name,
                'function': record.funcName
            })
            if culprit:
                data['culprit'] = culprit
        data['level'] = record.levelno
        data['logger'] = record.name
        if hasattr(record, 'tags'):
            kwargs['tags'] = record.tags
        elif self.tags:
            kwargs['tags'] = self.tags
        kwargs.update(handler_kwargs)
        return self.client.capture(event_type,
                                   stack=stack,
                                   data=data,
                                   extra=extra,
                                   date=date,
                                   **kwargs)
    def emit(self, record):
        if record.levelno <= logging.ERROR:
            request = None
            exc_info = None
            for frame_info in getouterframes(currentframe()):
                frame = frame_info[0]
                if not request:
                    request = frame.f_locals.get("request", None)
                    # i.e. collective.solr sets request as string
                    if isinstance(request, basestring):
                        request = None
                    if not request:
                        view = frame.f_locals.get("self", None)
                        try:
                            request = getattr(view, "request", None)
                        except RuntimeError:
                            request = None
                if not exc_info:
                    exc_info = frame.f_locals.get("exc_info", None)
                    if not hasattr(exc_info, "__getitem__"):
                        exc_info = None
                if request and exc_info:
                    break

            if exc_info:
                record.exc_info = exc_info
                record.stack = iter_stack_frames(getinnerframes(exc_info[2]))
            if request:
                try:
                    body_pos = request.stdin.tell()
                    request.stdin.seek(0)
                    body = request.stdin.read()
                    request.stdin.seek(body_pos)
                    # not all request.environ keys are json serializable
                    envCopy = {}
                    for key in request.environ:
                        try:
                            json.dumps(request.environ[key])
                            envCopy[key] = request.environ[key]
                        except (TypeError, UnicodeDecodeError, UnicodeEncodeError):
                            pass
                    http = dict(
                        headers=envCopy,
                        url=request.getURL(),
                        method=request.method,
                        host=request.environ.get("REMOTE_ADDR", ""),
                        data=body,
                    )
                    if "HTTP_USER_AGENT" in http["headers"]:
                        if "User-Agent" not in http["headers"]:
                            http["headers"]["User-Agent"] = http["headers"]["HTTP_USER_AGENT"]
                    if "QUERY_STRING" in http["headers"]:
                        http["query_string"] = http["headers"]["QUERY_STRING"]
                    setattr(record, "sentry.interfaces.Http", http)
                    user = request.get("AUTHENTICATED_USER", None)
                    if user is not None and user != nobody:
                        email = ""
                        if hasattr(user, "getProperty") and user.getProperty("email"):
                            email = user.getProperty("email")

                        user_dict = dict(id=user.getId(), is_authenticated=True, email=email)
                    else:
                        user_dict = {"is_authenticated": False}
                    setattr(record, "sentry.interfaces.User", user_dict)
                except (AttributeError, KeyError):
                    logger.warning("Could not extract data from request", exc_info=True)
        return super(ZopeSentryHandler, self).emit(record)
Ejemplo n.º 29
0
    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)
Ejemplo n.º 30
0
    def _emit(self, record, **kwargs):
        data = {}

        for k, v in record.__dict__.iteritems():
            if '.' not in k and k not in ('culprit', ):
                continue
            data[k] = v

        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            # we might need to traverse this multiple times, so coerce it to a list
            stack = list(stack)
            frames = []
            started = False
            last_mod = ''
            for item in stack:
                if isinstance(item, (list, tuple)):
                    frame, lineno = item
                else:
                    frame, lineno = item, item.f_lineno

                if not started:
                    f_globals = getattr(frame, 'f_globals', {})
                    module_name = f_globals.get('__name__', '')
                    if (last_mod and last_mod.startswith('logging')) \
                        and not module_name.startswith('logging'):
                        started = True
                    else:
                        last_mod = module_name
                        continue
                frames.append((frame, lineno))

            # We must've not found a starting point
            if not frames:
                frames = stack

            stack = frames

        extra = getattr(record, 'data', None)
        if not isinstance(extra, dict):
            if extra:
                extra = {'data': extra}
            else:
                extra = {}

        # Add in all of the data from the record that we aren't already capturing
        for k in record.__dict__.keys():
            if k in RESERVED:
                continue
            if k.startswith('_'):
                continue
            extra[k] = record.__dict__[k]

        date = datetime.datetime.utcfromtimestamp(record.created)
        event_type = 'raven.events.Message'
        handler_kwargs = {'message': record.msg, 'params': record.args}

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if record.exc_info and all(record.exc_info):
            # capture the standard message first so that we ensure
            # the event is recorded as an exception, in addition to having our
            # message interface attached
            handler = self.client.get_handler(event_type)
            data.update(handler.capture(**handler_kwargs))
            # ensure message is propagated, otherwise the exception will overwrite it
            data['message'] = handler.to_string(data)

            event_type = 'raven.events.Exception'
            handler_kwargs = {'exc_info': record.exc_info}

        # HACK: discover a culprit when we normally couldn't
        elif not (data.get('sentry.interfaces.Stacktrace')
                  or data.get('culprit')) and (record.name or record.funcName):
            culprit = label_from_frame({
                'module': record.name,
                'function': record.funcName
            })
            if culprit:
                data['culprit'] = culprit

        data['level'] = record.levelno
        data['logger'] = record.name

        if hasattr(record, 'tags'):
            kwargs['tags'] = record.tags

        kwargs.update(handler_kwargs)

        return self.client.capture(event_type,
                                   stack=stack,
                                   data=data,
                                   extra=extra,
                                   date=date,
                                   **kwargs)
Ejemplo n.º 31
0
    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)
Ejemplo n.º 32
0
    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
        print("SENTRY_EVENT_ID: " + event_id)

        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)
                    )

        transaction = None
        if not culprit:
            transaction = 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 transaction:
            data['transaction'] = transaction
        elif 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)
        data.setdefault('repos', self.repos)

        # 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
                })

        frame = data['exception']['values'][0]['stacktrace']['frames'][0]
        if frame['vars']['SENTRY_CODE_SNIPPET'][0] == "'" and frame['vars']['SENTRY_CODE_SNIPPET'][-1] == "'":
            code = frame['vars']['SENTRY_CODE_SNIPPET'][1:-1]
        else:
            code = frame['vars']['SENTRY_CODE_SNIPPET']
        lineno = frame['lineno']
        frame['context_line'] = code.split('\n')[lineno - 1]
        frame['post_context'] = code.split('\n')[lineno:]
        frame['pre_context'] = code.split('\n')[:lineno - 1]
        for var in ['request', 'SENTRY_CODE_SNIPPET', 'SENTRY_STDOUT_SOCKET', 'SENTRY_STDOUT_FUNCTION']:
            frame['vars'].pop(var, None)

        return data
Ejemplo n.º 33
0
    def test_logger(self):
        client = TempStoreClient(include_paths=['tests', 'raven'])
        handler = SentryHandler(client)

        logger = self.logger
        logger.handlers = []
        logger.addHandler(handler)

        logger.error('This is a test error')

        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['logger'], __name__)
        self.assertEquals(event['level'], logging.ERROR)
        self.assertEquals(event['message'], 'This is a test error')
        self.assertFalse('sentry.interfaces.Stacktrace' in event)
        self.assertFalse('sentry.interfaces.Exception' in event)
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test error')
        self.assertEquals(msg['params'], ())

        logger.warning('This is a test warning')
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['logger'], __name__)
        self.assertEquals(event['level'], logging.WARNING)
        self.assertEquals(event['message'], 'This is a test warning')
        self.assertFalse('sentry.interfaces.Stacktrace' in event)
        self.assertFalse('sentry.interfaces.Exception' in event)
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test warning')
        self.assertEquals(msg['params'], ())

        logger.info('This is a test info with a url', extra=dict(
            data=dict(
                url='http://example.com',
            ),
        ))
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['extra']['url'], 'http://example.com')
        self.assertFalse('sentry.interfaces.Stacktrace' in event)
        self.assertFalse('sentry.interfaces.Exception' in event)
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test info with a url')
        self.assertEquals(msg['params'], ())

        try:
            raise ValueError('This is a test ValueError')
        except ValueError:
            logger.info('This is a test info with an exception', exc_info=True)

        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)

        self.assertEquals(event['message'], 'This is a test info with an exception')
        self.assertTrue('sentry.interfaces.Stacktrace' in event)
        self.assertTrue('sentry.interfaces.Exception' in event)
        exc = event['sentry.interfaces.Exception']
        self.assertEquals(exc['type'], 'ValueError')
        self.assertEquals(exc['value'], 'This is a test ValueError')
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test info with an exception')
        self.assertEquals(msg['params'], ())

        # test stacks
        logger.info('This is a test of stacks', extra={'stack': True})
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertTrue('sentry.interfaces.Stacktrace' in event)
        frames = event['sentry.interfaces.Stacktrace']['frames']
        self.assertNotEquals(len(frames), 1)
        frame = frames[0]
        self.assertEquals(frame['module'], __name__)
        self.assertFalse('sentry.interfaces.Exception' in event)
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test of stacks')
        self.assertEquals(msg['params'], ())
        self.assertEquals(event['culprit'], 'tests.handlers.logging.tests.test_logger')
        self.assertEquals(event['message'], 'This is a test of stacks')

        # test no stacks
        logger.info('This is a test of no stacks', extra={'stack': False})
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event.get('culprit'), None)
        self.assertEquals(event['message'], 'This is a test of no stacks')
        self.assertFalse('sentry.interfaces.Stacktrace' in event)
        self.assertFalse('sentry.interfaces.Exception' in event)
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test of no stacks')
        self.assertEquals(msg['params'], ())

        # test args
        logger.info('This is a test of %s', 'args')
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['message'], 'This is a test of args')
        self.assertFalse('sentry.interfaces.Stacktrace' in event)
        self.assertFalse('sentry.interfaces.Exception' in event)
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test of %s')
        self.assertEquals(msg['params'], ('args',))

        # test explicit stack
        logger.info('This is a test of stacks', extra={'stack': iter_stack_frames()})
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['culprit'], 'tests.handlers.logging.tests.test_logger')
        self.assertEquals(event['message'], 'This is a test of stacks')
        self.assertFalse('sentry.interfaces.Exception' in event)
        self.assertTrue('sentry.interfaces.Message' in event)
        msg = event['sentry.interfaces.Message']
        self.assertEquals(msg['message'], 'This is a test of stacks')
        self.assertEquals(msg['params'], ())
        self.assertTrue('sentry.interfaces.Stacktrace' in event)
Ejemplo n.º 34
0
    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
Ejemplo n.º 35
0
    def _emit(self, record, **kwargs):
        data = {}

        extra = getattr(record, "data", None)
        if not isinstance(extra, dict):
            if extra:
                extra = {"data": extra}
            else:
                extra = {}

        for k, v in six.iteritems(vars(record)):
            if k in RESERVED:
                continue
            if k.startswith("_"):
                continue
            if "." not in k and k not in ("culprit", "server_name"):
                extra[k] = v
            else:
                data[k] = v

        stack = getattr(record, "stack", None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            stack = self._get_targetted_stack(stack, record)

        date = datetime.datetime.utcfromtimestamp(record.created)
        event_type = "raven.events.Message"
        handler_kwargs = {"params": record.args}
        try:
            handler_kwargs["message"] = six.text_type(record.msg)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs["message"] = repr(record.msg)[1:-1]

        try:
            handler_kwargs["formatted"] = six.text_type(record.message)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs["formatted"] = repr(record.message)[1:-1]

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if record.exc_info and all(record.exc_info):
            # capture the standard message first so that we ensure
            # the event is recorded as an exception, in addition to having our
            # message interface attached
            handler = self.client.get_handler(event_type)
            data.update(handler.capture(**handler_kwargs))

            event_type = "raven.events.Exception"
            handler_kwargs = {"exc_info": record.exc_info}

        # HACK: discover a culprit when we normally couldn't
        elif not (data.get("stacktrace") or data.get("culprit")) and (record.name or record.funcName):
            culprit = label_from_frame({"module": record.name, "function": record.funcName})
            if culprit:
                data["culprit"] = culprit

        data["level"] = record.levelno
        data["logger"] = record.name

        if hasattr(record, "tags"):
            kwargs["tags"] = record.tags

        kwargs.update(handler_kwargs)

        return self.client.capture(event_type, stack=stack, data=data, extra=extra, date=date, **kwargs)
Ejemplo n.º 36
0
Archivo: base.py Proyecto: d1on/raven
    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)
Ejemplo n.º 37
0
    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 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 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

        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 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.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
Ejemplo n.º 38
0
    def _emit(self, record, **kwargs):
        data = {}

        for k, v in record.__dict__.iteritems():
            if '.' not in k and k not in ('culprit',):
                continue
            data[k] = v

        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            # we might need to traverse this multiple times, so coerce it to a list
            stack = list(stack)
            frames = []
            started = False
            last_mod = ''
            for item in stack:
                if isinstance(item, (list, tuple)):
                    frame, lineno = item
                else:
                    frame, lineno = item, item.f_lineno

                if not started:
                    f_globals = getattr(frame, 'f_globals', {})
                    module_name = f_globals.get('__name__', '')
                    if (last_mod and last_mod.startswith('logging')) \
                        and not module_name.startswith('logging'):
                        started = True
                    else:
                        last_mod = module_name
                        continue
                frames.append((frame, lineno))

            # We must've not found a starting point
            if not frames:
                frames = stack

            stack = frames

        extra = getattr(record, 'data', None)
        if not isinstance(extra, dict):
            if extra:
                extra = {'data': extra}
            else:
                extra = {}

        # Add in all of the data from the record that we aren't already capturing
        for k in record.__dict__.keys():
            if k in RESERVED:
                continue
            if k.startswith('_'):
                continue
            extra[k] = record.__dict__[k]

        date = datetime.datetime.utcfromtimestamp(record.created)

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if record.exc_info and all(record.exc_info):
            handler = self.client.get_handler('raven.events.Exception')

            data.update(handler.capture(exc_info=record.exc_info))

        # HACK: discover a culprit when we normally couldn't
        elif not (data.get('sentry.interfaces.Stacktrace') or data.get('culprit')) and (record.name or record.funcName):
            data['culprit'] = '%s.%s' % (record.name or '<unknown>', record.funcName or '<unknown>')

        data['level'] = record.levelno
        data['logger'] = record.name

        return self.client.capture('Message', message=record.msg, params=record.args,
                            stack=stack, data=data, extra=extra,
                            date=date, **kwargs)
Ejemplo n.º 39
0
    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', {})
        data.setdefault('level', logging.ERROR)

        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:
            if 'sentry.interfaces.Stacktrace' in data:
                culprit = get_culprit(
                    data['sentry.interfaces.Stacktrace']['frames'])
            elif data.get('sentry.interfaces.Exception', {}).get('stacktrace'):
                culprit = get_culprit(data['sentry.interfaces.Exception']
                                      ['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'] = 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'] = 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
Ejemplo n.º 40
0
    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
Ejemplo n.º 41
0
    def _emit(self, record, **kwargs):
        data = {}

        extra = getattr(record, 'data', None)
        if not isinstance(extra, dict):
            if extra:
                extra = {'data': extra}
            else:
                extra = {}

        for k, v in six.iteritems(vars(record)):
            if k in RESERVED:
                continue
            if k.startswith('_'):
                continue
            if '.' not in k and k not in ('culprit',):
                extra[k] = v
            else:
                data[k] = v

        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            stack = self._get_targetted_stack(stack)

        date = datetime.datetime.utcfromtimestamp(record.created)
        event_type = 'raven.events.Message'
        handler_kwargs = {
            'message': record.msg,
            'params': record.args,
            'formatted': record.message,
        }

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if record.exc_info and all(record.exc_info):
            # capture the standard message first so that we ensure
            # the event is recorded as an exception, in addition to having our
            # message interface attached
            handler = self.client.get_handler(event_type)
            data.update(handler.capture(**handler_kwargs))

            event_type = 'raven.events.Exception'
            handler_kwargs = {'exc_info': record.exc_info}

        # HACK: discover a culprit when we normally couldn't
        elif not (data.get('sentry.interfaces.Stacktrace') or data.get('culprit')) and (record.name or record.funcName):
            culprit = label_from_frame({'module': record.name, 'function': record.funcName})
            if culprit:
                data['culprit'] = culprit

        data['level'] = record.levelno
        data['logger'] = record.name

        if hasattr(record, 'tags'):
            kwargs['tags'] = record.tags

        kwargs.update(handler_kwargs)

        return self.client.capture(
            event_type, stack=stack, data=data,
            extra=extra, date=date, **kwargs)
Ejemplo n.º 42
0
    def emit(self, record):
        if record.levelno <= logging.ERROR:
            request = None
            exc_info = None
            for frame_info in getouterframes(currentframe()):
                frame = frame_info[0]
                if not request:
                    request = frame.f_locals.get('request', None)
                    if not request:
                        view = frame.f_locals.get('self', None)
                        request = getattr(view, 'request', None)
                if not exc_info:
                    exc_info = frame.f_locals.get('exc_info', None)
                    if not hasattr(exc_info, '__getitem__'):
                        exc_info = None
                if request and exc_info:
                    break

            if exc_info:
                record.exc_info = exc_info
                record.stack = \
                    iter_stack_frames(getinnerframes(exc_info[2]))
            if request:
                try:
                    body_pos = request.stdin.tell()
                    request.stdin.seek(0)
                    body = request.stdin.read()
                    request.stdin.seek(body_pos)
                    http = dict(headers=request.environ,
                                url=request.getURL(),
                                method=request.get('REQUEST_METHOD', ''),
                                host=request.environ.get('REMOTE_ADDR',
                                ''), data=body)
                    if 'HTTP_USER_AGENT' in http['headers']:
                        if 'User-Agent' not in http['headers']:
                            http['headers']['User-Agent'] = \
                                http['headers']['HTTP_USER_AGENT']
                    if 'QUERY_STRING' in http['headers']:
                        http['query_string'] = http['headers'
                                ]['QUERY_STRING']
                    setattr(record, 'sentry.interfaces.Http', http)
                    user = request.get('AUTHENTICATED_USER', None)
                    if user is not None:
                        user_dict = dict(id=user.getId(),
                                         is_authenticated=user.has_role('Authenticated'),
                                         email=user.getProperty('email') or '',
                                         roles=getattr(request, 'roles', ()))
                    else:
                        user_dict = {'is_authenticated': False, 'roles': getattr(request, 'roles', ())}
                    setattr(record, 'sentry.interfaces.User', user_dict)
                except (AttributeError, KeyError):
                    # We don't want to go recursive
                    pass
        
        error_number = SITE_ERROR_NO.findall(record.msg)
        if error_number:
            error_number = error_number[0][0]
        else:
            error_number = None
        
        if error_number:
            setattr(record, 'zope.errorid', error_number)
            error_type = [line for line in CRITICAL_LINE.findall(record.msg) if 'Traceback' not in line]
            if error_type:
                error_type = error_type[0]
                new_msg = record.msg.replace(error_number, error_type)
                record.message = record.msg = new_msg
        try:
            e=sys.exc_info()
            if e[0]:
                exception_info = {"type":e[0].__name__, 
                    "value":str(e[1]), "module":e[0].__module__}
                setattr(record, 'sentry.interfaces.Exception', exception_info)
                if error_number:
                    # This is covered by the rest of our metadata
                    new_msg = "%(type)s: %(value)s" % (exception_info)
                    record.msg = new_msg
                    record.message = new_msg
            if e[2]:
                tb_info = {"frames": []}
                frames = traceback.extract_tb(e[2])
                for frame in frames:
                    try:
                        # I am an evil thing
                        tb_module_guess = [m for m in sys.modules.keys() if m.replace(".","/") in frame[0]]
                        # Longest guessed module name
                        tb_module_guess = sorted(tb_module_guess, key=lambda x:len(x))[-1]
                    except:
                        tb_module_guess = None
                    tb_info["frames"].append(
                            {"filename":frame[0],
                             "lineno":frame[1],
                             "function":frame[2],
                             "context_line":frame[3],
                             "module":tb_module_guess,
                             })
                setattr(record, 'sentry.interfaces.Stacktrace', tb_info)
                lowest_frame = tb_info['frames'][-1]
                if "/" not in lowest_frame['filename']:
                    culprit = "%s %s" % (lowest_frame['filename'], lowest_frame['function'])
                    setattr(record, 'culprit', culprit)
        except (AttributeError, KeyError, TypeError):
            pass
        
        return super(ZopeSentryHandler, self).emit(record)
Ejemplo n.º 43
0
    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
Ejemplo n.º 44
0
Archivo: tests.py Proyecto: d1on/raven
    def test_logger(self):
        client = TempStoreClient(include_paths=['tests'])
        handler = SentryHandler(client)

        logger = self.logger
        logger.handlers = []
        logger.addHandler(handler)

        logger.error('This is a test error')

        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['logger'], __name__)
        self.assertEquals(event['level'], logging.ERROR)
        self.assertEquals(event['message'], 'This is a test error')
        self.assertFalse('frames' in event['data']['__sentry__'])

        logger.warning('This is a test warning')
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['logger'], __name__)
        self.assertEquals(event['level'], logging.WARNING)
        self.assertEquals(event['message'], 'This is a test warning')
        self.assertFalse('frames' in event['data']['__sentry__'])

        logger.info('This is a test info with a url', extra=dict(url='http://example.com'))
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['url'], 'http://example.com')
        self.assertFalse('frames' in event['data']['__sentry__'])

        try:
            raise ValueError('This is a test ValueError')
        except ValueError:
            logger.info('This is a test info with an exception', exc_info=True)

        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)

        self.assertEquals(event['class_name'], 'ValueError')
        self.assertEquals(event['message'], 'This is a test info with an exception')
        self.assertTrue('__sentry__' in event['data'])
        self.assertTrue('exception' in event['data']['__sentry__'])
        self.assertTrue('frames' in event['data']['__sentry__'])

        # test stacks
        logger.info('This is a test of stacks', extra={'stack': True})
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['view'], 'tests.handlers.tests.test_logger')
        self.assertEquals(event['message'], 'This is a test of stacks')
        self.assertTrue('__sentry__' in event['data'])
        self.assertTrue('frames' in event['data']['__sentry__'])

        # test no stacks
        logger.info('This is a test of no stacks', extra={'stack': False})
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['view'], None)
        self.assertEquals(event['message'], 'This is a test of no stacks')
        self.assertTrue('__sentry__' in event['data'])
        self.assertFalse('frames' in event['data']['__sentry__'])

        # test explicit stack
        logger.info('This is a test of stacks', extra={'stack': iter_stack_frames()})
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['view'], 'tests.handlers.tests.test_logger')
        self.assertEquals(event['message'], 'This is a test of stacks')
        self.assertTrue('__sentry__' in event['data'])
        self.assertTrue('frames' in event['data']['__sentry__'])
Ejemplo n.º 45
0
    def _emit(self, record, **kwargs):
        data, extra = extract_extra(record)

        # Use client name as default user id
        data.setdefault('user', {'id': self.client.name})

        # Retrieve stack
        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            stack = self._get_targetted_stack(stack, record)

        # Build message
        date = datetime.datetime.utcfromtimestamp(record.created)
        event_type = 'raven.events.Message'
        handler_kwargs = {
            'params': record.args,
        }

        try:
            handler_kwargs['message'] = text_type(record.msg)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs['message'] = repr(record.msg)[1:-1]

        try:
            handler_kwargs['formatted'] = text_type(record.message)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs['formatted'] = repr(record.message)[1:-1]

        # Retrieve exception information from record
        try:
            exc_info = self._exc_info(record)
        except Exception as ex:
            log.info('Unable to retrieve exception info - %s',
                     ex,
                     exc_info=True)
            exc_info = None

        # Parse exception information
        exception_hash = None

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if exc_info and len(exc_info) == 3 and all(exc_info):
            message = handler_kwargs.get('formatted')

            # Replace exception messages with more helpful details
            if not record.exc_info and message and RE_TRACEBACK_HEADER.match(
                    message):
                # Generate new record title
                handler_kwargs['formatted'] = '%s\n\n%s' % (
                    self._generate_title(record, exc_info), message)
            elif not record.exc_info:
                log.debug("Message %r doesn't match traceback header", message)

            # capture the standard message first so that we ensure
            # the event is recorded as an exception, in addition to having our
            # message interface attached
            handler = self.client.get_handler(event_type)
            data.update(handler.capture(**handler_kwargs))

            event_type = 'raven.events.Exception'
            handler_kwargs = {'exc_info': exc_info}

            # Calculate exception hash
            exception_hash = ErrorHasher.hash(exc_info=exc_info)

        # HACK: discover a culprit when we normally couldn't
        elif not (data.get('stacktrace')
                  or data.get('culprit')) and (record.name or record.funcName):
            culprit = self._label_from_frame({
                'module': record.name,
                'function': record.funcName
            })

            if culprit:
                data['culprit'] = culprit

        data['level'] = record.levelno
        data['logger'] = record.name

        # Store record `tags` in message
        if hasattr(record, 'tags'):
            kwargs['tags'] = record.tags
        elif self.tags:
            kwargs['tags'] = self.tags

        # Store `exception_hash` in message (if defined)
        if exception_hash:
            if 'tags' not in kwargs:
                kwargs['tags'] = {}

            kwargs['tags']['exception.hash'] = exception_hash

        kwargs.update(handler_kwargs)

        return self.client.capture(event_type,
                                   stack=stack,
                                   data=data,
                                   extra=extra,
                                   date=date,
                                   **kwargs)
Ejemplo n.º 46
0
    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
Ejemplo n.º 47
0
    def _emit(self, record, **kwargs):
        data = {}

        for k, v in record.__dict__.iteritems():
            if '.' not in k and k not in ('culprit', ):
                continue
            data[k] = v

        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            # we might need to traverse this multiple times, so coerce it to a list
            stack = list(stack)
            frames = []
            started = False
            last_mod = ''
            for item in stack:
                if isinstance(item, (list, tuple)):
                    frame, lineno = item
                else:
                    frame, lineno = item, item.f_lineno

                if not started:
                    f_globals = getattr(frame, 'f_globals', {})
                    module_name = f_globals.get('__name__', '')
                    if (last_mod and last_mod.startswith('logging')) \
                        and not module_name.startswith('logging'):
                        started = True
                    else:
                        last_mod = module_name
                        continue
                frames.append((frame, lineno))

            # We must've not found a starting point
            if not frames:
                frames = stack

            stack = frames

        extra = getattr(record, 'data', None)
        if not isinstance(extra, dict):
            if extra:
                extra = {'data': extra}
            else:
                extra = {}

        # Add in all of the data from the record that we aren't already capturing
        for k in record.__dict__.keys():
            if k in RESERVED:
                continue
            if k.startswith('_'):
                continue
            extra[k] = record.__dict__[k]

        date = datetime.datetime.utcfromtimestamp(record.created)

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if record.exc_info and all(record.exc_info):
            handler = self.client.get_handler('raven.events.Exception')

            data.update(handler.capture(exc_info=record.exc_info))

        # HACK: discover a culprit when we normally couldn't
        elif not (data.get('sentry.interfaces.Stacktrace')
                  or data.get('culprit')) and (record.name or record.funcName):
            data['culprit'] = '%s.%s' % (record.name or '<unknown>',
                                         record.funcName or '<unknown>')

        data['level'] = record.levelno
        data['logger'] = record.name

        return self.client.capture('Message',
                                   message=record.msg,
                                   params=record.args,
                                   stack=stack,
                                   data=data,
                                   extra=extra,
                                   date=date,
                                   **kwargs)
Ejemplo n.º 48
0
    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
Ejemplo n.º 49
0
    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)
Ejemplo n.º 50
0
    def test_logger(self):
        client = TempStoreClient(include_paths=['tests'])
        handler = SentryHandler(client)

        logger = self.logger
        logger.handlers = []
        logger.addHandler(handler)

        logger.error('This is a test error')

        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['logger'], __name__)
        self.assertEquals(event['level'], logging.ERROR)
        self.assertEquals(event['message'], 'This is a test error')
        self.assertFalse('frames' in event['data']['__sentry__'])

        logger.warning('This is a test warning')
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['logger'], __name__)
        self.assertEquals(event['level'], logging.WARNING)
        self.assertEquals(event['message'], 'This is a test warning')
        self.assertFalse('frames' in event['data']['__sentry__'])

        logger.info('This is a test info with a url',
                    extra=dict(url='http://example.com'))
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['url'], 'http://example.com')
        self.assertFalse('frames' in event['data']['__sentry__'])

        try:
            raise ValueError('This is a test ValueError')
        except ValueError:
            logger.info('This is a test info with an exception', exc_info=True)

        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)

        self.assertEquals(event['class_name'], 'ValueError')
        self.assertEquals(event['message'],
                          'This is a test info with an exception')
        self.assertTrue('__sentry__' in event['data'])
        self.assertTrue('exception' in event['data']['__sentry__'])
        self.assertTrue('frames' in event['data']['__sentry__'])

        # test stacks
        logger.info('This is a test of stacks', extra={'stack': True})
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['view'], 'tests.handlers.tests.test_logger')
        self.assertEquals(event['message'], 'This is a test of stacks')
        self.assertTrue('__sentry__' in event['data'])
        self.assertTrue('frames' in event['data']['__sentry__'])

        # test no stacks
        logger.info('This is a test of no stacks', extra={'stack': False})
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['view'], None)
        self.assertEquals(event['message'], 'This is a test of no stacks')
        self.assertTrue('__sentry__' in event['data'])
        self.assertFalse('frames' in event['data']['__sentry__'])

        # test explicit stack
        logger.info('This is a test of stacks',
                    extra={'stack': iter_stack_frames()})
        self.assertEquals(len(client.events), 1)
        event = client.events.pop(0)
        self.assertEquals(event['view'], 'tests.handlers.tests.test_logger')
        self.assertEquals(event['message'], 'This is a test of stacks')
        self.assertTrue('__sentry__' in event['data'])
        self.assertTrue('frames' in event['data']['__sentry__'])
Ejemplo n.º 51
0
    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
Ejemplo n.º 52
0
    def _emit(self, record, **kwargs):
        data = {}

        extra = getattr(record, 'data', None)
        if not isinstance(extra, dict):
            if extra:
                extra = {'data': extra}
            else:
                extra = {}

        for k, v in iteritems(vars(record)):
            if k in RESERVED:
                continue
            if k.startswith('_'):
                continue
            if '.' not in k and k not in ('culprit', 'server_name', 'fingerprint'):
                extra[k] = v
            else:
                data[k] = v

        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            stack = self._get_targetted_stack(stack, record)

        date = datetime.datetime.utcfromtimestamp(record.created)
        event_type = 'raven.events.Message'
        handler_kwargs = {
            'params': record.args,
        }
        try:
            handler_kwargs['message'] = text_type(record.msg)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs['message'] = repr(record.msg)[1:-1]

        try:
            handler_kwargs['formatted'] = text_type(record.message)
        except UnicodeDecodeError:
            # Handle binary strings where it should be unicode...
            handler_kwargs['formatted'] = repr(record.message)[1:-1]

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if record.exc_info and all(record.exc_info):
            # capture the standard message first so that we ensure
            # the event is recorded as an exception, in addition to having our
            # message interface attached
            handler = self.client.get_handler(event_type)
            data.update(handler.capture(**handler_kwargs))

            event_type = 'raven.events.Exception'
            handler_kwargs = {'exc_info': record.exc_info}

        data['level'] = record.levelno
        data['logger'] = record.name

        if hasattr(record, 'tags'):
            kwargs['tags'] = record.tags
        elif self.tags:
            kwargs['tags'] = self.tags

        kwargs.update(handler_kwargs)

        return self.client.capture(
            event_type, stack=stack, data=data,
            extra=extra, date=date, **kwargs)
Ejemplo n.º 53
0
    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)
        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
Ejemplo n.º 54
0
    def _emit(self, record, **kwargs):
        data = {}

        for k, v in record.__dict__.iteritems():
            if '.' not in k and k not in ('culprit',):
                continue
            data[k] = v

        stack = getattr(record, 'stack', None)
        if stack is True:
            stack = iter_stack_frames()

        if stack:
            # we might need to traverse this multiple times, so coerce it to a list
            stack = list(stack)
            frames = []
            started = False
            last_mod = ''
            for item in stack:
                if isinstance(item, (list, tuple)):
                    frame, lineno = item
                else:
                    frame, lineno = item, item.f_lineno

                if not started:
                    f_globals = getattr(frame, 'f_globals', {})
                    module_name = f_globals.get('__name__', '')
                    if (last_mod and last_mod.startswith('logging')) \
                        and not module_name.startswith('logging'):
                        started = True
                    else:
                        last_mod = module_name
                        continue
                frames.append((frame, lineno))

            # We must've not found a starting point
            if not frames:
                frames = stack

            stack = frames

        extra = getattr(record, 'data', None)
        if not isinstance(extra, dict):
            if extra:
                extra = {'data': extra}
            else:
                extra = {}

        # Add in all of the data from the record that we aren't already capturing
        for k in record.__dict__.keys():
            if k in RESERVED:
                continue
            if k.startswith('_'):
                continue
            extra[k] = record.__dict__[k]

        date = datetime.datetime.utcfromtimestamp(record.created)
        event_type = 'raven.events.Message'
        handler_kwargs = {'message': record.msg, 'params': record.args}

        # If there's no exception being processed, exc_info may be a 3-tuple of None
        # http://docs.python.org/library/sys.html#sys.exc_info
        if record.exc_info and all(record.exc_info):
            # capture the standard message first so that we ensure
            # the event is recorded as an exception, in addition to having our
            # message interface attached
            handler = self.client.get_handler(event_type)
            data.update(handler.capture(**handler_kwargs))
            # ensure message is propagated, otherwise the exception will overwrite it
            data['message'] = record.message

            event_type = 'raven.events.Exception'
            handler_kwargs = {'exc_info': record.exc_info}

        # HACK: discover a culprit when we normally couldn't
        elif not (data.get('sentry.interfaces.Stacktrace') or data.get('culprit')) and (record.name or record.funcName):
            culprit = label_from_frame({'module': record.name, 'function': record.funcName})
            if culprit:
                data['culprit'] = culprit

        data['level'] = record.levelno
        data['logger'] = record.name

        if hasattr(record, 'tags'):
            kwargs['tags'] = record.tags

        kwargs.update(handler_kwargs)

        return self.client.capture(event_type, stack=stack, data=data, extra=extra,
            date=date, **kwargs)