Skip to content
This repository has been archived by the owner on Jan 31, 2018. It is now read-only.

Commit

Permalink
[bug 791381] Fix dashboard regarding ES errors
Browse files Browse the repository at this point in the history
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 21, 2012
1 parent f3c8e8a commit 7cea16d
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 64 deletions.
6 changes: 6 additions & 0 deletions fjord/analytics/templates/analytics/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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 %}
14 changes: 14 additions & 0 deletions fjord/analytics/templates/analytics/es_down.html
Original file line number Diff line number Diff line change
@@ -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 %}
26 changes: 23 additions & 3 deletions fjord/analytics/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -14,7 +15,6 @@


class TestCountsHelper(TestCase):

def setUp(self):
self.counts = [('apples', 5), ('bananas', 10), ('oranges', 6)]

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
89 changes: 29 additions & 60 deletions fjord/analytics/views.py
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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',
Expand All @@ -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},
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion vendor-local/src/elasticutils

0 comments on commit 7cea16d

Please sign in to comment.