Permalink
Browse files

[bug 791381] Fix dashboard regarding ES errors

This fixes the dashboard page so that if there are any
ElasticSearch-related errors, it shows the es_down.html template.

In doing this, I tweaked the structure of the dashboard.html template
so that I could extend it for the es_down.html template. I also
pulled in a new version of ElasticUtils.
  • Loading branch information...
willkg committed Sep 20, 2012
1 parent f3c8e8a commit 7cea16d6ff7c4753546e8fbe5425ba98b03c2206
@@ -47,16 +47,19 @@ <h3>{{ filter_set.display }}</h3>
{% block content %}
<div class="col">
+{% block content_leftside %}
<div class="block search">
{% for filter_set in filter_data %}
{{ filter_block(filter_set) }}
{% endfor %}
</div>
+{% endblock %}
</div>
<div class="col wide">
+{% block content_middle %}
<div class="block graph">
{# A graph will be dynamically inserted in these divs by Flot. #}
<div class="histogram" data-histogram="{{ histogram|to_json }}"></div>
@@ -84,13 +87,16 @@ <h2>{{ _('Latest Feedback') }}</h2>
{% endif %}
</div>
</div>
+{% endblock %}
</div>
<div class="col">
+{% block content_rightside %}
<div class="block count">
<h3>{{ _('Messages') }}</h3>
<p><strong>{{ opinion_count }}</strong></p>
</div>
+{% endblock %}
</div>
{% endblock %}
@@ -0,0 +1,14 @@
+{% extends "analytics/dashboard.html" %}
+
+{% block content_leftside %}{% endblock %}
+
+{% block content_middle %}
+<div class="block feedback">
+<h2>{{ _('Dashboard unavailable') }}</h2>
+<p>
+ {{ _('Dashboard is currently unavailable. Please try again in 10 minutes.') }}
+</p>
+</div>
+{% endblock %}
+
+{% block content_rightside %}{% endblock %}
@@ -1,9 +1,10 @@
import logging
from nose.tools import eq_
-
+import pyes
from pyquery import PyQuery
+from fjord.analytics import views
from fjord.analytics.views import counts_to_options
from fjord.base.tests import TestCase, LocalizingClient, reverse
from fjord.feedback.tests import simple
@@ -14,7 +15,6 @@
class TestCountsHelper(TestCase):
-
def setUp(self):
self.counts = [('apples', 5), ('bananas', 10), ('oranges', 6)]
@@ -98,7 +98,6 @@ def setUp(self):
self.setup_indexes()
self.refresh()
-
def test_front_page(self):
url = reverse('dashboard')
r = self.client.get(url)
@@ -150,3 +149,24 @@ def test_invalid_search(self):
eq_(r.status_code, 200)
pq = PyQuery(r.content)
eq_(len(pq('li.opinion')), 7)
+
+ def test_frontpage_index_missing(self):
+ """If index is missing, show es_down template."""
+ self.teardown_indexes()
+ resp = self.client.get(reverse('dashboard'))
+ self.assertTemplateUsed(resp, 'analytics/es_down.html')
+
+ def test_frontpage_es_down(self):
+ """If can't connect to ES, show es_down template."""
+ # TODO: When we add a real Mock library, rewrite this.
+ old_counts_to_options = views.counts_to_options
+ try:
+ def mock_counts_to_options(*args, **kwargs):
+ raise pyes.urllib3.MaxRetryError()
+ views.counts_to_options = mock_counts_to_options
+
+ resp = self.client.get(reverse('dashboard'))
+ self.assertTemplateUsed(resp, 'analytics/es_down.html')
+
+ finally:
+ views.counts_to_options = old_counts_to_options
View
@@ -1,13 +1,12 @@
from django.shortcuts import render
from django.template.defaultfilters import slugify
-import pyes
-from elasticutils import F
+from elasticutils.contrib.django import F, es_required_or_50x
from mobility.decorators import mobile_template
from tower import ugettext as _
-from fjord.feedback.models import SimpleIndex
from fjord.base.helpers import locale_name
+from fjord.feedback.models import SimpleIndex
def counts_to_options(counts, name, display=None, display_map=None,
@@ -75,6 +74,7 @@ def from_map(source, item):
return options
+@es_required_or_50x(error_template='analytics/es_down.html')
@mobile_template('analytics/{mobile/}dashboard.html')
def dashboard(request, template):
page = int(request.GET.get('page', 1))
@@ -105,25 +105,15 @@ def dashboard(request, template):
# This is probably something EU should be doing for us. Second, it
# restructures the data into a more convenient form.
counts = {'happy': {}, 'platform': {}, 'locale': {}}
- try:
- for param, terms in facets.facet_counts().items():
- for term in terms:
- name = term['term']
- if name == 'T':
- name = True
- elif name == 'F':
- name = False
-
- counts[param][name] = term['count']
- except (pyes.urllib3.TimeoutError,
- pyes.urllib3.MaxRetryError,
- pyes.exceptions.IndexMissingException,
- pyes.exceptions.ElasticSearchException):
-
- # TODO: Fix this--we should log an error or show a message or
- # something--anything except an HTTP 500 error on the front
- # page.
- pass
+ for param, terms in facets.facet_counts().items():
+ for term in terms:
+ name = term['term']
+ if name == 'T':
+ name = True
+ elif name == 'F':
+ name = False
+
+ counts[param][name] = term['count']
filter_data = [
counts_to_options(counts['happy'].items(), name='happy',
@@ -141,31 +131,21 @@ def dashboard(request, template):
happy_data = []
sad_data = []
- try:
- histograms = search.facet_raw(
- happy={
- 'date_histogram': {'interval': 'day', 'field': 'created'},
- 'facet_filter': (f & F(happy=True)).filters
- },
- sad={
- 'date_histogram': {'interval': 'day', 'field': 'created'},
- 'facet_filter': (f & F(happy=False)).filters
- },
- ).facet_counts()
-
- # p['time'] is number of milliseconds since the epoch. Which is
- # convenient, because that is what the front end wants.
- happy_data = [(p['time'], p['count']) for p in histograms['happy']]
- sad_data = [(p['time'], int(p['count'])) for p in histograms['sad']]
- except (pyes.urllib3.TimeoutError,
- pyes.urllib3.MaxRetryError,
- pyes.exceptions.IndexMissingException,
- pyes.exceptions.ElasticSearchException):
-
- # TODO: Fix this--we should log an error or show a message or
- # something--anything except an HTTP 500 error on the front
- # page.
- pass
+ histograms = search.facet_raw(
+ happy={
+ 'date_histogram': {'interval': 'day', 'field': 'created'},
+ 'facet_filter': (f & F(happy=True)).filters
+ },
+ sad={
+ 'date_histogram': {'interval': 'day', 'field': 'created'},
+ 'facet_filter': (f & F(happy=False)).filters
+ },
+ ).facet_counts()
+
+ # p['time'] is number of milliseconds since the epoch. Which is
+ # convenient, because that is what the front end wants.
+ happy_data = [(p['time'], p['count']) for p in histograms['happy']]
+ sad_data = [(p['time'], int(p['count'])) for p in histograms['sad']]
histogram = [
{'label': _('Happy'), 'data': happy_data},
@@ -179,19 +159,8 @@ def dashboard(request, template):
start = page_count * (page - 1)
end = start + page_count
- try:
- search_count = search.count()
- opinion_page = search[start:end]
- except (pyes.urllib3.TimeoutError,
- pyes.urllib3.MaxRetryError,
- pyes.exceptions.IndexMissingException,
- pyes.exceptions.ElasticSearchException):
-
- # TODO: Fix this--we should log an error or show a message or
- # something--anything except an HTTP 500 error on the front
- # page.
- search_count = 0
- opinion_page = []
+ search_count = search.count()
+ opinion_page = search[start:end]
return render(request, template, {
'opinions': opinion_page,

0 comments on commit 7cea16d

Please sign in to comment.