Beispiel #1
0
    def capture(self, exc_info=None, **kwargs):
        new_exc_info = False
        if not exc_info or exc_info is True:
            new_exc_info = True
            exc_info = sys.exc_info()

        if not exc_info:
            raise ValueError('No exception found')

        try:
            exc_type, exc_value, exc_traceback = exc_info

            frames = varmap(
                lambda k, v: shorten(v,
                                     string_length=self.client.
                                     string_max_length,
                                     list_length=self.client.list_max_length),
                get_stack_info(
                    iter_traceback_frames(exc_traceback),
                    list_max_length=self.client.list_max_length,
                    string_max_length=self.client.string_max_length))

            exc_module = getattr(exc_type, '__module__', None)
            if exc_module:
                exc_module = str(exc_module)
            exc_type = getattr(exc_type, '__name__', '<unknown>')
        finally:
            if new_exc_info:
                try:
                    del exc_info
                    del exc_traceback
                except Exception, e:
                    self.logger.exception(e)
Beispiel #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
    def metlog_call(self, *args, **kwargs):
        if self.kwargs is None:
            self.kwargs = {}
        str_length = self.kwargs.pop('str_length', 200)
        list_length = self.kwargs.pop('list_length', 50)

        try:
            result = self._fn(*args, **kwargs)
            return result
        except Exception, e:
            exc_info = sys.exc_info()
            exc_type, exc_value, exc_traceback = exc_info

            frames = varmap(lambda k, v: shorten(v,
                string_length=str_length,
                list_length=list_length),
                get_stack_info(iter_traceback_frames(exc_traceback)))

            culprit = get_culprit(frames)

            metlog_blob = {'culprit': culprit,
                    'frames': frames}

            CLIENT_WRAPPER.client.metlog('stacktrace',
                    logger=self._fn_fq_name,
                    fields=metlog_blob)

            # re-raise the exception so that callers up the call stack
            # have a chance to do the right thing
            raise
Beispiel #4
0
 def filter_stacktrace(self, data):
     if "frames" not in data:
         return
     for frame in data["frames"]:
         if "vars" not in frame:
             continue
         frame["vars"] = varmap(self.sanitize, frame["vars"])
Beispiel #5
0
    def capture(self, exc_info=None, **kwargs):
        new_exc_info = False
        if not exc_info or exc_info is True:
            new_exc_info = True
            exc_info = sys.exc_info()

        if not exc_info:
            raise ValueError("No exception found")

        try:
            exc_type, exc_value, exc_traceback = exc_info

            frames = varmap(
                lambda k, v: shorten(
                    v, string_length=self.client.string_max_length, list_length=self.client.list_max_length
                ),
                get_stack_info(
                    iter_traceback_frames(exc_traceback),
                    list_max_length=self.client.list_max_length,
                    string_max_length=self.client.string_max_length,
                ),
            )

            exc_module = getattr(exc_type, "__module__", None)
            if exc_module:
                exc_module = str(exc_module)
            exc_type = getattr(exc_type, "__name__", "<unknown>")
        finally:
            if new_exc_info:
                try:
                    del exc_info
                    del exc_traceback
                except Exception, e:
                    self.logger.exception(e)
Beispiel #6
0
 def filter_stacktrace(self, data):
     if 'frames' not in data:
         return
     for frame in data['frames']:
         if 'vars' not in frame:
             continue
         frame['vars'] = varmap(self.sanitize, frame['vars'])
Beispiel #7
0
    def capture(self, exc_info=None, **kwargs):
        new_exc_info = False
        if not exc_info or exc_info is True:
            new_exc_info = True
            exc_info = sys.exc_info()

        if not exc_info:
            raise ValueError('No exception found')

        try:
            exc_type, exc_value, exc_traceback = exc_info

            frames = varmap(lambda k, v: shorten(v,
                string_length=self.client.string_max_length, list_length=self.client.list_max_length),
            get_stack_info(iter_traceback_frames(exc_traceback)))

            culprit = get_culprit(frames, self.client.include_paths, self.client.exclude_paths)

            exc_module = getattr(exc_type, '__module__', None)
            exc_type = getattr(exc_type, '__name__', '<unknown>')
        finally:
            if new_exc_info:
                try:
                    del exc_info
                    del exc_traceback
                except Exception, e:
                    self.logger.exception(e)
