on master help sign in
show engine errors in infobox && add new error alert
243d3e4Noémi Ványi
searx/results.py+4
@@ -135,6 +135,7 @@ class ResultContainer(object):
135 self._number_of_results = []
135 self._number_of_results = []
136 self._ordered = False
136 self._ordered = False
137 self.paging = False
137 self.paging = False
138+ self.unresponsive_engines = []
138
139
139 def extend(self, engine_name, results):
140 def extend(self, engine_name, results):
140 for result in list(results):
141 for result in list(results):
@@ -304,3 +305,6 @@ class ResultContainer(object):
304 if not resultnum_sum or not self._number_of_results:
305 if not resultnum_sum or not self._number_of_results:
305 return 0
306 return 0
306 return resultnum_sum / len(self._number_of_results)
307 return resultnum_sum / len(self._number_of_results)
308+
309+ def add_unresponsive_engine(self, engine_name):
310+ self.unresponsive_engines.append(engine_name)
searx/search.py+4
@@ -20,6 +20,7 @@ import sys
20import threading
20import threading
21from time import time
21from time import time
22from uuid import uuid4
22from uuid import uuid4
23+from flask_babel import gettext
23import requests.exceptions
24import requests.exceptions
24import searx.poolrequests as requests_lib
25import searx.poolrequests as requests_lib
25from searx.engines import (
26from searx.engines import (
@@ -133,18 +134,21 @@ def search_one_request_safe(engine_name, query, request_params, result_container
133 requests_exception = False
134 requests_exception = False
134
135
135 if (issubclass(e.__class__, requests.exceptions.Timeout)):
136 if (issubclass(e.__class__, requests.exceptions.Timeout)):
137+ result_container.add_unresponsive_engine((engine_name, gettext('timeout')))
136 # requests timeout (connect or read)
138 # requests timeout (connect or read)
137 logger.error("engine {0} : HTTP requests timeout"
139 logger.error("engine {0} : HTTP requests timeout"
138 "(search duration : {1} s, timeout: {2} s) : {3}"
140 "(search duration : {1} s, timeout: {2} s) : {3}"
139 .format(engine_name, search_duration, timeout_limit, e.__class__.__name__))
141 .format(engine_name, search_duration, timeout_limit, e.__class__.__name__))
140 requests_exception = True
142 requests_exception = True
141 elif (issubclass(e.__class__, requests.exceptions.RequestException)):
143 elif (issubclass(e.__class__, requests.exceptions.RequestException)):
144+ result_container.add_unresponsive_engine((engine_name, gettext('request exception')))
142 # other requests exception
145 # other requests exception
143 logger.exception("engine {0} : requests exception"
146 logger.exception("engine {0} : requests exception"
144 "(search duration : {1} s, timeout: {2} s) : {3}"
147 "(search duration : {1} s, timeout: {2} s) : {3}"
145 .format(engine_name, search_duration, timeout_limit, e))
148 .format(engine_name, search_duration, timeout_limit, e))
146 requests_exception = True
149 requests_exception = True
147 else:
150 else:
151+ result_container.add_unresponsive_engine((engine_name, gettext('unexpected crash')))
148 # others errors
152 # others errors
149 logger.exception('engine {0} : exception : {1}'.format(engine_name, e))
153 logger.exception('engine {0} : exception : {1}'.format(engine_name, e))
150
154
searx/templates/oscar/messages/no_results.html+7−4
@@ -1,9 +1,12 @@
1{% from 'oscar/macros.html' import icon %}
1{% from 'oscar/macros.html' import icon %}
2+{% if unresponsive_engines %}
3+<div class="alert alert-danger fade in" role="alert">
4+ <p><strong class="lead">{{ icon('remove-sign') }} {{ _('Error!') }}</strong> {{ _('Engines cannot retrieve results.') }}</p>
5+ <p><small>{{ _('Please, try again later or find another searx instance.') }}</small></p>
6+</div>
7+{% else %}
2<div class="alert alert-info fade in" role="alert">
8<div class="alert alert-info fade in" role="alert">
3− <button class="close" data-dismiss="alert" type="button">
4− <span aria-hidden="true">×</span>
5− <span class="sr-only">{{ _('Close') }}</span>
6− </button>
7 <strong class="lead">{{ icon('info-sign') }} {{ _('Sorry!') }}</strong>
9 <strong class="lead">{{ icon('info-sign') }} {{ _('Sorry!') }}</strong>
8 {{ _('we didn\'t find any results. Please use another query or search in more categories.') }}
10 {{ _('we didn\'t find any results. Please use another query or search in more categories.') }}
9</div>
11</div>
12+{% endif %}
searx/templates/oscar/results.html+10
@@ -94,6 +94,16 @@
94 {% if number_of_results != '0' %}
94 {% if number_of_results != '0' %}
95 <p><small>{{ _('Number of results') }}: {{ number_of_results }}</small></p>
95 <p><small>{{ _('Number of results') }}: {{ number_of_results }}</small></p>
96 {% endif %}
96 {% endif %}
97+
98+ {% if unresponsive_engines and results|length >= 1 %}
99+ <div class="alert alert-danger fade in" role="alert">
100+ <p>{{ _('Engines cannot retrieve results') }}:</p>
101+ {% for engine_name, error_type in unresponsive_engines %}
102+ {{ engine_name }} ({{ error_type }}){% if not loop.last %}, {% endif %}
103+ {% endfor %}
104+ </div>
105+ {% endif %}
106+
97 {% if infoboxes %}
107 {% if infoboxes %}
98 {% for infobox in infoboxes %}
108 {% for infobox in infoboxes %}
99 {% include 'oscar/infobox.html' %}
109 {% include 'oscar/infobox.html' %}
searx/webapp.py+3−1
@@ -534,7 +534,8 @@ def index():
534 'answers': list(result_container.answers),
534 'answers': list(result_container.answers),
535 'corrections': list(result_container.corrections),
535 'corrections': list(result_container.corrections),
536 'infoboxes': result_container.infoboxes,
536 'infoboxes': result_container.infoboxes,
537− 'suggestions': list(result_container.suggestions)}),
537+ 'suggestions': list(result_container.suggestions),
538+ 'unresponsive_engines': list(result_container.unresponsive_engines)}),
538 mimetype='application/json')
539 mimetype='application/json')
539 elif output_format == 'csv':
540 elif output_format == 'csv':
540 csv = UnicodeWriter(StringIO())
541 csv = UnicodeWriter(StringIO())
@@ -573,6 +574,7 @@ def index():
573 corrections=result_container.corrections,
574 corrections=result_container.corrections,
574 infoboxes=result_container.infoboxes,
575 infoboxes=result_container.infoboxes,
575 paging=result_container.paging,
576 paging=result_container.paging,
577+ unresponsive_engines=result_container.unresponsive_engines,
576 current_language=search_query.lang,
578 current_language=search_query.lang,
577 base_url=get_base_url(),
579 base_url=get_base_url(),
578 theme=get_current_theme_name(),
580 theme=get_current_theme_name(),
tests/unit/test_webapp.py+1
@@ -39,6 +39,7 @@ class ViewsTestCase(SearxTestCase):
39 corrections=set(),
39 corrections=set(),
40 suggestions=set(),
40 suggestions=set(),
41 infoboxes=[],
41 infoboxes=[],
42+ unresponsive_engines=[],
42 results=self.test_results,
43 results=self.test_results,
43 results_number=lambda: 3,
44 results_number=lambda: 3,
44 results_length=lambda: len(self.test_results))
45 results_length=lambda: len(self.test_results))