Add error message

Improve error handling
This commit is contained in:
allegroai 2021-01-05 18:14:29 +02:00
parent b548958c80
commit df334d083e
2 changed files with 30 additions and 3 deletions

View File

@ -118,6 +118,7 @@ _error_codes = {
1: ('internal_error', 'internal server error'), 1: ('internal_error', 'internal server error'),
2: ('config_error', 'configuration error'), 2: ('config_error', 'configuration error'),
3: ('build_info_error', 'build info unavailable or corrupted'), 3: ('build_info_error', 'build info unavailable or corrupted'),
4: ('low_disk_space', 'Critical server error! Server reports low or insufficient disk space. Please resolve immediately by allocating additional disk space or freeing up storage space.'),
10: ('transaction_error', 'a transaction call has returned with an error'), 10: ('transaction_error', 'a transaction call has returned with an error'),
# Database-related issues # Database-related issues
100: ('data_error', 'general data error'), 100: ('data_error', 'general data error'),

View File

@ -1,6 +1,7 @@
import re import re
from contextlib import contextmanager from contextlib import contextmanager
from functools import wraps from functools import wraps
from textwrap import shorten
import dpath import dpath
from dpath.exceptions import InvalidKeyName from dpath.exceptions import InvalidKeyName
@ -33,7 +34,7 @@ class ParseCallError(Exception):
self.params = kwargs self.params = kwargs
def throws_default_error(err_cls): def throws_default_error(err_cls, shorten_width: int = None):
""" """
Used to make functions (Exception, str) -> Optional[str] searching for specialized error messages raise those Used to make functions (Exception, str) -> Optional[str] searching for specialized error messages raise those
messages in ``err_cls``. If the decorated function does not find a suitable error message, messages in ``err_cls``. If the decorated function does not find a suitable error message,
@ -45,25 +46,49 @@ def throws_default_error(err_cls):
@wraps(func) @wraps(func)
def wrapper(self, e, message, **kwargs): def wrapper(self, e, message, **kwargs):
extra_info = func(self, e, message, **kwargs) extra_info = func(self, e, message, **kwargs)
raise err_cls(message, err=e, extra_info=extra_info) err = str(e)
if shorten_width:
err = shorten(err, shorten_width, placeholder="...")
raise err_cls(message, err=err, extra_info=extra_info)
return wrapper return wrapper
return decorator return decorator
# noinspection RegExpRedundantEscape
class ElasticErrorsHandler(object): class ElasticErrorsHandler(object):
@classmethod @classmethod
@throws_default_error(errors.server_error.DataError) def _bulk_meta_error(cls, error):
try:
_, err_type = next(dpath.search(error, "*/error/type", yielded=True))
_, reason = next(dpath.search(error, "*/error/reason", yielded=True))
if err_type == "cluster_block_exception":
raise errors.server_error.LowDiskSpace(
"metrics, logs and all indexed data is in read-only mode!",
reason=re.sub(r"^index\s\[.*?\]\s", "", reason) if reason else ""
)
return
except StopIteration:
pass
@classmethod
@throws_default_error(errors.server_error.DataError, shorten_width=200)
def bulk_error(cls, e, _, **__): def bulk_error(cls, e, _, **__):
if not e.errors: if not e.errors:
return return
# Currently we only handle the first error
error = e.errors[0]
cls._bulk_meta_error(error)
# Else try returning a better error string # Else try returning a better error string
for _, reason in dpath.search(e.errors[0], "*/error/reason", yielded=True): for _, reason in dpath.search(e.errors[0], "*/error/reason", yielded=True):
return reason return reason
# noinspection RegExpRedundantEscape
class MongoEngineErrorsHandler(object): class MongoEngineErrorsHandler(object):
# NotUniqueError # NotUniqueError
__not_unique_regex = re.compile( __not_unique_regex = re.compile(
@ -81,6 +106,7 @@ class MongoEngineErrorsHandler(object):
def validation_error(cls, e: ValidationError, message, **_): def validation_error(cls, e: ValidationError, message, **_):
# Thrown when a document is validated. Documents are validated by default on save and on update # Thrown when a document is validated. Documents are validated by default on save and on update
err_dict = e.errors or {e.field_name: e.message} err_dict = e.errors or {e.field_name: e.message}
err_dict = {key: str(value) for key, value in err_dict.items()}
raise errors.bad_request.DataValidationError(message, **err_dict) raise errors.bad_request.DataValidationError(message, **err_dict)
@classmethod @classmethod