Beispiel #8
0
 def filter_stacktrace(self, data):
     if 'frames' not in data:
         return
     for frame in data['frames']:
         if 'vars' not in frame:
             continue
         frame['vars'] = varmap(self.sanitize, frame['vars'])
Beispiel #9
0
    def capture(self, exc_info=None, **kwargs):
        new_exc_info = False
        if not exc_info or exc_info is True:
            new_exc_info = True
            exc_info = sys.exc_info()

        try:
            exc_type, exc_value, exc_traceback = exc_info

            frames = varmap(lambda k, v: shorten(v), get_stack_info(iter_traceback_frames(exc_traceback)))

            culprit = get_culprit(frames, self.client.include_paths, self.client.exclude_paths)

            if hasattr(exc_type, '__module__'):
                exc_module = exc_type.__module__
                exc_type = exc_type.__name__
            else:
                exc_module = None
                exc_type = exc_type.__name__
        finally:
            if new_exc_info:
                try:
                    del exc_info
                    del exc_traceback
                except Exception, e:
                    self.logger.exception(e)
Beispiel #10
0
    def filter_stacktrace(self, data):
        """Filter out any local variables that contain sensitive-looking
        patterns in their repr()s"""
        super(PyramidSanitizePasswordsProcessor, self).filter_stacktrace(data)
        for frame in data.get('frames', []):
            if 'vars' not in frame:
                continue

            frame['vars'] = varmap(self.sensitive_repr_filter, frame['vars'])
 def filter_http(self, data):
     """Also descend into env, headers looking for keyval-ish strings"""
     super(PyramidSanitizePasswordsProcessor, self).filter_http(data)
     for n in ('headers', 'env'):
         if isinstance(data[n], dict):
             data[n] = varmap(
                 partial(self.vm_sanitize_keyval, delimiter='&'),
                 data[n],
             )
Beispiel #12
0
    def create_from_exception(self, exc_info=None, **kwargs):
        """
        Creates an event from an exception.

        >>> try:
        >>>     exc_info = sys.exc_info()
        >>>     client.create_from_exception(exc_info)
        >>> finally:
        >>>     del exc_info

        If exc_info is not provided, or is set to True, then this method will
        perform the ``exc_info = sys.exc_info()`` and the requisite clean-up
        for you.
        """
        new_exc = False
        if not exc_info or exc_info is True:
            new_exc = True
            exc_info = sys.exc_info()

        data = kwargs.pop('data', {}) or {}

        try:
            exc_type, exc_value, exc_traceback = exc_info

            frames = varmap(shorten, get_stack_info(iter_traceback_frames(exc_traceback)))

            if hasattr(exc_type, '__class__'):
                exc_module = exc_type.__class__.__module__
            else:
                exc_module = None

            data['__sentry__'] = {}
            data['__sentry__']['frames'] = frames
            data['__sentry__']['exception'] = [exc_module, exc_value.args]

            tb_message = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_traceback))

            kwargs.setdefault('message', transform(force_unicode(exc_value)))

            return self.process(
                class_name=exc_type.__name__,
                traceback=tb_message,
                data=data,
                **kwargs
            )
        finally:
            # It's important that we cleanup the frames object (specifically exc_info[2])
            # to ensure that GC can happen properly.
            if new_exc:
                try:
                    del exc_info
                    del exc_traceback
                except Exception, e:
                    logger.exception(e)
Beispiel #13
0
 def process(self, data):
     super(SanitizeSecretsProcessor, self).process(data)
     # sanitize anything else left unsanitized
     for key in data:
         if key in ('sentry.interfaces.Stacktrace',
                    'sentry.interfaces.Http',
                    'sentry.interfaces.User',
                    'modules'):
             continue
         data[key] = varmap(self.sanitize, data[key])
     return data
