def test_broken_500_handler_with_middleware(django_elasticapm_client, client): with override_settings(BREAK_THAT_500=True): client.handler = MockMiddleware(MockClientHandler()) with override_settings(**middleware_setting(django.VERSION, [])): with pytest.raises(Exception): client.get(reverse('elasticapm-raise-exc')) assert len(django_elasticapm_client.events) == 2 event = django_elasticapm_client.events.pop(0)['errors'][0] assert 'exception' in event exc = event['exception'] assert exc['type'] == 'Exception' assert exc['message'] == 'Exception: view exception' assert event['culprit'] == 'tests.contrib.django.testapp.views.raise_exc' event = django_elasticapm_client.events.pop(0)['errors'][0] assert 'exception' in event exc = event['exception'] assert exc['type'] == 'ValueError' assert exc['message'] == 'ValueError: handler500' assert event['culprit'] == 'tests.contrib.django.testapp.urls.handler500' assert event['handled'] is False
def test_transaction_request_response_data(django_elasticapm_client, client): client.cookies = SimpleCookie({'foo': 'bar'}) django_elasticapm_client.instrumentation_store.get_all() with override_settings(**middleware_setting( django.VERSION, ['elasticapm.contrib.django.middleware.TracingMiddleware'] )): client.get(reverse('elasticapm-no-error')) assert len(django_elasticapm_client.instrumentation_store) == 1 transactions = django_elasticapm_client.instrumentation_store.get_all() assert len(transactions) == 1 transaction = transactions[0] assert transaction['result'] == 'HTTP 2xx' assert 'request' in transaction['context'] request = transaction['context']['request'] assert request['method'] == 'GET' assert 'headers' in request headers = request['headers'] assert headers['cookie'] == ' foo=bar' env = request['env'] assert 'SERVER_NAME' in env, env.keys() assert env['SERVER_NAME'] == 'testserver' assert 'SERVER_PORT' in env, env.keys() assert env['SERVER_PORT'] == '80' assert 'response' in transaction['context'] response = transaction['context']['response'] assert response['status_code'] == 200 assert response['headers']['my-header'] == 'foo'
def test_request_metrics_301_append_slash(django_elasticapm_client, client): django_elasticapm_client.instrumentation_store.get_all() # clear the store # enable middleware wrapping django_elasticapm_client.config.instrument_django_middleware = True from elasticapm.contrib.django.middleware import TracingMiddleware TracingMiddleware._elasticapm_instrumented = False with override_settings( APPEND_SLASH=True, **middleware_setting(django.VERSION, [ 'elasticapm.contrib.django.middleware.TracingMiddleware', 'django.middleware.common.CommonMiddleware', ]) ): client.get(reverse('elasticapm-no-error-slash')[:-1]) transactions = django_elasticapm_client.instrumentation_store.get_all() assert transactions[0]['name'] in ( # django <= 1.8 'GET django.middleware.common.CommonMiddleware.process_request', # django 1.9+ 'GET django.middleware.common.CommonMiddleware.process_response', ) assert transactions[0]['result'] == 'HTTP 3xx'
def test_user_info(django_elasticapm_client, client): user = User(username='******', email='*****@*****.**') user.set_password('admin') user.save() with pytest.raises(Exception): client.get(reverse('elasticapm-raise-exc')) assert len(django_elasticapm_client.events) == 1 event = django_elasticapm_client.events.pop(0)['errors'][0] assert 'user' in event['context'] user_info = event['context']['user'] assert 'is_authenticated' in user_info assert not user_info['is_authenticated'] assert user_info['username'] == '' assert 'email' not in user_info assert client.login(username='******', password='******') with pytest.raises(Exception): client.get(reverse('elasticapm-raise-exc')) assert len(django_elasticapm_client.events) == 1 event = django_elasticapm_client.events.pop(0)['errors'][0] assert 'user' in event['context'] user_info = event['context']['user'] assert 'is_authenticated' in user_info assert user_info['is_authenticated'] assert 'username' in user_info assert user_info['username'] == 'admin' assert 'email' in user_info assert user_info['email'] == '*****@*****.**'
def test_request_metrics_404_resolve_error(django_elasticapm_client, client): django_elasticapm_client.instrumentation_store.get_all() # clear the store with override_settings( **middleware_setting(django.VERSION, ['elasticapm.contrib.django.middleware.TracingMiddleware']) ): client.get('/i-dont-exist/') transactions = django_elasticapm_client.instrumentation_store.get_all() assert transactions[0]['name'] == ''
def test_tracing_middleware_uses_test_client(client, django_elasticapm_client): with override_settings(**middleware_setting(django.VERSION, [ 'elasticapm.contrib.django.middleware.TracingMiddleware' ])): client.get('/') transactions = django_elasticapm_client.instrumentation_store.get_all() assert len(transactions) == 1 assert transactions[0]['context']['request']['url']['pathname'] == '/'
def test_exclude_modules_view(django_elasticapm_client, client): django_elasticapm_client.config.exclude_paths = ['tests.views.decorated_raise_exc'] with pytest.raises(Exception): client.get(reverse('elasticapm-raise-exc-decor')) assert len(django_elasticapm_client.events) == 1, django_elasticapm_client.events event = django_elasticapm_client.events.pop(0)['errors'][0] assert event['culprit'] == 'tests.contrib.django.testapp.views.raise_exc'
def test_user_info_without_auth_middleware_django_2(django_elasticapm_client, client): with override_settings(MIDDLEWARE_CLASSES=None, MIDDLEWARE=[ m for m in settings.MIDDLEWARE if m != 'django.contrib.auth.middleware.AuthenticationMiddleware' ]): with pytest.raises(Exception): client.get(reverse('elasticapm-raise-exc')) assert len(django_elasticapm_client.events) == 1 event = django_elasticapm_client.events.pop(0)['errors'][0] assert event['context']['user'] == {}
def test_include_modules(django_elasticapm_client, client): django_elasticapm_client.config.include_paths = ['django.shortcuts.get_object_or_404'] with pytest.raises(Exception): client.get(reverse('elasticapm-django-exc')) assert len(django_elasticapm_client.events) == 1 event = django_elasticapm_client.events.pop(0)['errors'][0] assert event['culprit'] == 'django.shortcuts.get_object_or_404'
def test_request_metrics_name_override(django_elasticapm_client, client): django_elasticapm_client.instrumentation_store.get_all() # clear the store with override_settings( **middleware_setting(django.VERSION, [ 'elasticapm.contrib.django.middleware.TracingMiddleware', 'tests.contrib.django.testapp.middleware.MetricsNameOverrideMiddleware', ]) ): client.get(reverse('elasticapm-no-error')) transactions = django_elasticapm_client.instrumentation_store.get_all() assert transactions[0]['name'] == 'GET foobar'
def test_view_exception(django_elasticapm_client, client): with pytest.raises(Exception): client.get(reverse('elasticapm-raise-exc')) assert len(django_elasticapm_client.events) == 1 event = django_elasticapm_client.events.pop(0)['errors'][0] assert 'exception' in event exc = event['exception'] assert exc['type'] == 'Exception' assert exc['message'] == 'Exception: view exception' assert event['culprit'] == 'tests.contrib.django.testapp.views.raise_exc' assert event['handled'] is False
def test_django_logging_middleware(django_elasticapm_client, client): handler = LoggingHandler() logger = logging.getLogger('logmiddleware') logger.handlers = [] logger.addHandler(handler) with override_settings(**middleware_setting(django.VERSION, ['elasticapm.contrib.django.middleware.LogMiddleware'])): client.get(reverse('elasticapm-logging')) assert len(django_elasticapm_client.events) == 1 event = django_elasticapm_client.events.pop(0)['errors'][0] assert 'request' in event['context'] assert event['context']['request']['url']['pathname'] == reverse('elasticapm-logging')
def test_view_middleware_exception(django_elasticapm_client, client): with override_settings(**middleware_setting(django.VERSION, ['tests.contrib.django.testapp.middleware.BrokenViewMiddleware'])): with pytest.raises(ImportError): client.get(reverse('elasticapm-raise-exc')) assert len(django_elasticapm_client.events) == 1 event = django_elasticapm_client.events.pop(0)['errors'][0] assert 'exception' in event exc = event['exception'] assert exc['type'] == 'ImportError' assert exc['message'] == 'ImportError: view' assert event['culprit'] == 'tests.contrib.django.testapp.middleware.process_view' assert event['handled'] is False
def test_transaction_metrics(django_elasticapm_client, client): django_elasticapm_client.instrumentation_store.get_all() # clear the store with override_settings(**middleware_setting( django.VERSION, ['elasticapm.contrib.django.middleware.TracingMiddleware'] )): assert len(django_elasticapm_client.instrumentation_store) == 0 client.get(reverse('elasticapm-no-error')) assert len(django_elasticapm_client.instrumentation_store) == 1 transactions = django_elasticapm_client.instrumentation_store.get_all() assert len(transactions) == 1 transaction = transactions[0] assert transaction['duration'] > 0 assert transaction['result'] == 'HTTP 2xx' assert transaction['name'] == 'GET tests.contrib.django.testapp.views.no_error'
def test_user_info_raises_database_error(django_elasticapm_client, client): user = User(username='******', email='*****@*****.**') user.set_password('admin') user.save() assert client.login(username='******', password='******') with mock.patch("django.contrib.auth.models.User.is_authenticated") as is_authenticated: is_authenticated.side_effect = DatabaseError("Test Exception") with pytest.raises(Exception): client.get(reverse('elasticapm-raise-exc')) assert len(django_elasticapm_client.events) == 1 event = django_elasticapm_client.events.pop(0)['errors'][0] assert 'user' in event['context'] user_info = event['context']['user'] assert user_info == {}
def test_response_middlware_exception(django_elasticapm_client, client): if django.VERSION[:2] < (1, 3): return with override_settings(**middleware_setting(django.VERSION, ['tests.contrib.django.testapp.middleware.BrokenResponseMiddleware'])): with pytest.raises(ImportError): client.get(reverse('elasticapm-no-error')) assert len(django_elasticapm_client.events) == 1 event = django_elasticapm_client.events.pop(0)['errors'][0] assert 'exception' in event exc = event['exception'] assert exc['type'] == 'ImportError' assert exc['message'] == 'ImportError: response' assert event['culprit'] == 'tests.contrib.django.testapp.middleware.process_response' assert event['handled'] is False
def test_request_metrics_301_prepend_www(django_elasticapm_client, client): django_elasticapm_client.instrumentation_store.get_all() # clear the store # enable middleware wrapping django_elasticapm_client.config.instrument_django_middleware = True from elasticapm.contrib.django.middleware import TracingMiddleware TracingMiddleware._elasticapm_instrumented = False with override_settings( PREPEND_WWW=True, **middleware_setting(django.VERSION, [ 'elasticapm.contrib.django.middleware.TracingMiddleware', 'django.middleware.common.CommonMiddleware', ]) ): client.get(reverse('elasticapm-no-error')) transactions = django_elasticapm_client.instrumentation_store.get_all() assert transactions[0]['name'] == 'GET django.middleware.common.CommonMiddleware.process_request' assert transactions[0]['result'] == 'HTTP 3xx'
def test_user_info_with_custom_user(django_elasticapm_client, client): with override_settings(AUTH_USER_MODEL='testapp.MyUser'): from django.contrib.auth import get_user_model MyUser = get_user_model() user = MyUser(my_username='******') user.set_password('admin') user.save() assert client.login(username='******', password='******') with pytest.raises(Exception): client.get(reverse('elasticapm-raise-exc')) assert len(django_elasticapm_client.events) == 1 event = django_elasticapm_client.events.pop(0)['errors'][0] assert 'user' in event['context'] user_info = event['context']['user'] assert 'is_authenticated' in user_info assert user_info['is_authenticated'] assert 'username' in user_info assert user_info['username'] == 'admin' assert 'email' not in user_info
def test_response_error_id_middleware(django_elasticapm_client, client): with override_settings(**middleware_setting(django.VERSION, [ 'elasticapm.contrib.django.middleware.ErrorIdMiddleware', 'elasticapm.contrib.django.middleware.Catch404Middleware'])): resp = client.get('/non-existant-page') assert resp.status_code == 404 headers = dict(resp.items()) assert 'X-ElasticAPM-ErrorId' in headers assert len(django_elasticapm_client.events) == 1 event = django_elasticapm_client.events.pop(0)['errors'][0] assert event['id'] == headers['X-ElasticAPM-ErrorId']
def test_404_middleware_with_debug(django_elasticapm_client, client): django_elasticapm_client.config.debug = False with override_settings( DEBUG=True, **middleware_setting(django.VERSION, [ 'elasticapm.contrib.django.middleware.Catch404Middleware' ]) ): resp = client.get('/non-existant-page') assert resp.status_code == 404 assert len(django_elasticapm_client.events) == 0
def test_user_info_with_non_django_auth(django_elasticapm_client, client): with override_settings(INSTALLED_APPS=[ app for app in settings.INSTALLED_APPS if app != 'django.contrib.auth' ]) and override_settings(MIDDLEWARE_CLASSES=[ m for m in settings.MIDDLEWARE_CLASSES if m != 'django.contrib.auth.middleware.AuthenticationMiddleware' ]): with pytest.raises(Exception): resp = client.get(reverse('elasticapm-raise-exc')) assert len(django_elasticapm_client.events) == 1 event = django_elasticapm_client.events.pop(0)['errors'][0] assert event['context']['user'] == {}
def test_404_middleware(django_elasticapm_client, client): with override_settings(**middleware_setting(django.VERSION, ['elasticapm.contrib.django.middleware.Catch404Middleware'])): resp = client.get('/non-existant-page') assert resp.status_code == 404 assert len(django_elasticapm_client.events) == 1 event = django_elasticapm_client.events.pop(0)['errors'][0] assert event['log']['level'] == 'info' assert event['log']['logger_name'] == 'http404' assert 'request' in event['context'] request = event['context']['request'] assert request['url']['full'] == u'http://testserver/non-existant-page' assert request['method'] == 'GET' assert request['body'] == None
def test_stacktrace_filtered_for_elasticapm(client, django_elasticapm_client): with mock.patch( "elasticapm.traces.TransactionsStore.should_collect") as should_collect: should_collect.return_value = False with override_settings(**middleware_setting(django.VERSION, ['elasticapm.contrib.django.middleware.TracingMiddleware'])): resp = client.get(reverse("render-heavy-template")) assert resp.status_code == 200 transactions = django_elasticapm_client.instrumentation_store.get_all() assert transactions[0]['result'] == 'HTTP 2xx' spans = transactions[0]['spans'] expected_signatures = ['transaction', 'list_users.html', 'something_expensive'] assert spans[1]['name'] == 'list_users.html' # Top frame should be inside django rendering assert spans[1]['stacktrace'][0]['module'].startswith('django.template')
def test_stacktraces_have_templates(client, django_elasticapm_client): # only Django 1.9+ have the necessary information stored on Node/Template # instances when TEMPLATE_DEBUG = False TEMPLATE_DEBUG = django.VERSION < (1, 9) with mock.patch("elasticapm.traces.TransactionsStore.should_collect") as should_collect: should_collect.return_value = False TEMPLATES_copy = deepcopy(settings.TEMPLATES) TEMPLATES_copy[0]['OPTIONS']['debug'] = TEMPLATE_DEBUG with override_settings( TEMPLATE_DEBUG=TEMPLATE_DEBUG, TEMPLATES=TEMPLATES_copy, **middleware_setting(django.VERSION, [ 'elasticapm.contrib.django.middleware.TracingMiddleware' ]) ): resp = client.get(reverse("render-heavy-template")) assert resp.status_code == 200 transactions = django_elasticapm_client.instrumentation_store.get_all() assert len(transactions) == 1 transaction = transactions[0] assert transaction['result'] == 'HTTP 2xx' spans = transaction['spans'] assert len(spans) == 2, [t['name'] for t in spans] expected_names = {'list_users.html', 'something_expensive'} assert {t['name'] for t in spans} == expected_names assert spans[0]['name'] == 'something_expensive' # Find the template for frame in spans[0]['stacktrace']: if frame['lineno'] == 4 and frame['filename'].endswith( 'django/testapp/templates/list_users.html' ): break else: assert False is True, "Template was not found"
def test_request_metrics_contrib_redirect(django_elasticapm_client, client): django_elasticapm_client.instrumentation_store.get_all() # clear the store # enable middleware wrapping django_elasticapm_client.config.instrument_django_middleware = True from elasticapm.contrib.django.middleware import TracingMiddleware TracingMiddleware._elasticapm_instrumented = False s = Site.objects.get(pk=1) Redirect.objects.create(site=s, old_path='/redirect/me/', new_path='/here/') with override_settings( **middleware_setting(django.VERSION, [ 'elasticapm.contrib.django.middleware.TracingMiddleware', 'django.contrib.redirects.middleware.RedirectFallbackMiddleware', ]) ): response = client.get('/redirect/me/') transactions = django_elasticapm_client.instrumentation_store.get_all() assert transactions[0]['name'] == 'GET django.contrib.redirects.middleware.RedirectFallbackMiddleware.process_response' assert transactions[0]['result'] == 'HTTP 3xx'
def client_get(client, url): return client.get(url)
def test_view_exception_elasticapm_debug(django_elasticapm_client, client): django_elasticapm_client.config.debug = True with override_settings(DEBUG=True): with pytest.raises(Exception): client.get(reverse('elasticapm-raise-exc')) assert len(django_elasticapm_client.events) == 1
def test_ignored_exception_is_ignored(django_elasticapm_client, client): with pytest.raises(IgnoredException): client.get(reverse('elasticapm-ignored-exception')) assert len(django_elasticapm_client.events) == 0