Permalink
Browse files

Added middleware to catch ES exceptions (bug 767578)

  • Loading branch information...
1 parent e970d07 commit 016d37c0a076ecb2d1fcc0e5880676b6360cb6c0 @robhudson robhudson committed Jul 12, 2012
View
2 apps/amo/decorators.py
@@ -81,6 +81,7 @@ def wrapper(request, *args, **kw):
return wrapper
return decorator
+
def restricted_content(f):
"""
Prevent access to a view function for accounts restricted from
@@ -97,7 +98,6 @@ def wrapper(request, *args, **kw):
return wrapper
-
def modal_view(f):
@functools.wraps(f)
def wrapper(*args, **kw):
View
3 apps/amo/search.py
@@ -1,11 +1,10 @@
import logging
from operator import itemgetter
-from django.conf import settings
-
import elasticutils
from django_statsd.clients import statsd
+
log = logging.getLogger('z.es')
View
17 apps/search/middleware.py
@@ -0,0 +1,17 @@
+import logging
+
+import jingo
+from pyes.exceptions import ElasticSearchException
+from pyes.urllib3.connectionpool import HTTPError
+
+
+log = logging.getLogger('z.es')
+
+
+class ElasticsearchExceptionMiddleware(object):
+
+ def process_exception(self, request, exception):
+ if (issubclass(exception.__class__, (ElasticSearchException,
+ HTTPError))):
+ log.error(u'Elasticsearch error: %s' % exception)
+ return jingo.render(request, 'search/down.html', status=503)
View
8 apps/search/templates/search/down.html
@@ -0,0 +1,8 @@
+{% extends "impala/base_shared.html" %}
+
+{% block content %}
+<section id="search-down" class="main">
+ <h1>{{ _('Search Unavailable') }}</h1>
+ <p>{{ _('Search is temporarily unavailable. Please try again in a few minutes.') }}</p>
+</section>
+{% endblock %}
View
36 apps/search/tests/test_middleware.py
@@ -0,0 +1,36 @@
+import jingo
+import mock
+from nose.tools import eq_
+from pyes.exceptions import ElasticSearchException, IndexMissingException
+from pyes.urllib3.connectionpool import HTTPError, MaxRetryError, TimeoutError
+from test_utils import RequestFactory
+
+import amo.tests
+from search.middleware import ElasticsearchExceptionMiddleware as ESM
+
+
+class TestElasticsearchExceptionMiddleware(amo.tests.TestCase):
@andymckay
Mozilla member
andymckay added a line comment Jul 13, 2012

you win. longest test case name ever?

@robhudson
Mozilla member
robhudson added a line comment Jul 13, 2012

I miss Java

@cvan
Mozilla member
cvan added a line comment Jul 13, 2012
@kumar303
Mozilla member
kumar303 added a line comment Jul 13, 2012

The name TestESExceptionMiddleware 😢 from rejection

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+ def setUp(self):
+ self.request = RequestFactory()
+
+ @mock.patch.object(jingo, 'render')
+ def test_exceptions_we_catch(self, jingo_mock):
+ # These are instantiated with an error string.
+ for e in [ElasticSearchException, IndexMissingException]:
+ ESM().process_exception(self.request, e('ES ERROR'))
+ jingo_mock.assert_called_with(self.request, 'search/down.html',
+ status=503)
+ jingo_mock.reset_mock()
+
+ # These are just Exception classes.
+ for e in [HTTPError, MaxRetryError, TimeoutError]:
+ ESM().process_exception(self.request, e('ES ERROR'))
+ jingo_mock.assert_called_with(self.request, 'search/down.html',
+ status=503)
+ jingo_mock.reset_mock()
+
+ @mock.patch.object(jingo, 'render')
+ def test_exceptions_we_do_not_catch(self, jingo_mock):
+ ESM().process_exception(self.request, Exception)
+ eq_(jingo_mock.called, False)
View
1 lib/settings_base.py
@@ -322,6 +322,7 @@ def JINJA_CONFIG():
'django.contrib.messages.middleware.MessageMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'commonware.log.ThreadRequestMiddleware',
+ 'apps.search.middleware.ElasticsearchExceptionMiddleware',
'session_csrf.CsrfMiddleware',
# This should come after authentication middleware
View
8 mkt/search/templates/search/down.html
@@ -0,0 +1,8 @@
+{% extends "mkt/base.html" %}
+
+{% block content %}
+<section id="search-down" class="c main">
+ <h1>{{ _('Search Unavailable') }}</h1>
+ <p>{{ _('Search is temporarily unavailable. Please try again in a few minutes.') }}</p>
+</section>
+{% endblock %}
View
2 mkt/search/views.py
@@ -4,9 +4,9 @@
from tower import ugettext as _
import amo
-from amo.urlresolvers import reverse
import amo.utils
from amo.decorators import json_view
+from amo.urlresolvers import reverse
from apps.addons.models import Category
from apps.search.views import name_query, WebappSuggestionsAjax
from mkt.webapps.models import Webapp

5 comments on commit 016d37c

@cvan
Mozilla member

❤️ it!

@andymckay
Mozilla member

Will we get a log or a statsd ping of the number of times this occurs?

@robhudson
Mozilla member

There's a log in the middleware. We could add statsd?

@andymckay
Mozilla member

It looks like there will be a 503 statsd ping, so all good.

@cvan
Mozilla member

can we add like one traceback to sentry? I don't know. or is a statsd ping enough?

Please sign in to comment.