Beispiel #14
0
    def create_from_exception(self, exc_info=None, **kwargs):
        """
        Creates an event from an exception.

        >>> try:
        >>>     exc_info = sys.exc_info()
        >>>     client.create_from_exception(exc_info)
        >>> finally:
        >>>     del exc_info

        If exc_info is not provided, or is set to True, then this method will
        perform the ``exc_info = sys.exc_info()`` and the requisite clean-up
        for you.
        """
        new_exc = False
        if not exc_info or exc_info is True:
            new_exc = True
            exc_info = sys.exc_info()

        data = kwargs.pop('data', {}) or {}

        try:
            exc_type, exc_value, exc_traceback = exc_info

            frames = varmap(
                shorten, get_stack_info(iter_traceback_frames(exc_traceback)))

            if hasattr(exc_type, '__class__'):
                exc_module = exc_type.__class__.__module__
            else:
                exc_module = None

            data['__sentry__'] = {}
            data['__sentry__']['frames'] = frames
            data['__sentry__']['exception'] = [exc_module, exc_value.args]

            tb_message = '\n'.join(
                traceback.format_exception(exc_type, exc_value, exc_traceback))

            kwargs.setdefault('message', transform(force_unicode(exc_value)))

            return self.process(class_name=exc_type.__name__,
                                traceback=tb_message,
                                data=data,
                                **kwargs)
        finally:
            # It's important that we cleanup the frames object (specifically exc_info[2])
            # to ensure that GC can happen properly.
            if new_exc:
                try:
                    del exc_info
                    del exc_traceback
                except Exception, e:
                    logger.exception(e)
Beispiel #15
0
    def filter_http(self, data):
        for n in ('data', 'cookies', 'headers', 'env', 'query_string'):
            if n not in data:
                continue

            if isinstance(data[n], basestring) and '=' in data[n]:
                # at this point we've assumed it's a standard HTTP query
                querystring = [c.split('=') for c in data[n].split('&')]
                querystring = [(k, self.sanitize(k, v)) for k, v in querystring]
                data[n] = '&'.join('='.join(k) for k in querystring)
            else:
                data[n] = varmap(self.sanitize, data[n])
    def filter_http(self, data):
        for n in ('data', 'cookies', 'headers', 'env', 'query_string'):
            if n not in data:
                continue

            if isinstance(data[n], basestring) and '=' in data[n]:
                # at this point we've assumed it's a standard HTTP query
                querystring = [c.split('=') for c in data[n].split('&')]
                querystring = [(k, self.sanitize(k, v))
                               for k, v in querystring]
                data[n] = '&'.join('='.join(k) for k in querystring)
            else:
                data[n] = varmap(self.sanitize, data[n])
Beispiel #17
0
 def filter_http(self, data):
     """Also descend into env, headers looking for keyval-ish strings"""
     super(PyramidSanitizePasswordsProcessor, self).filter_http(data)
     for n in ('headers', 'env', 'data'):
         if isinstance(data.get(n), dict):
             data[n] = varmap(
                 partial(self.vm_sanitize_keyval, delimiter='&'),
                 data[n],
             )
         elif isinstance(data.get(n), binary_type):
             data[n] = self.sensitive_repr_filter(
                 n, data.get(n).decode('utf8')
             ).encode('utf8')
Beispiel #18
0
 def filter_http(self, data):
     for n in ('data', 'cookies', 'headers', 'env', 'query_string'):
         if n not in data:
             continue
         if isinstance(data[n], string_types) and '=' in data[n]:
             if n == 'cookies':
                 delimiter = ';'
             else:
                 delimiter = '&'
             data[n] = self._sanitize_keyvals(data[n], delimiter)
         else:
             data[n] = varmap(self.sanitize, data[n])
             if n == 'headers' and 'Cookie' in data[n]:
                 data[n]['Cookie'] = self._sanitize_keyvals(
                     data[n]['Cookie'], ';')
 def filter_stacktrace(self, data):
     if 'frames' not in data:
         return
     for frame in data['frames']:
         if 'vars' not in frame:
             continue
         self_obj = frame['vars'].get('self', '').split(' ')[0][1:]
         if (self_obj in ('netsvc.SimpleXMLRPCRequestHandler',
                          'netsvc.SecureXMLRPCRequestHandler',
                          'netsvc.LocalService')
             and 'params' in frame['vars']):
             if isinstance(frame['vars']['params'], tuple):
                 frame['vars']['params'] = list(frame['vars']['params'])
             frame['vars']['params'][2] = self.MASK
         else:
             frame['vars'] = varmap(self.sanitize, frame['vars'])
