From 36316455a27198ece25d4a66261ace17da85d8b9 Mon Sep 17 00:00:00 2001 From: Tim McCormack Date: Mon, 29 Sep 2025 13:39:38 -0400 Subject: [PATCH 1/2] fix: Fix deprecated newrelic function calls These shims were removed in newrelic 11.0.0. --- CHANGELOG.rst | 4 ++++ edx_django_utils/__init__.py | 2 +- edx_django_utils/monitoring/internal/backends.py | 9 ++------- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bff41b39..e905df43 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,10 @@ Change Log Unreleased ---------- +8.0.1 - 2025-09-29 +------------------ +* Stop using deprecated newrelic function calls that were removed in newrelic 11.0.0 (use newer names instead) + 8.0.0 - 2025-05-22 ------------------ * **BREAKING CHANGE**: ``newrelic`` removed from dependencies. Users of New Relic should install the package separately in their services. `See relevant DEPR `_. diff --git a/edx_django_utils/__init__.py b/edx_django_utils/__init__.py index c432bb41..c000c754 100644 --- a/edx_django_utils/__init__.py +++ b/edx_django_utils/__init__.py @@ -2,4 +2,4 @@ EdX utilities for Django Application development.. """ -__version__ = "8.0.0" +__version__ = "8.0.1" diff --git a/edx_django_utils/monitoring/internal/backends.py b/edx_django_utils/monitoring/internal/backends.py index d257abbe..6a1f1986 100644 --- a/edx_django_utils/monitoring/internal/backends.py +++ b/edx_django_utils/monitoring/internal/backends.py @@ -93,15 +93,10 @@ def set_attribute(self, key, value): # `add_custom_span_attribute` that would better match # OpenTelemetry's behavior, which we could try exposing # through a new, more specific TelemetryBackend method. - # - # TODO: Update to newer name `add_custom_attribute` - # https://docs.newrelic.com/docs/apm/agents/python-agent/python-agent-api/addcustomparameter-python-agent-api/ - newrelic.agent.add_custom_parameter(key, value) + newrelic.agent.add_custom_attribute(key, value) def record_exception(self): - # TODO: Replace with newrelic.agent.notice_error() - # https://docs.newrelic.com/docs/apm/agents/python-agent/python-agent-api/recordexception-python-agent-api/ - newrelic.agent.record_exception() + newrelic.agent.notice_error() def create_span(self, name): if newrelic.version_info[0] >= 5: From 119dbc9ab140cde3c9786d412e782ce2301b6339 Mon Sep 17 00:00:00 2001 From: Tim McCormack Date: Mon, 29 Sep 2025 14:05:27 -0400 Subject: [PATCH 2/2] fixup! tests --- .../monitoring/tests/test_backends.py | 12 ++++++------ .../monitoring/tests/test_middleware.py | 4 ++-- .../monitoring/tests/test_monitoring_support.py | 16 ++++++++-------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/edx_django_utils/monitoring/tests/test_backends.py b/edx_django_utils/monitoring/tests/test_backends.py index 29b65d3c..feed6209 100644 --- a/edx_django_utils/monitoring/tests/test_backends.py +++ b/edx_django_utils/monitoring/tests/test_backends.py @@ -112,7 +112,7 @@ class TestBackendsFanOut(TestCase): Test that certain utility functions fan out to the backends. """ - @patch('newrelic.agent.add_custom_parameter') + @patch('newrelic.agent.add_custom_attribute') @patch('opentelemetry.trace.span.NonRecordingSpan.set_attribute') # Patch out the span-getter, not the set_attribute call, because # it doesn't give us a span unless one is active. And I didn't @@ -122,7 +122,7 @@ class TestBackendsFanOut(TestCase): @patch('ddtrace._trace.tracer.Tracer.current_root_span') def test_set_custom_attribute( self, mock_dd_root_span, - mock_otel_set_attribute, mock_nr_add_custom_parameter, + mock_otel_set_attribute, mock_nr_add_custom_attribute, ): with override_settings(OPENEDX_TELEMETRY=[ 'edx_django_utils.monitoring.NewRelicBackend', @@ -130,17 +130,17 @@ def test_set_custom_attribute( 'edx_django_utils.monitoring.DatadogBackend', ]): set_custom_attribute('some_key', 'some_value') - mock_nr_add_custom_parameter.assert_called_once_with('some_key', 'some_value') + mock_nr_add_custom_attribute.assert_called_once_with('some_key', 'some_value') mock_otel_set_attribute.assert_called_once() mock_dd_root_span.assert_called_once() - @patch('newrelic.agent.record_exception') + @patch('newrelic.agent.notice_error') @patch('opentelemetry.trace.span.NonRecordingSpan.record_exception') # Record exception on current span, not root span. @patch('ddtrace._trace.tracer.Tracer.current_span') def test_record_exception( self, mock_dd_span, - mock_otel_record_exception, mock_nr_record_exception, + mock_otel_record_exception, mock_nr_notice_error, ): with override_settings(OPENEDX_TELEMETRY=[ 'edx_django_utils.monitoring.NewRelicBackend', @@ -148,6 +148,6 @@ def test_record_exception( 'edx_django_utils.monitoring.DatadogBackend', ]): record_exception() - mock_nr_record_exception.assert_called_once() + mock_nr_notice_error.assert_called_once() mock_otel_record_exception.assert_called_once() mock_dd_span.assert_called_once() diff --git a/edx_django_utils/monitoring/tests/test_middleware.py b/edx_django_utils/monitoring/tests/test_middleware.py index a2e75e02..d26e62f8 100644 --- a/edx_django_utils/monitoring/tests/test_middleware.py +++ b/edx_django_utils/monitoring/tests/test_middleware.py @@ -76,10 +76,10 @@ def test_record_python_and_django_version(self, mock_newrelic_agent): middleware = DeploymentMonitoringMiddleware(Mock()) middleware(Mock()) - parameter_calls_count = mock_newrelic_agent.add_custom_parameter.call_count + parameter_calls_count = mock_newrelic_agent.add_custom_attribute.call_count assert parameter_calls_count == 2 - function_calls = mock_newrelic_agent.add_custom_parameter.call_args_list + function_calls = mock_newrelic_agent.add_custom_attribute.call_args_list self._test_key_value_pair(function_calls[0], 'python_version') self._test_key_value_pair(function_calls[1], 'django_version') diff --git a/edx_django_utils/monitoring/tests/test_monitoring_support.py b/edx_django_utils/monitoring/tests/test_monitoring_support.py index 41a6f5eb..fb7f4ec2 100644 --- a/edx_django_utils/monitoring/tests/test_monitoring_support.py +++ b/edx_django_utils/monitoring/tests/test_monitoring_support.py @@ -71,16 +71,16 @@ def test_accumulate_and_increment( 'fake response', ) - # Assert call counts to newrelic.agent.add_custom_parameter() + # Assert call counts to newrelic.agent.add_custom_attribute() expected_call_count = len(nr_agent_calls_expected) if is_deprecated: expected_call_count += 1 - measured_call_count = mock_newrelic_agent.add_custom_parameter.call_count + measured_call_count = mock_newrelic_agent.add_custom_attribute.call_count self.assertEqual(expected_call_count, measured_call_count) - # Assert call args to newrelic.agent.add_custom_parameter(). Due to + # Assert call args to newrelic.agent.add_custom_attribute(). Due to # the nature of python dicts, call order is undefined. - mock_newrelic_agent.add_custom_parameter.assert_has_calls(nr_agent_calls_expected, any_order=True) + mock_newrelic_agent.add_custom_attribute.assert_has_calls(nr_agent_calls_expected, any_order=True) @patch('newrelic.agent') @ddt.data( @@ -110,15 +110,15 @@ def test_accumulate_with_illegal_value( 'fake response', ) - # Assert call counts to newrelic.agent.add_custom_parameter() + # Assert call counts to newrelic.agent.add_custom_attribute() expected_call_count = len(nr_agent_calls_expected) if is_deprecated: expected_call_count += 1 - measured_call_count = mock_newrelic_agent.add_custom_parameter.call_count + measured_call_count = mock_newrelic_agent.add_custom_attribute.call_count self.assertEqual(expected_call_count, measured_call_count) - # Assert call args to newrelic.agent.add_custom_parameter(). - mock_newrelic_agent.add_custom_parameter.assert_has_calls(nr_agent_calls_expected, any_order=True) + # Assert call args to newrelic.agent.add_custom_attribute(). + mock_newrelic_agent.add_custom_attribute.assert_has_calls(nr_agent_calls_expected, any_order=True) @contextmanager def catch_signal(self, signal):