6from json
import JSONDecodeError
7from urllib.parse
import urlparse
8from httpx
import HTTPError, HTTPStatusError
10 SearxXPathSyntaxException,
11 SearxEngineXPathException,
12 SearxEngineAPIException,
13 SearxEngineAccessDeniedException,
15from searx
import searx_parent_dir, settings
19errors_per_engines = {}
29 'exception_classname',
36 self, filename, function, line_no, code, exception_classname, log_message, log_parameters, secondary
48 if not isinstance(o, ErrorContext):
54 and self.
code == o.code
76 return "ErrorContext({!r}, {!r}, {!r}, {!r}, {!r}, {!r}) {!r}".
format(
88 errors_for_engine = errors_per_engines.setdefault(engine_name, {})
89 errors_for_engine[error_context] = errors_for_engine.get(error_context, 0) + 1
90 engines[engine_name].logger.warning(
'%s', str(error_context))
94 for trace
in reversed(traces):
95 split_filename = trace.filename.split(
'/')
96 if '/'.join(split_filename[-3:-1]) ==
'searx/engines':
98 if '/'.join(split_filename[-4:-1]) ==
'searx/search/processors':
104 url = exc.request.url
105 if url
is None and exc.response
is not None:
106 url = exc.response.url
107 return urlparse(url).netloc
112) -> typing.Tuple[typing.Optional[str], typing.Optional[str], typing.Optional[str]]:
117 if hasattr(exc,
'_request')
and exc._request
is not None:
120 url = exc.request.url
121 if url
is None and hasattr(exc,
'response')
and exc.response
is not None:
122 url = exc.response.url
125 if isinstance(exc, HTTPStatusError):
126 status_code = str(exc.response.status_code)
127 reason = exc.response.reason_phrase
128 return (status_code, reason, hostname)
132 if isinstance(exc, JSONDecodeError):
134 if isinstance(exc, TypeError):
136 if isinstance(exc, ValueError)
and 'lxml' in filename:
138 if isinstance(exc, HTTPError):
140 if isinstance(exc, SearxXPathSyntaxException):
141 return (exc.xpath_str, exc.message)
142 if isinstance(exc, SearxEngineXPathException):
143 return (exc.xpath_str, exc.message)
144 if isinstance(exc, SearxEngineAPIException):
145 return (str(exc.args[0]),)
146 if isinstance(exc, SearxEngineAccessDeniedException):
147 return (exc.message,)
152 exc_class = exc.__class__
153 exc_name = exc_class.__qualname__
154 exc_module = exc_class.__module__
155 if exc_module
is None or exc_module == str.__class__.__module__:
157 return exc_module +
'.' + exc_name
160def get_error_context(framerecords, exception_classname, log_message, log_parameters, secondary) -> ErrorContext:
162 filename = searx_frame.filename
163 if filename.startswith(searx_parent_dir):
164 filename = filename[len(searx_parent_dir) + 1 :]
165 function = searx_frame.function
166 line_no = searx_frame.lineno
167 code = searx_frame.code_context[0].strip()
169 return ErrorContext(filename, function, line_no, code, exception_classname, log_message, log_parameters, secondary)
172def count_exception(engine_name: str, exc: Exception, secondary: bool =
False) ->
None:
173 if not settings[
'general'][
'enable_metrics']:
175 framerecords = inspect.trace()
179 error_context =
get_error_context(framerecords, exception_classname,
None, log_parameters, secondary)
186 engine_name: str, log_message: str, log_parameters: typing.Optional[typing.Tuple] =
None, secondary: bool =
False
188 if not settings[
'general'][
'enable_metrics']:
190 framerecords = list(reversed(inspect.stack()[1:]))
192 error_context =
get_error_context(framerecords,
None, log_message, log_parameters
or (), secondary)
__init__(self, filename, function, line_no, code, exception_classname, log_message, log_parameters, secondary)
ErrorContext get_error_context(framerecords, exception_classname, log_message, log_parameters, secondary)
typing.Tuple get_messages(exc, filename)
None count_exception(str engine_name, Exception exc, bool secondary=False)
str get_exception_classname(Exception exc)
typing.Optional[None] get_hostname(HTTPError exc)
None add_error_context(str engine_name, ErrorContext error_context)
typing.Tuple[typing.Optional[str], typing.Optional[str], typing.Optional[str]] get_request_exception_messages(HTTPError exc)
None count_error(str engine_name, str log_message, typing.Optional[typing.Tuple] log_parameters=None, bool secondary=False)