Beispiel #20
0
    def create_from_exception(self, exc_info=None, **kwargs):
        """
        Creates an event from an exception.

        >>> try:
        >>>     exc_info = sys.exc_info()
        >>>     client.create_from_exception(exc_info)
        >>> finally:
        >>>     del exc_info
        """
        new_exc = bool(exc_info)
        if not exc_info or exc_info is True:
            exc_info = sys.exc_info()

        data = kwargs.pop('data', {}) or {}

        try:
            exc_type, exc_value, exc_traceback = exc_info

            frames = varmap(shorten, get_stack_info(iter_traceback_frames(exc_traceback)))

            if hasattr(exc_type, '__class__'):
                exc_module = exc_type.__class__.__module__
            else:
                exc_module = None

            data['__sentry__'] = {}
            data['__sentry__']['frames'] = frames
            data['__sentry__']['exception'] = [exc_module, exc_value.args]

            tb_message = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_traceback))

            kwargs.setdefault('message', transform(force_unicode(exc_value)))

            return self.process(
                class_name=exc_type.__name__,
                traceback=tb_message,
                data=data,
                **kwargs
            )
        finally:
            if new_exc:
                try:
                    del exc_info
                except Exception, e:
                    logger.exception(e)
Beispiel #21
0
    def filter_http(self, data):
        for n in ('data', 'cookies', 'headers', 'env', 'query_string'):
            if n not in data:
                continue

            if isinstance(data[n], basestring) and '=' in data[n]:
                # at this point we've assumed it's a standard HTTP query
                querybits = []
                for bit in data[n].split('&'):
                    chunk = bit.split('=')
                    if len(chunk) == 2:
                        querybits.append((chunk[0], self.sanitize(*chunk)))
                    else:
                        querybits.append(chunk)

                data[n] = '&'.join('='.join(k) for k in querybits)
            else:
                data[n] = varmap(self.sanitize, data[n])
Beispiel #22
0
    def filter_http(self, data):
        for n in ("data", "cookies", "headers", "env", "query_string"):
            if n not in data:
                continue

            if isinstance(data[n], six.string_types) and "=" in data[n]:
                # at this point we've assumed it's a standard HTTP query
                querybits = []
                for bit in data[n].split("&"):
                    chunk = bit.split("=")
                    if len(chunk) == 2:
                        querybits.append((chunk[0], self.sanitize(*chunk)))
                    else:
                        querybits.append(chunk)

                data[n] = "&".join("=".join(k) for k in querybits)
            else:
                data[n] = varmap(self.sanitize, data[n])
    def filter_http(self, data):
        for n in ('data', 'cookies', 'headers', 'env', 'query_string'):
            if n not in data:
                continue

            if isinstance(data[n], six.string_types) and '=' in data[n]:
                # at this point we've assumed it's a standard HTTP query
                querybits = []
                for bit in data[n].split('&'):
                    chunk = bit.split('=')
                    if len(chunk) == 2:
                        querybits.append((chunk[0], self.sanitize(*chunk)))
                    else:
                        querybits.append(chunk)

                data[n] = '&'.join('='.join(k) for k in querybits)
            else:
                data[n] = varmap(self.sanitize, data[n])
    def filter_http(self, data):
        for n in ("data", "cookies", "headers", "env", "query_string"):
            if n not in data:
                continue

            if isinstance(data[n], six.string_types) and "=" in data[n]:
                # at this point we've assumed it's a standard HTTP query
                # or cookie
                if n == "cookies":
                    delimiter = ";"
                else:
                    delimiter = "&"

                data[n] = self._sanitize_keyvals(data[n], delimiter)
            else:
                data[n] = varmap(self.sanitize, data[n])
                if n == "headers" and "Cookie" in data[n]:
                    data[n]["Cookie"] = self._sanitize_keyvals(data[n]["Cookie"], ";")
