7from json
import JSONDecodeError
8from urllib.parse
import urlparse
9from httpx
import HTTPError, HTTPStatusError
11 SearxXPathSyntaxException,
12 SearxEngineXPathException,
13 SearxEngineAPIException,
14 SearxEngineAccessDeniedException,
16from searx
import searx_parent_dir, settings
20errors_per_engines: dict[str, t.Any] = {}
22LogParametersType = tuple[str, ...]
32 'exception_classname',
44 exception_classname: str,
46 log_parameters: LogParametersType,
59 if not isinstance(o, ErrorContext):
65 and self.
code == o.code
87 return "ErrorContext({!r}, {!r}, {!r}, {!r}, {!r}, {!r}) {!r}".format(
99 errors_for_engine = errors_per_engines.setdefault(engine_name, {})
100 errors_for_engine[error_context] = errors_for_engine.get(error_context, 0) + 1
101 engines[engine_name].logger.warning(
'%s', str(error_context))
105 for trace
in reversed(traces):
106 split_filename: list[str] = trace.filename.split(
'/')
107 if '/'.join(split_filename[-3:-1]) ==
'searx/engines':
109 if '/'.join(split_filename[-4:-1]) ==
'searx/search/processors':
115 url = exc.request.url
116 if url
is None and exc.response
is not None:
117 url = exc.response.url
118 return urlparse(url).netloc
123) -> tuple[str |
None, str |
None, str |
None]:
128 if hasattr(exc,
'_request')
and exc._request
is not None:
131 url = exc.request.url
132 if url
is None and hasattr(exc,
'response')
and exc.response
is not None:
133 url = exc.response.url
136 if isinstance(exc, HTTPStatusError):
137 status_code = str(exc.response.status_code)
138 reason = exc.response.reason_phrase
139 return (status_code, reason, hostname)
143 if isinstance(exc, JSONDecodeError):
145 if isinstance(exc, TypeError):
147 if isinstance(exc, ValueError)
and 'lxml' in filename:
149 if isinstance(exc, HTTPError):
151 if isinstance(exc, SearxXPathSyntaxException):
152 return (exc.xpath_str, exc.message)
153 if isinstance(exc, SearxEngineXPathException):
154 return (exc.xpath_str, exc.message)
155 if isinstance(exc, SearxEngineAPIException):
156 return (str(exc.args[0]),)
157 if isinstance(exc, SearxEngineAccessDeniedException):
158 return (exc.message,)
163 exc_class = exc.__class__
164 exc_name = exc_class.__qualname__
165 exc_module = exc_class.__module__
166 if exc_module
is None or exc_module == str.__class__.__module__:
168 return exc_module +
'.' + exc_name
172 framerecords, exception_classname, log_message, log_parameters: LogParametersType, secondary: bool
175 filename = searx_frame.filename
176 if filename.startswith(searx_parent_dir):
177 filename = filename[len(searx_parent_dir) + 1 :]
178 function = searx_frame.function
179 line_no = searx_frame.lineno
180 code = searx_frame.code_context[0].strip()
182 return ErrorContext(filename, function, line_no, code, exception_classname, log_message, log_parameters, secondary)
185def count_exception(engine_name: str, exc: Exception, secondary: bool =
False) ->
None:
186 if not settings[
'general'][
'enable_metrics']:
188 framerecords = inspect.trace()
192 error_context =
get_error_context(framerecords, exception_classname,
None, log_parameters, secondary)
201 log_parameters: LogParametersType |
None =
None,
202 secondary: bool =
False,
204 if not settings[
'general'][
'enable_metrics']:
206 framerecords = list(reversed(inspect.stack()[1:]))
208 error_context =
get_error_context(framerecords,
None, log_message, log_parameters
or (), secondary)
LogParametersType log_parameters
__init__(self, str filename, str function, int line_no, str code, str exception_classname, str log_message, LogParametersType log_parameters, bool secondary)
ErrorContext get_error_context(framerecords, exception_classname, log_message, LogParametersType log_parameters, bool secondary)
None count_exception(str engine_name, Exception exc, bool secondary=False)
str get_exception_classname(Exception exc)
None count_error(str engine_name, str log_message, LogParametersType|None log_parameters=None, bool secondary=False)
str|None get_hostname(HTTPError exc)
tuple[str|None, str|None, str|None] get_request_exception_messages(HTTPError exc)
None add_error_context(str engine_name, ErrorContext error_context)
tuple[str,...] get_messages(exc, filename)