def __init__(self, get_response=None): self.get_response = get_response self.propagator = get_tracer_propagator() self.exporter = get_tracer_exporter() self.sampler = get_tracer_sampler() settings_ = getattr(settings, 'OPENCENSUS', {}) settings_ = settings_.get('TRACE', {}) self.blacklist_paths = settings_.get(BLACKLIST_PATHS, None) self.blacklist_hostnames = settings_.get(BLACKLIST_HOSTNAMES, None) self.resolver = RouteResolver()
class OpencensusMiddleware(_OpencensusMiddleware): def __init__(self, get_response=None): self.get_response = get_response self.propagator = get_tracer_propagator() self.exporter = get_tracer_exporter() self.sampler = get_tracer_sampler() settings_ = getattr(settings, 'OPENCENSUS', {}) settings_ = settings_.get('TRACE', {}) self.blacklist_paths = settings_.get(BLACKLIST_PATHS, None) self.blacklist_hostnames = settings_.get(BLACKLIST_HOSTNAMES, None) self.resolver = RouteResolver() def process_view(self, request, view_func, *args, **kwargs): """Process view is executed before the view function, here we get the function name add set it as the span name. """ # Do not trace if the url is blacklisted if utils.disable_tracing_url(request.path, self.blacklist_paths): return try: # Get the current span and set the span name to the current # function name of the request. tracer = _get_current_tracer() span = tracer.current_span() span.name = 'Recv.' + self.resolver.resolve(request.path_info) tracer.add_attribute_to_current_span( attribute_key='django.view', attribute_value=utils.get_func_name(view_func)) except Exception: # pragma: no cover logger.error('Failed to trace request', exc_info=True)
class SentryMiddleware(threading.local): resolver = RouteResolver() # backwards compat @property def thread(self): return self def _get_transaction_from_request(self, request): # TODO(dcramer): it'd be nice to pull out parameters # and make this a normalized path return self.resolver.resolve(request.path) def process_request(self, request): self._txid = None self.thread.request = request def process_view(self, request, func, args, kwargs): from raven.contrib.django.models import client try: self._txid = client.transaction.push( self._get_transaction_from_request(request)) except Exception as exc: client.error_logger.exception(repr(exc)) else: # we utilize request_finished as the exception gets reported # *after* process_response is executed, and thus clearing the # transaction there would leave it empty # XXX(dcramer): weakref's cause a threading issue in certain # versions of Django (e.g. 1.6). While they'd be ideal, we're under # the assumption that Django will always call our function except # in the situation of a process or thread dying. request_finished.connect(self.request_finished, weak=False) return None def request_finished(self, **kwargs): from raven.contrib.django.models import client if getattr(self, '_txid', None): client.transaction.pop(self._txid) self._txid = None request_finished.disconnect(self.request_finished)
class DjangoClient(Client): logger = logging.getLogger('sentry.errors.client.django') resolver = RouteResolver() def __init__(self, *args, **kwargs): install_sql_hook = kwargs.pop('install_sql_hook', True) Client.__init__(self, *args, **kwargs) if install_sql_hook: self.install_sql_hook() def install_sql_hook(self): install_sql_hook() def get_user_info(self, request): user_info = { 'ip_address': get_client_ip(request.META), } user = getattr(request, 'user', None) if user is None: return user_info try: if hasattr(user, 'is_authenticated'): # is_authenticated was a method in Django < 1.10 if callable(user.is_authenticated): authenticated = user.is_authenticated() else: authenticated = user.is_authenticated if not authenticated: return user_info user_info['id'] = user.pk if hasattr(user, 'email'): user_info['email'] = user.email if hasattr(user, 'get_username'): user_info['username'] = user.get_username() elif hasattr(user, 'username'): user_info['username'] = user.username except Exception: # We expect that user objects can be somewhat broken at times # and try to just handle as much as possible and ignore errors # as good as possible here. pass return user_info def get_data_from_request(self, request): result = {} result['user'] = self.get_user_info(request) try: uri = request.build_absolute_uri() except SuspiciousOperation: # attempt to build a URL for reporting as Django won't allow us to # use get_host() if request.is_secure(): scheme = 'https' else: scheme = 'http' host = get_host(request) uri = '%s://%s%s' % (scheme, host, request.path) if request.method not in ('GET', 'HEAD'): try: data = request.body except Exception: try: data = request.raw_post_data except Exception: # assume we had a partial read. try: data = request.POST or '<unavailable>' except Exception: data = '<unavailable>' else: if isinstance(data, MultiValueDict): data = dict((k, v[0] if len(v) == 1 else v) for k, v in iterlists(data)) else: data = None environ = request.META result.update({ 'request': { 'method': request.method, 'url': uri, 'query_string': request.META.get('QUERY_STRING'), 'data': data, 'cookies': dict(request.COOKIES), 'headers': dict(get_headers(environ)), 'env': dict(get_environ(environ)), } }) return result def build_msg(self, *args, **kwargs): data = super(DjangoClient, self).build_msg(*args, **kwargs) for frame in self._iter_frames(data): module = frame.get('module') if not module: continue if module.startswith('django.'): frame['in_app'] = False if not self.site and 'django.contrib.sites' in settings.INSTALLED_APPS: try: from django.contrib.sites.models import Site site = Site.objects.get_current() site_name = site.name or site.domain data['tags'].setdefault('site', site_name) except Exception: # Database error? Fallback to the id try: data['tags'].setdefault('site', settings.SITE_ID) except AttributeError: # SITE_ID wasn't set, so just ignore pass return data def capture(self, event_type, request=None, **kwargs): if 'data' not in kwargs: kwargs['data'] = data = {} else: data = kwargs['data'] if request is None: request = getattr(SentryMiddleware.thread, 'request', None) is_http_request = isinstance(request, HttpRequest) if is_http_request: data.update(self.get_data_from_request(request)) if kwargs.get('exc_info'): exc_value = kwargs['exc_info'][1] # As of r16833 (Django) all exceptions may contain a # ``django_template_source`` attribute (rather than the legacy # ``TemplateSyntaxError.source`` check) which describes # template information. As of Django 1.9 or so the new # template debug thing showed up. if hasattr(exc_value, 'django_template_source') or \ ((isinstance(exc_value, TemplateSyntaxError) and isinstance(getattr(exc_value, 'source', None), (tuple, list)) and isinstance(exc_value.source[0], Origin))) or \ hasattr(exc_value, 'template_debug'): source = getattr(exc_value, 'django_template_source', getattr(exc_value, 'source', None)) debug = getattr(exc_value, 'template_debug', None) if source is None: self.logger.info( 'Unable to get template source from exception') data.update(get_data_from_template(source, debug)) result = super(DjangoClient, self).capture(event_type, **kwargs) if is_http_request and result: # attach the sentry object to the request request.sentry = { 'project_id': data.get('project', self.remote.project), 'id': result, } return result def get_transaction_from_request(self, request): return self.resolver.resolve(request.path)
def test_resolver(self): resolver = get_resolver() route_resolver = RouteResolver() result = route_resolver._resolve(resolver, '/api/v1/example/') assert result == '/api/{api_name}/{resource_name}/'
def test_included_match(): resolver = RouteResolver() result = resolver.resolve('/example/foo/bar/baz', example_url_conf) assert result == '/example/foo/bar/{param}'
def test_complex_match(): resolver = RouteResolver() result = resolver.resolve('/api/1234/store/', example_url_conf) assert result == '/api/{project_id}/store/'
def test_simple_match(): resolver = RouteResolver() result = resolver.resolve('/report/', example_url_conf) assert result == '/report/'
def test_simple_match( ): # TODO: ash add matchedstring to make this test actually test something resolver = RouteResolver() result = resolver.resolve('/report/', example_url_conf) assert result == '/report/'
def handle(self, *args, **options): resolver = get_resolver() route_resolver = RouteResolver() print(route_resolver._resolve(resolver, '/api/v1/thing/'))
def test_no_match(): resolver = RouteResolver() result = resolver.resolve('/foo/bar', example_url_conf) assert result == '/foo/bar'
def route_resolver(): return RouteResolver()
def test_simple_match(): # TODO: ash add matchedstring to make this test actually test something resolver = RouteResolver() result = resolver.resolve('/report/', example_url_conf) assert result == '/report/'