Coverage for src/backend/InvenTree/InvenTree/sentry.py: 42%

40 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 17:47 +0000

1"""Configuration for Sentry.io error reporting.""" 

2 

3from typing import Optional 

4 

5from django.conf import settings 

6from django.core.exceptions import ValidationError 

7from django.http import Http404 

8from django.template.exceptions import TemplateSyntaxError 

9 

10import rest_framework.exceptions 

11import sentry_sdk 

12import structlog 

13from djmoney.contrib.exchange.exceptions import MissingRate 

14from sentry_sdk.integrations.django import DjangoIntegration 

15 

16import InvenTree.version 

17 

18logger = structlog.get_logger('inventree') 

19 

20 

21def default_sentry_dsn(): 

22 """Return the default Sentry.io DSN for InvenTree.""" 

23 return 'https://3928ccdba1d34895abde28031fd00100@o378676.ingest.sentry.io/6494600' 

24 

25 

26def sentry_ignore_errors(): # pragma: no cover 

27 """Return a list of error types to ignore. 

28 

29 These error types will *not* be reported to sentry.io. 

30 """ 

31 return [ 

32 Http404, 

33 MissingRate, 

34 TemplateSyntaxError, 

35 ValidationError, 

36 rest_framework.exceptions.AuthenticationFailed, 

37 rest_framework.exceptions.NotAuthenticated, 

38 rest_framework.exceptions.PermissionDenied, 

39 rest_framework.exceptions.ValidationError, 

40 ] 

41 

42 

43def init_sentry(dsn, sample_rate, tags): # pragma: no cover 

44 """Initialize sentry.io error reporting.""" 

45 logger.info('Initializing sentry.io integration') 

46 

47 sentry_sdk.init( 

48 dsn=dsn, 

49 integrations=[DjangoIntegration()], 

50 traces_sample_rate=sample_rate, 

51 send_default_pii=True, 

52 ignore_errors=sentry_ignore_errors(), 

53 release=InvenTree.version.INVENTREE_SW_VERSION, 

54 environment='development' 

55 if InvenTree.version.isInvenTreeDevelopmentVersion() 

56 else 'production', 

57 ) 

58 

59 for key, val in tags.items(): 

60 sentry_sdk.set_tag(f'inventree_{key}', val) 

61 

62 sentry_sdk.set_tag('api', InvenTree.version.inventreeApiVersion()) 

63 sentry_sdk.set_tag('platform', InvenTree.version.inventreePlatform()) 

64 sentry_sdk.set_tag('git_branch', InvenTree.version.inventreeBranch()) 

65 sentry_sdk.set_tag('git_commit', InvenTree.version.inventreeCommitHash()) 

66 sentry_sdk.set_tag('git_date', InvenTree.version.inventreeCommitDate()) 

67 

68 

69def report_exception(exc, scope: Optional[dict] = None): # pragma: no cover 

70 """Report an exception to sentry.io.""" 

71 assert settings.TESTING == False, ( 

72 'report_exception should not be called in testing mode' 

73 ) 

74 

75 # Skip if sentry not enabled, or not configured 

76 if not settings.SENTRY_ENABLED or not settings.SENTRY_DSN: 76 ↛ 80line 76 didn't jump to line 80 because the condition on line 76 was always true

77 return 

78 

79 # Skip if this error type is in the ignore list 

80 if any(isinstance(exc, e) for e in sentry_ignore_errors()): 

81 return 

82 

83 # Error may also be passed in from the loggingn context 

84 if hasattr(exc, 'event'): 

85 event = getattr(exc, 'event', None) 

86 

87 if any(isinstance(event, e) for e in sentry_ignore_errors()): 

88 return 

89 

90 try: 

91 sentry_sdk.capture_exception(exc, scope=scope) 

92 except Exception: 

93 logger.warning('Failed to report exception to sentry.io')