def test_get_versions(self): import sentry from sentry.utils import get_versions versions = get_versions(['sentry']) self.assertEquals(versions.get('sentry'), sentry.VERSION) versions = get_versions(['sentry.client']) self.assertEquals(versions.get('sentry'), sentry.VERSION)
def process(self, **kwargs): "Processes the message before passing it on to the server" from sentry.utils import get_filters if kwargs.get('data'): # Ensure we're not changing the original data which was passed # to Sentry kwargs['data'] = kwargs['data'].copy() request = kwargs.pop('request', None) if request: if not kwargs.get('data'): kwargs['data'] = {} if not request.POST and request.raw_post_data: post_data = request.raw_post_data else: post_data = request.POST kwargs['data'].update(dict( META=request.META, POST=post_data, GET=request.GET, COOKIES=request.COOKIES, )) if not kwargs.get('url'): kwargs['url'] = request.build_absolute_uri() kwargs.setdefault('level', logging.ERROR) kwargs.setdefault('server_name', settings.NAME) # save versions of all installed apps if 'data' not in kwargs or '__sentry__' not in (kwargs['data'] or {}): if kwargs.get('data') is None: kwargs['data'] = {} kwargs['data']['__sentry__'] = {} versions = get_versions() kwargs['data']['__sentry__']['versions'] = versions # Shorten lists/strings for k, v in kwargs['data'].iteritems(): if k == '__sentry__': continue kwargs['data'][k] = shorten(v) 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: kwargs['data']['__sentry__'].update({ 'version': version, 'module': module, }) if 'checksum' not in kwargs: checksum = construct_checksum(**kwargs) else: checksum = kwargs['checksum'] (is_thrashing, message_id) = self.check_throttle(checksum) if is_thrashing: if request and message_id: # attach the sentry object to the request request.sentry = { 'id': message_id, 'thrashed': True, } return message_id for filter_ in get_filters(): kwargs = filter_(None).process(kwargs) or kwargs # 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(kwargs['data']) if 'timestamp' not in kwargs: kwargs['timestamp'] = datetime.datetime.now() self.send(**kwargs) if request: # attach the sentry object to the request request.sentry = { 'id': message_id, 'trashed': False, } # store the last message_id incase we hit thrashing limits self.set_last_message_id(checksum, message_id) return message_id
def capture(self, event_type, tags=None, data=None, date=None, time_spent=None, event_id=None, extra=None, culprit=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': {}, >>> 'querystring': '...', >>> 'method': 'POST', >>> }, >>> }) The finalized ``data`` structure contains the following (some optional) builtin values: >>> { >>> 'culprit': 'full.module.name', # or /arbitrary/path >>> # the culprit version information >>> 'version': ('full.module.name', 'version string'), >>> # 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 tags is None: tags = [] if extra is None: extra = {} if date is None: date = datetime.datetime.now() if '.' not in event_type: # Assume it's a builtin event_type = 'sentry.events.%s' % event_type handler = self.module_cache[event_type]() result = handler.capture(**kwargs) tags = list(tags) + result.pop('tags', []) if not culprit: culprit = result.pop('culprit') for k, v in result.iteritems(): if k not in data: data[k] = v else: data[k].update(v) for k, v in data.iteritems(): if '.' not in k: continue interface = self.module_cache[k] data[k] = interface(**v).serialize() tags.append(('server', app.config['NAME'])) versions = get_versions() data['modules'] = versions if culprit: data['culprit'] = culprit # get list of modules from right to left parts = culprit.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['version'] = (module, version), # TODO: Cache should be handled by the db backend by default (as we expect a fast access backend) # if app.config['THRASHING_TIMEOUT'] and app.config['THRASHING_LIMIT']: # cache_key = 'sentry:%s:%s' % (kwargs.get('class_name') or '', checksum) # added = cache.add(cache_key, 1, app.config['THRASHING_TIMEOUT']) # if not added: # try: # thrash_count = cache.incr(cache_key) # except (KeyError, ValueError): # # cache.incr can fail. Assume we aren't thrashing yet, and # # if we are, hope that the next error has a successful # # cache.incr call. # thrash_count = 0 # if thrash_count > app.config['THRASHING_LIMIT']: # return # for filter_ in filters.all(): # kwargs = filter_(None).process(kwargs) or kwargs # 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 processors.all(): data.update(self.module_cache[processor].process(data)) # Make sure all data is coerced data = transform(data) self.send(event_type=event_type, tags=tags, data=data, date=date, time_spent=time_spent, event_id=event_id) return event_id
def process(self, **kwargs): "Processes the message before passing it on to the server" from sentry.utils import get_filters if kwargs.get('data'): # Ensure we're not changing the original data which was passed # to Sentry kwargs['data'] = kwargs['data'].copy() else: kwargs['data'] = {} if '__sentry__' not in kwargs['data']: kwargs['data']['__sentry__'] = {} request = kwargs.pop('request', None) if isinstance(request, HttpRequest): try: post_data = not request.POST and request.raw_post_data or request.POST except: post_data = request.POST kwargs['data'].update(dict( META=request.META, POST=post_data, GET=request.GET, COOKIES=request.COOKIES, )) if hasattr(request, 'user'): if request.user.is_authenticated(): user_info = { 'is_authenticated': True, 'id': request.user.pk, 'username': request.user.username, 'email': request.user.email, } else: user_info = { 'is_authenticated': False, } kwargs['data']['__sentry__']['user'] = user_info if not kwargs.get('url'): kwargs['url'] = request.build_absolute_uri() kwargs.setdefault('level', logging.ERROR) kwargs.setdefault('server_name', settings.NAME) versions = get_versions() kwargs['data']['__sentry__']['versions'] = versions # Shorten lists/strings for k, v in kwargs['data'].iteritems(): if k == '__sentry__': continue kwargs['data'][k] = shorten(v) # if we've passed frames, lets try to fetch the culprit if not kwargs.get('view') and kwargs['data']['__sentry__'].get('frames'): # This should be cached modules = get_installed_apps() if settings.INCLUDE_PATHS: modules = set(list(modules) + settings.INCLUDE_PATHS) def contains(iterator, value): for k in iterator: if value.startswith(k): return True return False # 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". best_guess = None view = None for frame in kwargs['data']['__sentry__']['frames']: try: view = '.'.join([frame['module'], frame['function']]) except: continue if contains(modules, view): if not (contains(settings.EXCLUDE_PATHS, view) and best_guess): best_guess = view elif best_guess: break if best_guess: view = best_guess 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: kwargs['data']['__sentry__'].update({ 'version': version, 'module': module, }) if 'checksum' not in kwargs: checksum = construct_checksum(**kwargs) else: checksum = kwargs['checksum'] (is_thrashing, message_id) = self.check_throttle(checksum) if is_thrashing: if request and message_id: # attach the sentry object to the request request.sentry = { 'id': '%s$%s' % (message_id, checksum), 'thrashed': True, } return message_id for filter_ in get_filters(): kwargs = filter_(None).process(kwargs) or kwargs # 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(kwargs['data']) if 'timestamp' not in kwargs: kwargs['timestamp'] = datetime.datetime.now() self.send(**kwargs) if request: # attach the sentry object to the request request.sentry = { 'id': '%s$%s' % (message_id, checksum), 'thrashed': False, } # store the last message_id incase we hit thrashing limits self.set_last_message_id(checksum, message_id) return message_id
def process(self, **kwargs): "Processes the message before passing it on to the server" from sentry.utils import get_filters if kwargs.get('data'): # Ensure we're not changing the original data which was passed # to Sentry kwargs['data'] = kwargs['data'].copy() request = kwargs.pop('request', None) if request: if not kwargs.get('data'): kwargs['data'] = {} if not request.POST and request.raw_post_data: post_data = request.raw_post_data else: post_data = request.POST kwargs['data'].update( dict( META=request.META, POST=post_data, GET=request.GET, COOKIES=request.COOKIES, )) if not kwargs.get('url'): kwargs['url'] = request.build_absolute_uri() kwargs.setdefault('level', logging.ERROR) kwargs.setdefault('server_name', settings.NAME) # save versions of all installed apps if 'data' not in kwargs or '__sentry__' not in (kwargs['data'] or {}): if kwargs.get('data') is None: kwargs['data'] = {} kwargs['data']['__sentry__'] = {} versions = get_versions() kwargs['data']['__sentry__']['versions'] = versions # Shorten lists/strings for k, v in kwargs['data'].iteritems(): if k == '__sentry__': continue kwargs['data'][k] = shorten(v) 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: kwargs['data']['__sentry__'].update({ 'version': version, 'module': module, }) if 'checksum' not in kwargs: checksum = construct_checksum(**kwargs) else: checksum = kwargs['checksum'] (is_thrashing, message_id) = self.check_throttle(checksum) if is_thrashing: if request and message_id: # attach the sentry object to the request request.sentry = { 'id': message_id, 'thrashed': True, } return message_id for filter_ in get_filters(): kwargs = filter_(None).process(kwargs) or kwargs # 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(kwargs['data']) if 'timestamp' not in kwargs: kwargs['timestamp'] = datetime.datetime.now() self.send(**kwargs) if request: # attach the sentry object to the request request.sentry = { 'id': message_id, 'trashed': False, } # store the last message_id incase we hit thrashing limits self.set_last_message_id(checksum, message_id) return message_id
def process(self, tags=[], date=None, time_spent=None, request=None, **data): "Processes the message before passing it on to the server" if request: data.update(dict( s_meta=request.META, s_post=request.POST, s_get=request.GET, s_cookies=request.COOKIES, )) tags.append(('url', request.build_absolute_uri())) tags.append(('server', app.config['NAME'])) versions = get_versions() data['s_versions'] = versions if data.get('s_view'): # get list of modules from right to left parts = data['s_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] # data['s_view'] = view # store our "best guess" for application version if version: data.update({ 's_version': version, 's_module': module, }) # TODO: Cache should be handled by the db backend by default (as we expect a fast access backend) # if app.config['THRASHING_TIMEOUT'] and app.config['THRASHING_LIMIT']: # cache_key = 'sentry:%s:%s' % (kwargs.get('class_name') or '', checksum) # added = cache.add(cache_key, 1, app.config['THRASHING_TIMEOUT']) # if not added: # try: # thrash_count = cache.incr(cache_key) # except (KeyError, ValueError): # # cache.incr can fail. Assume we aren't thrashing yet, and # # if we are, hope that the next error has a successful # # cache.incr call. # thrash_count = 0 # if thrash_count > app.config['THRASHING_LIMIT']: # return # for filter_ in get_filters(): # kwargs = filter_(None).process(kwargs) or kwargs # create ID client-side so that it can be passed to application event_id = uuid.uuid4().hex # Make sure all data is coerced data = transform(data) app.client.send(type=self.get_id(), tags=tags, data=data, date=date, time_spent=time_spent, event_id=event_id) return event_id
def capture(self, event_type, tags=None, data=None, date=None, time_spent=None, event_id=None, extra=None, culprit=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': {}, >>> 'querystring': '...', >>> 'method': 'POST', >>> }, >>> }) The finalized ``data`` structure contains the following (some optional) builtin values: >>> { >>> 'culprit': 'full.module.name', # or /arbitrary/path >>> # the culprit version information >>> 'version': ('full.module.name', 'version string'), >>> # 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 tags is None: tags = [] if extra is None: extra = {} if date is None: date = datetime.datetime.now() if '.' not in event_type: # Assume it's a builtin event_type = 'sentry.events.%s' % event_type handler = self.module_cache[event_type]() result = handler.capture(**kwargs) tags = list(tags) + result.pop('tags', []) if not culprit: culprit = result.pop('culprit') for k, v in result.iteritems(): if k not in data: data[k] = v else: data[k].update(v) for k, v in data.iteritems(): if '.' not in k: continue interface = self.module_cache[k] data[k] = interface(**v).serialize() tags.append(('server', app.config['NAME'])) versions = get_versions() data['modules'] = versions if culprit: data['culprit'] = culprit # get list of modules from right to left parts = culprit.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['version'] = (module, version), # TODO: Cache should be handled by the db backend by default (as we expect a fast access backend) # if app.config['THRASHING_TIMEOUT'] and app.config['THRASHING_LIMIT']: # cache_key = 'sentry:%s:%s' % (kwargs.get('class_name') or '', checksum) # added = cache.add(cache_key, 1, app.config['THRASHING_TIMEOUT']) # if not added: # try: # thrash_count = cache.incr(cache_key) # except (KeyError, ValueError): # # cache.incr can fail. Assume we aren't thrashing yet, and # # if we are, hope that the next error has a successful # # cache.incr call. # thrash_count = 0 # if thrash_count > app.config['THRASHING_LIMIT']: # return # for filter_ in filters.all(): # kwargs = filter_(None).process(kwargs) or kwargs # 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 processors.all(): data.update(self.module_cache[processor].process(data)) # Make sure all data is coerced data = transform(data) self.send(event_type=event_type, tags=tags, data=data, date=date, time_spent=time_spent, event_id=event_id) return event_id
def process(self, **kwargs): "Processes the message before passing it on to the server" from sentry.utils import get_filters if kwargs.get('data'): # Ensure we're not changing the original data which was passed # to Sentry kwargs['data'] = kwargs['data'].copy() else: kwargs['data'] = {} if '__sentry__' not in kwargs['data']: kwargs['data']['__sentry__'] = {} request = kwargs.pop('request', None) if isinstance(request, HttpRequest): try: post_data = not request.POST and request.raw_post_data or request.POST except: post_data = request.POST kwargs['data'].update( dict( META=request.META, POST=post_data, GET=request.GET, COOKIES=request.COOKIES, )) if hasattr(request, 'user'): if request.user.is_authenticated(): user_info = { 'is_authenticated': True, 'id': request.user.pk, 'username': request.user.username, 'email': request.user.email, } else: user_info = { 'is_authenticated': False, } kwargs['data']['__sentry__']['user'] = user_info if not kwargs.get('url'): kwargs['url'] = request.build_absolute_uri() kwargs.setdefault('level', logging.ERROR) kwargs.setdefault('server_name', settings.NAME) versions = get_versions() kwargs['data']['__sentry__']['versions'] = versions # Shorten lists/strings for k, v in kwargs['data'].iteritems(): if k == '__sentry__': continue kwargs['data'][k] = shorten(v) # if we've passed frames, lets try to fetch the culprit if not kwargs.get('view') and kwargs['data']['__sentry__'].get( 'frames'): # This should be cached modules = get_installed_apps() if settings.INCLUDE_PATHS: modules = set(list(modules) + settings.INCLUDE_PATHS) def contains(iterator, value): for k in iterator: if value.startswith(k): return True return False # 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". best_guess = None view = None for frame in kwargs['data']['__sentry__']['frames']: try: view = '.'.join([frame['module'], frame['function']]) except: continue if contains(modules, view): if not (contains(settings.EXCLUDE_PATHS, view) and best_guess): best_guess = view elif best_guess: break if best_guess: view = best_guess 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: kwargs['data']['__sentry__'].update({ 'version': version, 'module': module, }) if 'checksum' not in kwargs: checksum = construct_checksum(**kwargs) else: checksum = kwargs['checksum'] (is_thrashing, message_id) = self.check_throttle(checksum) if is_thrashing: if request and message_id: # attach the sentry object to the request request.sentry = { 'id': '%s$%s' % (message_id, checksum), 'thrashed': True, } return message_id for filter_ in get_filters(): kwargs = filter_(None).process(kwargs) or kwargs # 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(kwargs['data']) if 'timestamp' not in kwargs: kwargs['timestamp'] = datetime.datetime.now() self.send(**kwargs) if request: # attach the sentry object to the request request.sentry = { 'id': '%s$%s' % (message_id, checksum), 'thrashed': False, } # store the last message_id incase we hit thrashing limits self.set_last_message_id(checksum, message_id) return message_id
def capture(self, event_type, tags=[], data={}, date=None, time_spent=None, event_id=None, extra={}, culprit=None, http={}, **kwargs): "Captures and processes an event and pipes it off to SentryClient.send." # TODO: http should be some kind of pluggable interface so others can be added if not date: date = datetime.datetime.now() if '.' not in event_type: # Assume it's a builtin event_type = 'sentry.events.%s' % event_type handler = self.module_cache[event_type]() result = handler.capture(**kwargs) tags = list(tags) + result['tags'] data['extra'] = extra data['event'] = result['data'] if not culprit: culprit = result.get('culprit') for k, v in kwargs.iteritems(): if k.startswith('interface:'): interface_name = k.split('interface:', 1)[1] if '.' not in interface_name: # Assume it's a builtin interface_name = 'sentry.interfaces.%s' % interface_name interface = self.module_cache[interface_name] data[k] = interface(**v).serialize() tags.append(('server', app.config['NAME'])) versions = get_versions() data['modules'] = versions if culprit: data['culprit'] = culprit # get list of modules from right to left parts = culprit.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['version'] = (module, version), # TODO: Cache should be handled by the db backend by default (as we expect a fast access backend) # if app.config['THRASHING_TIMEOUT'] and app.config['THRASHING_LIMIT']: # cache_key = 'sentry:%s:%s' % (kwargs.get('class_name') or '', checksum) # added = cache.add(cache_key, 1, app.config['THRASHING_TIMEOUT']) # if not added: # try: # thrash_count = cache.incr(cache_key) # except (KeyError, ValueError): # # cache.incr can fail. Assume we aren't thrashing yet, and # # if we are, hope that the next error has a successful # # cache.incr call. # thrash_count = 0 # if thrash_count > app.config['THRASHING_LIMIT']: # return # for filter_ in get_filters(): # kwargs = filter_(None).process(kwargs) or kwargs # create ID client-side so that it can be passed to application event_id = uuid.uuid4().hex # Make sure all data is coerced data = transform(data) self.send(event_type=event_type, tags=tags, data=data, date=date, time_spent=time_spent, event_id=event_id) return event_id
def process(self, **kwargs): "Processes the message before passing it on to the server" from sentry.utils import get_filters if kwargs.get("data"): # Ensure we're not changing the original data which was passed # to Sentry kwargs["data"] = kwargs["data"].copy() else: kwargs["data"] = {} if "__sentry__" not in kwargs["data"]: kwargs["data"]["__sentry__"] = {} request = kwargs.pop("request", None) if isinstance(request, HttpRequest): if not request.POST and request.body: post_data = request.body else: post_data = request.POST kwargs["data"].update(dict(META=request.META, POST=post_data, GET=request.GET, COOKIES=request.COOKIES)) if hasattr(request, "user"): if request.user.is_authenticated(): user_info = { "is_authenticated": True, "id": request.user.pk, "username": request.user.username, "email": request.user.email, } else: user_info = {"is_authenticated": False} kwargs["data"]["__sentry__"]["user"] = user_info if not kwargs.get("url"): kwargs["url"] = request.build_absolute_uri() kwargs.setdefault("level", logging.ERROR) kwargs.setdefault("server_name", settings.NAME) versions = get_versions() kwargs["data"]["__sentry__"]["versions"] = versions # Shorten lists/strings for k, v in kwargs["data"].iteritems(): if k == "__sentry__": continue kwargs["data"][k] = shorten(v) # if we've passed frames, lets try to fetch the culprit if not kwargs.get("view") and kwargs["data"]["__sentry__"].get("frames"): # This should be cached modules = get_installed_apps() if settings.INCLUDE_PATHS: modules = set(list(modules) + settings.INCLUDE_PATHS) def contains(iterator, value): for k in iterator: if value.startswith(k): return True return False # 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". best_guess = None view = None for frame in kwargs["data"]["__sentry__"]["frames"]: try: view = ".".join([frame["module"], frame["function"]]) except: continue if contains(modules, view): if not (contains(settings.EXCLUDE_PATHS, view) and best_guess): best_guess = view elif best_guess: break if best_guess: view = best_guess 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: kwargs["data"]["__sentry__"].update({"version": version, "module": module}) if "checksum" not in kwargs: checksum = construct_checksum(**kwargs) else: checksum = kwargs["checksum"] (is_thrashing, message_id) = self.check_throttle(checksum) if is_thrashing: if request and message_id: # attach the sentry object to the request request.sentry = {"id": message_id, "thrashed": True} return message_id for filter_ in get_filters(): kwargs = filter_(None).process(kwargs) or kwargs # 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(kwargs["data"]) if "timestamp" not in kwargs: kwargs["timestamp"] = now_with_tz_if_supported() self.send(**kwargs) if request: # attach the sentry object to the request request.sentry = {"id": message_id, "thrashed": False} # store the last message_id incase we hit thrashing limits self.set_last_message_id(checksum, message_id) return message_id
def capture(self, event_type, tags=[], data={}, date=None, time_spent=None, event_id=None, **kwargs): "Captures and processes an event and pipes it off to SentryClient.send." if not date: date = datetime.datetime.now() if '.' not in event_type: # Assume it's a builtin event_type = 'sentry.events.%s' % event_type module, class_name = event_type.rsplit('.', 1) handler = getattr(__import__(module, {}, {}, [class_name], -1), class_name)() result = handler.capture(**kwargs) tags = list(tags) + result['tags'] data['__event__'] = result['data'] # if request: # data.update(dict( # s_meta=request.META, # s_post=request.POST, # s_get=request.GET, # s_cookies=request.COOKIES, # )) # tags.append(('url', request.build_absolute_uri())) tags.append(('server', app.config['NAME'])) versions = get_versions() if '__sentry__' not in data: data['__sentry__'] = {} data['__sentry__']['versions'] = versions # TODO: view should probably be passable via kwargs if data['__sentry__'].get('culprit'): # get list of modules from right to left parts = data['__sentry__']['culprit'].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, }) # TODO: Cache should be handled by the db backend by default (as we expect a fast access backend) # if app.config['THRASHING_TIMEOUT'] and app.config['THRASHING_LIMIT']: # cache_key = 'sentry:%s:%s' % (kwargs.get('class_name') or '', checksum) # added = cache.add(cache_key, 1, app.config['THRASHING_TIMEOUT']) # if not added: # try: # thrash_count = cache.incr(cache_key) # except (KeyError, ValueError): # # cache.incr can fail. Assume we aren't thrashing yet, and # # if we are, hope that the next error has a successful # # cache.incr call. # thrash_count = 0 # if thrash_count > app.config['THRASHING_LIMIT']: # return # for filter_ in get_filters(): # kwargs = filter_(None).process(kwargs) or kwargs # create ID client-side so that it can be passed to application event_id = uuid.uuid4().hex # Make sure all data is coerced data = transform(data) self.send(event_type=event_type, tags=tags, data=data, date=date, time_spent=time_spent, event_id=event_id) return event_id