Skip to content

Commit

Permalink
Feat (debug-notifications): Adds a optional setting `APM_NOTIFY_ON_DE…
Browse files Browse the repository at this point in the history
…BUG_TRUE` that when set to `True` will dispatch the error notification even if DEBUG is turned on. By default notifications won't be sent when DEBUG is True.
  • Loading branch information
leandrodesouzadev committed Oct 31, 2022
1 parent 96ecbcf commit bda7a6b
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 13 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ Install the package using your favorite packaging tool: pip / poetry / pdm, etc.
- `APM_REQUEST_SAVE_QUERY_PARAMETERS`: Boolean that when set to `True` will save the request query parameters as json. Defaults to `True`;
- `APM_REQUEST_SAVE_QUERY_STRING`: Boolean that when set to `True` will save the request raw query string. Defaults to `True`;
- `APM_NOTIFY_USING_CELERY`: Boolean that when set to `True` will dispatch a celery task when notificating. Since the process of notificating Integration can take a long time, we suggest you to set this to `True`. Defaults to `False`.
- `APM_NOTIFY_ON_DEBUG_TRUE`: Boolean that when set to `True` will notify errors even when `DEBUG=True`. Defaults to `False`.

## Storage considerations

Expand Down
1 change: 1 addition & 0 deletions djapm/apm/dflt_conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
APM_REQUEST_SAVE_QUERY_STRING = True

APM_NOTIFY_USING_CELERY = False
APM_NOTIFY_ON_DEBUG_TRUE = False
10 changes: 10 additions & 0 deletions djapm/apm/middlewares.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
from time import perf_counter
import traceback
import warnings

from django.conf import settings
from django.http import HttpRequest
Expand Down Expand Up @@ -113,6 +114,15 @@ def process_exception(
# This request was not processed by the decorator `apm_api_view`
return
trace = self._register_error_trace(request, exception)
notify_on_debug_true = getattr(
settings, "APM_NOTIFY_ON_DEBUG_TRUE", dflt_conf.APM_NOTIFY_ON_DEBUG_TRUE
)
if settings.DEBUG and not notify_on_debug_true:
warnings.warn(
"Errors Notifications aren't sent when DEBUG=True and APM_NOTIFY_ON_DEBUG_TRUE=False"
)
return

use_celery = getattr(
settings, "APM_NOTIFY_USING_CELERY", dflt_conf.APM_NOTIFY_USING_CELERY
)
Expand Down
30 changes: 30 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from typing import Any

from django.test.client import RequestFactory
import pytest

from djapm.apm.contrib import _contribute_to_request
from djapm.apm.types import ApmRequest, PatchedHttpRequest

from tests.types import ApmRequestFactory


@pytest.fixture
def apm_rf(rf: RequestFactory, admin_user) -> ApmRequestFactory:
"""Request factory for a APM view, that calls `_contribute_to_request`"""

def wrapper(
method: str, url: str, view: Any, drf_req: bool = False, user=None
) -> PatchedHttpRequest:
func = getattr(rf, method.lower())
req = func(url)
req.user = user or admin_user

rest_req = None
if drf_req:
rest_req = ApmRequest(req)

_contribute_to_request(req, view=view, logger_name=None, rest_request=rest_req)
return req

return wrapper
22 changes: 9 additions & 13 deletions tests/test_apm/test_contrib/test_view_name.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import pytest

from django.test.client import RequestFactory
from django.urls import reverse
from rest_framework.request import Request

from djapm.apm.contrib import _contribute_to_request
from polls.views import OrderedPolls, get_polls_page, get_polls
from tests.types import ApmRequestFactory


def test_contribute_to_request_on_regular_class_based_view(rf: RequestFactory):
request = rf.get(reverse("polls-page-list-cbv"))
_contribute_to_request(request, view=OrderedPolls.as_view(), logger_name=None)
def test_contribute_to_request_on_regular_class_based_view(apm_rf: ApmRequestFactory):
request = apm_rf("GET", reverse("polls-page-list-cbv"), OrderedPolls.as_view())
assert request.view_name == "polls.dj.OrderedPolls"


def test_contribute_to_request_on_regular_function_based_view(rf: RequestFactory):
request = rf.get(reverse("polls-page-list"))
_contribute_to_request(request, view=get_polls_page, logger_name=None)
def test_contribute_to_request_on_regular_function_based_view(
apm_rf: ApmRequestFactory,
):
request = apm_rf("GET", reverse("polls-page-list"), get_polls_page)
assert request.view_name == "polls.dj.get_polls_page"


Expand All @@ -25,9 +24,6 @@ def test_contribute_to_request_on_drf_class_based_view():
assert False


def test_contribute_to_request_on_drf_function_based_view(rf: RequestFactory):
request = rf.get(reverse("polls-list"))
_contribute_to_request(
request, view=get_polls, logger_name=None, rest_request=Request(request)
)
def test_contribute_to_request_on_drf_function_based_view(apm_rf: ApmRequestFactory):
request = apm_rf("GET", reverse("polls-list"), get_polls, drf_req=True)
assert request.view_name == "polls.drf.get_polls"
22 changes: 22 additions & 0 deletions tests/test_apm/test_middlewares/test_error_trace_middleware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import warnings

from django.urls import reverse

from djapm.apm.middlewares import ErrorTraceMiddleware
from polls.views import get_polls
from tests.types import ApmRequestFactory


def test_process_exception_warns_when_debug_true_and_notify_on_debug_true_is_false(
settings, apm_rf: ApmRequestFactory
):
settings.DEBUG = True
settings.APM_NOTIFY_ON_DEBUG_TRUE = False

middleware = ErrorTraceMiddleware(lambda r: r)

with warnings.catch_warnings(record=True) as w:
request = apm_rf("GET", reverse("polls-list"), get_polls, drf_req=True)
middleware.process_exception(request, ValueError("Oops, A exception occurred"))

assert len(w) == 1, "No warnings were emitted"
10 changes: 10 additions & 0 deletions tests/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from typing import Any, Protocol

from djapm.apm.types import PatchedHttpRequest


class ApmRequestFactory(Protocol):
def __call__(
self, method: str, url: str, view: Any, drf_req: bool = False, user=None
) -> PatchedHttpRequest:
...

0 comments on commit bda7a6b

Please sign in to comment.