Browse Source

Merge pull request #688 from dalf/settings_enable_stats

[enh] settings.yml: implement general.enable_metrics
Markus Heiser 3 years ago
parent
commit
0ebad8220f

+ 3 - 0
docs/admin/engines/settings.rst

@@ -81,6 +81,9 @@ Global Settings
 ``contact_url``:
 ``contact_url``:
   Contact ``mailto:`` address or WEB form.
   Contact ``mailto:`` address or WEB form.
 
 
+``enable_metrics``:
+  Enabled by default. Record various anonymous metrics availabled at ``/stats``,
+  ``/stats/errors`` and ``/preferences``.
 
 
 .. _settings global server:
 .. _settings global server:
 
 

+ 8 - 4
searx/metrics/__init__.py

@@ -9,7 +9,7 @@ from timeit import default_timer
 from operator import itemgetter
 from operator import itemgetter
 
 
 from searx.engines import engines
 from searx.engines import engines
-from .models import HistogramStorage, CounterStorage
+from .models import HistogramStorage, CounterStorage, VoidHistogram, VoidCounterStorage
 from .error_recorder import count_error, count_exception, errors_per_engines
 from .error_recorder import count_error, count_exception, errors_per_engines
 
 
 __all__ = [
 __all__ = [
@@ -69,14 +69,18 @@ def counter(*args):
     return counter_storage.get(*args)
     return counter_storage.get(*args)
 
 
 
 
-def initialize(engine_names=None):
+def initialize(engine_names=None, enabled=True):
     """
     """
     Initialize metrics
     Initialize metrics
     """
     """
     global counter_storage, histogram_storage  # pylint: disable=global-statement
     global counter_storage, histogram_storage  # pylint: disable=global-statement
 
 
-    counter_storage = CounterStorage()
-    histogram_storage = HistogramStorage()
+    if enabled:
+        counter_storage = CounterStorage()
+        histogram_storage = HistogramStorage()
+    else:
+        counter_storage = VoidCounterStorage()
+        histogram_storage = HistogramStorage(histogram_class=VoidHistogram)
 
 
     # max_timeout = max of all the engine.timeout
     # max_timeout = max of all the engine.timeout
     max_timeout = 2
     max_timeout = 2

+ 5 - 1
searx/metrics/error_recorder.py

@@ -9,7 +9,7 @@ from searx.exceptions import (
     SearxEngineAPIException,
     SearxEngineAPIException,
     SearxEngineAccessDeniedException,
     SearxEngineAccessDeniedException,
 )
 )
-from searx import searx_parent_dir
+from searx import searx_parent_dir, settings
 from searx.engines import engines
 from searx.engines import engines
 
 
 
 
@@ -165,6 +165,8 @@ def get_error_context(framerecords, exception_classname, log_message, log_parame
 
 
 
 
 def count_exception(engine_name: str, exc: Exception, secondary: bool = False) -> None:
 def count_exception(engine_name: str, exc: Exception, secondary: bool = False) -> None:
+    if not settings['general']['enable_metrics']:
+        return
     framerecords = inspect.trace()
     framerecords = inspect.trace()
     try:
     try:
         exception_classname = get_exception_classname(exc)
         exception_classname = get_exception_classname(exc)
@@ -178,6 +180,8 @@ def count_exception(engine_name: str, exc: Exception, secondary: bool = False) -
 def count_error(
 def count_error(
     engine_name: str, log_message: str, log_parameters: typing.Optional[typing.Tuple] = None, secondary: bool = False
     engine_name: str, log_message: str, log_parameters: typing.Optional[typing.Tuple] = None, secondary: bool = False
 ) -> None:
 ) -> None:
+    if not settings['general']['enable_metrics']:
+        return
     framerecords = list(reversed(inspect.stack()[1:]))
     framerecords = list(reversed(inspect.stack()[1:]))
     try:
     try:
         error_context = get_error_context(framerecords, None, log_message, log_parameters or (), secondary)
         error_context = get_error_context(framerecords, None, log_message, log_parameters or (), secondary)

+ 14 - 3
searx/metrics/models.py

@@ -102,16 +102,17 @@ class Histogram:
 
 
 class HistogramStorage:
 class HistogramStorage:
 
 
-    __slots__ = 'measures'
+    __slots__ = 'measures', 'histogram_class'
 
 
-    def __init__(self):
+    def __init__(self, histogram_class=Histogram):
         self.clear()
         self.clear()
+        self.histogram_class = histogram_class
 
 
     def clear(self):
     def clear(self):
         self.measures = {}
         self.measures = {}
 
 
     def configure(self, width, size, *args):
     def configure(self, width, size, *args):
-        measure = Histogram(width, size)
+        measure = self.histogram_class(width, size)
         self.measures[args] = measure
         self.measures[args] = measure
         return measure
         return measure
 
 
@@ -154,3 +155,13 @@ class CounterStorage:
         logger.debug("Counters:")
         logger.debug("Counters:")
         for k in ks:
         for k in ks:
             logger.debug("- %-60s %s", '|'.join(k), self.counters[k])
             logger.debug("- %-60s %s", '|'.join(k), self.counters[k])
+
+
+class VoidHistogram(Histogram):
+    def observe(self, value):
+        pass
+
+
+class VoidCounterStorage(CounterStorage):
+    def add(self, value, *args):
+        pass

+ 2 - 2
searx/search/__init__.py

@@ -24,13 +24,13 @@ from searx.search.checker import initialize as initialize_checker
 logger = logger.getChild('search')
 logger = logger.getChild('search')
 
 
 
 
-def initialize(settings_engines=None, enable_checker=False, check_network=False):
+def initialize(settings_engines=None, enable_checker=False, check_network=False, enable_metrics=True):
     settings_engines = settings_engines or settings['engines']
     settings_engines = settings_engines or settings['engines']
     load_engines(settings_engines)
     load_engines(settings_engines)
     initialize_network(settings_engines, settings['outgoing'])
     initialize_network(settings_engines, settings['outgoing'])
     if check_network:
     if check_network:
         check_network_configuration()
         check_network_configuration()
-    initialize_metrics([engine['name'] for engine in settings_engines])
+    initialize_metrics([engine['name'] for engine in settings_engines], enable_metrics)
     initialize_processors(settings_engines)
     initialize_processors(settings_engines)
     if enable_checker:
     if enable_checker:
         initialize_checker()
         initialize_checker()

+ 1 - 0
searx/settings.yml

@@ -2,6 +2,7 @@ general:
   debug: false              # Debug mode, only for development
   debug: false              # Debug mode, only for development
   instance_name: "SearXNG"  # displayed name
   instance_name: "SearXNG"  # displayed name
   contact_url: false        # mailto:contact@example.com
   contact_url: false        # mailto:contact@example.com
+  enable_metrics: true      # record stats
 
 
 brand:
 brand:
   new_issue_url: https://github.com/searxng/searxng/issues/new
   new_issue_url: https://github.com/searxng/searxng/issues/new

+ 1 - 0
searx/settings_defaults.py

@@ -142,6 +142,7 @@ SCHEMA = {
         'debug': SettingsValue(bool, False, 'SEARXNG_DEBUG'),
         'debug': SettingsValue(bool, False, 'SEARXNG_DEBUG'),
         'instance_name': SettingsValue(str, 'SearXNG'),
         'instance_name': SettingsValue(str, 'SearXNG'),
         'contact_url': SettingsValue((None, False, str), None),
         'contact_url': SettingsValue((None, False, str), None),
+        'enable_metrics': SettingsValue(bool, True),
     },
     },
     'brand': {
     'brand': {
         'issue_url': SettingsValue(str, 'https://github.com/searxng/searxng/issues'),
         'issue_url': SettingsValue(str, 'https://github.com/searxng/searxng/issues'),

+ 1 - 1
searx/webapp.py

@@ -1333,7 +1333,7 @@ werkzeug_reloader = flask_run_development or (searx_debug and __name__ == "__mai
 # initialize the engines except on the first run of the werkzeug server.
 # initialize the engines except on the first run of the werkzeug server.
 if not werkzeug_reloader or (werkzeug_reloader and os.environ.get("WERKZEUG_RUN_MAIN") == "true"):
 if not werkzeug_reloader or (werkzeug_reloader and os.environ.get("WERKZEUG_RUN_MAIN") == "true"):
     plugin_initialize(app)
     plugin_initialize(app)
-    search_initialize(enable_checker=True, check_network=True)
+    search_initialize(enable_checker=True, check_network=True, enable_metrics=settings['general']['enable_metrics'])
 
 
 
 
 def run():
 def run():