Skip to content

Commit 13508df

Browse files
authored
Update all framework instrumentation with new error logic (#218)
* Switch out error API and return status codes directly. * Switch ignore_status_code calls with should_ignore_error. * Fix tornado and bottle tests. * Pass status code to notice_error directly. * Pass ignore iterable to wrap_error_trace. * Remove unused imports
1 parent b3fa944 commit 13508df

21 files changed

+83
-115
lines changed

newrelic/agent.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@
1515
from newrelic.config import (
1616
initialize as __initialize,
1717
extra_settings as __extra_settings)
18-
from newrelic.core.config import (
19-
global_settings as __global_settings,
20-
ignore_status_code as __ignore_status_code)
18+
19+
from newrelic.core.config import global_settings as __global_settings
2120

2221
from newrelic.core.agent import (
2322
shutdown_agent as __shutdown_agent,
@@ -200,8 +199,6 @@ def __asgi_application(*args, **kwargs):
200199
'extra_settings')
201200
global_settings = __wrap_api_call(__global_settings,
202201
'global_settings')
203-
ignore_status_code = __wrap_api_call(__ignore_status_code,
204-
'ignore_status_code')
205202
shutdown_agent = __wrap_api_call(__shutdown_agent,
206203
'shutdown_agent')
207204
register_data_source = __wrap_api_call(__register_data_source,

newrelic/hooks/application_gearman.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ def wrapper_callback_function(wrapped, instance, args, kwargs):
156156
try:
157157
return wrapped(*args, **kwargs)
158158
except: # Catch all
159-
trace.record_exception()
159+
trace.notice_error()
160160
raise
161161

162162
def wrapper_GearmanWorker_register_task(wrapped, instance, args, kwargs):

newrelic/hooks/component_flask_rest.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,19 @@
1313
# limitations under the License.
1414

1515
from newrelic.api.transaction import current_transaction
16-
from newrelic.api.time_trace import record_exception
17-
from newrelic.core.config import ignore_status_code
16+
from newrelic.api.time_trace import notice_error
1817
from newrelic.common.object_wrapper import wrap_function_wrapper
1918

2019

21-
def should_ignore(exc, value, tb):
20+
def status_code(exc, value, tb):
2221
from werkzeug.exceptions import HTTPException
2322

2423
# Werkzeug HTTPException can be raised internally by Flask or in
2524
# user code if they mix Flask with Werkzeug. Filter based on the
2625
# HTTP status code.
2726

2827
if isinstance(value, HTTPException):
29-
if ignore_status_code(value.code):
30-
return True
28+
return value.code
3129

3230

3331
def _nr_wrap_Api_handle_error_(wrapped, instance, args, kwargs):
@@ -36,7 +34,7 @@ def _nr_wrap_Api_handle_error_(wrapped, instance, args, kwargs):
3634
# flask's exception handler and we will capture it there.
3735
resp = wrapped(*args, **kwargs)
3836

39-
record_exception(ignore_errors=should_ignore)
37+
notice_error(status_code=status_code)
4038

4139
return resp
4240

newrelic/hooks/component_tastypie.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,15 @@
1717
from newrelic.api.function_trace import FunctionTrace
1818
from newrelic.api.object_wrapper import ObjectWrapper, callable_name
1919
from newrelic.api.transaction import current_transaction
20-
from newrelic.api.time_trace import record_exception
20+
from newrelic.api.time_trace import notice_error
2121
from newrelic.common.object_wrapper import wrap_function_wrapper
22-
from newrelic.core.config import ignore_status_code
2322

2423

2524
def _nr_wrap_handle_exception(wrapped, instance, args, kwargs):
2625

2726
response = wrapped(*args, **kwargs)
2827

29-
if not ignore_status_code(response.status_code):
30-
record_exception()
28+
notice_error(status_code=response.status_code)
3129

3230
return response
3331

newrelic/hooks/framework_aiohttp.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
from newrelic.common.object_names import callable_name
2424
from newrelic.common.object_wrapper import (wrap_function_wrapper,
2525
function_wrapper, ObjectProxy)
26-
from newrelic.core.config import ignore_status_code
26+
from newrelic.core.config import should_ignore_error
27+
2728

2829

2930
SUPPORTED_METHODS = ('connect', 'head', 'get', 'delete', 'options', 'patch',
@@ -51,7 +52,7 @@ def should_ignore(exc, value, tb):
5152

5253
if isinstance(value, web.HTTPException):
5354
status_code = value.status_code
54-
return ignore_status_code(status_code)
55+
return should_ignore_error((exc, value, tb), status_code)
5556

5657

5758
def _nr_process_response_proxy(response, transaction):
@@ -345,7 +346,7 @@ def _coro(*_args, **_kwargs):
345346
response = yield from coro
346347
return response
347348

348-
# Patch in should_ignore to all record_exception calls
349+
# Patch in should_ignore to all notice_error calls
349350
transaction._ignore_errors = should_ignore
350351

351352
import aiohttp

newrelic/hooks/framework_bottle.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,23 @@
2626
from newrelic.common.object_wrapper import (wrap_out_function,
2727
function_wrapper, ObjectProxy, wrap_object_attribute,
2828
wrap_function_wrapper)
29-
from newrelic.core.config import ignore_status_code
3029

3130
module_bottle = None
3231

33-
def should_ignore(exc, value, tb):
32+
def status_code(exc, value, tb):
3433
# The HTTPError class derives from HTTPResponse and so we do not
3534
# need to check for it seperately as isinstance() will pick it up.
3635

3736
if isinstance(value, module_bottle.HTTPResponse):
3837
if hasattr(value, 'status_code'):
39-
if ignore_status_code(value.status_code):
40-
return True
38+
return value.status_code
4139
elif hasattr(value, 'status'):
42-
if ignore_status_code(value.status):
43-
return True
40+
return value.status
4441
elif hasattr(value, 'http_status_code'):
45-
if ignore_status_code(value.http_status_code):
46-
return True
42+
return value.http_status_code
4743

48-
elif hasattr(module_bottle, 'RouteReset'):
44+
def should_ignore(exc, value, tb):
45+
if hasattr(module_bottle, 'RouteReset'):
4946
if isinstance(value, module_bottle.RouteReset):
5047
return True
5148

@@ -75,7 +72,7 @@ def callback_wrapper(wrapped, instance, args, kwargs):
7572
# return it instead. This doesn't always seem to be the case
7673
# though when plugins are used, although that may depend on
7774
# the specific bottle version being used.
78-
trace.record_exception(ignore_errors=should_ignore)
75+
trace.notice_error(status_code=status_code, ignore=should_ignore)
7976
raise
8077

8178
def output_wrapper_Bottle_match(result):

newrelic/hooks/framework_cherrypy.py

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,11 @@
3939

4040
from newrelic.api.function_trace import FunctionTrace, wrap_function_trace
4141
from newrelic.api.transaction import current_transaction
42-
from newrelic.api.time_trace import record_exception
42+
from newrelic.api.time_trace import notice_error
4343
from newrelic.api.wsgi_application import wrap_wsgi_application
4444
from newrelic.common.object_names import callable_name
4545
from newrelic.common.object_wrapper import (ObjectProxy, function_wrapper,
4646
wrap_function_wrapper)
47-
from newrelic.core.config import ignore_status_code
4847
from newrelic.api.error_trace import wrap_error_trace
4948

5049

@@ -53,7 +52,7 @@ def framework_details():
5352
return ('CherryPy', getattr(cherrypy, '__version__', None))
5453

5554

56-
def should_ignore(exc, value, tb):
55+
def status_code(exc, value, tb):
5756
from cherrypy import HTTPError, HTTPRedirect
5857

5958
# Ignore certain exceptions based on HTTP status codes.
@@ -64,20 +63,7 @@ def should_ignore(exc, value, tb):
6463
# HTTPError("10 Bad error")), value will not have a code attr.
6564
# In both of those cases, we fall back to value.status
6665
code = getattr(value, 'code', value.status)
67-
68-
if ignore_status_code(code):
69-
return True
70-
71-
# Ignore certain exceptions based on their name.
72-
73-
module = value.__class__.__module__
74-
name = value.__class__.__name__
75-
fullname = '%s:%s' % (module, name)
76-
77-
ignore_exceptions = ('cherrypy._cperror:InternalRedirect',)
78-
79-
if fullname in ignore_exceptions:
80-
return True
66+
return code
8167

8268

8369
@function_wrapper
@@ -122,7 +108,7 @@ def wrapper_Dispatcher_find_handler(wrapped, instance, args, kwargs):
122108
except: # Catch all
123109
# Can end up here when a custom _cp_dispatch() method is
124110
# used and that raises an exception.
125-
record_exception()
111+
notice_error()
126112
raise
127113

128114
if obj:
@@ -173,7 +159,7 @@ def wrapper_RoutesDispatcher_find_handler(wrapped, instance, args, kwargs):
173159

174160
except: # Catch all
175161
# Can end up here when the URL was invalid in some way.
176-
record_exception()
162+
notice_error()
177163
raise
178164

179165
if handler:
@@ -206,7 +192,7 @@ def instrument_cherrypy__cpdispatch(module):
206192
wrap_function_wrapper(module, 'RoutesDispatcher.find_handler',
207193
wrapper_RoutesDispatcher_find_handler)
208194
wrap_error_trace(module, 'PageHandler.__call__',
209-
ignore=should_ignore)
195+
ignore=['cherrypy._cperror:InternalRedirect'], status_code=status_code)
210196

211197

212198
def instrument_cherrypy__cpwsgi(module):

newrelic/hooks/framework_django.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@
2626
FunctionTraceWrapper)
2727
from newrelic.api.html_insertion import insert_html_snippet
2828
from newrelic.api.transaction import current_transaction
29-
from newrelic.api.time_trace import record_exception
29+
from newrelic.api.time_trace import notice_error
3030
from newrelic.api.transaction_name import wrap_transaction_name
3131
from newrelic.api.wsgi_application import WSGIApplicationWrapper
3232

3333
from newrelic.common.object_wrapper import (FunctionWrapper, wrap_in_function,
3434
wrap_post_function, wrap_function_wrapper, function_wrapper)
3535
from newrelic.common.object_names import callable_name
3636
from newrelic.config import extra_settings
37-
from newrelic.core.config import global_settings, ignore_status_code
37+
from newrelic.core.config import global_settings
3838
from newrelic.common.coroutine import is_coroutine_function, is_asyncio_coroutine
3939

4040
if six.PY3:
@@ -445,8 +445,7 @@ def _nr_wrapper_BaseHandler_get_response_(wrapped, instance, args, kwargs):
445445
request = _bind_get_response(*args, **kwargs)
446446

447447
if hasattr(request, '_nr_exc_info'):
448-
if not ignore_status_code(response.status_code):
449-
record_exception(*request._nr_exc_info)
448+
notice_error(error=request._nr_exc_info, status_code=response.status_code)
450449
delattr(request, '_nr_exc_info')
451450

452451
return response
@@ -496,13 +495,13 @@ def wrapper(wrapped, instance, args, kwargs):
496495

497496
def _wrapped(request, resolver, exc_info):
498497
transaction.set_transaction_name(name, priority=1)
499-
record_exception(*exc_info)
498+
notice_error(exc_info)
500499

501500
try:
502501
return wrapped(request, resolver, exc_info)
503502

504503
except: # Catch all
505-
record_exception()
504+
notice_error()
506505
raise
507506

508507
with FunctionTrace(name=name):
@@ -569,7 +568,7 @@ def wrapper(wrapped, instance, args, kwargs):
569568
# prior to reporting
570569
args[0]._nr_exc_info = exc_info
571570
except:
572-
record_exception(*exc_info)
571+
notice_error(exc_info)
573572
raise
574573

575574
result = FunctionWrapper(wrapped, wrapper)

newrelic/hooks/framework_django_py3.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
from newrelic.api.time_trace import record_exception
1+
from newrelic.api.time_trace import notice_error
22
from newrelic.api.transaction import current_transaction
3-
from newrelic.core.config import ignore_status_code
43
from newrelic.common.object_wrapper import function_wrapper
54
from newrelic.api.function_trace import FunctionTrace
65

@@ -19,8 +18,7 @@ async def _nr_wrapper_BaseHandler_get_response_async_(
1918
request = _bind_get_response(*args, **kwargs)
2019

2120
if hasattr(request, '_nr_exc_info'):
22-
if not ignore_status_code(response.status_code):
23-
record_exception(*request._nr_exc_info)
21+
notice_error(error=request._nr_exc_info, status_code=response.status_code)
2422
delattr(request, '_nr_exc_info')
2523

2624
return response

newrelic/hooks/framework_falcon.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@
1717
from newrelic.common.object_wrapper import (wrap_function_wrapper,
1818
function_wrapper)
1919
from newrelic.api.transaction import current_transaction
20-
from newrelic.api.time_trace import record_exception
20+
from newrelic.api.time_trace import notice_error
2121
from newrelic.api.wsgi_application import wrap_wsgi_application
22-
from newrelic.core.config import ignore_status_code
2322
from newrelic.api.function_trace import function_trace
2423

2524

@@ -47,11 +46,9 @@ def wrap_handle_exception(wrapped, instance, args, kwargs):
4746
try:
4847
resp = bind_handle_exception(*args, **kwargs)
4948
response_code = int(resp.status.split()[0])
50-
if ignore_status_code(response_code):
51-
return result
52-
record_exception(*exc_info)
49+
notice_error(error=exc_info, status_code=response_code)
5350
except:
54-
record_exception(*exc_info)
51+
notice_error(exc_info)
5552
finally:
5653
exc_info = None
5754

0 commit comments

Comments
 (0)