sentry.io improvements (#4712)

* Write function to catch sentry.io events before sending

- Will let us ignore certain types of errors which we are not interested in

* Cleanup

* Include release info

* Allow sentry reporting in debug mode

* Consolidate DRF sentry code into InvenTree/sentry.py

* Add more error types to ignore

* update docs
This commit is contained in:
Oliver 2023-04-28 06:54:31 +10:00 committed by GitHub
parent 8d28fc06be
commit f6021c4749
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 28 deletions

View File

@ -18,6 +18,8 @@ from rest_framework import serializers
from rest_framework.exceptions import ValidationError as DRFValidationError
from rest_framework.response import Response
import InvenTree.sentry
logger = logging.getLogger('inventree')
@ -61,18 +63,12 @@ def exception_handler(exc, context):
"""
response = None
if settings.SENTRY_ENABLED and settings.SENTRY_DSN and not settings.DEBUG:
# Report this exception to sentry.io
from sentry_sdk import capture_exception
# The following types of errors are ignored, they are "expected"
do_not_report = [
DjangoValidationError,
DRFValidationError,
]
if not any([isinstance(exc, err) for err in do_not_report]):
capture_exception(exc)
# Pass exception to sentry.io handler
try:
InvenTree.sentry.report_exception(exc)
except Exception:
# If sentry.io fails, we don't want to crash the server!
pass
# Catch any django validation error, and re-throw a DRF validation error
if isinstance(exc, DjangoValidationError):

View File

@ -0,0 +1,68 @@
"""Configuration for Sentry.io error reporting."""
import logging
from django.conf import settings
from django.core.exceptions import ValidationError
from django.http import Http404
import rest_framework.exceptions
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
from InvenTree.version import INVENTREE_SW_VERSION
logger = logging.getLogger('inventree')
def default_sentry_dsn():
"""Return the default Sentry.io DSN for InvenTree"""
return 'https://3928ccdba1d34895abde28031fd00100@o378676.ingest.sentry.io/6494600'
def sentry_ignore_errors():
"""Return a list of error types to ignore.
These error types will *not* be reported to sentry.io.
"""
return [
Http404,
ValidationError,
rest_framework.exceptions.AuthenticationFailed,
rest_framework.exceptions.PermissionDenied,
rest_framework.exceptions.ValidationError,
]
def init_sentry(dsn, sample_rate, tags):
"""Initialize sentry.io error reporting"""
logger.info("Initializing sentry.io integration")
sentry_sdk.init(
dsn=dsn,
integrations=[DjangoIntegration()],
traces_sample_rate=sample_rate,
send_default_pii=True,
ignore_errors=sentry_ignore_errors(),
release=INVENTREE_SW_VERSION,
)
for key, val in tags.items():
sentry_sdk.set_tag(f'inventree_{key}', val)
def report_exception(exc):
"""Report an exception to sentry.io"""
if settings.SENTRY_ENABLED and settings.SENTRY_DSN:
if not any([isinstance(exc, e) for e in sentry_ignore_errors()]):
logger.info(f"Reporting exception to sentry.io: {exc}")
try:
sentry_sdk.capture_exception(exc)
except Exception:
logger.warning("Failed to report exception to sentry.io")

View File

@ -21,12 +21,12 @@ from django.http import Http404
from django.utils.translation import gettext_lazy as _
import moneyed
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
from InvenTree.config import get_boolean_setting, get_custom_file, get_setting
from InvenTree.sentry import default_sentry_dsn, init_sentry
from InvenTree.version import inventreeApiVersion
from . import config
from .config import get_boolean_setting, get_custom_file, get_setting
from .version import inventreeApiVersion
INVENTREE_NEWS_URL = 'https://inventree.org/news/feed.atom'
@ -573,29 +573,21 @@ REMOTE_LOGIN_HEADER = get_setting('INVENTREE_REMOTE_LOGIN_HEADER', 'remote_login
# sentry.io integration for error reporting
SENTRY_ENABLED = get_boolean_setting('INVENTREE_SENTRY_ENABLED', 'sentry_enabled', False)
# Default Sentry DSN (can be overriden if user wants custom sentry integration)
INVENTREE_DSN = 'https://3928ccdba1d34895abde28031fd00100@o378676.ingest.sentry.io/6494600'
SENTRY_DSN = get_setting('INVENTREE_SENTRY_DSN', 'sentry_dsn', INVENTREE_DSN)
SENTRY_DSN = get_setting('INVENTREE_SENTRY_DSN', 'sentry_dsn', default_sentry_dsn())
SENTRY_SAMPLE_RATE = float(get_setting('INVENTREE_SENTRY_SAMPLE_RATE', 'sentry_sample_rate', 0.1))
if SENTRY_ENABLED and SENTRY_DSN: # pragma: no cover
logger.info("Running with sentry.io integration enabled")
sentry_sdk.init(
dsn=SENTRY_DSN,
integrations=[DjangoIntegration(), ],
traces_sample_rate=1.0 if DEBUG else SENTRY_SAMPLE_RATE,
send_default_pii=True
)
inventree_tags = {
'testing': TESTING,
'docker': DOCKER,
'debug': DEBUG,
'remote': REMOTE_LOGIN,
}
for key, val in inventree_tags.items():
sentry_sdk.set_tag(f'inventree_{key}', val)
init_sentry(SENTRY_DSN, SENTRY_SAMPLE_RATE, inventree_tags)
# Cache configuration
cache_host = get_setting('INVENTREE_CACHE_HOST', 'cache.host', None)

View File

@ -27,3 +27,7 @@ A list of error logs is presented.
## Reporting Errors
Errors should be reported to the [InvenTree GitHub page](https://github.com/inventree/inventree/issues), and include the full error output as recorded to the error log.
### Sentry Integration
If [sentry.io integration](../start/config.md#sentry-integration) is enabled, some error logs are automatically reported to sentry.io