mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Ensure an error gets logged when a delivery method fails (#3144)
* Ensure an error gets logged when a delivery method fails - Refactor existing code to log a custom error to the database - Limit error notifications to UI * Adjust unit test * Clear existing notifications before run * Add some debug to work out what is going on * Accommodate extra notification
This commit is contained in:
parent
5870b21a91
commit
c0148c0a38
@ -9,7 +9,6 @@ import traceback
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.debug import ExceptionReporter
|
||||
|
||||
import rest_framework.views as drfviews
|
||||
from error_report.models import Error
|
||||
@ -18,6 +17,23 @@ from rest_framework.exceptions import ValidationError as DRFValidationError
|
||||
from rest_framework.response import Response
|
||||
|
||||
|
||||
def log_error(path):
|
||||
"""Log an error to the database.
|
||||
|
||||
- Uses python exception handling to extract error details
|
||||
|
||||
Arguments:
|
||||
path: The 'path' (most likely a URL) associated with this error (optional)
|
||||
"""
|
||||
kind, info, data = sys.exc_info()
|
||||
Error.objects.create(
|
||||
kind=kind.__name__,
|
||||
info=info,
|
||||
data='\n'.join(traceback.format_exception(kind, info, data)),
|
||||
path=path,
|
||||
)
|
||||
|
||||
|
||||
def exception_handler(exc, context):
|
||||
"""Custom exception handler for DRF framework.
|
||||
|
||||
@ -55,16 +71,7 @@ def exception_handler(exc, context):
|
||||
|
||||
response = Response(response_data, status=500)
|
||||
|
||||
# Log the exception to the database, too
|
||||
kind, info, data = sys.exc_info()
|
||||
|
||||
Error.objects.create(
|
||||
kind=kind.__name__,
|
||||
info=info,
|
||||
data='\n'.join(traceback.format_exception(kind, info, data)),
|
||||
path=context['request'].path,
|
||||
html=ExceptionReporter(context['request'], kind, info, data).get_traceback_html(),
|
||||
)
|
||||
log_error(context['request'].path)
|
||||
|
||||
if response is not None:
|
||||
# Convert errors returned under the label '__all__' to 'non_field_errors'
|
||||
|
@ -475,6 +475,7 @@ def after_error_logged(sender, instance: Error, created: bool, **kwargs):
|
||||
'inventree.error_log',
|
||||
context=context,
|
||||
targets=users,
|
||||
delivery_methods=set([common.notifications.UIMessageNotification]),
|
||||
)
|
||||
|
||||
except Exception as exc:
|
||||
|
@ -3,7 +3,6 @@
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
|
||||
@ -21,7 +20,6 @@ from django.utils.translation import gettext_lazy as _
|
||||
from djmoney.contrib.exchange.exceptions import MissingRate
|
||||
from djmoney.contrib.exchange.models import convert_money
|
||||
from djmoney.money import Money
|
||||
from error_report.models import Error
|
||||
from markdownx.models import MarkdownxField
|
||||
from mptt.models import TreeForeignKey
|
||||
|
||||
@ -29,6 +27,7 @@ import InvenTree.helpers
|
||||
import InvenTree.ready
|
||||
from common.settings import currency_code_default
|
||||
from company.models import Company, SupplierPart
|
||||
from InvenTree.exceptions import log_error
|
||||
from InvenTree.fields import InvenTreeModelMoneyField, RoundingDecimalField
|
||||
from InvenTree.helpers import (decimal2string, getSetting, increment,
|
||||
notify_responsible)
|
||||
@ -186,13 +185,7 @@ class Order(MetadataMixin, ReferenceIndexingMixin):
|
||||
# Record the error, try to press on
|
||||
kind, info, data = sys.exc_info()
|
||||
|
||||
Error.objects.create(
|
||||
kind=kind.__name__,
|
||||
info=info,
|
||||
data='\n'.join(traceback.format_exception(kind, info, data)),
|
||||
path='order.get_total_price',
|
||||
)
|
||||
|
||||
log_error('order.get_total_price')
|
||||
logger.error(f"Missing exchange rate for '{target_currency}'")
|
||||
|
||||
# Return None to indicate the calculated price is invalid
|
||||
@ -208,15 +201,8 @@ class Order(MetadataMixin, ReferenceIndexingMixin):
|
||||
total += line.quantity * convert_money(line.price, target_currency)
|
||||
except MissingRate:
|
||||
# Record the error, try to press on
|
||||
kind, info, data = sys.exc_info()
|
||||
|
||||
Error.objects.create(
|
||||
kind=kind.__name__,
|
||||
info=info,
|
||||
data='\n'.join(traceback.format_exception(kind, info, data)),
|
||||
path='order.get_total_price',
|
||||
)
|
||||
|
||||
log_error('order.get_total_price')
|
||||
logger.error(f"Missing exchange rate for '{target_currency}'")
|
||||
|
||||
# Return None to indicate the calculated price is invalid
|
||||
|
@ -616,6 +616,8 @@ class BaseNotificationIntegrationTest(InvenTreeTestCase):
|
||||
# reload notification methods
|
||||
storage.collect(run_class)
|
||||
|
||||
NotificationEntry.objects.all().delete()
|
||||
|
||||
# There should be no notification runs
|
||||
self.assertEqual(NotificationEntry.objects.all().count(), 0)
|
||||
|
||||
@ -630,8 +632,8 @@ class BaseNotificationIntegrationTest(InvenTreeTestCase):
|
||||
self.part.set_starred(self.user, True)
|
||||
self.part.save()
|
||||
|
||||
# There should be 1 notification
|
||||
self.assertEqual(NotificationEntry.objects.all().count(), 1)
|
||||
# There should be 1 (or 2) notifications - in some cases an error is generated, which creates a subsequent notification
|
||||
self.assertIn(NotificationEntry.objects.all().count(), [1, 2])
|
||||
|
||||
|
||||
class PartNotificationTest(BaseNotificationIntegrationTest):
|
||||
|
@ -1,17 +1,14 @@
|
||||
"""Functions to print a label to a mixin printer."""
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.debug import ExceptionReporter
|
||||
|
||||
import pdf2image
|
||||
from error_report.models import Error
|
||||
|
||||
import common.notifications
|
||||
from InvenTree.exceptions import log_error
|
||||
from plugin.registry import registry
|
||||
|
||||
logger = logging.getLogger('inventree')
|
||||
@ -63,16 +60,7 @@ def print_label(plugin_slug: str, pdf_data, filename=None, label_instance=None,
|
||||
}
|
||||
|
||||
# Log an error message to the database
|
||||
kind, info, data = sys.exc_info()
|
||||
|
||||
Error.objects.create(
|
||||
kind=kind.__name__,
|
||||
info=info,
|
||||
data='\n'.join(traceback.format_exception(kind, info, data)),
|
||||
path='print_label',
|
||||
html=ExceptionReporter(None, kind, info, data).get_traceback_html(),
|
||||
)
|
||||
|
||||
log_error('plugin.print_label')
|
||||
logger.error(f"Label printing failed: Sending notification to user '{user}'") # pragma: no cover
|
||||
|
||||
# Throw an error against the plugin instance
|
||||
|
@ -1,14 +1,10 @@
|
||||
"""Views for plugin app."""
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from django.conf import settings
|
||||
from django.views.debug import ExceptionReporter
|
||||
|
||||
from error_report.models import Error
|
||||
|
||||
from InvenTree.exceptions import log_error
|
||||
from plugin.registry import registry
|
||||
|
||||
logger = logging.getLogger('inventree')
|
||||
@ -29,18 +25,8 @@ class InvenTreePluginViewMixin:
|
||||
try:
|
||||
panels += plug.render_panels(self, self.request, ctx)
|
||||
except Exception:
|
||||
# Prevent any plugin error from crashing the page render
|
||||
kind, info, data = sys.exc_info()
|
||||
|
||||
# Log the error to the database
|
||||
Error.objects.create(
|
||||
kind=kind.__name__,
|
||||
info=info,
|
||||
data='\n'.join(traceback.format_exception(kind, info, data)),
|
||||
path=self.request.path,
|
||||
html=ExceptionReporter(self.request, kind, info, data).get_traceback_html(),
|
||||
)
|
||||
|
||||
log_error(self.request.path)
|
||||
logger.error(f"Plugin '{plug.slug}' could not render custom panels at '{self.request.path}'")
|
||||
|
||||
return panels
|
||||
|
Loading…
Reference in New Issue
Block a user