Skip to content

Commit 8cc9468

Browse files
Merge pull request #9342 from netbox-community/9340-sentry
Closes #9340: Enable Sentry integration
2 parents 1726593 + 312d6c8 commit 8cc9468

File tree

9 files changed

+106
-3
lines changed

9 files changed

+106
-3
lines changed

base_requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ psycopg2-binary
102102
# https://github.com/yaml/pyyaml
103103
PyYAML
104104

105+
# Sentry SDK
106+
# https://github.com/getsentry/sentry-python
107+
sentry-sdk
108+
105109
# Social authentication framework
106110
# https://github.com/python-social-auth/social-core
107111
social-auth-core
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Error Reporting
2+
3+
## Sentry
4+
5+
NetBox v3.2.3 and later support native integration with [Sentry](https://sentry.io/) for automatic error reporting. To enable this feature, begin by creating a new project in Sentry to represent your NetBox deployment and obtain its corresponding data source name (DSN). This looks like a URL similar to the example below:
6+
7+
```
8+
9+
```
10+
11+
Once you have obtained a DSN, configure Sentry in NetBox's `configuration.py` file with the following parameters:
12+
13+
```python
14+
SENTRY_ENABLED = True
15+
SENTRY_DSN = "https://[email protected]/0"
16+
```
17+
18+
You can optionally attach one or more arbitrary tags to the outgoing error reports if desired by setting the `SENTRY_TAGS` parameter:
19+
20+
```python
21+
SENTRY_TAGS = {
22+
"custom.foo": "123",
23+
"custom.bar": "abc",
24+
}
25+
```
26+
27+
Once the configuration has been saved, restart the NetBox service.
28+
29+
To test Sentry operation, try generating a 404 (page not found) error by navigating to an invalid URL, such as `https://netbox/404-error-testing`. After receiving a 404 response from the NetBox server, you should see the issue appear shortly in Sentry.

docs/configuration/optional-settings.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,39 @@ The file path to the location where [custom scripts](../customization/custom-scr
404404

405405
---
406406

407+
## SENTRY_DSN
408+
409+
Default: None
410+
411+
Defines a Sentry data source name (DSN) for automated error reporting. `SENTRY_ENABLED` must be True for this parameter to take effect. For example:
412+
413+
```
414+
SENTRY_DSN = "https://[email protected]/0"
415+
```
416+
417+
---
418+
419+
## SENTRY_ENABLED
420+
421+
Default: False
422+
423+
Set to True to enable automatic error reporting via [Sentry](https://sentry.io/). Requires `SENTRY_DSN` to be defined.
424+
425+
---
426+
427+
## SENTRY_TAGS
428+
429+
An optional dictionary of tags to apply to Sentry error reports. `SENTRY_ENABLED` must be True for this parameter to take effect. For example:
430+
431+
```
432+
SENTRY_TAGS = {
433+
"custom.foo": "123",
434+
"custom.bar": "abc",
435+
}
436+
```
437+
438+
---
439+
407440
## SESSION_COOKIE_NAME
408441

409442
Default: `sessionid`

docs/release-notes/version-3.2.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* [#9278](https://github.com/netbox-community/netbox/issues/9278) - Linkify device types count under manufacturers list
1212
* [#9280](https://github.com/netbox-community/netbox/issues/9280) - Allow adopting existing components when installing a module
1313
* [#9314](https://github.com/netbox-community/netbox/issues/9314) - Add device and VM filters for FHRP group assignments
14+
* [#9340](https://github.com/netbox-community/netbox/issues/9340) - Introduce support for error reporting via Sentry
1415

1516
### Bug Fixes
1617

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ nav:
123123
- Microsoft Azure AD: 'administration/authentication/microsoft-azure-ad.md'
124124
- Okta: 'administration/authentication/okta.md'
125125
- Permissions: 'administration/permissions.md'
126+
- Error Reporting: 'administration/error-reporting.md'
126127
- Housekeeping: 'administration/housekeeping.md'
127128
- Replicating NetBox: 'administration/replicating-netbox.md'
128129
- NetBox Shell: 'administration/netbox-shell.md'

netbox/netbox/settings.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
import warnings
99
from urllib.parse import urlsplit
1010

11+
import sentry_sdk
1112
from django.contrib.messages import constants as messages
1213
from django.core.exceptions import ImproperlyConfigured, ValidationError
1314
from django.core.validators import URLValidator
15+
from sentry_sdk.integrations.django import DjangoIntegration
1416

1517
from netbox.config import PARAMS
1618

@@ -113,6 +115,9 @@
113115
REPORTS_ROOT = getattr(configuration, 'REPORTS_ROOT', os.path.join(BASE_DIR, 'reports')).rstrip('/')
114116
RQ_DEFAULT_TIMEOUT = getattr(configuration, 'RQ_DEFAULT_TIMEOUT', 300)
115117
SCRIPTS_ROOT = getattr(configuration, 'SCRIPTS_ROOT', os.path.join(BASE_DIR, 'scripts')).rstrip('/')
118+
SENTRY_DSN = getattr(configuration, 'SENTRY_DSN', None)
119+
SENTRY_ENABLED = getattr(configuration, 'SENTRY_ENABLED', False)
120+
SENTRY_TAGS = getattr(configuration, 'SENTRY_TAGS', {})
116121
SESSION_FILE_PATH = getattr(configuration, 'SESSION_FILE_PATH', None)
117122
SESSION_COOKIE_NAME = getattr(configuration, 'SESSION_COOKIE_NAME', 'sessionid')
118123
SHORT_DATE_FORMAT = getattr(configuration, 'SHORT_DATE_FORMAT', 'Y-m-d')
@@ -428,6 +433,26 @@ def _setting(name, default=None):
428433
)
429434

430435

436+
#
437+
# Sentry
438+
#
439+
440+
if SENTRY_ENABLED:
441+
if not SENTRY_DSN:
442+
raise ImproperlyConfigured("SENTRY_ENABLED is True but SENTRY_DSN has not been defined.")
443+
sentry_sdk.init(
444+
dsn=SENTRY_DSN,
445+
release=VERSION,
446+
integrations=[DjangoIntegration()],
447+
traces_sample_rate=1.0,
448+
send_default_pii=True,
449+
http_proxy=HTTP_PROXIES.get('http') if HTTP_PROXIES else None,
450+
https_proxy=HTTP_PROXIES.get('https') if HTTP_PROXIES else None
451+
)
452+
for k, v in SENTRY_TAGS.items():
453+
sentry_sdk.set_tag(k, v)
454+
455+
431456
#
432457
# Django social auth
433458
#

netbox/netbox/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,5 @@
100100
path('{}'.format(settings.BASE_PATH), include(_patterns))
101101
]
102102

103+
handler404 = 'netbox.views.handler_404'
103104
handler500 = 'netbox.views.server_error'

netbox/netbox/views/__init__.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import sys
33

44
from django.conf import settings
5-
from django.contrib.contenttypes.models import ContentType
65
from django.core.cache import cache
76
from django.db.models import F
87
from django.http import HttpResponseServerError
@@ -11,9 +10,10 @@
1110
from django.template.exceptions import TemplateDoesNotExist
1211
from django.urls import reverse
1312
from django.views.decorators.csrf import requires_csrf_token
14-
from django.views.defaults import ERROR_500_TEMPLATE_NAME
13+
from django.views.defaults import ERROR_500_TEMPLATE_NAME, page_not_found
1514
from django.views.generic import View
1615
from packaging import version
16+
from sentry_sdk import capture_message
1717

1818
from circuits.models import Circuit, Provider
1919
from dcim.models import (
@@ -190,13 +190,21 @@ class StaticMediaFailureView(View):
190190
"""
191191
Display a user-friendly error message with troubleshooting tips when a static media file fails to load.
192192
"""
193-
194193
def get(self, request):
195194
return render(request, 'media_failure.html', {
196195
'filename': request.GET.get('filename')
197196
})
198197

199198

199+
def handler_404(request, exception):
200+
"""
201+
Wrap Django's default 404 handler to enable Sentry reporting.
202+
"""
203+
capture_message("Page not found", level="error")
204+
205+
return page_not_found(request, exception)
206+
207+
200208
@requires_csrf_token
201209
def server_error(request, template_name=ERROR_500_TEMPLATE_NAME):
202210
"""

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ netaddr==0.8.0
2424
Pillow==9.1.0
2525
psycopg2-binary==2.9.3
2626
PyYAML==6.0
27+
sentry-sdk==1.5.12
2728
social-auth-app-django==5.0.0
2829
social-auth-core==4.2.0
2930
svgwrite==1.4.2

0 commit comments

Comments
 (0)