-
{{ stat_name }}
-
- {% for engine in stat_category %}
-
-
{{ engine.name }}
-
-
-
- {{ '%.02f'|format(engine.avg) }}
-
-
+
+
+ {% if not engine_stats.get('time') %}
+
+ {% include 'oscar/messages/no_data_available.html' %}
-
- {% endfor %}
- {% if not stat_category %}
-
- {% include 'oscar/messages/no_data_available.html' %}
-
+ {% else %}
+
+
+ {{ th_sort('name', _("Engine name")) }} |
+ {{ th_sort('score', _('Scores')) }} |
+ {{ th_sort('result_count', _('Result count')) }} |
+ {{ th_sort('time', _('Response time')) }} |
+ {{ th_sort('reliability', _('Reliability')) }} |
+
+ {% for engine_stat in engine_stats.get('time', []) %}
+
+ {{ engine_stat.name }} |
+
+ {% if engine_stat.score %}
+ {{ engine_stat.score|round(1) }}
+ {{- "" -}}
+ {{ _('Scores per result') }}: {{ engine_stat.score_per_result | round(3) }}
+
+ {% endif %}
+ |
+
+ {%- if engine_stat.result_count -%}
+ {{- engine_stat.result_count | int -}}{{- "" -}}
+ {{- "" -}}
+ {{- "" -}}
+
+ {%- endif -%}
+ |
+
+ {%- if engine_stat.total -%}
+ {{- engine_stat.total | round(1) -}}{{- "" -}}
+ {{- "" -}}
+ {{- "" -}}
+ {{- "" -}}
+ {{- "" -}}
+ {{- "" -}}
+
+
+ |
+ {{ _('Total') }} |
+ {{ _('HTTP') }} |
+ {{ _('Processing') }} |
+
+
+ {{ _('Median') }} |
+ {{ engine_stat.total }} |
+ {{ engine_stat.http }} |
+ {{ engine_stat.processing }} |
+
+
+ {{ _('P80') }} |
+ {{ engine_stat.total_p80 }} |
+ {{ engine_stat.http_p80 }} |
+ {{ engine_stat.processing_p80 }} |
+
+
+ {{ _('P95') }} |
+ {{ engine_stat.total_p95 }} |
+ {{ engine_stat.http_p95 }} |
+ {{ engine_stat.processing_p95 }} |
+
+
+
+ {%- endif -%}
+ |
+ {{ engine_reliabilities.get(engine_stat.name, {}).get('reliablity') }} |
+
+ {% endfor %}
+
{% endif %}
- {% endfor %}
{% endblock %}
diff --git a/searx/templates/simple/stats.html b/searx/templates/simple/stats.html
index 462ab4aa9..eecd88903 100644
--- a/searx/templates/simple/stats.html
+++ b/searx/templates/simple/stats.html
@@ -1,4 +1,15 @@
+{% from 'simple/macros.html' import icon %}
+
{% extends "simple/base.html" %}
+
+{%- macro th_sort(column_order, column_name) -%}
+ {% if column_order==sort_order %}
+ {{ column_name }} {{ icon('arrow-dropdown') }}
+ {% else %}
+
{{ column_name }}
+ {% endif %}
+{%- endmacro -%}
+
{% block head %} {% endblock %}
{% block content %}
@@ -6,20 +17,77 @@
{{ _('Engine stats') }}
-{% for stat_name,stat_category in stats %}
-
-
-
- {{ stat_name }} |
-
- {% for engine in stat_category %}
-
- {{ engine.name }} |
- {{ '%.02f'|format(engine.avg) }} |
- |
-
- {% endfor %}
-
-
-{% endfor %}
+{% if not engine_stats.get('time') %}
+{{ _('There is currently no data available. ') }}
+{% else %}
+
+
+ {{ th_sort('name', _("Engine name")) }} |
+ {{ th_sort('score', _('Scores')) }} |
+ {{ th_sort('result_count', _('Result count')) }} |
+ {{ th_sort('time', _('Response time')) }} |
+ {{ th_sort('reliability', _('Reliability')) }} |
+
+ {% for engine_stat in engine_stats.get('time', []) %}
+
+ {{ engine_stat.name }} |
+
+ {% if engine_stat.score %}
+ {{ engine_stat.score|round(1) }}
+
+ {% endif %}
+ |
+
+ {%- if engine_stat.result_count -%}
+ {{- engine_stat.result_count | int -}}{{- "" -}}
+ {{- "" -}}
+ {{- "" -}}
+
+ {%- endif -%}
+ |
+
+ {%- if engine_stat.total -%}
+ {{- engine_stat.total | round(1) -}}{{- "" -}}
+ {{- "" -}}
+ {{- "" -}}
+ {{- "" -}}
+ {{- "" -}}
+
+ {%- endif -%}
+ |
+ {{ engine_reliabilities.get(engine_stat.name, {}).get('reliablity') }} |
+
+ {% endfor %}
+
+{% endif %}
+
{% endblock %}
diff --git a/searx/webapp.py b/searx/webapp.py
index d02e142fc..d917c16d4 100755
--- a/searx/webapp.py
+++ b/searx/webapp.py
@@ -93,7 +93,7 @@ from searx.preferences import Preferences, ValidationException, LANGUAGE_CODES
from searx.answerers import answerers
from searx.network import stream as http_stream
from searx.answerers import ask
-from searx.metrics import get_engines_stats, get_engine_errors, histogram, counter
+from searx.metrics import get_engines_stats, get_engine_errors, get_reliabilities, histogram, counter
# serve pages with HTTP/1.1
from werkzeug.serving import WSGIRequestHandler
@@ -1073,16 +1073,47 @@ def image_proxy():
@app.route('/stats', methods=['GET'])
def stats():
"""Render engine statistics page."""
+ checker_results = checker_get_result()
+ checker_results = checker_results['engines'] \
+ if checker_results['status'] == 'ok' and 'engines' in checker_results else {}
+
filtered_engines = dict(filter(lambda kv: (kv[0], request.preferences.validate_token(kv[1])), engines.items()))
engine_stats = get_engines_stats(filtered_engines)
+ engine_reliabilities = get_reliabilities(filtered_engines, checker_results)
+
+ sort_order = request.args.get('sort', default='name', type=str)
+
+ SORT_PARAMETERS = {
+ 'name': (False, 'name', ''),
+ 'score': (True, 'score', 0),
+ 'result_count': (True, 'result_count', 0),
+ 'time': (False, 'total', 0),
+ 'reliability': (False, 'reliability', 100),
+ }
+
+ if sort_order not in SORT_PARAMETERS:
+ sort_order = 'name'
+
+ reverse, key_name, default_value = SORT_PARAMETERS[sort_order]
+
+ def get_key(engine_stat):
+ reliability = engine_reliabilities.get(engine_stat['name']).get('reliablity', 0)
+ reliability_order = 0 if reliability else 1
+ if key_name == 'reliability':
+ key = reliability
+ reliability_order = 0
+ else:
+ key = engine_stat.get(key_name) or default_value
+ if reverse:
+ reliability_order = 1 - reliability_order
+ return (reliability_order, key, engine_stat['name'])
+
+ engine_stats['time'] = sorted(engine_stats['time'], reverse=reverse, key=get_key)
return render(
'stats.html',
- stats=[(gettext('Engine time (sec)'), engine_stats['time_total']),
- (gettext('Page loads (sec)'), engine_stats['time_http']),
- (gettext('Number of results'), engine_stats['result_count']),
- (gettext('Scores'), engine_stats['scores']),
- (gettext('Scores per result'), engine_stats['scores_per_result']),
- (gettext('Errors'), engine_stats['error_count'])]
+ sort_order=sort_order,
+ engine_stats=engine_stats,
+ engine_reliabilities=engine_reliabilities,
)