Beispiel #25
0
    def capture(self, exc_info=None, **kwargs):
        new_exc_info = False
        if not exc_info or exc_info is True:
            new_exc_info = True
            exc_info = sys.exc_info()

        if not exc_info:
            raise ValueError('No exception found')

        try:
            exc_type, exc_value, exc_traceback = exc_info

            frames = varmap(
                lambda k, v: shorten(v,
                                     string_length=self.client.
                                     string_max_length,
                                     list_length=self.client.list_max_length),
                get_stack_info(iter_traceback_frames(exc_traceback)))

            culprit = get_culprit(frames, self.client.include_paths,
                                  self.client.exclude_paths)

            exc_module = getattr(exc_type, '__module__', None)
            exc_type = getattr(exc_type, '__name__', '<unknown>')
        finally:
            if new_exc_info:
                try:
                    del exc_info
                    del exc_traceback
                except Exception as e:
                    self.logger.exception(e)

        return {
            'level': logging.ERROR,
            'culprit': culprit,
            'sentry.interfaces.Exception': {
                'value': to_unicode(exc_value),
                'type': str(exc_type),
                'module': str(exc_module),
            },
            'sentry.interfaces.Stacktrace': {
                'frames': frames
            },
        }
Beispiel #26
0
    def filter_http(self, data):
        for n in ("data", "cookies", "headers", "env", "query_string"):
            if n not in data:
                continue

            if isinstance(data[n], six.string_types) and "=" in data[n]:
                # at this point we've assumed it's a standard HTTP query
                querybits = []

                for bit in data[n].split("&"):
                    chunk = bit.split("=")
                    if len(chunk) == 2:
                        querybits.append((chunk[0], self.sanitize(*chunk)))
                    else:
                        querybits.append(chunk)

                data[n] = "&".join("=".join(k) for k in querybits)
            else:
                data[n] = varmap(self.sanitize, data[n])
Beispiel #27
0
    def filter_http(self, data):
        for n in ('data', 'cookies', 'headers', 'env', 'query_string'):
            if n not in data:
                continue

            if isinstance(data[n], six.string_types) and '=' in data[n]:
                # at this point we've assumed it's a standard HTTP query
                # or cookie
                if n == 'cookies':
                    delimiter = ';'
                else:
                    delimiter = '&'

                data[n] = self._sanitize_keyvals(data[n], delimiter)
            else:
                data[n] = varmap(self.sanitize, data[n])
                if n == 'headers' and 'Cookie' in data[n]:
                    data[n]['Cookie'] = self._sanitize_keyvals(
                        data[n]['Cookie'], ';'
                    )
Beispiel #28
0
    def capture(self, exc_info=None, **kwargs):
        new_exc_info = False
        if not exc_info or exc_info is True:
            new_exc_info = True
            exc_info = sys.exc_info()

        if not exc_info:
            raise ValueError('No exception found')

        try:
            exc_type, exc_value, exc_traceback = exc_info

            frames = varmap(lambda k, v: shorten(v,
                string_length=self.client.string_max_length, list_length=self.client.list_max_length),
            get_stack_info(iter_traceback_frames(exc_traceback),
                list_max_length=self.client.list_max_length,
                string_max_length=self.client.string_max_length))

            exc_module = getattr(exc_type, '__module__', None)
            if exc_module:
                exc_module = str(exc_module)
            exc_type = getattr(exc_type, '__name__', '<unknown>')
        finally:
            if new_exc_info:
                try:
                    del exc_info
                    del exc_traceback
                except Exception as e:
                    self.logger.exception(e)

        return {
            'level': logging.ERROR,
            'sentry.interfaces.Exception': {
                'value': to_unicode(exc_value),
                'type': str(exc_type),
                'module': exc_module,
            },
            'sentry.interfaces.Stacktrace': {
                'frames': frames
            },
        }
    def metlog_exceptor(self, logger=default_str_length, msg=default_msg,
            str_length=default_str_length,
            list_length=default_list_length,
            exc_info=None):
        if exc_info is None:
            exc_info = sys.exc_info()

        exc_type, exc_value, exc_traceback = exc_info

        frames = varmap(lambda k, v: shorten(v,
            string_length=str_length,
            list_length=list_length),
            get_stack_info(iter_traceback_frames(exc_traceback)))

        culprit = get_culprit(frames)

        metlog_blob = {'culprit': culprit,
                'frames': frames}

        self.metlog(type='stacktrace',
                logger=logger,
                fields=metlog_blob)
