Skip to content

Commit 56923f5

Browse files
Clean Up Ignore/Expected Errors Test Suite (#222)
* Add validator for time metrics outside transaction Co-authored-by: Uma Annamalai <[email protected]> * Remove now defunct record_exception tests * Clean up test suite for ignore/expected errors * Add expected errors metrics tests Co-authored-by: Uma Annamalai <[email protected]>
1 parent 950a63e commit 56923f5

File tree

3 files changed

+141
-497
lines changed

3 files changed

+141
-497
lines changed

tests/agent_features/test_ignore_expected_errors.py

Lines changed: 69 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,23 @@
1313
# limitations under the License.
1414

1515
import pytest
16-
17-
from newrelic.api.background_task import background_task
18-
from newrelic.api.function_trace import FunctionTrace
19-
from newrelic.api.time_trace import notice_error
20-
from newrelic.api.transaction import current_transaction
21-
from newrelic.api.application import application_instance
22-
23-
from newrelic.common.object_names import callable_name
24-
2516
from testing_support.fixtures import (
2617
override_application_settings,
2718
reset_core_stats_engine,
2819
validate_error_event_attributes_outside_transaction,
2920
validate_error_event_sample_data,
3021
validate_error_trace_attributes_outside_transaction,
22+
validate_time_metrics_outside_transaction,
3123
validate_transaction_error_trace_attributes,
3224
validate_transaction_errors,
3325
validate_transaction_metrics,
3426
)
3527

28+
from newrelic.api.application import application_instance
29+
from newrelic.api.background_task import background_task
30+
from newrelic.api.time_trace import notice_error
31+
from newrelic.api.transaction import current_transaction
32+
from newrelic.common.object_names import callable_name
3633

3734
_runtime_error_name = callable_name(RuntimeError)
3835
_error_message = "Test error message."
@@ -46,16 +43,10 @@
4643
ignore_runtime_error_settings = {
4744
"error_collector.ignore_classes": [_runtime_error_name]
4845
}
49-
combined_runtime_error_settings = {}
50-
combined_runtime_error_settings.update(expected_runtime_error_settings)
51-
combined_runtime_error_settings.update(ignore_runtime_error_settings)
5246

5347
# Status code settings
5448
expected_status_code_settings = {"error_collector.expected_status_codes": [418]}
5549
ignore_status_code_settings = {"error_collector.ignore_status_codes": [418]}
56-
combined_status_code_settings = {}
57-
combined_status_code_settings.update(expected_status_code_settings)
58-
combined_status_code_settings.update(ignore_status_code_settings)
5950

6051
_test_runtime_error = [(_runtime_error_name, _error_message)]
6152
_intrinsic_attributes = {
@@ -64,51 +55,35 @@
6455
"error.expected": False,
6556
"transactionName": "OtherTransaction/Function/test",
6657
}
67-
_metrics_normal = [
68-
("Errors/all", 1),
69-
("Errors/OtherTransaction/Function/test", 1),
70-
("Errors/allOther", 1),
71-
]
72-
7358

74-
# =============== Test ignored/expected classes within transaction ===============
59+
# =============== Test ignored/expected classes ===============
7560

7661
classes_settings_matrix = [
7762
({}, False, False),
7863
(ignore_runtime_error_settings, False, True),
7964
(expected_runtime_error_settings, True, False),
80-
(combined_runtime_error_settings, False, True),
8165
]
8266
override_expected_matrix = (True, False, None)
8367

8468

85-
def exercise(expected=None, ignore=None, status_code=None):
69+
def exercise(expected=None, ignore=None, status_code=None, application=None):
8670
try:
8771
raise RuntimeError(_error_message)
8872
except RuntimeError:
89-
if current_transaction() is not None:
73+
if current_transaction() is None:
9074
# Record exception inside transaction
91-
notice_error(
92-
expected=expected,
93-
ignore=ignore,
94-
status_code=status_code,
95-
)
96-
else:
97-
# Record exception outside context of transaction
98-
application_instance().notice_error(
99-
expected=expected,
100-
ignore=ignore,
101-
status_code=status_code,
102-
)
75+
application = application or application_instance()
10376

77+
notice_error(
78+
expected=expected,
79+
ignore=ignore,
80+
status_code=status_code,
81+
application=application,
82+
)
10483

105-
@pytest.mark.parametrize("settings,expected,ignore", classes_settings_matrix)
106-
@pytest.mark.parametrize("override_expected", override_expected_matrix)
107-
def test_classes_error_event_inside_transaction(
108-
settings, expected, ignore, override_expected
109-
):
110-
expected = override_expected if override_expected is not None else expected
11184

85+
@pytest.mark.parametrize("settings,expected,ignore", classes_settings_matrix)
86+
def test_classes_error_event_inside_transaction(settings, expected, ignore):
11287
# Update attributes with parameters
11388
attributes = _intrinsic_attributes.copy()
11489
attributes["error.expected"] = expected
@@ -125,21 +100,13 @@ def test_classes_error_event_inside_transaction(
125100
@background_task(name="test")
126101
@override_application_settings(settings)
127102
def _test():
128-
exercise(override_expected)
103+
exercise()
129104

130105
_test()
131106

132107

133-
# =============== Test ignored/expected classes outside transaction ===============
134-
135-
136108
@pytest.mark.parametrize("settings,expected,ignore", classes_settings_matrix)
137-
@pytest.mark.parametrize("override_expected", override_expected_matrix)
138-
def test_classes_error_event_outside_transaction(
139-
settings, expected, ignore, override_expected
140-
):
141-
expected = override_expected if override_expected is not None else expected
142-
109+
def test_classes_error_event_outside_transaction(settings, expected, ignore):
143110
# Update attributes with parameters
144111
attributes = _intrinsic_attributes.copy()
145112
attributes["error.expected"] = expected
@@ -154,12 +121,15 @@ def test_classes_error_event_outside_transaction(
154121
)
155122
@override_application_settings(settings)
156123
def _test():
157-
exercise(override_expected)
124+
exercise()
158125

159126
_test()
160127

161128

162129
# =============== Test error trace attributes ===============
130+
# Override testing is required to ensure the proper handling of
131+
# overrides. First attempt at implementation did not correctly handle this
132+
# and resulted in discrepancies between error events and traced errors.
163133

164134

165135
error_trace_settings_matrix = [
@@ -213,8 +183,7 @@ def test_error_trace_attributes_outside_transaction(
213183

214184
@reset_core_stats_engine()
215185
@validate_error_trace_attributes_outside_transaction(
216-
_runtime_error_name,
217-
exact_attrs=error_trace_attributes
186+
_runtime_error_name, exact_attrs=error_trace_attributes
218187
)
219188
@override_application_settings(settings)
220189
def _test():
@@ -226,18 +195,40 @@ def _test():
226195
# =============== Test metrics not incremented ===============
227196

228197

229-
@pytest.mark.skip()
230-
@pytest.mark.parametrize("settings,expected,ignore", classes_settings_matrix)
231-
@pytest.mark.parametrize("override_expected", override_expected_matrix)
232-
def test_classes_exception_metrics(settings, expected, ignore, override_expected):
233-
expected = override_expected or expected
234-
metrics = _metrics_normal if not (expected or ignore) else []
198+
@pytest.mark.parametrize("expected", override_expected_matrix)
199+
def test_error_metrics_inside_transaction(expected):
200+
normal_metrics_count = None if expected else 1
201+
expected_metrics_count = 1 if expected else None
202+
metrics_payload = [
203+
("Errors/all", normal_metrics_count),
204+
("Errors/OtherTransaction/Function/test", normal_metrics_count),
205+
("Errors/allOther", normal_metrics_count),
206+
("ErrorsExpected/all", expected_metrics_count),
207+
]
235208

236-
@override_application_settings(settings)
237-
@validate_transaction_metrics("test", background_task=True, rollup_metrics=metrics)
209+
@validate_transaction_metrics(
210+
"test", background_task=True, rollup_metrics=metrics_payload
211+
)
238212
@background_task(name="test")
239213
def _test():
240-
exercise(override_expected)
214+
exercise(expected)
215+
216+
_test()
217+
218+
219+
@pytest.mark.parametrize("expected", override_expected_matrix)
220+
def test_error_metrics_outside_transaction(expected):
221+
normal_metrics_count = None if expected else 1
222+
expected_metrics_count = 1 if expected else None
223+
metrics_payload = [
224+
("Errors/all", normal_metrics_count),
225+
("ErrorsExpected/all", expected_metrics_count),
226+
]
227+
228+
@reset_core_stats_engine()
229+
@validate_time_metrics_outside_transaction(metrics_payload)
230+
def _test():
231+
exercise(expected)
241232

242233
_test()
243234

@@ -261,25 +252,19 @@ def retrieve_status_code(exc, value, tb):
261252
({}, False, False),
262253
(ignore_status_code_settings, False, True),
263254
(expected_status_code_settings, True, False),
264-
(combined_status_code_settings, False, True),
265255
]
266256

267257
status_code_matrix = [None, 418, retrieve_status_code]
268258

269259

270260
@pytest.mark.parametrize("settings,expected,ignore", status_codes_settings_matrix)
271-
@pytest.mark.parametrize("override_expected", override_expected_matrix)
272261
@pytest.mark.parametrize("status_code", status_code_matrix)
273-
def test_status_codes_inside_transaction(
274-
settings, expected, ignore, override_expected, status_code
275-
):
262+
def test_status_codes_inside_transaction(settings, expected, ignore, status_code):
276263
if status_code is None:
277264
# Override all settings
278265
ignore = False
279266
expected = False
280267

281-
expected = override_expected if override_expected is not None else expected
282-
283268
# Update attributes with parameters
284269
attributes = _intrinsic_attributes.copy()
285270
attributes["error.expected"] = expected
@@ -300,24 +285,19 @@ def _test():
300285
try:
301286
raise TeapotError(_error_message)
302287
except:
303-
notice_error(expected=override_expected, status_code=status_code)
288+
notice_error(status_code=status_code)
304289

305290
_test()
306291

307292

308293
@pytest.mark.parametrize("settings,expected,ignore", status_codes_settings_matrix)
309-
@pytest.mark.parametrize("override_expected", override_expected_matrix)
310294
@pytest.mark.parametrize("status_code", status_code_matrix)
311-
def test_status_codes_outside_transaction(
312-
settings, expected, ignore, override_expected, status_code
313-
):
295+
def test_status_codes_outside_transaction(settings, expected, ignore, status_code):
314296
if status_code is None:
315297
# Override all settings
316298
ignore = False
317299
expected = False
318300

319-
expected = override_expected if override_expected is not None else expected
320-
321301
# Update attributes with parameters
322302
attributes = _intrinsic_attributes.copy()
323303
attributes["error.expected"] = expected
@@ -336,24 +316,33 @@ def _test():
336316
try:
337317
raise TeapotError(_error_message)
338318
except:
339-
notice_error(expected=override_expected, status_code=status_code)
319+
notice_error(status_code=status_code)
340320

341321
_test()
342322

343323

344324
# =============== Test mixed ignored and expected settings ===============
345325

326+
# Aggregate settings
346327
ignore_status_code_expected_class_settings = {}
347328
ignore_status_code_expected_class_settings.update(ignore_status_code_settings)
348329
ignore_status_code_expected_class_settings.update(expected_runtime_error_settings)
349330
expected_status_code_ignore_class_settings = {}
350331
expected_status_code_ignore_class_settings.update(expected_status_code_settings)
351332
expected_status_code_ignore_class_settings.update(ignore_runtime_error_settings)
333+
combined_runtime_error_settings = {}
334+
combined_runtime_error_settings.update(expected_runtime_error_settings)
335+
combined_runtime_error_settings.update(ignore_runtime_error_settings)
336+
combined_status_code_settings = {}
337+
combined_status_code_settings.update(expected_status_code_settings)
338+
combined_status_code_settings.update(ignore_status_code_settings)
352339

353340
mixed_settings_matrix = [
354341
({}, False, False),
355342
(ignore_status_code_expected_class_settings, True, True),
356343
(expected_status_code_ignore_class_settings, True, True),
344+
(combined_runtime_error_settings, True, True),
345+
(combined_status_code_settings, True, True),
357346
]
358347
override_expected_matrix = (True, False, None)
359348
override_ignore_matrix = (True, False, None)

0 commit comments

Comments
 (0)