Beispiel #30
0
    def filter_http(self, data):
        for n in ('data', 'cookies', 'headers', 'env', 'query_string'):
            if n not in data:
                continue

            # data could be provided as bytes
            if PY3 and isinstance(data[n], bytes):
                data[n] = data[n].decode('utf-8', 'replace')

            if isinstance(data[n], string_types) and '=' in data[n]:
                # at this point we've assumed it's a standard HTTP query
                # or cookie
                if n == 'cookies':
                    delimiter = ';'
                else:
                    delimiter = '&'

                data[n] = self._sanitize_keyvals(data[n], delimiter)
            else:
                data[n] = varmap(self.sanitize, data[n])
                if n == 'headers' and 'Cookie' in data[n]:
                    data[n]['Cookie'] = self._sanitize_keyvals(
                        data[n]['Cookie'], ';')
Beispiel #31
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
Beispiel #32
0
    def filter_http(self, data):
        for n in ('data', 'cookies', 'headers', 'env', 'query_string'):
            if n not in data:
                continue

            # data could be provided as bytes
            if PY3 and isinstance(data[n], bytes):
                data[n] = data[n].decode('utf-8', 'replace')

            if isinstance(data[n], string_types) and '=' in data[n]:
                # at this point we've assumed it's a standard HTTP query
                # or cookie
                if n == 'cookies':
                    delimiter = ';'
                else:
                    delimiter = '&'

                data[n] = self._sanitize_keyvals(data[n], delimiter)
            else:
                data[n] = varmap(self.sanitize, data[n])
                if n == 'headers' and 'Cookie' in data[n]:
                    data[n]['Cookie'] = self._sanitize_keyvals(
                        data[n]['Cookie'], ';'
                    )
 def filter_stacktrace(self, data):
     for frame in data.get("frames", []):
         if "vars" not in frame:
             continue
         frame["vars"] = varmap(self.sanitize, frame["vars"])
Beispiel #34
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
Beispiel #35
0
 def filter_extra(self, data):
     return varmap(self.sanitize, data)
Beispiel #36
0
    def filter_stacktrace(self, data):
        for frame in data.get('frames', []):
            if 'vars' not in frame:
                continue

            frame['vars'] = varmap(self.sanitize, frame['vars'])
Beispiel #37
0
 def filter_stacktrace(self, data):
     for frame in data.get('frames', []):
         if 'vars' not in frame:
             continue
         frame['vars'] = varmap(self.sanitize, frame['vars'])
    def filter_http(self, data):
        for n in ('body', 'cookies', 'headers', 'env'):
            if n not in data:
                continue

            data[n] = varmap(self.sanitize, data[n])
Beispiel #39
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)
    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
Beispiel #41
0
 def filter_extra(self, data):
     return varmap(self.sanitize, data)
Beispiel #42
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)
Beispiel #43
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
Beispiel #44
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)
Beispiel #45
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)
Beispiel #46
0
    def filter_stacktrace(self, data):
        for frame in data.get("frames", []):
            if "vars" not in frame:
                continue

            frame["vars"] = varmap(self.sanitize, frame["vars"])
Beispiel #47
0
    def filter_http(self, data):
        for n in ('data', 'cookies', 'headers', 'env'):
            if n not in data:
                continue

            data[n] = varmap(self.sanitize, data[n])