From 9f0e03be00b57bd75b9eebf0fd6c64f8c520d633 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Tue, 30 Aug 2022 11:35:25 -0700 Subject: [PATCH 01/23] Move validate_transaction_metrics to validators directory --- tests/adapter_cheroot/test_wsgi.py | 2 +- .../test_supportability_metrics.py | 2 +- tests/agent_features/test_time_trace.py | 2 +- tests/agent_features/test_transaction_name.py | 2 +- tests/application_celery/test_celery.py | 2 +- .../test_custom_conn_pool.py | 2 +- .../test_execute_command.py | 2 +- tests/datastore_aioredis/test_get_and_set.py | 2 +- tests/datastore_aioredis/test_multiple_dbs.py | 2 +- tests/datastore_bmemcached/test_memcache.py | 2 +- tests/datastore_mysql/test_database.py | 2 +- tests/datastore_postgresql/test_database.py | 2 +- tests/datastore_pylibmc/test_memcache.py | 2 +- tests/datastore_pymemcache/test_memcache.py | 2 +- tests/datastore_pysolr/test_solr.py | 2 +- tests/datastore_solrpy/test_solr.py | 2 +- tests/datastore_sqlite/test_database.py | 2 +- tests/datastore_umemcache/test_memcache.py | 2 +- tests/external_feedparser/test_feedparser.py | 2 +- tests/external_httplib/test_urllib.py | 3 +- tests/external_httplib/test_urllib2.py | 3 +- tests/framework_aiohttp/test_client.py | 2 +- .../test_client_async_await.py | 3 +- .../test_application_async.py | 3 +- tests/framework_ariadne/test_asgi.py | 3 +- tests/framework_ariadne/test_wsgi.py | 3 +- tests/framework_fastapi/test_application.py | 2 +- .../test_application_async.py | 3 +- tests/framework_starlette/test_bg_tasks.py | 2 +- tests/framework_starlette/test_graphql.py | 3 +- .../test_application_async.py | 3 +- tests/framework_strawberry/test_asgi.py | 3 +- .../framework_tornado/test_custom_handler.py | 2 +- .../test_pika_supportability.py | 2 +- tests/template_mako/test_mako.py | 2 +- .../validate_transaction_metrics.py | 135 ++++++++++++++++++ 36 files changed, 180 insertions(+), 35 deletions(-) create mode 100644 tests/testing_support/validators/validate_transaction_metrics.py diff --git a/tests/adapter_cheroot/test_wsgi.py b/tests/adapter_cheroot/test_wsgi.py index b59a12c2d..49858e2f5 100644 --- a/tests/adapter_cheroot/test_wsgi.py +++ b/tests/adapter_cheroot/test_wsgi.py @@ -16,7 +16,7 @@ import cheroot.wsgi import newrelic.api.transaction -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics def get_open_port(): diff --git a/tests/agent_features/test_supportability_metrics.py b/tests/agent_features/test_supportability_metrics.py index d3e4b9a69..d77502180 100644 --- a/tests/agent_features/test_supportability_metrics.py +++ b/tests/agent_features/test_supportability_metrics.py @@ -20,7 +20,7 @@ from newrelic.core.agent import agent_instance -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_metric_payload import ( validate_metric_payload) diff --git a/tests/agent_features/test_time_trace.py b/tests/agent_features/test_time_trace.py index f81e8750d..2b53b9985 100644 --- a/tests/agent_features/test_time_trace.py +++ b/tests/agent_features/test_time_trace.py @@ -14,7 +14,7 @@ import logging -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task from newrelic.api.function_trace import FunctionTrace diff --git a/tests/agent_features/test_transaction_name.py b/tests/agent_features/test_transaction_name.py index 492f64df3..beaf83b57 100644 --- a/tests/agent_features/test_transaction_name.py +++ b/tests/agent_features/test_transaction_name.py @@ -15,7 +15,7 @@ from newrelic.api.background_task import background_task from newrelic.api.transaction import set_transaction_name, set_background_task -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics # test diff --git a/tests/application_celery/test_celery.py b/tests/application_celery/test_celery.py index 5bde17714..c2f9177fa 100644 --- a/tests/application_celery/test_celery.py +++ b/tests/application_celery/test_celery.py @@ -15,7 +15,7 @@ from newrelic.api.background_task import background_task from newrelic.api.transaction import ignore_transaction, end_of_transaction -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from tasks import add, tsum diff --git a/tests/datastore_aioredis/test_custom_conn_pool.py b/tests/datastore_aioredis/test_custom_conn_pool.py index 155765e5a..9530961a4 100644 --- a/tests/datastore_aioredis/test_custom_conn_pool.py +++ b/tests/datastore_aioredis/test_custom_conn_pool.py @@ -26,7 +26,7 @@ from newrelic.api.background_task import background_task # from testing_support.fixture.event_loop import event_loop as loop -from testing_support.fixtures import validate_transaction_metrics, override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics, override_application_settings from testing_support.db_settings import redis_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_aioredis/test_execute_command.py b/tests/datastore_aioredis/test_execute_command.py index 690007d6c..89d6c5413 100644 --- a/tests/datastore_aioredis/test_execute_command.py +++ b/tests/datastore_aioredis/test_execute_command.py @@ -16,7 +16,7 @@ import aioredis from newrelic.api.background_task import background_task -from testing_support.fixtures import validate_transaction_metrics, override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics, override_application_settings from conftest import event_loop, loop, AIOREDIS_VERSION from testing_support.db_settings import redis_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_aioredis/test_get_and_set.py b/tests/datastore_aioredis/test_get_and_set.py index b363f14d5..7e880f875 100644 --- a/tests/datastore_aioredis/test_get_and_set.py +++ b/tests/datastore_aioredis/test_get_and_set.py @@ -18,7 +18,7 @@ from newrelic.api.background_task import background_task from conftest import event_loop, loop, AIOREDIS_VERSION -from testing_support.fixtures import validate_transaction_metrics, override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics, override_application_settings from testing_support.db_settings import redis_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_aioredis/test_multiple_dbs.py b/tests/datastore_aioredis/test_multiple_dbs.py index 248fb847d..4ac98abf8 100644 --- a/tests/datastore_aioredis/test_multiple_dbs.py +++ b/tests/datastore_aioredis/test_multiple_dbs.py @@ -16,7 +16,7 @@ import aioredis from newrelic.api.background_task import background_task -from testing_support.fixtures import validate_transaction_metrics, override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics, override_application_settings from conftest import event_loop, loop, AIOREDIS_VERSION from testing_support.db_settings import redis_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_bmemcached/test_memcache.py b/tests/datastore_bmemcached/test_memcache.py index 1bef31f59..68eee0633 100644 --- a/tests/datastore_bmemcached/test_memcache.py +++ b/tests/datastore_bmemcached/test_memcache.py @@ -19,7 +19,7 @@ from newrelic.api.background_task import background_task from newrelic.api.transaction import set_background_task -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import memcached_settings diff --git a/tests/datastore_mysql/test_database.py b/tests/datastore_mysql/test_database.py index 0991d6df0..2fc8ca129 100644 --- a/tests/datastore_mysql/test_database.py +++ b/tests/datastore_mysql/test_database.py @@ -14,7 +14,7 @@ import mysql.connector -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_database_trace_inputs import validate_database_trace_inputs from testing_support.db_settings import mysql_settings diff --git a/tests/datastore_postgresql/test_database.py b/tests/datastore_postgresql/test_database.py index de53808c6..2ea930b05 100644 --- a/tests/datastore_postgresql/test_database.py +++ b/tests/datastore_postgresql/test_database.py @@ -15,7 +15,7 @@ import postgresql.driver.dbapi20 -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_database_trace_inputs import ( validate_database_trace_inputs, diff --git a/tests/datastore_pylibmc/test_memcache.py b/tests/datastore_pylibmc/test_memcache.py index 554581fdc..769f3b483 100644 --- a/tests/datastore_pylibmc/test_memcache.py +++ b/tests/datastore_pylibmc/test_memcache.py @@ -17,7 +17,7 @@ import pylibmc from testing_support.db_settings import memcached_settings -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task from newrelic.api.transaction import set_background_task diff --git a/tests/datastore_pymemcache/test_memcache.py b/tests/datastore_pymemcache/test_memcache.py index 12bd5da1a..9aeea4d54 100644 --- a/tests/datastore_pymemcache/test_memcache.py +++ b/tests/datastore_pymemcache/test_memcache.py @@ -16,7 +16,7 @@ import pymemcache.client -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import memcached_settings from newrelic.api.background_task import background_task diff --git a/tests/datastore_pysolr/test_solr.py b/tests/datastore_pysolr/test_solr.py index 785c3cb9f..a987a29ac 100644 --- a/tests/datastore_pysolr/test_solr.py +++ b/tests/datastore_pysolr/test_solr.py @@ -14,7 +14,7 @@ from pysolr import Solr -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import solr_settings from newrelic.api.background_task import background_task diff --git a/tests/datastore_solrpy/test_solr.py b/tests/datastore_solrpy/test_solr.py index 86dc23d4a..ee1a7e91e 100644 --- a/tests/datastore_solrpy/test_solr.py +++ b/tests/datastore_solrpy/test_solr.py @@ -14,7 +14,7 @@ from solr import SolrConnection -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import solr_settings from newrelic.api.background_task import background_task diff --git a/tests/datastore_sqlite/test_database.py b/tests/datastore_sqlite/test_database.py index 5443ca1c9..4ca534c39 100644 --- a/tests/datastore_sqlite/test_database.py +++ b/tests/datastore_sqlite/test_database.py @@ -18,7 +18,7 @@ is_pypy = hasattr(sys, 'pypy_version_info') -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_database_trace_inputs import validate_database_trace_inputs from newrelic.api.background_task import background_task diff --git a/tests/datastore_umemcache/test_memcache.py b/tests/datastore_umemcache/test_memcache.py index ce6475a49..4683a20d5 100644 --- a/tests/datastore_umemcache/test_memcache.py +++ b/tests/datastore_umemcache/test_memcache.py @@ -17,7 +17,7 @@ import umemcache from testing_support.db_settings import memcached_settings -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task from newrelic.api.transaction import set_background_task diff --git a/tests/external_feedparser/test_feedparser.py b/tests/external_feedparser/test_feedparser.py index 9cb175711..5e515cfc3 100644 --- a/tests/external_feedparser/test_feedparser.py +++ b/tests/external_feedparser/test_feedparser.py @@ -14,7 +14,7 @@ import pytest from newrelic.api.background_task import background_task -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics @pytest.fixture(scope="session") diff --git a/tests/external_httplib/test_urllib.py b/tests/external_httplib/test_urllib.py index 38cf4f713..cea88a8dd 100644 --- a/tests/external_httplib/test_urllib.py +++ b/tests/external_httplib/test_urllib.py @@ -25,7 +25,8 @@ cache_outgoing_headers, insert_incoming_headers, ) -from testing_support.fixtures import cat_enabled, validate_transaction_metrics +from testing_support.fixtures import cat_enabled +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_cross_process_headers import ( validate_cross_process_headers, ) diff --git a/tests/external_httplib/test_urllib2.py b/tests/external_httplib/test_urllib2.py index cbcb25a2f..62ed23074 100644 --- a/tests/external_httplib/test_urllib2.py +++ b/tests/external_httplib/test_urllib2.py @@ -25,7 +25,8 @@ cache_outgoing_headers, insert_incoming_headers, ) -from testing_support.fixtures import cat_enabled, validate_transaction_metrics +from testing_support.fixtures import cat_enabled +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_cross_process_headers import ( validate_cross_process_headers, ) diff --git a/tests/framework_aiohttp/test_client.py b/tests/framework_aiohttp/test_client.py index b2d23dd23..172d349bb 100644 --- a/tests/framework_aiohttp/test_client.py +++ b/tests/framework_aiohttp/test_client.py @@ -16,7 +16,7 @@ import aiohttp import pytest -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from yarl import URL from newrelic.api.background_task import background_task diff --git a/tests/framework_aiohttp/test_client_async_await.py b/tests/framework_aiohttp/test_client_async_await.py index 1e3eb79ec..dedc64c9d 100644 --- a/tests/framework_aiohttp/test_client_async_await.py +++ b/tests/framework_aiohttp/test_client_async_await.py @@ -16,7 +16,8 @@ import aiohttp import pytest -from testing_support.fixtures import cat_enabled, validate_transaction_metrics +from testing_support.fixtures import cat_enabled +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from yarl import URL from newrelic.api.background_task import background_task diff --git a/tests/framework_ariadne/test_application_async.py b/tests/framework_ariadne/test_application_async.py index 8e46752f2..ada34ffad 100644 --- a/tests/framework_ariadne/test_application_async.py +++ b/tests/framework_ariadne/test_application_async.py @@ -15,7 +15,8 @@ import asyncio import pytest -from testing_support.fixtures import dt_enabled, validate_transaction_metrics +from testing_support.fixtures import dt_enabled +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_span_events import validate_span_events from newrelic.api.background_task import background_task diff --git a/tests/framework_ariadne/test_asgi.py b/tests/framework_ariadne/test_asgi.py index 6275e781f..861f2aa93 100644 --- a/tests/framework_ariadne/test_asgi.py +++ b/tests/framework_ariadne/test_asgi.py @@ -16,7 +16,8 @@ import pytest from testing_support.asgi_testing import AsgiTest -from testing_support.fixtures import dt_enabled, validate_transaction_metrics +from testing_support.fixtures import dt_enabled +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_span_events import validate_span_events diff --git a/tests/framework_ariadne/test_wsgi.py b/tests/framework_ariadne/test_wsgi.py index 2c11276ed..9ce2373d4 100644 --- a/tests/framework_ariadne/test_wsgi.py +++ b/tests/framework_ariadne/test_wsgi.py @@ -14,7 +14,8 @@ import pytest import webtest -from testing_support.fixtures import dt_enabled, validate_transaction_metrics +from testing_support.fixtures import dt_enabled +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_span_events import validate_span_events diff --git a/tests/framework_fastapi/test_application.py b/tests/framework_fastapi/test_application.py index 8fe4be34f..85d230e26 100644 --- a/tests/framework_fastapi/test_application.py +++ b/tests/framework_fastapi/test_application.py @@ -15,7 +15,7 @@ import logging import pytest -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics diff --git a/tests/framework_graphql/test_application_async.py b/tests/framework_graphql/test_application_async.py index 19b8b1493..28b435c43 100644 --- a/tests/framework_graphql/test_application_async.py +++ b/tests/framework_graphql/test_application_async.py @@ -16,7 +16,8 @@ import pytest from test_application import is_graphql_2 -from testing_support.fixtures import dt_enabled, validate_transaction_metrics +from testing_support.fixtures import dt_enabled +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_span_events import validate_span_events from newrelic.api.background_task import background_task diff --git a/tests/framework_starlette/test_bg_tasks.py b/tests/framework_starlette/test_bg_tasks.py index af929895f..3a5a78bf2 100644 --- a/tests/framework_starlette/test_bg_tasks.py +++ b/tests/framework_starlette/test_bg_tasks.py @@ -14,7 +14,7 @@ import pytest import sys -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_transaction_count import ( validate_transaction_count, ) diff --git a/tests/framework_starlette/test_graphql.py b/tests/framework_starlette/test_graphql.py index 241371eb1..24ec3ab38 100644 --- a/tests/framework_starlette/test_graphql.py +++ b/tests/framework_starlette/test_graphql.py @@ -15,7 +15,8 @@ import json import pytest -from testing_support.fixtures import dt_enabled, validate_transaction_metrics +from testing_support.fixtures import dt_enabled +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_span_events import validate_span_events diff --git a/tests/framework_strawberry/test_application_async.py b/tests/framework_strawberry/test_application_async.py index 8174eb36e..1354c4c01 100644 --- a/tests/framework_strawberry/test_application_async.py +++ b/tests/framework_strawberry/test_application_async.py @@ -15,7 +15,8 @@ import asyncio import pytest -from testing_support.fixtures import dt_enabled, validate_transaction_metrics +from testing_support.fixtures import dt_enabled +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_span_events import validate_span_events from newrelic.api.background_task import background_task diff --git a/tests/framework_strawberry/test_asgi.py b/tests/framework_strawberry/test_asgi.py index 0db1e8a58..8acbaedfb 100644 --- a/tests/framework_strawberry/test_asgi.py +++ b/tests/framework_strawberry/test_asgi.py @@ -16,7 +16,8 @@ import pytest from testing_support.asgi_testing import AsgiTest -from testing_support.fixtures import dt_enabled, validate_transaction_metrics +from testing_support.fixtures import dt_enabled +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_span_events import validate_span_events diff --git a/tests/framework_tornado/test_custom_handler.py b/tests/framework_tornado/test_custom_handler.py index 4cabc5e1f..a8cb77d76 100644 --- a/tests/framework_tornado/test_custom_handler.py +++ b/tests/framework_tornado/test_custom_handler.py @@ -13,7 +13,7 @@ # limitations under the License. import pytest -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics pytestmark = pytest.mark.custom_app diff --git a/tests/messagebroker_pika/test_pika_supportability.py b/tests/messagebroker_pika/test_pika_supportability.py index fa0e46639..9f0d94e90 100644 --- a/tests/messagebroker_pika/test_pika_supportability.py +++ b/tests/messagebroker_pika/test_pika_supportability.py @@ -19,7 +19,7 @@ from newrelic.api.background_task import background_task from conftest import QUEUE, BODY -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import rabbitmq_settings DB_SETTINGS = rabbitmq_settings()[0] diff --git a/tests/template_mako/test_mako.py b/tests/template_mako/test_mako.py index fd598d786..07d8f4974 100644 --- a/tests/template_mako/test_mako.py +++ b/tests/template_mako/test_mako.py @@ -13,7 +13,7 @@ # limitations under the License. from mako.template import Template -from testing_support.fixtures import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task diff --git a/tests/testing_support/validators/validate_transaction_metrics.py b/tests/testing_support/validators/validate_transaction_metrics.py new file mode 100644 index 000000000..7122b009a --- /dev/null +++ b/tests/testing_support/validators/validate_transaction_metrics.py @@ -0,0 +1,135 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import copy + +from newrelic.common.object_wrapper import ( + function_wrapper, + transient_function_wrapper, +) +from testing_support.fixtures import catch_background_exceptions + +def validate_transaction_metrics( + name, + group="Function", + background_task=False, + scoped_metrics=None, + rollup_metrics=None, + custom_metrics=None, + index=-1, +): + scoped_metrics = scoped_metrics or [] + rollup_metrics = rollup_metrics or [] + custom_metrics = custom_metrics or [] + + if background_task: + unscoped_metrics = [ + "OtherTransaction/all", + "OtherTransaction/%s/%s" % (group, name), + "OtherTransactionTotalTime", + "OtherTransactionTotalTime/%s/%s" % (group, name), + ] + transaction_scope_name = "OtherTransaction/%s/%s" % (group, name) + else: + unscoped_metrics = [ + "WebTransaction", + "WebTransaction/%s/%s" % (group, name), + "WebTransactionTotalTime", + "WebTransactionTotalTime/%s/%s" % (group, name), + "HttpDispatcher", + ] + transaction_scope_name = "WebTransaction/%s/%s" % (group, name) + + @function_wrapper + def _validate_wrapper(wrapped, instance, args, kwargs): + + record_transaction_called = [] + recorded_metrics = [] + + @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") + @catch_background_exceptions + def _validate_transaction_metrics(wrapped, instance, args, kwargs): + record_transaction_called.append(True) + try: + result = wrapped(*args, **kwargs) + except: + raise + else: + metrics = instance.stats_table + # Record a copy of the metric value so that the values aren't + # merged in the future + _metrics = {} + for k, v in metrics.items(): + _metrics[k] = copy.copy(v) + recorded_metrics.append(_metrics) + + return result + + def _validate(metrics, name, scope, count): + key = (name, scope) + metric = metrics.get(key) + + def _metrics_table(): + out = [""] + out.append("Expected: {0}: {1}".format(key, count)) + for metric_key, metric_value in metrics.items(): + out.append("{0}: {1}".format(metric_key, metric_value[0])) + return "\n".join(out) + + def _metric_details(): + return "metric=%r, count=%r" % (key, metric.call_count) + + if count is not None: + assert metric is not None, _metrics_table() + if count == "present": + assert metric.call_count > 0, _metric_details() + else: + assert metric.call_count == count, _metric_details() + + assert metric.total_call_time >= 0, (key, metric) + assert metric.total_exclusive_call_time >= 0, (key, metric) + assert metric.min_call_time >= 0, (key, metric) + assert metric.sum_of_squares >= 0, (key, metric) + + else: + assert metric is None, _metrics_table() + + _new_wrapper = _validate_transaction_metrics(wrapped) + val = _new_wrapper(*args, **kwargs) + assert record_transaction_called + metrics = recorded_metrics[index] + + record_transaction_called[:] = [] + recorded_metrics[:] = [] + + for unscoped_metric in unscoped_metrics: + _validate(metrics, unscoped_metric, "", 1) + + for scoped_name, scoped_count in scoped_metrics: + _validate(metrics, scoped_name, transaction_scope_name, scoped_count) + + for rollup_name, rollup_count in rollup_metrics: + _validate(metrics, rollup_name, "", rollup_count) + + for custom_name, custom_count in custom_metrics: + _validate(metrics, custom_name, "", custom_count) + + custom_metric_names = {name for name, _ in custom_metrics} + for name, _ in metrics: + if name not in custom_metric_names: + assert not name.startswith("Supportability/api/"), name + + return val + + return _validate_wrapper \ No newline at end of file From f3d788f129f9ddef6d67dc4a17f9f51388a4d07f Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Tue, 30 Aug 2022 11:38:22 -0700 Subject: [PATCH 02/23] Comment out original validate_transaction_metrics from fixtures.py --- tests/testing_support/fixtures.py | 226 +++++++++++++++--------------- 1 file changed, 113 insertions(+), 113 deletions(-) diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index a89730377..e70c900c4 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -385,119 +385,119 @@ def make_synthetics_header(account_id, resource_id, job_id, monitor_id, encoding return {"X-NewRelic-Synthetics": value} -def validate_transaction_metrics( - name, - group="Function", - background_task=False, - scoped_metrics=None, - rollup_metrics=None, - custom_metrics=None, - index=-1, -): - scoped_metrics = scoped_metrics or [] - rollup_metrics = rollup_metrics or [] - custom_metrics = custom_metrics or [] - - if background_task: - unscoped_metrics = [ - "OtherTransaction/all", - "OtherTransaction/%s/%s" % (group, name), - "OtherTransactionTotalTime", - "OtherTransactionTotalTime/%s/%s" % (group, name), - ] - transaction_scope_name = "OtherTransaction/%s/%s" % (group, name) - else: - unscoped_metrics = [ - "WebTransaction", - "WebTransaction/%s/%s" % (group, name), - "WebTransactionTotalTime", - "WebTransactionTotalTime/%s/%s" % (group, name), - "HttpDispatcher", - ] - transaction_scope_name = "WebTransaction/%s/%s" % (group, name) - - @function_wrapper - def _validate_wrapper(wrapped, instance, args, kwargs): - - record_transaction_called = [] - recorded_metrics = [] - - @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") - @catch_background_exceptions - def _validate_transaction_metrics(wrapped, instance, args, kwargs): - record_transaction_called.append(True) - try: - result = wrapped(*args, **kwargs) - except: - raise - else: - metrics = instance.stats_table - # Record a copy of the metric value so that the values aren't - # merged in the future - _metrics = {} - for k, v in metrics.items(): - _metrics[k] = copy.copy(v) - recorded_metrics.append(_metrics) - - return result - - def _validate(metrics, name, scope, count): - key = (name, scope) - metric = metrics.get(key) - - def _metrics_table(): - out = [""] - out.append("Expected: {0}: {1}".format(key, count)) - for metric_key, metric_value in metrics.items(): - out.append("{0}: {1}".format(metric_key, metric_value[0])) - return "\n".join(out) - - def _metric_details(): - return "metric=%r, count=%r" % (key, metric.call_count) - - if count is not None: - assert metric is not None, _metrics_table() - if count == "present": - assert metric.call_count > 0, _metric_details() - else: - assert metric.call_count == count, _metric_details() - - assert metric.total_call_time >= 0, (key, metric) - assert metric.total_exclusive_call_time >= 0, (key, metric) - assert metric.min_call_time >= 0, (key, metric) - assert metric.sum_of_squares >= 0, (key, metric) - - else: - assert metric is None, _metrics_table() - - _new_wrapper = _validate_transaction_metrics(wrapped) - val = _new_wrapper(*args, **kwargs) - assert record_transaction_called - metrics = recorded_metrics[index] - - record_transaction_called[:] = [] - recorded_metrics[:] = [] - - for unscoped_metric in unscoped_metrics: - _validate(metrics, unscoped_metric, "", 1) - - for scoped_name, scoped_count in scoped_metrics: - _validate(metrics, scoped_name, transaction_scope_name, scoped_count) - - for rollup_name, rollup_count in rollup_metrics: - _validate(metrics, rollup_name, "", rollup_count) - - for custom_name, custom_count in custom_metrics: - _validate(metrics, custom_name, "", custom_count) - - custom_metric_names = {name for name, _ in custom_metrics} - for name, _ in metrics: - if name not in custom_metric_names: - assert not name.startswith("Supportability/api/"), name - - return val - - return _validate_wrapper +# def validate_transaction_metrics( +# name, +# group="Function", +# background_task=False, +# scoped_metrics=None, +# rollup_metrics=None, +# custom_metrics=None, +# index=-1, +# ): +# scoped_metrics = scoped_metrics or [] +# rollup_metrics = rollup_metrics or [] +# custom_metrics = custom_metrics or [] + +# if background_task: +# unscoped_metrics = [ +# "OtherTransaction/all", +# "OtherTransaction/%s/%s" % (group, name), +# "OtherTransactionTotalTime", +# "OtherTransactionTotalTime/%s/%s" % (group, name), +# ] +# transaction_scope_name = "OtherTransaction/%s/%s" % (group, name) +# else: +# unscoped_metrics = [ +# "WebTransaction", +# "WebTransaction/%s/%s" % (group, name), +# "WebTransactionTotalTime", +# "WebTransactionTotalTime/%s/%s" % (group, name), +# "HttpDispatcher", +# ] +# transaction_scope_name = "WebTransaction/%s/%s" % (group, name) + +# @function_wrapper +# def _validate_wrapper(wrapped, instance, args, kwargs): + +# record_transaction_called = [] +# recorded_metrics = [] + +# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") +# @catch_background_exceptions +# def _validate_transaction_metrics(wrapped, instance, args, kwargs): +# record_transaction_called.append(True) +# try: +# result = wrapped(*args, **kwargs) +# except: +# raise +# else: +# metrics = instance.stats_table +# # Record a copy of the metric value so that the values aren't +# # merged in the future +# _metrics = {} +# for k, v in metrics.items(): +# _metrics[k] = copy.copy(v) +# recorded_metrics.append(_metrics) + +# return result + +# def _validate(metrics, name, scope, count): +# key = (name, scope) +# metric = metrics.get(key) + +# def _metrics_table(): +# out = [""] +# out.append("Expected: {0}: {1}".format(key, count)) +# for metric_key, metric_value in metrics.items(): +# out.append("{0}: {1}".format(metric_key, metric_value[0])) +# return "\n".join(out) + +# def _metric_details(): +# return "metric=%r, count=%r" % (key, metric.call_count) + +# if count is not None: +# assert metric is not None, _metrics_table() +# if count == "present": +# assert metric.call_count > 0, _metric_details() +# else: +# assert metric.call_count == count, _metric_details() + +# assert metric.total_call_time >= 0, (key, metric) +# assert metric.total_exclusive_call_time >= 0, (key, metric) +# assert metric.min_call_time >= 0, (key, metric) +# assert metric.sum_of_squares >= 0, (key, metric) + +# else: +# assert metric is None, _metrics_table() + +# _new_wrapper = _validate_transaction_metrics(wrapped) +# val = _new_wrapper(*args, **kwargs) +# assert record_transaction_called +# metrics = recorded_metrics[index] + +# record_transaction_called[:] = [] +# recorded_metrics[:] = [] + +# for unscoped_metric in unscoped_metrics: +# _validate(metrics, unscoped_metric, "", 1) + +# for scoped_name, scoped_count in scoped_metrics: +# _validate(metrics, scoped_name, transaction_scope_name, scoped_count) + +# for rollup_name, rollup_count in rollup_metrics: +# _validate(metrics, rollup_name, "", rollup_count) + +# for custom_name, custom_count in custom_metrics: +# _validate(metrics, custom_name, "", custom_count) + +# custom_metric_names = {name for name, _ in custom_metrics} +# for name, _ in metrics: +# if name not in custom_metric_names: +# assert not name.startswith("Supportability/api/"), name + +# return val + +# return _validate_wrapper def validate_time_metrics_outside_transaction(time_metrics=None, index=-1): From 96e752f951f9921ca5025d1904022ca20a3ea7b9 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Tue, 30 Aug 2022 11:45:40 -0700 Subject: [PATCH 03/23] Move validate_time_metrics_outside_transaction to validators directory --- .../test_ignore_expected_errors.py | 2 +- tests/testing_support/fixtures.py | 112 +++++++++--------- ...lidate_time_metrics_outside_transaction.py | 93 +++++++++++++++ 3 files changed, 150 insertions(+), 57 deletions(-) create mode 100644 tests/testing_support/validators/validate_time_metrics_outside_transaction.py diff --git a/tests/agent_features/test_ignore_expected_errors.py b/tests/agent_features/test_ignore_expected_errors.py index 7adc07e1c..b044c8fa5 100644 --- a/tests/agent_features/test_ignore_expected_errors.py +++ b/tests/agent_features/test_ignore_expected_errors.py @@ -19,11 +19,11 @@ validate_error_event_attributes_outside_transaction, validate_error_event_sample_data, validate_error_trace_attributes_outside_transaction, - validate_time_metrics_outside_transaction, validate_transaction_error_trace_attributes, validate_transaction_errors, validate_transaction_metrics, ) +from testing_support.validators.validate_time_metrics_outside_transaction import validate_time_metrics_outside_transaction from newrelic.api.application import application_instance from newrelic.api.background_task import background_task diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index e70c900c4..30c0815f0 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -500,77 +500,77 @@ def make_synthetics_header(account_id, resource_id, job_id, monitor_id, encoding # return _validate_wrapper -def validate_time_metrics_outside_transaction(time_metrics=None, index=-1): - time_metrics = time_metrics or [] +# def validate_time_metrics_outside_transaction(time_metrics=None, index=-1): +# time_metrics = time_metrics or [] - @function_wrapper - def _validate_wrapper(wrapped, instance, args, kwargs): +# @function_wrapper +# def _validate_wrapper(wrapped, instance, args, kwargs): - record_time_metric_called = [] - recorded_metrics = [] +# record_time_metric_called = [] +# recorded_metrics = [] - @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_time_metric") - @catch_background_exceptions - def _validate_transaction_metrics(wrapped, instance, args, kwargs): - record_time_metric_called.append(True) - try: - result = wrapped(*args, **kwargs) - except: - raise - else: - metrics = instance.stats_table - # Record a copy of the metric value so that the values aren't - # merged in the future - _metrics = {} - for k, v in metrics.items(): - _metrics[k] = copy.copy(v) - recorded_metrics.append(_metrics) +# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_time_metric") +# @catch_background_exceptions +# def _validate_transaction_metrics(wrapped, instance, args, kwargs): +# record_time_metric_called.append(True) +# try: +# result = wrapped(*args, **kwargs) +# except: +# raise +# else: +# metrics = instance.stats_table +# # Record a copy of the metric value so that the values aren't +# # merged in the future +# _metrics = {} +# for k, v in metrics.items(): +# _metrics[k] = copy.copy(v) +# recorded_metrics.append(_metrics) - return result +# return result - def _validate(metrics, name, count): - key = (name, "") - metric = metrics.get(key) +# def _validate(metrics, name, count): +# key = (name, "") +# metric = metrics.get(key) - def _metrics_table(): - out = [""] - out.append("Expected: {0}: {1}".format(key, count)) - for metric_key, metric_value in metrics.items(): - out.append("{0}: {1}".format(metric_key, metric_value[0])) - return "\n".join(out) +# def _metrics_table(): +# out = [""] +# out.append("Expected: {0}: {1}".format(key, count)) +# for metric_key, metric_value in metrics.items(): +# out.append("{0}: {1}".format(metric_key, metric_value[0])) +# return "\n".join(out) - def _metric_details(): - return "metric=%r, count=%r" % (key, metric.call_count) +# def _metric_details(): +# return "metric=%r, count=%r" % (key, metric.call_count) - if count is not None: - assert metric is not None, _metrics_table() - if count == "present": - assert metric.call_count > 0, _metric_details() - else: - assert metric.call_count == count, _metric_details() +# if count is not None: +# assert metric is not None, _metrics_table() +# if count == "present": +# assert metric.call_count > 0, _metric_details() +# else: +# assert metric.call_count == count, _metric_details() - assert metric.total_call_time >= 0, (key, metric) - assert metric.total_exclusive_call_time >= 0, (key, metric) - assert metric.min_call_time >= 0, (key, metric) - assert metric.sum_of_squares >= 0, (key, metric) +# assert metric.total_call_time >= 0, (key, metric) +# assert metric.total_exclusive_call_time >= 0, (key, metric) +# assert metric.min_call_time >= 0, (key, metric) +# assert metric.sum_of_squares >= 0, (key, metric) - else: - assert metric is None, _metrics_table() +# else: +# assert metric is None, _metrics_table() - _new_wrapper = _validate_transaction_metrics(wrapped) - val = _new_wrapper(*args, **kwargs) - assert record_time_metric_called - metrics = recorded_metrics[index] +# _new_wrapper = _validate_transaction_metrics(wrapped) +# val = _new_wrapper(*args, **kwargs) +# assert record_time_metric_called +# metrics = recorded_metrics[index] - record_time_metric_called[:] = [] - recorded_metrics[:] = [] +# record_time_metric_called[:] = [] +# recorded_metrics[:] = [] - for time_metric, count in time_metrics: - _validate(metrics, time_metric, count) +# for time_metric, count in time_metrics: +# _validate(metrics, time_metric, count) - return val +# return val - return _validate_wrapper +# return _validate_wrapper def capture_transaction_metrics(metrics_list, full_metrics=None): diff --git a/tests/testing_support/validators/validate_time_metrics_outside_transaction.py b/tests/testing_support/validators/validate_time_metrics_outside_transaction.py new file mode 100644 index 000000000..1f6173a67 --- /dev/null +++ b/tests/testing_support/validators/validate_time_metrics_outside_transaction.py @@ -0,0 +1,93 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import copy + +from newrelic.common.object_wrapper import ( + function_wrapper, + transient_function_wrapper, +) +from testing_support.fixtures import catch_background_exceptions + +def validate_time_metrics_outside_transaction(time_metrics=None, index=-1): + time_metrics = time_metrics or [] + + @function_wrapper + def _validate_wrapper(wrapped, instance, args, kwargs): + + record_time_metric_called = [] + recorded_metrics = [] + + @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_time_metric") + @catch_background_exceptions + def _validate_transaction_metrics(wrapped, instance, args, kwargs): + record_time_metric_called.append(True) + try: + result = wrapped(*args, **kwargs) + except: + raise + else: + metrics = instance.stats_table + # Record a copy of the metric value so that the values aren't + # merged in the future + _metrics = {} + for k, v in metrics.items(): + _metrics[k] = copy.copy(v) + recorded_metrics.append(_metrics) + + return result + + def _validate(metrics, name, count): + key = (name, "") + metric = metrics.get(key) + + def _metrics_table(): + out = [""] + out.append("Expected: {0}: {1}".format(key, count)) + for metric_key, metric_value in metrics.items(): + out.append("{0}: {1}".format(metric_key, metric_value[0])) + return "\n".join(out) + + def _metric_details(): + return "metric=%r, count=%r" % (key, metric.call_count) + + if count is not None: + assert metric is not None, _metrics_table() + if count == "present": + assert metric.call_count > 0, _metric_details() + else: + assert metric.call_count == count, _metric_details() + + assert metric.total_call_time >= 0, (key, metric) + assert metric.total_exclusive_call_time >= 0, (key, metric) + assert metric.min_call_time >= 0, (key, metric) + assert metric.sum_of_squares >= 0, (key, metric) + + else: + assert metric is None, _metrics_table() + + _new_wrapper = _validate_transaction_metrics(wrapped) + val = _new_wrapper(*args, **kwargs) + assert record_time_metric_called + metrics = recorded_metrics[index] + + record_time_metric_called[:] = [] + recorded_metrics[:] = [] + + for time_metric, count in time_metrics: + _validate(metrics, time_metric, count) + + return val + + return _validate_wrapper From 16d0361f0a96cf1faa4964e76fe6e978138098b0 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Tue, 30 Aug 2022 12:26:05 -0700 Subject: [PATCH 04/23] Move validate_internal_metrics into validators directory and fixed validate_transaction_metrics --- tests/adapter_daphne/test_daphne.py | 2 +- tests/adapter_uvicorn/test_uvicorn.py | 2 +- .../_test_async_coroutine_trace.py | 2 +- .../test_asgi_distributed_tracing.py | 4 +- tests/agent_features/test_asgi_transaction.py | 2 +- .../test_asgi_w3c_trace_context.py | 3 +- tests/agent_features/test_function_trace.py | 5 +- tests/agent_features/test_web_transaction.py | 4 +- tests/agent_unittests/test_agent_connect.py | 3 +- .../test_application.py | 6 +- .../component_flask_rest/test_application.py | 6 +- tests/component_tastypie/test_application.py | 6 +- .../cross_agent/test_aws_utilization_data.py | 2 +- .../test_azure_utilization_data.py | 2 +- .../test_boot_id_utilization_data.py | 2 +- .../cross_agent/test_gcp_utilization_data.py | 2 +- .../cross_agent/test_pcf_utilization_data.py | 2 +- .../datastore_aredis/test_custom_conn_pool.py | 4 +- .../datastore_aredis/test_execute_command.py | 4 +- tests/datastore_aredis/test_get_and_set.py | 4 +- .../test_elasticsearch.py | 6 +- tests/datastore_elasticsearch/test_mget.py | 4 +- .../test_multiple_dbs.py | 4 +- tests/datastore_memcache/test_memcache.py | 4 +- tests/datastore_memcache/test_multiple_dbs.py | 4 +- tests/datastore_psycopg2/test_async.py | 3 +- tests/datastore_psycopg2/test_cursor.py | 4 +- tests/datastore_psycopg2/test_multiple_dbs.py | 4 +- tests/datastore_psycopg2/test_register.py | 4 +- tests/datastore_psycopg2/test_rollback.py | 4 +- tests/datastore_psycopg2cffi/test_database.py | 3 +- .../test_pyelasticsearch.py | 4 +- tests/datastore_pymysql/test_database.py | 3 +- .../datastore_redis/test_custom_conn_pool.py | 4 +- tests/datastore_redis/test_execute_command.py | 4 +- tests/datastore_redis/test_get_and_set.py | 4 +- tests/datastore_redis/test_multiple_dbs.py | 4 +- tests/datastore_redis/test_rb.py | 4 +- tests/external_boto3/test_boto3_iam.py | 3 +- tests/external_boto3/test_boto3_s3.py | 7 +- tests/external_boto3/test_boto3_sns.py | 6 +- .../test_botocore_dynamodb.py | 3 +- tests/external_botocore/test_botocore_ec2.py | 3 +- tests/external_botocore/test_botocore_s3.py | 4 +- tests/external_botocore/test_botocore_sqs.py | 4 +- tests/framework_aiohttp/test_externals.py | 4 +- tests/framework_aiohttp/test_middleware.py | 4 +- tests/framework_aiohttp/test_server.py | 3 +- tests/framework_bottle/test_application.py | 4 +- tests/framework_django/test_application.py | 3 +- .../framework_django/test_asgi_application.py | 3 +- tests/framework_falcon/test_application.py | 3 +- tests/framework_flask/test_application.py | 3 +- tests/framework_flask/test_blueprints.py | 3 +- tests/framework_flask/test_compress.py | 3 +- tests/framework_flask/test_middleware.py | 3 +- tests/framework_flask/test_not_found.py | 4 +- tests/framework_flask/test_user_exceptions.py | 4 +- tests/framework_grpc/test_clients.py | 4 +- tests/framework_grpc/test_server.py | 4 +- .../test_append_slash_app.py | 4 +- tests/framework_pyramid/test_application.py | 3 +- tests/framework_sanic/test_application.py | 4 +- tests/framework_tornado/test_server.py | 4 +- ...a_blocking_connection_consume_generator.py | 4 +- tests/testing_support/fixtures.py | 66 +++++++++---------- .../validators/validate_internal_metrics.py | 64 ++++++++++++++++++ 67 files changed, 226 insertions(+), 143 deletions(-) create mode 100644 tests/testing_support/validators/validate_internal_metrics.py diff --git a/tests/adapter_daphne/test_daphne.py b/tests/adapter_daphne/test_daphne.py index 4953e9a9f..a289e1311 100644 --- a/tests/adapter_daphne/test_daphne.py +++ b/tests/adapter_daphne/test_daphne.py @@ -22,9 +22,9 @@ override_application_settings, raise_background_exceptions, validate_transaction_errors, - validate_transaction_metrics, wait_for_background_threads, ) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.sample_asgi_applications import ( AppWithCall, AppWithCallRaw, diff --git a/tests/adapter_uvicorn/test_uvicorn.py b/tests/adapter_uvicorn/test_uvicorn.py index e3261f4e8..8d81778fc 100644 --- a/tests/adapter_uvicorn/test_uvicorn.py +++ b/tests/adapter_uvicorn/test_uvicorn.py @@ -24,9 +24,9 @@ override_application_settings, raise_background_exceptions, validate_transaction_errors, - validate_transaction_metrics, wait_for_background_threads, ) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.sample_asgi_applications import ( AppWithCall, AppWithCallRaw, diff --git a/tests/agent_features/_test_async_coroutine_trace.py b/tests/agent_features/_test_async_coroutine_trace.py index 96cb3c7dc..0b3aaa312 100644 --- a/tests/agent_features/_test_async_coroutine_trace.py +++ b/tests/agent_features/_test_async_coroutine_trace.py @@ -19,8 +19,8 @@ import pytest from testing_support.fixtures import ( capture_transaction_metrics, - validate_transaction_metrics, ) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task from newrelic.api.database_trace import database_trace diff --git a/tests/agent_features/test_asgi_distributed_tracing.py b/tests/agent_features/test_asgi_distributed_tracing.py index bb34aba20..90f57becc 100644 --- a/tests/agent_features/test_asgi_distributed_tracing.py +++ b/tests/agent_features/test_asgi_distributed_tracing.py @@ -22,8 +22,8 @@ from newrelic.api.asgi_application import asgi_application, ASGIWebTransaction from testing_support.asgi_testing import AsgiTest -from testing_support.fixtures import (override_application_settings, - validate_transaction_metrics) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics distributed_trace_intrinsics = ['guid', 'traceId', 'priority', 'sampled'] diff --git a/tests/agent_features/test_asgi_transaction.py b/tests/agent_features/test_asgi_transaction.py index 1820efa86..cb930ba5b 100644 --- a/tests/agent_features/test_asgi_transaction.py +++ b/tests/agent_features/test_asgi_transaction.py @@ -20,8 +20,8 @@ from testing_support.fixtures import ( override_application_settings, validate_transaction_errors, - validate_transaction_metrics, ) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.sample_asgi_applications import ( AppWithDescriptor, simple_app_v2, diff --git a/tests/agent_features/test_asgi_w3c_trace_context.py b/tests/agent_features/test_asgi_w3c_trace_context.py index 68c192a5d..234e08409 100644 --- a/tests/agent_features/test_asgi_w3c_trace_context.py +++ b/tests/agent_features/test_asgi_w3c_trace_context.py @@ -20,7 +20,8 @@ from testing_support.asgi_testing import AsgiTest from testing_support.fixtures import (override_application_settings, - validate_transaction_event_attributes, validate_transaction_metrics) + validate_transaction_event_attributes) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_span_events import ( validate_span_events) diff --git a/tests/agent_features/test_function_trace.py b/tests/agent_features/test_function_trace.py index 78c012b30..f1f0cd9ac 100644 --- a/tests/agent_features/test_function_trace.py +++ b/tests/agent_features/test_function_trace.py @@ -17,9 +17,8 @@ from newrelic.api.background_task import background_task from newrelic.api.function_trace import FunctionTrace -from testing_support.fixtures import (validate_transaction_metrics, - validate_tt_parenting) - +from testing_support.fixtures import validate_tt_parenting +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics _test_function_trace_default_group_scoped_metrics = [ ('Function/FunctionTrace', 1)] diff --git a/tests/agent_features/test_web_transaction.py b/tests/agent_features/test_web_transaction.py index 22bfd6eb8..5a6eeda69 100644 --- a/tests/agent_features/test_web_transaction.py +++ b/tests/agent_features/test_web_transaction.py @@ -19,8 +19,8 @@ import time from newrelic.api.application import application_instance from newrelic.api.web_transaction import WebTransaction -from testing_support.fixtures import (validate_transaction_metrics, - validate_attributes) +from testing_support.fixtures import validate_attributes +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.sample_applications import simple_app import newrelic.packages.six as six application = webtest.TestApp(simple_app) diff --git a/tests/agent_unittests/test_agent_connect.py b/tests/agent_unittests/test_agent_connect.py index 46c4edf44..eb944c072 100644 --- a/tests/agent_unittests/test_agent_connect.py +++ b/tests/agent_unittests/test_agent_connect.py @@ -19,10 +19,9 @@ from testing_support.fixtures import ( override_generic_settings, - validate_internal_metrics, failing_endpoint ) - +from testing_support.validators.validate_internal_metrics import validate_internal_metrics SETTINGS = global_settings() diff --git a/tests/component_djangorestframework/test_application.py b/tests/component_djangorestframework/test_application.py index 2951e0401..472f2f029 100644 --- a/tests/component_djangorestframework/test_application.py +++ b/tests/component_djangorestframework/test_application.py @@ -18,9 +18,11 @@ from newrelic.packages import six from newrelic.core.config import global_settings -from testing_support.fixtures import (validate_transaction_metrics, - validate_transaction_errors, override_generic_settings, +from testing_support.fixtures import ( + validate_transaction_errors, + override_generic_settings, function_not_called) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics import django diff --git a/tests/component_flask_rest/test_application.py b/tests/component_flask_rest/test_application.py index 94b6fbc5c..391a35674 100644 --- a/tests/component_flask_rest/test_application.py +++ b/tests/component_flask_rest/test_application.py @@ -15,9 +15,11 @@ import pytest from newrelic.packages import six -from testing_support.fixtures import (validate_transaction_metrics, - validate_transaction_errors, override_ignore_status_codes, +from testing_support.fixtures import ( + validate_transaction_errors, + override_ignore_status_codes, override_generic_settings) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from newrelic.core.config import global_settings diff --git a/tests/component_tastypie/test_application.py b/tests/component_tastypie/test_application.py index 16521425c..378a94c16 100644 --- a/tests/component_tastypie/test_application.py +++ b/tests/component_tastypie/test_application.py @@ -21,8 +21,10 @@ from newrelic.api.background_task import background_task from newrelic.api.transaction import end_of_transaction -from testing_support.fixtures import (validate_transaction_metrics, - validate_transaction_errors, override_ignore_status_codes) +from testing_support.fixtures import ( + validate_transaction_errors, + override_ignore_status_codes) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from wsgi import application diff --git a/tests/cross_agent/test_aws_utilization_data.py b/tests/cross_agent/test_aws_utilization_data.py index 7ff2e623b..807b1a97b 100644 --- a/tests/cross_agent/test_aws_utilization_data.py +++ b/tests/cross_agent/test_aws_utilization_data.py @@ -18,7 +18,7 @@ from newrelic.common.utilization import AWSUtilization from testing_support.mock_http_client import create_client_cls -from testing_support.fixtures import validate_internal_metrics +from testing_support.validators.validate_internal_metrics import validate_internal_metrics CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) diff --git a/tests/cross_agent/test_azure_utilization_data.py b/tests/cross_agent/test_azure_utilization_data.py index 897fadec0..772a96f98 100644 --- a/tests/cross_agent/test_azure_utilization_data.py +++ b/tests/cross_agent/test_azure_utilization_data.py @@ -18,7 +18,7 @@ from newrelic.common.utilization import AzureUtilization from testing_support.mock_http_client import create_client_cls -from testing_support.fixtures import validate_internal_metrics +from testing_support.validators.validate_internal_metrics import validate_internal_metrics CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) diff --git a/tests/cross_agent/test_boot_id_utilization_data.py b/tests/cross_agent/test_boot_id_utilization_data.py index 2eaeae670..ea5b26a9e 100644 --- a/tests/cross_agent/test_boot_id_utilization_data.py +++ b/tests/cross_agent/test_boot_id_utilization_data.py @@ -20,7 +20,7 @@ from newrelic.common.system_info import BootIdUtilization -from testing_support.fixtures import validate_internal_metrics +from testing_support.validators.validate_internal_metrics import validate_internal_metrics CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) diff --git a/tests/cross_agent/test_gcp_utilization_data.py b/tests/cross_agent/test_gcp_utilization_data.py index 1d77ed0a2..7bbf6ce0a 100644 --- a/tests/cross_agent/test_gcp_utilization_data.py +++ b/tests/cross_agent/test_gcp_utilization_data.py @@ -18,7 +18,7 @@ from newrelic.common.utilization import GCPUtilization from testing_support.mock_http_client import create_client_cls -from testing_support.fixtures import validate_internal_metrics +from testing_support.validators.validate_internal_metrics import validate_internal_metrics CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) diff --git a/tests/cross_agent/test_pcf_utilization_data.py b/tests/cross_agent/test_pcf_utilization_data.py index ce86bfb9f..28b56f759 100644 --- a/tests/cross_agent/test_pcf_utilization_data.py +++ b/tests/cross_agent/test_pcf_utilization_data.py @@ -18,7 +18,7 @@ from newrelic.common.utilization import PCFUtilization -from testing_support.fixtures import validate_internal_metrics +from testing_support.validators.validate_internal_metrics import validate_internal_metrics CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) diff --git a/tests/datastore_aredis/test_custom_conn_pool.py b/tests/datastore_aredis/test_custom_conn_pool.py index 344154412..70c75de9e 100644 --- a/tests/datastore_aredis/test_custom_conn_pool.py +++ b/tests/datastore_aredis/test_custom_conn_pool.py @@ -23,8 +23,8 @@ from newrelic.api.background_task import background_task from testing_support.fixture.event_loop import event_loop as loop -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import redis_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_aredis/test_execute_command.py b/tests/datastore_aredis/test_execute_command.py index 7db3c9c59..c5b0fc332 100644 --- a/tests/datastore_aredis/test_execute_command.py +++ b/tests/datastore_aredis/test_execute_command.py @@ -17,8 +17,8 @@ from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.fixture.event_loop import event_loop as loop from testing_support.db_settings import redis_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_aredis/test_get_and_set.py b/tests/datastore_aredis/test_get_and_set.py index fbde29d86..2eeee947b 100644 --- a/tests/datastore_aredis/test_get_and_set.py +++ b/tests/datastore_aredis/test_get_and_set.py @@ -17,8 +17,8 @@ from newrelic.api.background_task import background_task from testing_support.fixture.event_loop import event_loop as loop -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import redis_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_elasticsearch/test_elasticsearch.py b/tests/datastore_elasticsearch/test_elasticsearch.py index 548043216..f219e01b5 100644 --- a/tests/datastore_elasticsearch/test_elasticsearch.py +++ b/tests/datastore_elasticsearch/test_elasticsearch.py @@ -17,8 +17,10 @@ from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, - validate_transaction_errors, override_application_settings) +from testing_support.fixtures import ( + validate_transaction_errors, + override_application_settings) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import elasticsearch_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_elasticsearch/test_mget.py b/tests/datastore_elasticsearch/test_mget.py index 417b231d6..9f0b442e8 100644 --- a/tests/datastore_elasticsearch/test_mget.py +++ b/tests/datastore_elasticsearch/test_mget.py @@ -17,8 +17,8 @@ from elasticsearch import Elasticsearch from elasticsearch.connection_pool import RoundRobinSelector -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import elasticsearch_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_elasticsearch/test_multiple_dbs.py b/tests/datastore_elasticsearch/test_multiple_dbs.py index b4b1559a7..70a7be4f1 100644 --- a/tests/datastore_elasticsearch/test_multiple_dbs.py +++ b/tests/datastore_elasticsearch/test_multiple_dbs.py @@ -16,8 +16,8 @@ from elasticsearch import Elasticsearch -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import elasticsearch_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_memcache/test_memcache.py b/tests/datastore_memcache/test_memcache.py index d8afab3b1..a66c114ee 100644 --- a/tests/datastore_memcache/test_memcache.py +++ b/tests/datastore_memcache/test_memcache.py @@ -14,8 +14,8 @@ import memcache -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import memcached_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_memcache/test_multiple_dbs.py b/tests/datastore_memcache/test_multiple_dbs.py index b83d7dfcc..dbc3ea2b3 100644 --- a/tests/datastore_memcache/test_multiple_dbs.py +++ b/tests/datastore_memcache/test_multiple_dbs.py @@ -17,8 +17,8 @@ from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import memcached_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_psycopg2/test_async.py b/tests/datastore_psycopg2/test_async.py index 78df2beca..32224b681 100644 --- a/tests/datastore_psycopg2/test_async.py +++ b/tests/datastore_psycopg2/test_async.py @@ -16,10 +16,11 @@ import psycopg2.extras import pytest -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_transaction_errors, validate_stats_engine_explain_plan_output_is_none, override_application_settings) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_database_trace_inputs import validate_database_trace_inputs from testing_support.validators.validate_transaction_slow_sql_count import ( diff --git a/tests/datastore_psycopg2/test_cursor.py b/tests/datastore_psycopg2/test_cursor.py index e7a549c13..d66d73ff8 100644 --- a/tests/datastore_psycopg2/test_cursor.py +++ b/tests/datastore_psycopg2/test_cursor.py @@ -21,8 +21,8 @@ except ImportError: sql = None -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_database_trace_inputs import validate_database_trace_inputs from testing_support.util import instance_hostname from utils import DB_SETTINGS diff --git a/tests/datastore_psycopg2/test_multiple_dbs.py b/tests/datastore_psycopg2/test_multiple_dbs.py index bf7629ebf..afbdd66f2 100644 --- a/tests/datastore_psycopg2/test_multiple_dbs.py +++ b/tests/datastore_psycopg2/test_multiple_dbs.py @@ -15,8 +15,8 @@ import psycopg2 import pytest -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_database_trace_inputs import validate_database_trace_inputs from testing_support.util import instance_hostname from utils import DB_MULTIPLE_SETTINGS diff --git a/tests/datastore_psycopg2/test_register.py b/tests/datastore_psycopg2/test_register.py index 03b553749..8f6d8bfd9 100644 --- a/tests/datastore_psycopg2/test_register.py +++ b/tests/datastore_psycopg2/test_register.py @@ -16,8 +16,8 @@ import psycopg2 import psycopg2.extras -from testing_support.fixtures import (validate_transaction_metrics, - validate_transaction_errors) +from testing_support.fixtures import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from utils import DB_SETTINGS from newrelic.api.background_task import background_task diff --git a/tests/datastore_psycopg2/test_rollback.py b/tests/datastore_psycopg2/test_rollback.py index f0ef8149f..0a23b1005 100644 --- a/tests/datastore_psycopg2/test_rollback.py +++ b/tests/datastore_psycopg2/test_rollback.py @@ -15,8 +15,8 @@ import psycopg2 import pytest -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_database_trace_inputs import validate_database_trace_inputs from testing_support.util import instance_hostname from utils import DB_SETTINGS diff --git a/tests/datastore_psycopg2cffi/test_database.py b/tests/datastore_psycopg2cffi/test_database.py index c0eb6e722..48e85e77b 100644 --- a/tests/datastore_psycopg2cffi/test_database.py +++ b/tests/datastore_psycopg2cffi/test_database.py @@ -16,8 +16,9 @@ import psycopg2cffi.extensions import psycopg2cffi.extras -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_transaction_errors, validate_stats_engine_explain_plan_output_is_none) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_transaction_slow_sql_count import \ validate_transaction_slow_sql_count from testing_support.validators.validate_database_trace_inputs import validate_database_trace_inputs diff --git a/tests/datastore_pyelasticsearch/test_pyelasticsearch.py b/tests/datastore_pyelasticsearch/test_pyelasticsearch.py index 837c9ae19..7554e9a3d 100644 --- a/tests/datastore_pyelasticsearch/test_pyelasticsearch.py +++ b/tests/datastore_pyelasticsearch/test_pyelasticsearch.py @@ -15,8 +15,8 @@ import sqlite3 from pyelasticsearch import ElasticSearch -from testing_support.fixtures import (validate_transaction_metrics, - validate_transaction_errors) +from testing_support.fixtures import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import elasticsearch_settings from testing_support.validators.validate_database_duration import validate_database_duration diff --git a/tests/datastore_pymysql/test_database.py b/tests/datastore_pymysql/test_database.py index 2f20d8cbd..5943b1266 100644 --- a/tests/datastore_pymysql/test_database.py +++ b/tests/datastore_pymysql/test_database.py @@ -14,8 +14,7 @@ import pymysql -from testing_support.fixtures import (validate_transaction_metrics, - ) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_database_trace_inputs import validate_database_trace_inputs from testing_support.db_settings import mysql_settings diff --git a/tests/datastore_redis/test_custom_conn_pool.py b/tests/datastore_redis/test_custom_conn_pool.py index 9700392cc..156c9ce31 100644 --- a/tests/datastore_redis/test_custom_conn_pool.py +++ b/tests/datastore_redis/test_custom_conn_pool.py @@ -22,8 +22,8 @@ from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import redis_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_redis/test_execute_command.py b/tests/datastore_redis/test_execute_command.py index c86295b35..747588072 100644 --- a/tests/datastore_redis/test_execute_command.py +++ b/tests/datastore_redis/test_execute_command.py @@ -17,8 +17,8 @@ from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import redis_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_redis/test_get_and_set.py b/tests/datastore_redis/test_get_and_set.py index 2c40ddc12..0e2df4bb1 100644 --- a/tests/datastore_redis/test_get_and_set.py +++ b/tests/datastore_redis/test_get_and_set.py @@ -16,8 +16,8 @@ from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import redis_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_redis/test_multiple_dbs.py b/tests/datastore_redis/test_multiple_dbs.py index 67f7b7fe8..15777cc38 100644 --- a/tests/datastore_redis/test_multiple_dbs.py +++ b/tests/datastore_redis/test_multiple_dbs.py @@ -17,8 +17,8 @@ from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import redis_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_redis/test_rb.py b/tests/datastore_redis/test_rb.py index 7f4feeda7..5678c2787 100644 --- a/tests/datastore_redis/test_rb.py +++ b/tests/datastore_redis/test_rb.py @@ -24,8 +24,8 @@ from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import redis_settings from testing_support.util import instance_hostname diff --git a/tests/external_boto3/test_boto3_iam.py b/tests/external_boto3/test_boto3_iam.py index 9c6246c8c..ac49214f4 100644 --- a/tests/external_boto3/test_boto3_iam.py +++ b/tests/external_boto3/test_boto3_iam.py @@ -19,10 +19,11 @@ import moto from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_tt_segment_params, override_application_settings) from testing_support.validators.validate_span_events import ( validate_span_events) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics MOTO_VERSION = tuple(int(v) for v in moto.__version__.split('.')[:3]) diff --git a/tests/external_boto3/test_boto3_s3.py b/tests/external_boto3/test_boto3_s3.py index ba65bc950..7d232a689 100644 --- a/tests/external_boto3/test_boto3_s3.py +++ b/tests/external_boto3/test_boto3_s3.py @@ -20,10 +20,9 @@ import moto from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) -from testing_support.validators.validate_span_events import ( - validate_span_events) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_span_events import validate_span_events +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics MOTO_VERSION = tuple(int(v) for v in moto.__version__.split('.')[:3]) diff --git a/tests/external_boto3/test_boto3_sns.py b/tests/external_boto3/test_boto3_sns.py index 38c8c951c..3718d5292 100644 --- a/tests/external_boto3/test_boto3_sns.py +++ b/tests/external_boto3/test_boto3_sns.py @@ -18,10 +18,10 @@ import pytest from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_tt_segment_params, override_application_settings) -from testing_support.validators.validate_span_events import ( - validate_span_events) +from testing_support.validators.validate_span_events import validate_span_events +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics MOTO_VERSION = tuple(int(v) for v in moto.__version__.split('.')[:3]) diff --git a/tests/external_botocore/test_botocore_dynamodb.py b/tests/external_botocore/test_botocore_dynamodb.py index eb0432aba..44862d827 100644 --- a/tests/external_botocore/test_botocore_dynamodb.py +++ b/tests/external_botocore/test_botocore_dynamodb.py @@ -19,10 +19,11 @@ import moto from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_tt_segment_params, override_application_settings) from testing_support.validators.validate_span_events import ( validate_span_events) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics MOTO_VERSION = tuple(int(v) for v in moto.__version__.split('.')[:3]) diff --git a/tests/external_botocore/test_botocore_ec2.py b/tests/external_botocore/test_botocore_ec2.py index 6f91ad75f..0cfd09b6f 100644 --- a/tests/external_botocore/test_botocore_ec2.py +++ b/tests/external_botocore/test_botocore_ec2.py @@ -19,10 +19,11 @@ import moto from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_tt_segment_params, override_application_settings) from testing_support.validators.validate_span_events import ( validate_span_events) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics MOTO_VERSION = tuple(int(v) for v in moto.__version__.split('.')[:3]) diff --git a/tests/external_botocore/test_botocore_s3.py b/tests/external_botocore/test_botocore_s3.py index 3cd4ecd93..35f3f07d2 100644 --- a/tests/external_botocore/test_botocore_s3.py +++ b/tests/external_botocore/test_botocore_s3.py @@ -19,10 +19,10 @@ import moto from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings from testing_support.validators.validate_span_events import ( validate_span_events) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics MOTO_VERSION = tuple(int(v) for v in moto.__version__.split('.')[:3]) diff --git a/tests/external_botocore/test_botocore_sqs.py b/tests/external_botocore/test_botocore_sqs.py index 46482c675..63b3566d6 100644 --- a/tests/external_botocore/test_botocore_sqs.py +++ b/tests/external_botocore/test_botocore_sqs.py @@ -20,10 +20,10 @@ import moto from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, - override_application_settings) +from testing_support.fixtures import override_application_settings from testing_support.validators.validate_span_events import ( validate_span_events) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics MOTO_VERSION = tuple(int(v) for v in moto.__version__.split('.')[:3]) diff --git a/tests/framework_aiohttp/test_externals.py b/tests/framework_aiohttp/test_externals.py index a410590ef..97710630a 100644 --- a/tests/framework_aiohttp/test_externals.py +++ b/tests/framework_aiohttp/test_externals.py @@ -15,8 +15,8 @@ import pytest import asyncio -from testing_support.fixtures import (validate_transaction_metrics, - validate_tt_parenting) +from testing_support.fixtures import validate_tt_parenting +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics expected_parenting = ( 'TransactionNode', [ diff --git a/tests/framework_aiohttp/test_middleware.py b/tests/framework_aiohttp/test_middleware.py index 47050232f..7e3ac97d4 100644 --- a/tests/framework_aiohttp/test_middleware.py +++ b/tests/framework_aiohttp/test_middleware.py @@ -17,9 +17,9 @@ import aiohttp from newrelic.core.config import global_settings -from testing_support.fixtures import (validate_transaction_metrics, - override_generic_settings) +from testing_support.fixtures import override_generic_settings from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics version_info = tuple(int(_) for _ in aiohttp.__version__.split('.')[:2]) diff --git a/tests/framework_aiohttp/test_server.py b/tests/framework_aiohttp/test_server.py index 2b4e28b5f..f09f2b615 100644 --- a/tests/framework_aiohttp/test_server.py +++ b/tests/framework_aiohttp/test_server.py @@ -17,11 +17,12 @@ import aiohttp from newrelic.core.config import global_settings -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_transaction_errors, validate_transaction_event_attributes, count_transactions, override_generic_settings, override_application_settings, override_ignore_status_codes) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics version_info = tuple(int(_) for _ in aiohttp.__version__.split('.')[:2]) diff --git a/tests/framework_bottle/test_application.py b/tests/framework_bottle/test_application.py index f9fb0915e..56e3b0f65 100644 --- a/tests/framework_bottle/test_application.py +++ b/tests/framework_bottle/test_application.py @@ -15,10 +15,10 @@ import pytest import base64 -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_transaction_errors, override_ignore_status_codes, override_application_settings) - +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.packages import six from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics diff --git a/tests/framework_django/test_application.py b/tests/framework_django/test_application.py index 1876b9a69..1bee82346 100644 --- a/tests/framework_django/test_application.py +++ b/tests/framework_django/test_application.py @@ -12,11 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_transaction_errors, override_application_settings, override_generic_settings, override_ignore_status_codes) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from newrelic.hooks.framework_django import django_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics import os diff --git a/tests/framework_django/test_asgi_application.py b/tests/framework_django/test_asgi_application.py index 98f157f85..e714d5277 100644 --- a/tests/framework_django/test_asgi_application.py +++ b/tests/framework_django/test_asgi_application.py @@ -18,10 +18,11 @@ from newrelic.core.config import global_settings from newrelic.common.encoding_utils import gzip_decompress -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_transaction_errors, override_application_settings, override_generic_settings, override_ignore_status_codes) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics DJANGO_VERSION = tuple(map(int, django.get_version().split('.')[:2])) diff --git a/tests/framework_falcon/test_application.py b/tests/framework_falcon/test_application.py index 6f59ea826..e0810c345 100644 --- a/tests/framework_falcon/test_application.py +++ b/tests/framework_falcon/test_application.py @@ -14,10 +14,11 @@ import pytest from newrelic.core.config import global_settings -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_transaction_errors, override_ignore_status_codes, override_generic_settings) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics SETTINGS = global_settings() diff --git a/tests/framework_flask/test_application.py b/tests/framework_flask/test_application.py index 98757a805..5aebc1117 100644 --- a/tests/framework_flask/test_application.py +++ b/tests/framework_flask/test_application.py @@ -14,10 +14,11 @@ import pytest -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_transaction_errors, override_application_settings, validate_tt_parenting) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.packages import six diff --git a/tests/framework_flask/test_blueprints.py b/tests/framework_flask/test_blueprints.py index 6a76d405b..5f8abd441 100644 --- a/tests/framework_flask/test_blueprints.py +++ b/tests/framework_flask/test_blueprints.py @@ -14,9 +14,10 @@ import pytest -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_transaction_errors, override_application_settings) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.packages import six diff --git a/tests/framework_flask/test_compress.py b/tests/framework_flask/test_compress.py index ac7f323fd..49138fe27 100644 --- a/tests/framework_flask/test_compress.py +++ b/tests/framework_flask/test_compress.py @@ -12,8 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_transaction_errors, override_application_settings) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics diff --git a/tests/framework_flask/test_middleware.py b/tests/framework_flask/test_middleware.py index d92d4d851..9f56163b7 100644 --- a/tests/framework_flask/test_middleware.py +++ b/tests/framework_flask/test_middleware.py @@ -14,9 +14,10 @@ import pytest -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_transaction_errors, override_application_settings) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics def target_application(): # We need to delay Flask application creation because of ordering diff --git a/tests/framework_flask/test_not_found.py b/tests/framework_flask/test_not_found.py index 22ad5efcd..523a8e593 100644 --- a/tests/framework_flask/test_not_found.py +++ b/tests/framework_flask/test_not_found.py @@ -14,8 +14,8 @@ import pytest -from testing_support.fixtures import (validate_transaction_metrics, - validate_transaction_errors) +from testing_support.fixtures import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics def target_application(): # We need to delay Flask application creation because of ordering diff --git a/tests/framework_flask/test_user_exceptions.py b/tests/framework_flask/test_user_exceptions.py index 5c8f3a658..a69c69b92 100644 --- a/tests/framework_flask/test_user_exceptions.py +++ b/tests/framework_flask/test_user_exceptions.py @@ -14,8 +14,8 @@ import pytest -from testing_support.fixtures import (validate_transaction_metrics, - validate_transaction_errors) +from testing_support.fixtures import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics def target_application(): # We need to delay Flask application creation because of ordering diff --git a/tests/framework_grpc/test_clients.py b/tests/framework_grpc/test_clients.py index e8fed1da5..9fa62d557 100644 --- a/tests/framework_grpc/test_clients.py +++ b/tests/framework_grpc/test_clients.py @@ -18,8 +18,8 @@ from newrelic.api.background_task import background_task -from testing_support.fixtures import (validate_transaction_metrics, - validate_transaction_errors) +from testing_support.fixtures import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from _test_common import create_request, get_result diff --git a/tests/framework_grpc/test_server.py b/tests/framework_grpc/test_server.py index d1ed47ff5..e80b103b8 100644 --- a/tests/framework_grpc/test_server.py +++ b/tests/framework_grpc/test_server.py @@ -18,12 +18,12 @@ from conftest import create_stub_and_channel from _test_common import create_request, wait_for_transaction_completion from newrelic.core.config import global_settings -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_transaction_event_attributes, override_application_settings, override_generic_settings, function_not_called, validate_transaction_errors) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics - +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics def select_python_version(py2, py3): return six.PY3 and py3 or py2 diff --git a/tests/framework_pyramid/test_append_slash_app.py b/tests/framework_pyramid/test_append_slash_app.py index 875f91012..10053e7cc 100644 --- a/tests/framework_pyramid/test_append_slash_app.py +++ b/tests/framework_pyramid/test_append_slash_app.py @@ -34,9 +34,9 @@ import pytest import re -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_transaction_errors, override_application_settings) - +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics def _to_int(version_str): m = re.match(r'\d+', version_str) diff --git a/tests/framework_pyramid/test_application.py b/tests/framework_pyramid/test_application.py index 6b912d632..6bae117e9 100644 --- a/tests/framework_pyramid/test_application.py +++ b/tests/framework_pyramid/test_application.py @@ -14,8 +14,9 @@ import pytest -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( validate_transaction_errors, override_application_settings) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.packages import six from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics diff --git a/tests/framework_sanic/test_application.py b/tests/framework_sanic/test_application.py index ac2726bd9..9ea9b92c4 100644 --- a/tests/framework_sanic/test_application.py +++ b/tests/framework_sanic/test_application.py @@ -22,13 +22,13 @@ from newrelic.api.transaction import Transaction from newrelic.api.external_trace import ExternalTrace -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( override_application_settings, validate_transaction_errors, validate_transaction_event_attributes, override_ignore_status_codes, override_generic_settings, function_not_called) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics - +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics sanic_21 = int(sanic.__version__.split('.', 1)[0]) >= 21 diff --git a/tests/framework_tornado/test_server.py b/tests/framework_tornado/test_server.py index 16aced356..9a0bb96d4 100644 --- a/tests/framework_tornado/test_server.py +++ b/tests/framework_tornado/test_server.py @@ -14,7 +14,7 @@ import pytest from newrelic.core.config import global_settings -from testing_support.fixtures import (validate_transaction_metrics, +from testing_support.fixtures import ( override_generic_settings, function_not_called, validate_transaction_event_attributes, validate_transaction_errors, override_ignore_status_codes, @@ -22,7 +22,7 @@ from testing_support.validators.validate_transaction_count import ( validate_transaction_count) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics - +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics @pytest.mark.parametrize('uri,name,metrics, method_metric', ( # ('/native-simple', '_target_application:NativeSimpleHandler.get', None, diff --git a/tests/messagebroker_pika/test_pika_blocking_connection_consume_generator.py b/tests/messagebroker_pika/test_pika_blocking_connection_consume_generator.py index a9ee1b331..4fff11487 100644 --- a/tests/messagebroker_pika/test_pika_blocking_connection_consume_generator.py +++ b/tests/messagebroker_pika/test_pika_blocking_connection_consume_generator.py @@ -17,9 +17,9 @@ from newrelic.api.background_task import background_task from conftest import QUEUE, EXCHANGE, CORRELATION_ID, REPLY_TO, HEADERS, BODY -from testing_support.fixtures import (validate_transaction_metrics, - validate_tt_collector_json) +from testing_support.fixtures import validate_tt_collector_json from testing_support.db_settings import rabbitmq_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics DB_SETTINGS = rabbitmq_settings()[0] diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index 30c0815f0..0d2f73c06 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -65,8 +65,8 @@ ) from newrelic.core.config import apply_config_setting, flatten_settings, global_settings from newrelic.core.database_utils import SQLConnections -from newrelic.core.internal_metrics import InternalTraceContext -from newrelic.core.stats_engine import CustomMetrics +#from newrelic.core.internal_metrics import InternalTraceContext +#from newrelic.core.stats_engine import CustomMetrics from newrelic.network.exceptions import RetryDataForRequest from newrelic.packages import six @@ -594,48 +594,48 @@ def _capture_transaction_metrics(wrapped, instance, args, kwargs): return _capture_transaction_metrics -def validate_internal_metrics(metrics=None): - metrics = metrics or [] +# def validate_internal_metrics(metrics=None): +# metrics = metrics or [] - def no_op(wrapped, instance, args, kwargs): - pass +# def no_op(wrapped, instance, args, kwargs): +# pass - @function_wrapper - def _validate_wrapper(wrapped, instance, args, kwargs): - # Apply no-op wrappers to prevent new internal trace contexts from being started, preventing capture - wrapped = transient_function_wrapper("newrelic.core.internal_metrics", "InternalTraceContext.__enter__")(no_op)(wrapped) - wrapped = transient_function_wrapper("newrelic.core.internal_metrics", "InternalTraceContext.__exit__")(no_op)(wrapped) +# @function_wrapper +# def _validate_wrapper(wrapped, instance, args, kwargs): +# # Apply no-op wrappers to prevent new internal trace contexts from being started, preventing capture +# wrapped = transient_function_wrapper("newrelic.core.internal_metrics", "InternalTraceContext.__enter__")(no_op)(wrapped) +# wrapped = transient_function_wrapper("newrelic.core.internal_metrics", "InternalTraceContext.__exit__")(no_op)(wrapped) - captured_metrics = CustomMetrics() - with InternalTraceContext(captured_metrics): - result = wrapped(*args, **kwargs) - captured_metrics = dict(captured_metrics.metrics()) +# captured_metrics = CustomMetrics() +# with InternalTraceContext(captured_metrics): +# result = wrapped(*args, **kwargs) +# captured_metrics = dict(captured_metrics.metrics()) - def _validate(name, count): - metric = captured_metrics.get(name) +# def _validate(name, count): +# metric = captured_metrics.get(name) - def _metrics_table(): - return "metric=%r, metrics=%r" % (name, captured_metrics) +# def _metrics_table(): +# return "metric=%r, metrics=%r" % (name, captured_metrics) - def _metric_details(): - return "metric=%r, count=%r" % (name, metric.call_count) +# def _metric_details(): +# return "metric=%r, count=%r" % (name, metric.call_count) - if count is not None and count > 0: - assert metric is not None, _metrics_table() - if count == "present": - assert metric.call_count > 0, _metric_details() - else: - assert metric.call_count == count, _metric_details() +# if count is not None and count > 0: +# assert metric is not None, _metrics_table() +# if count == "present": +# assert metric.call_count > 0, _metric_details() +# else: +# assert metric.call_count == count, _metric_details() - else: - assert metric is None, _metrics_table() +# else: +# assert metric is None, _metrics_table() - for metric, count in metrics: - _validate(metric, count) +# for metric, count in metrics: +# _validate(metric, count) - return result +# return result - return _validate_wrapper +# return _validate_wrapper def validate_transaction_errors(errors=None, required_params=None, forgone_params=None): diff --git a/tests/testing_support/validators/validate_internal_metrics.py b/tests/testing_support/validators/validate_internal_metrics.py new file mode 100644 index 000000000..c685d9b5f --- /dev/null +++ b/tests/testing_support/validators/validate_internal_metrics.py @@ -0,0 +1,64 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from newrelic.common.object_wrapper import ( + function_wrapper, + transient_function_wrapper, +) +from newrelic.core.stats_engine import CustomMetrics +from newrelic.core.internal_metrics import InternalTraceContext + + +def validate_internal_metrics(metrics=None): + metrics = metrics or [] + + def no_op(wrapped, instance, args, kwargs): + pass + + @function_wrapper + def _validate_wrapper(wrapped, instance, args, kwargs): + # Apply no-op wrappers to prevent new internal trace contexts from being started, preventing capture + wrapped = transient_function_wrapper("newrelic.core.internal_metrics", "InternalTraceContext.__enter__")(no_op)(wrapped) + wrapped = transient_function_wrapper("newrelic.core.internal_metrics", "InternalTraceContext.__exit__")(no_op)(wrapped) + + captured_metrics = CustomMetrics() + with InternalTraceContext(captured_metrics): + result = wrapped(*args, **kwargs) + captured_metrics = dict(captured_metrics.metrics()) + + def _validate(name, count): + metric = captured_metrics.get(name) + + def _metrics_table(): + return "metric=%r, metrics=%r" % (name, captured_metrics) + + def _metric_details(): + return "metric=%r, count=%r" % (name, metric.call_count) + + if count is not None and count > 0: + assert metric is not None, _metrics_table() + if count == "present": + assert metric.call_count > 0, _metric_details() + else: + assert metric.call_count == count, _metric_details() + + else: + assert metric is None, _metrics_table() + + for metric, count in metrics: + _validate(metric, count) + + return result + + return _validate_wrapper \ No newline at end of file From 2dbea7910758fdb05f12c8a142db9f8faa63c570 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Tue, 30 Aug 2022 17:08:26 -0700 Subject: [PATCH 05/23] Move validate_transaction_errors into validators directory --- tests/adapter_daphne/test_daphne.py | 2 +- tests/adapter_uvicorn/test_uvicorn.py | 2 +- tests/agent_features/test_asgi_browser.py | 4 +- tests/agent_features/test_asgi_transaction.py | 6 +- .../test_async_context_propagation.py | 3 +- tests/agent_features/test_browser.py | 4 +- tests/agent_features/test_coroutine_trace.py | 5 +- .../test_coroutine_transaction.py | 3 +- .../test_distributed_tracing.py | 3 +- .../test_event_loop_wait_time.py | 2 +- .../agent_features/test_high_security_mode.py | 3 +- .../test_ignore_expected_errors.py | 5 +- tests/agent_features/test_notice_error.py | 2 +- tests/agent_features/test_span_events.py | 3 +- .../agent_features/test_w3c_trace_context.py | 4 +- .../test_application.py | 2 +- .../component_flask_rest/test_application.py | 2 +- tests/component_graphqlserver/test_graphql.py | 8 +- tests/component_tastypie/test_application.py | 5 +- .../test_context_propagation.py | 2 +- tests/cross_agent/test_distributed_tracing.py | 3 +- tests/cross_agent/test_w3c_trace_context.py | 3 +- tests/datastore_aredis/test_multiple_dbs.py | 6 +- tests/datastore_asyncpg/test_multiple_dbs.py | 6 +- tests/datastore_asyncpg/test_query.py | 6 +- .../test_elasticsearch.py | 5 +- tests/datastore_psycopg2/test_async.py | 3 +- tests/datastore_psycopg2/test_register.py | 2 +- tests/datastore_psycopg2cffi/test_database.py | 4 +- .../test_pyelasticsearch.py | 2 +- tests/datastore_pymongo/test_pymongo.py | 7 +- tests/external_http/test_http.py | 2 +- tests/external_httplib/test_httplib.py | 2 +- tests/external_httplib2/test_httplib2.py | 2 +- tests/external_httpx/test_client.py | 4 +- tests/external_requests/test_requests.py | 5 +- tests/external_urllib3/test_urllib3.py | 5 +- tests/framework_aiohttp/test_client_cat.py | 6 +- tests/framework_aiohttp/test_server.py | 3 +- tests/framework_ariadne/test_application.py | 12 +-- tests/framework_bottle/test_application.py | 3 +- tests/framework_cherrypy/test_application.py | 6 +- tests/framework_cherrypy/test_dispatch.py | 2 +- tests/framework_cherrypy/test_resource.py | 2 +- tests/framework_cherrypy/test_routes.py | 2 +- tests/framework_django/test_application.py | 3 +- .../framework_django/test_asgi_application.py | 3 +- tests/framework_falcon/test_application.py | 3 +- tests/framework_flask/test_application.py | 3 +- tests/framework_flask/test_blueprints.py | 4 +- tests/framework_flask/test_compress.py | 4 +- tests/framework_flask/test_middleware.py | 4 +- tests/framework_flask/test_not_found.py | 2 +- tests/framework_flask/test_user_exceptions.py | 2 +- tests/framework_flask/test_views.py | 7 +- tests/framework_graphene/test_application.py | 8 +- tests/framework_graphql/test_application.py | 8 +- tests/framework_grpc/test_clients.py | 2 +- .../test_distributed_tracing.py | 5 +- tests/framework_grpc/test_server.py | 4 +- .../test_append_slash_app.py | 4 +- tests/framework_pyramid/test_application.py | 4 +- tests/framework_pyramid/test_cornice.py | 4 +- tests/framework_sanic/test_application.py | 3 +- .../framework_sanic/test_cross_application.py | 4 +- tests/framework_starlette/test_application.py | 8 +- .../framework_strawberry/test_application.py | 12 +-- tests/framework_tornado/test_externals.py | 6 +- tests/framework_tornado/test_inbound_cat.py | 4 +- tests/framework_tornado/test_server.py | 3 +- tests/logger_logging/test_metrics.py | 5 +- tests/logger_logging/test_settings.py | 7 +- tests/logger_loguru/test_metrics.py | 4 +- tests/logger_loguru/test_settings.py | 7 +- tests/messagebroker_pika/test_cat.py | 3 +- .../test_distributed_tracing.py | 4 +- .../test_pika_async_connection_consume.py | 4 +- .../test_pika_blocking_connection_consume.py | 3 +- tests/messagebroker_pika/test_pika_produce.py | 2 +- tests/testing_support/fixtures.py | 82 +++++++++---------- .../validators/validate_transaction_errors.py | 76 +++++++++++++++++ 81 files changed, 260 insertions(+), 224 deletions(-) create mode 100644 tests/testing_support/validators/validate_transaction_errors.py diff --git a/tests/adapter_daphne/test_daphne.py b/tests/adapter_daphne/test_daphne.py index a289e1311..34438482e 100644 --- a/tests/adapter_daphne/test_daphne.py +++ b/tests/adapter_daphne/test_daphne.py @@ -21,10 +21,10 @@ from testing_support.fixtures import ( override_application_settings, raise_background_exceptions, - validate_transaction_errors, wait_for_background_threads, ) from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.sample_asgi_applications import ( AppWithCall, AppWithCallRaw, diff --git a/tests/adapter_uvicorn/test_uvicorn.py b/tests/adapter_uvicorn/test_uvicorn.py index 8d81778fc..93d155aa8 100644 --- a/tests/adapter_uvicorn/test_uvicorn.py +++ b/tests/adapter_uvicorn/test_uvicorn.py @@ -23,10 +23,10 @@ from testing_support.fixtures import ( override_application_settings, raise_background_exceptions, - validate_transaction_errors, wait_for_background_threads, ) from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.sample_asgi_applications import ( AppWithCall, AppWithCallRaw, diff --git a/tests/agent_features/test_asgi_browser.py b/tests/agent_features/test_asgi_browser.py index c2c7ce715..ef21d7a0b 100644 --- a/tests/agent_features/test_asgi_browser.py +++ b/tests/agent_features/test_asgi_browser.py @@ -19,9 +19,9 @@ import six from testing_support.fixtures import (override_application_settings, - validate_transaction_errors, validate_custom_parameters) + validate_custom_parameters) from testing_support.asgi_testing import AsgiTest - +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from newrelic.api.application import application_settings from newrelic.api.transaction import (get_browser_timing_header, get_browser_timing_footer, add_custom_parameter, diff --git a/tests/agent_features/test_asgi_transaction.py b/tests/agent_features/test_asgi_transaction.py index cb930ba5b..1f4b21354 100644 --- a/tests/agent_features/test_asgi_transaction.py +++ b/tests/agent_features/test_asgi_transaction.py @@ -17,10 +17,8 @@ import pytest from testing_support.asgi_testing import AsgiTest -from testing_support.fixtures import ( - override_application_settings, - validate_transaction_errors, -) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.sample_asgi_applications import ( AppWithDescriptor, diff --git a/tests/agent_features/test_async_context_propagation.py b/tests/agent_features/test_async_context_propagation.py index ea850c095..8026cbbcc 100644 --- a/tests/agent_features/test_async_context_propagation.py +++ b/tests/agent_features/test_async_context_propagation.py @@ -16,9 +16,8 @@ from testing_support.fixtures import ( function_not_called, override_generic_settings, - validate_transaction_metrics, ) - +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.application import application_instance as application from newrelic.api.background_task import BackgroundTask, background_task from newrelic.api.database_trace import database_trace diff --git a/tests/agent_features/test_browser.py b/tests/agent_features/test_browser.py index 5f8492016..98ad22192 100644 --- a/tests/agent_features/test_browser.py +++ b/tests/agent_features/test_browser.py @@ -19,8 +19,8 @@ import six from testing_support.fixtures import (override_application_settings, - validate_transaction_errors, validate_custom_parameters) - + validate_custom_parameters) +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from newrelic.api.application import application_settings from newrelic.api.transaction import (get_browser_timing_header, get_browser_timing_footer, add_custom_parameter, diff --git a/tests/agent_features/test_coroutine_trace.py b/tests/agent_features/test_coroutine_trace.py index b15537573..31cb3cb9a 100644 --- a/tests/agent_features/test_coroutine_trace.py +++ b/tests/agent_features/test_coroutine_trace.py @@ -20,11 +20,10 @@ import pytest from testing_support.fixtures import ( capture_transaction_metrics, - validate_transaction_errors, - validate_transaction_metrics, validate_tt_parenting, ) - +from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task from newrelic.api.database_trace import database_trace from newrelic.api.datastore_trace import datastore_trace diff --git a/tests/agent_features/test_coroutine_transaction.py b/tests/agent_features/test_coroutine_transaction.py index 1a55385c7..315707bc2 100644 --- a/tests/agent_features/test_coroutine_transaction.py +++ b/tests/agent_features/test_coroutine_transaction.py @@ -19,9 +19,8 @@ from testing_support.fixtures import ( capture_transaction_metrics, override_generic_settings, - validate_transaction_errors, ) - +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from newrelic.api.background_task import background_task from newrelic.api.function_trace import function_trace from newrelic.api.message_transaction import message_transaction diff --git a/tests/agent_features/test_distributed_tracing.py b/tests/agent_features/test_distributed_tracing.py index ae6b4f32d..aed7de100 100644 --- a/tests/agent_features/test_distributed_tracing.py +++ b/tests/agent_features/test_distributed_tracing.py @@ -27,7 +27,8 @@ from testing_support.fixtures import (override_application_settings, validate_attributes, validate_transaction_event_attributes, - validate_error_event_attributes, validate_transaction_metrics) + validate_error_event_attributes) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics distributed_trace_intrinsics = ['guid', 'traceId', 'priority', 'sampled'] inbound_payload_intrinsics = ['parent.type', 'parent.app', 'parent.account', diff --git a/tests/agent_features/test_event_loop_wait_time.py b/tests/agent_features/test_event_loop_wait_time.py index ccf57c9a4..f93e78c23 100644 --- a/tests/agent_features/test_event_loop_wait_time.py +++ b/tests/agent_features/test_event_loop_wait_time.py @@ -19,10 +19,10 @@ from testing_support.fixtures import ( override_application_settings, validate_transaction_event_attributes, - validate_transaction_metrics, validate_transaction_trace_attributes, ) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task from newrelic.api.function_trace import FunctionTrace, function_trace from newrelic.api.transaction import current_transaction diff --git a/tests/agent_features/test_high_security_mode.py b/tests/agent_features/test_high_security_mode.py index 89499d365..fd6065b91 100644 --- a/tests/agent_features/test_high_security_mode.py +++ b/tests/agent_features/test_high_security_mode.py @@ -27,10 +27,9 @@ validate_custom_parameters, validate_non_transaction_error_event, validate_request_params_omitted, - validate_transaction_errors, validate_tt_segment_params, ) - +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from newrelic.api.application import application_instance as application from newrelic.api.background_task import background_task from newrelic.api.function_trace import FunctionTrace diff --git a/tests/agent_features/test_ignore_expected_errors.py b/tests/agent_features/test_ignore_expected_errors.py index b044c8fa5..f2cd8861a 100644 --- a/tests/agent_features/test_ignore_expected_errors.py +++ b/tests/agent_features/test_ignore_expected_errors.py @@ -20,11 +20,10 @@ validate_error_event_sample_data, validate_error_trace_attributes_outside_transaction, validate_transaction_error_trace_attributes, - validate_transaction_errors, - validate_transaction_metrics, ) from testing_support.validators.validate_time_metrics_outside_transaction import validate_time_metrics_outside_transaction - +from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.application import application_instance from newrelic.api.background_task import background_task from newrelic.api.time_trace import notice_error diff --git a/tests/agent_features/test_notice_error.py b/tests/agent_features/test_notice_error.py index e052602a0..b47335068 100644 --- a/tests/agent_features/test_notice_error.py +++ b/tests/agent_features/test_notice_error.py @@ -24,9 +24,9 @@ validate_application_errors, validate_transaction_error_event_count, validate_transaction_error_trace_count, - validate_transaction_errors, ) +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from newrelic.api.application import application_instance as application from newrelic.api.application import application_settings from newrelic.api.background_task import background_task diff --git a/tests/agent_features/test_span_events.py b/tests/agent_features/test_span_events.py index 0024c1b8b..4c4eecc69 100644 --- a/tests/agent_features/test_span_events.py +++ b/tests/agent_features/test_span_events.py @@ -31,10 +31,11 @@ from testing_support.fixtures import (override_application_settings, function_not_called, validate_tt_segment_params, - validate_transaction_metrics, dt_enabled, + dt_enabled, validate_transaction_event_attributes) from testing_support.validators.validate_span_events import ( validate_span_events) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics ERROR = ValueError("whoops") ERROR_NAME = callable_name(ERROR) diff --git a/tests/agent_features/test_w3c_trace_context.py b/tests/agent_features/test_w3c_trace_context.py index 17e40fdb0..7143e0f46 100644 --- a/tests/agent_features/test_w3c_trace_context.py +++ b/tests/agent_features/test_w3c_trace_context.py @@ -20,10 +20,10 @@ from newrelic.api.external_trace import ExternalTrace from newrelic.api.wsgi_application import wsgi_application from testing_support.fixtures import (override_application_settings, - validate_transaction_event_attributes, validate_transaction_metrics) + validate_transaction_event_attributes) from testing_support.validators.validate_span_events import ( validate_span_events) - +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics @wsgi_application() def target_wsgi_application(environ, start_response): diff --git a/tests/component_djangorestframework/test_application.py b/tests/component_djangorestframework/test_application.py index 472f2f029..9ed60aa33 100644 --- a/tests/component_djangorestframework/test_application.py +++ b/tests/component_djangorestframework/test_application.py @@ -19,9 +19,9 @@ from newrelic.core.config import global_settings from testing_support.fixtures import ( - validate_transaction_errors, override_generic_settings, function_not_called) +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics import django diff --git a/tests/component_flask_rest/test_application.py b/tests/component_flask_rest/test_application.py index 391a35674..bd54b3eba 100644 --- a/tests/component_flask_rest/test_application.py +++ b/tests/component_flask_rest/test_application.py @@ -16,11 +16,11 @@ from newrelic.packages import six from testing_support.fixtures import ( - validate_transaction_errors, override_ignore_status_codes, override_generic_settings) from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from newrelic.core.config import global_settings from newrelic.common.object_names import callable_name diff --git a/tests/component_graphqlserver/test_graphql.py b/tests/component_graphqlserver/test_graphql.py index 997df1174..e5566047e 100644 --- a/tests/component_graphqlserver/test_graphql.py +++ b/tests/component_graphqlserver/test_graphql.py @@ -15,11 +15,9 @@ import importlib import pytest -from testing_support.fixtures import ( - dt_enabled, - validate_transaction_errors, - validate_transaction_metrics, -) +from testing_support.fixtures import dt_enabled +from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_span_events import validate_span_events from testing_support.validators.validate_transaction_count import ( validate_transaction_count, diff --git a/tests/component_tastypie/test_application.py b/tests/component_tastypie/test_application.py index 378a94c16..5f81d0831 100644 --- a/tests/component_tastypie/test_application.py +++ b/tests/component_tastypie/test_application.py @@ -21,9 +21,8 @@ from newrelic.api.background_task import background_task from newrelic.api.transaction import end_of_transaction -from testing_support.fixtures import ( - validate_transaction_errors, - override_ignore_status_codes) +from testing_support.fixtures import override_ignore_status_codes +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics diff --git a/tests/coroutines_asyncio/test_context_propagation.py b/tests/coroutines_asyncio/test_context_propagation.py index 3beef38d0..09fccffb2 100644 --- a/tests/coroutines_asyncio/test_context_propagation.py +++ b/tests/coroutines_asyncio/test_context_propagation.py @@ -18,9 +18,9 @@ from testing_support.fixtures import ( function_not_called, override_generic_settings, - validate_transaction_metrics, ) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.application import application_instance as application from newrelic.api.background_task import BackgroundTask, background_task from newrelic.api.database_trace import database_trace diff --git a/tests/cross_agent/test_distributed_tracing.py b/tests/cross_agent/test_distributed_tracing.py index 2ec246275..7b0be1ca2 100644 --- a/tests/cross_agent/test_distributed_tracing.py +++ b/tests/cross_agent/test_distributed_tracing.py @@ -23,10 +23,11 @@ from newrelic.common.object_wrapper import transient_function_wrapper from testing_support.fixtures import (override_application_settings, - validate_transaction_metrics, validate_transaction_event_attributes, + validate_transaction_event_attributes, validate_error_event_attributes, validate_attributes) from testing_support.validators.validate_span_events import ( validate_span_events) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) JSON_DIR = os.path.normpath(os.path.join(CURRENT_DIR, 'fixtures', diff --git a/tests/cross_agent/test_w3c_trace_context.py b/tests/cross_agent/test_w3c_trace_context.py index 479d799bc..efc13c25d 100644 --- a/tests/cross_agent/test_w3c_trace_context.py +++ b/tests/cross_agent/test_w3c_trace_context.py @@ -24,9 +24,10 @@ from testing_support.validators.validate_span_events import ( validate_span_events) from testing_support.fixtures import (override_application_settings, - validate_transaction_metrics, validate_transaction_event_attributes, + validate_transaction_event_attributes, validate_attributes) from newrelic.common.encoding_utils import W3CTraceState +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) JSON_DIR = os.path.normpath(os.path.join(CURRENT_DIR, 'fixtures', diff --git a/tests/datastore_aredis/test_multiple_dbs.py b/tests/datastore_aredis/test_multiple_dbs.py index e16ae9483..cb4cbac5b 100644 --- a/tests/datastore_aredis/test_multiple_dbs.py +++ b/tests/datastore_aredis/test_multiple_dbs.py @@ -15,10 +15,8 @@ import aredis import pytest from testing_support.db_settings import redis_settings -from testing_support.fixtures import ( - override_application_settings, - validate_transaction_metrics, -) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.util import instance_hostname from newrelic.api.background_task import background_task diff --git a/tests/datastore_asyncpg/test_multiple_dbs.py b/tests/datastore_asyncpg/test_multiple_dbs.py index a24eaa388..a917a9e83 100644 --- a/tests/datastore_asyncpg/test_multiple_dbs.py +++ b/tests/datastore_asyncpg/test_multiple_dbs.py @@ -17,10 +17,8 @@ import asyncpg import pytest from testing_support.db_settings import postgresql_settings -from testing_support.fixtures import ( - override_application_settings, - validate_transaction_metrics, -) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.util import instance_hostname from newrelic.api.background_task import background_task diff --git a/tests/datastore_asyncpg/test_query.py b/tests/datastore_asyncpg/test_query.py index eb44cfd16..a952e062a 100644 --- a/tests/datastore_asyncpg/test_query.py +++ b/tests/datastore_asyncpg/test_query.py @@ -20,10 +20,8 @@ import asyncpg import pytest from testing_support.db_settings import postgresql_settings -from testing_support.fixtures import ( - validate_transaction_metrics, - validate_tt_collector_json, -) +from testing_support.fixtures import validate_tt_collector_json +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.util import instance_hostname from newrelic.api.background_task import background_task diff --git a/tests/datastore_elasticsearch/test_elasticsearch.py b/tests/datastore_elasticsearch/test_elasticsearch.py index f219e01b5..65a0374df 100644 --- a/tests/datastore_elasticsearch/test_elasticsearch.py +++ b/tests/datastore_elasticsearch/test_elasticsearch.py @@ -17,9 +17,8 @@ from newrelic.api.background_task import background_task -from testing_support.fixtures import ( - validate_transaction_errors, - override_application_settings) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import elasticsearch_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_psycopg2/test_async.py b/tests/datastore_psycopg2/test_async.py index 32224b681..7af9adc6a 100644 --- a/tests/datastore_psycopg2/test_async.py +++ b/tests/datastore_psycopg2/test_async.py @@ -17,11 +17,10 @@ import pytest from testing_support.fixtures import ( - validate_transaction_errors, validate_stats_engine_explain_plan_output_is_none, override_application_settings) from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics - +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.validators.validate_database_trace_inputs import validate_database_trace_inputs from testing_support.validators.validate_transaction_slow_sql_count import ( validate_transaction_slow_sql_count) diff --git a/tests/datastore_psycopg2/test_register.py b/tests/datastore_psycopg2/test_register.py index 8f6d8bfd9..b5450c358 100644 --- a/tests/datastore_psycopg2/test_register.py +++ b/tests/datastore_psycopg2/test_register.py @@ -16,7 +16,7 @@ import psycopg2 import psycopg2.extras -from testing_support.fixtures import validate_transaction_errors +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from utils import DB_SETTINGS diff --git a/tests/datastore_psycopg2cffi/test_database.py b/tests/datastore_psycopg2cffi/test_database.py index 48e85e77b..54ff6ad09 100644 --- a/tests/datastore_psycopg2cffi/test_database.py +++ b/tests/datastore_psycopg2cffi/test_database.py @@ -16,8 +16,8 @@ import psycopg2cffi.extensions import psycopg2cffi.extras -from testing_support.fixtures import ( - validate_transaction_errors, validate_stats_engine_explain_plan_output_is_none) +from testing_support.fixtures import validate_stats_engine_explain_plan_output_is_none +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_transaction_slow_sql_count import \ validate_transaction_slow_sql_count diff --git a/tests/datastore_pyelasticsearch/test_pyelasticsearch.py b/tests/datastore_pyelasticsearch/test_pyelasticsearch.py index 7554e9a3d..deb3f68ff 100644 --- a/tests/datastore_pyelasticsearch/test_pyelasticsearch.py +++ b/tests/datastore_pyelasticsearch/test_pyelasticsearch.py @@ -15,7 +15,7 @@ import sqlite3 from pyelasticsearch import ElasticSearch -from testing_support.fixtures import validate_transaction_errors +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.db_settings import elasticsearch_settings from testing_support.validators.validate_database_duration import validate_database_duration diff --git a/tests/datastore_pymongo/test_pymongo.py b/tests/datastore_pymongo/test_pymongo.py index 09ea62e0b..4649062ce 100644 --- a/tests/datastore_pymongo/test_pymongo.py +++ b/tests/datastore_pymongo/test_pymongo.py @@ -16,14 +16,11 @@ import pymongo from testing_support.db_settings import mongodb_settings -from testing_support.fixtures import ( - validate_transaction_errors, - validate_transaction_metrics, -) from testing_support.validators.validate_database_duration import ( validate_database_duration, ) - +from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task from newrelic.packages import six diff --git a/tests/external_http/test_http.py b/tests/external_http/test_http.py index 16bef3f2a..e08518f5f 100644 --- a/tests/external_http/test_http.py +++ b/tests/external_http/test_http.py @@ -21,8 +21,8 @@ from testing_support.fixtures import ( cat_enabled, override_application_settings, - validate_transaction_metrics, ) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_cross_process_headers import ( validate_cross_process_headers, ) diff --git a/tests/external_httplib/test_httplib.py b/tests/external_httplib/test_httplib.py index 69f790846..c7747f8ff 100644 --- a/tests/external_httplib/test_httplib.py +++ b/tests/external_httplib/test_httplib.py @@ -26,9 +26,9 @@ from testing_support.fixtures import ( cat_enabled, override_application_settings, - validate_transaction_metrics, validate_tt_segment_params, ) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_cross_process_headers import ( validate_cross_process_headers, ) diff --git a/tests/external_httplib2/test_httplib2.py b/tests/external_httplib2/test_httplib2.py index d3e71e7b3..288aa84ee 100644 --- a/tests/external_httplib2/test_httplib2.py +++ b/tests/external_httplib2/test_httplib2.py @@ -21,7 +21,6 @@ from testing_support.fixtures import ( cat_enabled, override_application_settings, - validate_transaction_metrics, ) from testing_support.validators.validate_cross_process_headers import ( validate_cross_process_headers, @@ -29,6 +28,7 @@ from testing_support.validators.validate_external_node_params import ( validate_external_node_params, ) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task diff --git a/tests/external_httpx/test_client.py b/tests/external_httpx/test_client.py index 1d170a5fa..87a1bc7d0 100644 --- a/tests/external_httpx/test_client.py +++ b/tests/external_httpx/test_client.py @@ -19,8 +19,6 @@ dt_enabled, override_application_settings, override_generic_settings, - validate_transaction_errors, - validate_transaction_metrics, validate_tt_segment_params, ) from testing_support.mock_external_http_server import ( @@ -30,6 +28,8 @@ validate_cross_process_headers, ) from testing_support.validators.validate_span_events import validate_span_events +from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task from newrelic.api.time_trace import current_trace diff --git a/tests/external_requests/test_requests.py b/tests/external_requests/test_requests.py index b61cf36df..f6f4506e5 100644 --- a/tests/external_requests/test_requests.py +++ b/tests/external_requests/test_requests.py @@ -22,8 +22,6 @@ from testing_support.fixtures import ( cat_enabled, override_application_settings, - validate_transaction_errors, - validate_transaction_metrics, validate_tt_parenting, ) from testing_support.validators.validate_cross_process_headers import ( @@ -32,7 +30,8 @@ from testing_support.validators.validate_external_node_params import ( validate_external_node_params, ) - +from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task diff --git a/tests/external_urllib3/test_urllib3.py b/tests/external_urllib3/test_urllib3.py index 93287e000..68e15d463 100644 --- a/tests/external_urllib3/test_urllib3.py +++ b/tests/external_urllib3/test_urllib3.py @@ -28,8 +28,6 @@ from testing_support.fixtures import ( cat_enabled, override_application_settings, - validate_transaction_errors, - validate_transaction_metrics, ) from testing_support.util import version2tuple from testing_support.validators.validate_cross_process_headers import ( @@ -38,7 +36,8 @@ from testing_support.validators.validate_external_node_params import ( validate_external_node_params, ) - +from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task diff --git a/tests/framework_aiohttp/test_client_cat.py b/tests/framework_aiohttp/test_client_cat.py index a830c2269..0cb39a604 100644 --- a/tests/framework_aiohttp/test_client_cat.py +++ b/tests/framework_aiohttp/test_client_cat.py @@ -18,10 +18,8 @@ import aiohttp import pytest from testing_support.external_fixtures import create_incoming_headers -from testing_support.fixtures import ( - override_application_settings, - validate_transaction_metrics, -) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_cross_process_headers import ( validate_cross_process_headers, ) diff --git a/tests/framework_aiohttp/test_server.py b/tests/framework_aiohttp/test_server.py index f09f2b615..4f0347df1 100644 --- a/tests/framework_aiohttp/test_server.py +++ b/tests/framework_aiohttp/test_server.py @@ -18,11 +18,12 @@ from newrelic.core.config import global_settings from testing_support.fixtures import ( - validate_transaction_errors, validate_transaction_event_attributes, + validate_transaction_event_attributes, count_transactions, override_generic_settings, override_application_settings, override_ignore_status_codes) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors version_info = tuple(int(_) for _ in aiohttp.__version__.split('.')[:2]) diff --git a/tests/framework_ariadne/test_application.py b/tests/framework_ariadne/test_application.py index f0b3587b8..ed60397b9 100644 --- a/tests/framework_ariadne/test_application.py +++ b/tests/framework_ariadne/test_application.py @@ -13,15 +13,11 @@ # limitations under the License. import pytest -from testing_support.fixtures import ( - dt_enabled, - validate_transaction_errors, - validate_transaction_metrics, -) +from testing_support.fixtures import dt_enabled from testing_support.validators.validate_span_events import validate_span_events -from testing_support.validators.validate_transaction_count import ( - validate_transaction_count, -) +from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_count import validate_transaction_count from newrelic.api.background_task import background_task from newrelic.common.object_names import callable_name diff --git a/tests/framework_bottle/test_application.py b/tests/framework_bottle/test_application.py index 56e3b0f65..28619d5eb 100644 --- a/tests/framework_bottle/test_application.py +++ b/tests/framework_bottle/test_application.py @@ -16,11 +16,12 @@ import base64 from testing_support.fixtures import ( - validate_transaction_errors, override_ignore_status_codes, + override_ignore_status_codes, override_application_settings) from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.packages import six from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors import webtest diff --git a/tests/framework_cherrypy/test_application.py b/tests/framework_cherrypy/test_application.py index 1dd7f837d..39f8b5c16 100644 --- a/tests/framework_cherrypy/test_application.py +++ b/tests/framework_cherrypy/test_application.py @@ -17,9 +17,11 @@ from newrelic.packages import six -from testing_support.fixtures import (validate_transaction_errors, - override_application_settings, override_ignore_status_codes) +from testing_support.fixtures import ( + override_application_settings, + override_ignore_status_codes) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors import cherrypy diff --git a/tests/framework_cherrypy/test_dispatch.py b/tests/framework_cherrypy/test_dispatch.py index 0a3f8e7c7..64dccb214 100644 --- a/tests/framework_cherrypy/test_dispatch.py +++ b/tests/framework_cherrypy/test_dispatch.py @@ -17,7 +17,7 @@ from newrelic.packages import six -from testing_support.fixtures import validate_transaction_errors +from testing_support.validators.validate_transaction_errors import validate_transaction_errors import cherrypy diff --git a/tests/framework_cherrypy/test_resource.py b/tests/framework_cherrypy/test_resource.py index 09c68f9fc..385d28d91 100644 --- a/tests/framework_cherrypy/test_resource.py +++ b/tests/framework_cherrypy/test_resource.py @@ -14,7 +14,7 @@ import webtest -from testing_support.fixtures import validate_transaction_errors +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics import cherrypy diff --git a/tests/framework_cherrypy/test_routes.py b/tests/framework_cherrypy/test_routes.py index 7c1b23181..9111a29ce 100644 --- a/tests/framework_cherrypy/test_routes.py +++ b/tests/framework_cherrypy/test_routes.py @@ -16,7 +16,7 @@ import sys import webtest -from testing_support.fixtures import validate_transaction_errors +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics import cherrypy diff --git a/tests/framework_django/test_application.py b/tests/framework_django/test_application.py index 1bee82346..1f2616b0f 100644 --- a/tests/framework_django/test_application.py +++ b/tests/framework_django/test_application.py @@ -13,11 +13,12 @@ # limitations under the License. from testing_support.fixtures import ( - validate_transaction_errors, override_application_settings, + override_application_settings, override_generic_settings, override_ignore_status_codes) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from newrelic.hooks.framework_django import django_settings from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors import os diff --git a/tests/framework_django/test_asgi_application.py b/tests/framework_django/test_asgi_application.py index e714d5277..457042766 100644 --- a/tests/framework_django/test_asgi_application.py +++ b/tests/framework_django/test_asgi_application.py @@ -19,10 +19,11 @@ from newrelic.core.config import global_settings from newrelic.common.encoding_utils import gzip_decompress from testing_support.fixtures import ( - validate_transaction_errors, override_application_settings, + override_application_settings, override_generic_settings, override_ignore_status_codes) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors DJANGO_VERSION = tuple(map(int, django.get_version().split('.')[:2])) diff --git a/tests/framework_falcon/test_application.py b/tests/framework_falcon/test_application.py index e0810c345..6b64c8c67 100644 --- a/tests/framework_falcon/test_application.py +++ b/tests/framework_falcon/test_application.py @@ -15,10 +15,11 @@ import pytest from newrelic.core.config import global_settings from testing_support.fixtures import ( - validate_transaction_errors, override_ignore_status_codes, + override_ignore_status_codes, override_generic_settings) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors SETTINGS = global_settings() diff --git a/tests/framework_flask/test_application.py b/tests/framework_flask/test_application.py index 5aebc1117..de7a43019 100644 --- a/tests/framework_flask/test_application.py +++ b/tests/framework_flask/test_application.py @@ -15,10 +15,11 @@ import pytest from testing_support.fixtures import ( - validate_transaction_errors, override_application_settings, + override_application_settings, validate_tt_parenting) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from newrelic.packages import six diff --git a/tests/framework_flask/test_blueprints.py b/tests/framework_flask/test_blueprints.py index 5f8abd441..4a1e361fb 100644 --- a/tests/framework_flask/test_blueprints.py +++ b/tests/framework_flask/test_blueprints.py @@ -14,10 +14,10 @@ import pytest -from testing_support.fixtures import ( - validate_transaction_errors, override_application_settings) +from testing_support.fixtures import override_application_settings from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from newrelic.packages import six diff --git a/tests/framework_flask/test_compress.py b/tests/framework_flask/test_compress.py index 49138fe27..f6feb01ee 100644 --- a/tests/framework_flask/test_compress.py +++ b/tests/framework_flask/test_compress.py @@ -12,9 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -from testing_support.fixtures import ( - validate_transaction_errors, override_application_settings) +from testing_support.fixtures import override_application_settings from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics diff --git a/tests/framework_flask/test_middleware.py b/tests/framework_flask/test_middleware.py index 9f56163b7..3c81ebc47 100644 --- a/tests/framework_flask/test_middleware.py +++ b/tests/framework_flask/test_middleware.py @@ -14,10 +14,10 @@ import pytest -from testing_support.fixtures import ( - validate_transaction_errors, override_application_settings) +from testing_support.fixtures import override_application_settings from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors def target_application(): # We need to delay Flask application creation because of ordering diff --git a/tests/framework_flask/test_not_found.py b/tests/framework_flask/test_not_found.py index 523a8e593..c1c55475e 100644 --- a/tests/framework_flask/test_not_found.py +++ b/tests/framework_flask/test_not_found.py @@ -14,7 +14,7 @@ import pytest -from testing_support.fixtures import validate_transaction_errors +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics def target_application(): diff --git a/tests/framework_flask/test_user_exceptions.py b/tests/framework_flask/test_user_exceptions.py index a69c69b92..844b4b9ef 100644 --- a/tests/framework_flask/test_user_exceptions.py +++ b/tests/framework_flask/test_user_exceptions.py @@ -14,7 +14,7 @@ import pytest -from testing_support.fixtures import validate_transaction_errors +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics def target_application(): diff --git a/tests/framework_flask/test_views.py b/tests/framework_flask/test_views.py index d4dd8178f..d45021bff 100644 --- a/tests/framework_flask/test_views.py +++ b/tests/framework_flask/test_views.py @@ -16,10 +16,9 @@ async_handler_support, skip_if_not_async_handler_support, ) -from testing_support.fixtures import ( - validate_transaction_errors, - validate_transaction_metrics, -) +from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics + scoped_metrics = [ ("Function/flask.app:Flask.wsgi_app", 1), diff --git a/tests/framework_graphene/test_application.py b/tests/framework_graphene/test_application.py index b4e8e0739..b9d374a3c 100644 --- a/tests/framework_graphene/test_application.py +++ b/tests/framework_graphene/test_application.py @@ -14,15 +14,13 @@ import pytest import six -from testing_support.fixtures import ( - dt_enabled, - validate_transaction_errors, - validate_transaction_metrics, -) +from testing_support.fixtures import dt_enabled from testing_support.validators.validate_span_events import validate_span_events from testing_support.validators.validate_transaction_count import ( validate_transaction_count, ) +from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task from newrelic.common.object_names import callable_name diff --git a/tests/framework_graphql/test_application.py b/tests/framework_graphql/test_application.py index 770c6f6e1..56dc3a738 100644 --- a/tests/framework_graphql/test_application.py +++ b/tests/framework_graphql/test_application.py @@ -13,16 +13,14 @@ # limitations under the License. import pytest -from testing_support.fixtures import ( - dt_enabled, - validate_transaction_errors, - validate_transaction_metrics, -) +from testing_support.fixtures import dt_enabled from testing_support.validators.validate_span_events import validate_span_events from testing_support.validators.validate_transaction_count import ( validate_transaction_count, ) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task from newrelic.common.object_names import callable_name diff --git a/tests/framework_grpc/test_clients.py b/tests/framework_grpc/test_clients.py index 9fa62d557..c6ada806b 100644 --- a/tests/framework_grpc/test_clients.py +++ b/tests/framework_grpc/test_clients.py @@ -18,7 +18,7 @@ from newrelic.api.background_task import background_task -from testing_support.fixtures import validate_transaction_errors +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from _test_common import create_request, get_result diff --git a/tests/framework_grpc/test_distributed_tracing.py b/tests/framework_grpc/test_distributed_tracing.py index 7cd134ca0..7f253651d 100644 --- a/tests/framework_grpc/test_distributed_tracing.py +++ b/tests/framework_grpc/test_distributed_tracing.py @@ -21,12 +21,11 @@ from newrelic.common.encoding_utils import ( DistributedTracePayload, W3CTraceParent, W3CTraceState, NrTraceState) -from testing_support.fixtures import (override_application_settings, - validate_transaction_metrics) +from testing_support.fixtures import override_application_settings from testing_support.validators.validate_span_events import ( validate_span_events) from _test_common import create_request, wait_for_transaction_completion - +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics _test_matrix = ('method_name,streaming_request', ( ('DoUnaryUnary', False), diff --git a/tests/framework_grpc/test_server.py b/tests/framework_grpc/test_server.py index e80b103b8..92ec9c4b3 100644 --- a/tests/framework_grpc/test_server.py +++ b/tests/framework_grpc/test_server.py @@ -20,10 +20,10 @@ from newrelic.core.config import global_settings from testing_support.fixtures import ( validate_transaction_event_attributes, override_application_settings, - override_generic_settings, function_not_called, - validate_transaction_errors) + override_generic_settings, function_not_called) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors def select_python_version(py2, py3): return six.PY3 and py3 or py2 diff --git a/tests/framework_pyramid/test_append_slash_app.py b/tests/framework_pyramid/test_append_slash_app.py index 10053e7cc..f09e14b55 100644 --- a/tests/framework_pyramid/test_append_slash_app.py +++ b/tests/framework_pyramid/test_append_slash_app.py @@ -34,9 +34,9 @@ import pytest import re -from testing_support.fixtures import ( - validate_transaction_errors, override_application_settings) +from testing_support.fixtures import override_application_settings from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors def _to_int(version_str): m = re.match(r'\d+', version_str) diff --git a/tests/framework_pyramid/test_application.py b/tests/framework_pyramid/test_application.py index 6bae117e9..132e0f72a 100644 --- a/tests/framework_pyramid/test_application.py +++ b/tests/framework_pyramid/test_application.py @@ -14,9 +14,9 @@ import pytest -from testing_support.fixtures import ( - validate_transaction_errors, override_application_settings) +from testing_support.fixtures import override_application_settings from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from newrelic.packages import six from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics diff --git a/tests/framework_pyramid/test_cornice.py b/tests/framework_pyramid/test_cornice.py index 8b8dc58d2..fe36831e0 100644 --- a/tests/framework_pyramid/test_cornice.py +++ b/tests/framework_pyramid/test_cornice.py @@ -14,9 +14,9 @@ import pytest -from testing_support.fixtures import (validate_transaction_errors, - validate_transaction_metrics) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors from newrelic.packages import six diff --git a/tests/framework_sanic/test_application.py b/tests/framework_sanic/test_application.py index 9ea9b92c4..ccb0dec67 100644 --- a/tests/framework_sanic/test_application.py +++ b/tests/framework_sanic/test_application.py @@ -23,12 +23,13 @@ from newrelic.api.external_trace import ExternalTrace from testing_support.fixtures import ( - override_application_settings, validate_transaction_errors, + override_application_settings, validate_transaction_event_attributes, override_ignore_status_codes, override_generic_settings, function_not_called) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors sanic_21 = int(sanic.__version__.split('.', 1)[0]) >= 21 diff --git a/tests/framework_sanic/test_cross_application.py b/tests/framework_sanic/test_cross_application.py index 0c1c724cf..55e5a3578 100644 --- a/tests/framework_sanic/test_cross_application.py +++ b/tests/framework_sanic/test_cross_application.py @@ -25,8 +25,8 @@ from testing_support.fixtures import (override_application_settings, make_cross_agent_headers, validate_analytics_catmap_data, - validate_transaction_metrics, validate_transaction_event_attributes) - + validate_transaction_event_attributes) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics BASE_METRICS = [ ('Function/_target_application:index', 1), diff --git a/tests/framework_starlette/test_application.py b/tests/framework_starlette/test_application.py index 9c5944bd0..7d36d66cc 100644 --- a/tests/framework_starlette/test_application.py +++ b/tests/framework_starlette/test_application.py @@ -16,14 +16,12 @@ import pytest import starlette -from testing_support.fixtures import ( - override_ignore_status_codes, - validate_transaction_errors, - validate_transaction_metrics, -) +from testing_support.fixtures import override_ignore_status_codes from newrelic.common.object_names import callable_name from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics starlette_version = tuple(int(x) for x in starlette.__version__.split(".")) diff --git a/tests/framework_strawberry/test_application.py b/tests/framework_strawberry/test_application.py index ff6d0e2ed..d57de74f4 100644 --- a/tests/framework_strawberry/test_application.py +++ b/tests/framework_strawberry/test_application.py @@ -13,15 +13,11 @@ # limitations under the License. import pytest -from testing_support.fixtures import ( - dt_enabled, - validate_transaction_errors, - validate_transaction_metrics, -) +from testing_support.fixtures import dt_enabled from testing_support.validators.validate_span_events import validate_span_events -from testing_support.validators.validate_transaction_count import ( - validate_transaction_count, -) +from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_count import validate_transaction_count from newrelic.api.background_task import background_task from newrelic.common.object_names import callable_name diff --git a/tests/framework_tornado/test_externals.py b/tests/framework_tornado/test_externals.py index 7d973ac5f..0c44e4336 100644 --- a/tests/framework_tornado/test_externals.py +++ b/tests/framework_tornado/test_externals.py @@ -17,10 +17,8 @@ import sys import pytest -from testing_support.fixtures import ( - override_application_settings, - validate_transaction_metrics, -) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.mock_external_http_server import ( MockExternalHTTPHResponseHeadersServer, MockExternalHTTPServer, diff --git a/tests/framework_tornado/test_inbound_cat.py b/tests/framework_tornado/test_inbound_cat.py index 87ebe03d0..c399f70d5 100644 --- a/tests/framework_tornado/test_inbound_cat.py +++ b/tests/framework_tornado/test_inbound_cat.py @@ -15,8 +15,8 @@ import json import pytest from testing_support.fixtures import (make_cross_agent_headers, - override_application_settings, validate_transaction_event_attributes, - validate_transaction_metrics) + override_application_settings, validate_transaction_event_attributes) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics ENCODING_KEY = '1234567890123456789012345678901234567890' diff --git a/tests/framework_tornado/test_server.py b/tests/framework_tornado/test_server.py index 9a0bb96d4..57eb8b576 100644 --- a/tests/framework_tornado/test_server.py +++ b/tests/framework_tornado/test_server.py @@ -17,12 +17,13 @@ from testing_support.fixtures import ( override_generic_settings, function_not_called, validate_transaction_event_attributes, - validate_transaction_errors, override_ignore_status_codes, + override_ignore_status_codes, override_application_settings) from testing_support.validators.validate_transaction_count import ( validate_transaction_count) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import validate_transaction_errors @pytest.mark.parametrize('uri,name,metrics, method_metric', ( # ('/native-simple', '_target_application:NativeSimpleHandler.get', None, diff --git a/tests/logger_logging/test_metrics.py b/tests/logger_logging/test_metrics.py index eb9419daf..f5a1c5e8d 100644 --- a/tests/logger_logging/test_metrics.py +++ b/tests/logger_logging/test_metrics.py @@ -16,10 +16,7 @@ from newrelic.api.background_task import background_task from testing_support.fixtures import reset_core_stats_engine from testing_support.validators.validate_custom_metrics_outside_transaction import validate_custom_metrics_outside_transaction -from testing_support.fixtures import ( - validate_transaction_metrics, -) - +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics def exercise_logging(logger): logger.debug("A") diff --git a/tests/logger_logging/test_settings.py b/tests/logger_logging/test_settings.py index 2406d87c0..0581e6218 100644 --- a/tests/logger_logging/test_settings.py +++ b/tests/logger_logging/test_settings.py @@ -18,11 +18,8 @@ from newrelic.api.background_task import background_task from testing_support.fixtures import reset_core_stats_engine from testing_support.validators.validate_log_event_count import validate_log_event_count -from testing_support.fixtures import ( - override_application_settings, - validate_transaction_metrics, -) - +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics def basic_logging(logger): logger.warning("C") diff --git a/tests/logger_loguru/test_metrics.py b/tests/logger_loguru/test_metrics.py index c8a9299c8..9c02d405e 100644 --- a/tests/logger_loguru/test_metrics.py +++ b/tests/logger_loguru/test_metrics.py @@ -15,9 +15,7 @@ from newrelic.api.background_task import background_task from testing_support.fixtures import reset_core_stats_engine from testing_support.validators.validate_custom_metrics_outside_transaction import validate_custom_metrics_outside_transaction -from testing_support.fixtures import ( - validate_transaction_metrics, -) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics def exercise_logging(logger): diff --git a/tests/logger_loguru/test_settings.py b/tests/logger_loguru/test_settings.py index 4e5dadf5d..43d675d56 100644 --- a/tests/logger_loguru/test_settings.py +++ b/tests/logger_loguru/test_settings.py @@ -19,11 +19,8 @@ from newrelic.api.background_task import background_task from testing_support.fixtures import reset_core_stats_engine from testing_support.validators.validate_log_event_count import validate_log_event_count -from testing_support.fixtures import ( - override_application_settings, - validate_transaction_metrics, -) - +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics def get_metadata_string(log_message, is_txn): host = platform.uname().node diff --git a/tests/messagebroker_pika/test_cat.py b/tests/messagebroker_pika/test_cat.py index 2b1aac4a7..e6ca848cc 100644 --- a/tests/messagebroker_pika/test_cat.py +++ b/tests/messagebroker_pika/test_cat.py @@ -23,9 +23,8 @@ from testing_support.fixtures import ( cat_enabled, override_application_settings, - validate_transaction_metrics, ) - +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task from newrelic.api.transaction import current_transaction diff --git a/tests/messagebroker_pika/test_distributed_tracing.py b/tests/messagebroker_pika/test_distributed_tracing.py index f911aaad8..548d41a0d 100644 --- a/tests/messagebroker_pika/test_distributed_tracing.py +++ b/tests/messagebroker_pika/test_distributed_tracing.py @@ -23,8 +23,8 @@ from newrelic.common.encoding_utils import DistributedTracePayload from testing_support.db_settings import rabbitmq_settings -from testing_support.fixtures import (override_application_settings, - validate_transaction_metrics) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics DB_SETTINGS = rabbitmq_settings()[0] diff --git a/tests/messagebroker_pika/test_pika_async_connection_consume.py b/tests/messagebroker_pika/test_pika_async_connection_consume.py index 0ed76503f..7edf6b644 100644 --- a/tests/messagebroker_pika/test_pika_async_connection_consume.py +++ b/tests/messagebroker_pika/test_pika_async_connection_consume.py @@ -26,11 +26,11 @@ from conftest import (QUEUE, QUEUE_2, EXCHANGE, EXCHANGE_2, CORRELATION_ID, REPLY_TO, HEADERS, BODY) from testing_support.fixtures import (capture_transaction_metrics, - validate_transaction_metrics, validate_tt_collector_json, + validate_tt_collector_json, function_not_called, override_application_settings) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from testing_support.db_settings import rabbitmq_settings - +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics DB_SETTINGS = rabbitmq_settings()[0] diff --git a/tests/messagebroker_pika/test_pika_blocking_connection_consume.py b/tests/messagebroker_pika/test_pika_blocking_connection_consume.py index 417055bfc..c96d42d98 100644 --- a/tests/messagebroker_pika/test_pika_blocking_connection_consume.py +++ b/tests/messagebroker_pika/test_pika_blocking_connection_consume.py @@ -24,9 +24,10 @@ from conftest import QUEUE, EXCHANGE, CORRELATION_ID, REPLY_TO, HEADERS, BODY from testing_support.fixtures import (capture_transaction_metrics, - validate_transaction_metrics, validate_tt_collector_json) + validate_tt_collector_json) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from testing_support.db_settings import rabbitmq_settings +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics DB_SETTINGS = rabbitmq_settings()[0] diff --git a/tests/messagebroker_pika/test_pika_produce.py b/tests/messagebroker_pika/test_pika_produce.py index 60e6526e4..0960159fa 100644 --- a/tests/messagebroker_pika/test_pika_produce.py +++ b/tests/messagebroker_pika/test_pika_produce.py @@ -17,12 +17,12 @@ from testing_support.db_settings import rabbitmq_settings from testing_support.fixtures import ( override_application_settings, - validate_transaction_metrics, validate_tt_collector_json, ) from testing_support.validators.validate_messagebroker_headers import ( validate_messagebroker_headers, ) +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task from newrelic.api.transaction import current_transaction diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index 0d2f73c06..80122eeeb 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -638,60 +638,60 @@ def _capture_transaction_metrics(wrapped, instance, args, kwargs): # return _validate_wrapper -def validate_transaction_errors(errors=None, required_params=None, forgone_params=None): - errors = errors or [] - required_params = required_params or [] - forgone_params = forgone_params or [] - captured_errors = [] +# def validate_transaction_errors(errors=None, required_params=None, forgone_params=None): +# errors = errors or [] +# required_params = required_params or [] +# forgone_params = forgone_params or [] +# captured_errors = [] - @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") - @catch_background_exceptions - def _capture_transaction_errors(wrapped, instance, args, kwargs): - def _bind_params(transaction, *args, **kwargs): - return transaction +# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") +# @catch_background_exceptions +# def _capture_transaction_errors(wrapped, instance, args, kwargs): +# def _bind_params(transaction, *args, **kwargs): +# return transaction - transaction = _bind_params(*args, **kwargs) - captured = transaction.errors +# transaction = _bind_params(*args, **kwargs) +# captured = transaction.errors - captured_errors.append(captured) +# captured_errors.append(captured) - return wrapped(*args, **kwargs) +# return wrapped(*args, **kwargs) - @function_wrapper - def _validate_transaction_errors(wrapped, instance, args, kwargs): - _new_wrapped = _capture_transaction_errors(wrapped) - output = _new_wrapped(*args, **kwargs) +# @function_wrapper +# def _validate_transaction_errors(wrapped, instance, args, kwargs): +# _new_wrapped = _capture_transaction_errors(wrapped) +# output = _new_wrapped(*args, **kwargs) - expected = sorted(errors) +# expected = sorted(errors) - if captured_errors: - captured = captured_errors[0] - else: - captured = [] +# if captured_errors: +# captured = captured_errors[0] +# else: +# captured = [] - if errors and isinstance(errors[0], (tuple, list)): - compare_to = sorted([(e.type, e.message) for e in captured]) - else: - compare_to = sorted([e.type for e in captured]) +# if errors and isinstance(errors[0], (tuple, list)): +# compare_to = sorted([(e.type, e.message) for e in captured]) +# else: +# compare_to = sorted([e.type for e in captured]) - assert expected == compare_to, "expected=%r, captured=%r, errors=%r" % (expected, compare_to, captured) +# assert expected == compare_to, "expected=%r, captured=%r, errors=%r" % (expected, compare_to, captured) - for e in captured: - assert e.span_id - for name, value in required_params: - assert name in e.custom_params, "name=%r, params=%r" % (name, e.custom_params) - assert e.custom_params[name] == value, "name=%r, value=%r, params=%r" % ( - name, - value, - e.custom_params, - ) +# for e in captured: +# assert e.span_id +# for name, value in required_params: +# assert name in e.custom_params, "name=%r, params=%r" % (name, e.custom_params) +# assert e.custom_params[name] == value, "name=%r, value=%r, params=%r" % ( +# name, +# value, +# e.custom_params, +# ) - for name, value in forgone_params: - assert name not in e.custom_params, "name=%r, params=%r" % (name, e.custom_params) +# for name, value in forgone_params: +# assert name not in e.custom_params, "name=%r, params=%r" % (name, e.custom_params) - return output +# return output - return _validate_transaction_errors +# return _validate_transaction_errors def validate_application_errors(errors=None, required_params=None, forgone_params=None): diff --git a/tests/testing_support/validators/validate_transaction_errors.py b/tests/testing_support/validators/validate_transaction_errors.py new file mode 100644 index 000000000..b00b7facd --- /dev/null +++ b/tests/testing_support/validators/validate_transaction_errors.py @@ -0,0 +1,76 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import copy + +from newrelic.common.object_wrapper import ( + function_wrapper, + transient_function_wrapper, +) +from testing_support.fixtures import catch_background_exceptions + +def validate_transaction_errors(errors=None, required_params=None, forgone_params=None): + errors = errors or [] + required_params = required_params or [] + forgone_params = forgone_params or [] + captured_errors = [] + + @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") + @catch_background_exceptions + def _capture_transaction_errors(wrapped, instance, args, kwargs): + def _bind_params(transaction, *args, **kwargs): + return transaction + + transaction = _bind_params(*args, **kwargs) + captured = transaction.errors + + captured_errors.append(captured) + + return wrapped(*args, **kwargs) + + @function_wrapper + def _validate_transaction_errors(wrapped, instance, args, kwargs): + _new_wrapped = _capture_transaction_errors(wrapped) + output = _new_wrapped(*args, **kwargs) + + expected = sorted(errors) + + if captured_errors: + captured = captured_errors[0] + else: + captured = [] + + if errors and isinstance(errors[0], (tuple, list)): + compare_to = sorted([(e.type, e.message) for e in captured]) + else: + compare_to = sorted([e.type for e in captured]) + + assert expected == compare_to, "expected=%r, captured=%r, errors=%r" % (expected, compare_to, captured) + + for e in captured: + assert e.span_id + for name, value in required_params: + assert name in e.custom_params, "name=%r, params=%r" % (name, e.custom_params) + assert e.custom_params[name] == value, "name=%r, value=%r, params=%r" % ( + name, + value, + e.custom_params, + ) + + for name, value in forgone_params: + assert name not in e.custom_params, "name=%r, params=%r" % (name, e.custom_params) + + return output + + return _validate_transaction_errors From f20b9b56f883531441fdef69477a36d656e0045b Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Tue, 30 Aug 2022 17:22:38 -0700 Subject: [PATCH 06/23] Move validate_application_errors into validators directory --- tests/agent_features/test_notice_error.py | 2 +- tests/testing_support/fixtures.py | 56 +++++++++---------- .../validators/validate_application_errors.py | 56 +++++++++++++++++++ 3 files changed, 85 insertions(+), 29 deletions(-) create mode 100644 tests/testing_support/validators/validate_application_errors.py diff --git a/tests/agent_features/test_notice_error.py b/tests/agent_features/test_notice_error.py index b47335068..a4509e215 100644 --- a/tests/agent_features/test_notice_error.py +++ b/tests/agent_features/test_notice_error.py @@ -21,11 +21,11 @@ reset_core_stats_engine, validate_application_error_event_count, validate_application_error_trace_count, - validate_application_errors, validate_transaction_error_event_count, validate_transaction_error_trace_count, ) +from testing_support.validators.validate_application_errors import validate_application_errors from testing_support.validators.validate_transaction_errors import validate_transaction_errors from newrelic.api.application import application_instance as application from newrelic.api.application import application_settings diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index 80122eeeb..fc53fc895 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -694,44 +694,44 @@ def _capture_transaction_metrics(wrapped, instance, args, kwargs): # return _validate_transaction_errors -def validate_application_errors(errors=None, required_params=None, forgone_params=None): - errors = errors or [] - required_params = required_params or [] - forgone_params = forgone_params or [] +# def validate_application_errors(errors=None, required_params=None, forgone_params=None): +# errors = errors or [] +# required_params = required_params or [] +# forgone_params = forgone_params or [] - @function_wrapper - def _validate_application_errors(wrapped, instace, args, kwargs): +# @function_wrapper +# def _validate_application_errors(wrapped, instace, args, kwargs): - try: - result = wrapped(*args, **kwargs) - except: - raise - else: +# try: +# result = wrapped(*args, **kwargs) +# except: +# raise +# else: - stats = core_application_stats_engine() +# stats = core_application_stats_engine() - app_errors = stats.error_data() +# app_errors = stats.error_data() - expected = sorted(errors) - captured = sorted([(e.type, e.message) for e in stats.error_data()]) +# expected = sorted(errors) +# captured = sorted([(e.type, e.message) for e in stats.error_data()]) - assert expected == captured, "expected=%r, captured=%r, errors=%r" % (expected, captured, app_errors) +# assert expected == captured, "expected=%r, captured=%r, errors=%r" % (expected, captured, app_errors) - for e in app_errors: - for name, value in required_params: - assert name in e.parameters["userAttributes"], "name=%r, params=%r" % (name, e.parameters) - assert e.parameters["userAttributes"][name] == value, "name=%r, value=%r, params=%r" % ( - name, - value, - e.parameters, - ) +# for e in app_errors: +# for name, value in required_params: +# assert name in e.parameters["userAttributes"], "name=%r, params=%r" % (name, e.parameters) +# assert e.parameters["userAttributes"][name] == value, "name=%r, value=%r, params=%r" % ( +# name, +# value, +# e.parameters, +# ) - for name, value in forgone_params: - assert name not in e.parameters["userAttributes"], "name=%r, params=%r" % (name, e.parameters) +# for name, value in forgone_params: +# assert name not in e.parameters["userAttributes"], "name=%r, params=%r" % (name, e.parameters) - return result +# return result - return _validate_application_errors +# return _validate_application_errors def validate_custom_parameters(required_params=None, forgone_params=None): diff --git a/tests/testing_support/validators/validate_application_errors.py b/tests/testing_support/validators/validate_application_errors.py new file mode 100644 index 000000000..7f653d691 --- /dev/null +++ b/tests/testing_support/validators/validate_application_errors.py @@ -0,0 +1,56 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from newrelic.common.object_wrapper import function_wrapper +from testing_support.fixtures import core_application_stats_engine + +def validate_application_errors(errors=None, required_params=None, forgone_params=None): + errors = errors or [] + required_params = required_params or [] + forgone_params = forgone_params or [] + + @function_wrapper + def _validate_application_errors(wrapped, instace, args, kwargs): + + try: + result = wrapped(*args, **kwargs) + except: + raise + else: + + stats = core_application_stats_engine() + + app_errors = stats.error_data() + + expected = sorted(errors) + captured = sorted([(e.type, e.message) for e in stats.error_data()]) + + assert expected == captured, "expected=%r, captured=%r, errors=%r" % (expected, captured, app_errors) + + for e in app_errors: + for name, value in required_params: + assert name in e.parameters["userAttributes"], "name=%r, params=%r" % (name, e.parameters) + assert e.parameters["userAttributes"][name] == value, "name=%r, value=%r, params=%r" % ( + name, + value, + e.parameters, + ) + + for name, value in forgone_params: + assert name not in e.parameters["userAttributes"], "name=%r, params=%r" % (name, e.parameters) + + return result + + return _validate_application_errors From 5efcfa80f6a13ec5367859906d7d80739be70124 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Tue, 30 Aug 2022 17:27:09 -0700 Subject: [PATCH 07/23] Move validate_custom_parameters into validators directory --- tests/agent_features/test_asgi_browser.py | 4 +- tests/agent_features/test_attribute.py | 4 +- tests/agent_features/test_browser.py | 4 +- .../agent_features/test_high_security_mode.py | 2 +- tests/testing_support/fixtures.py | 44 ++++++++--------- .../validators/validate_custom_parameters.py | 48 +++++++++++++++++++ 6 files changed, 77 insertions(+), 29 deletions(-) create mode 100644 tests/testing_support/validators/validate_custom_parameters.py diff --git a/tests/agent_features/test_asgi_browser.py b/tests/agent_features/test_asgi_browser.py index ef21d7a0b..379f6752c 100644 --- a/tests/agent_features/test_asgi_browser.py +++ b/tests/agent_features/test_asgi_browser.py @@ -18,10 +18,10 @@ import pytest import six -from testing_support.fixtures import (override_application_settings, - validate_custom_parameters) +from testing_support.fixtures import override_application_settings from testing_support.asgi_testing import AsgiTest from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_custom_parameters import validate_custom_parameters from newrelic.api.application import application_settings from newrelic.api.transaction import (get_browser_timing_header, get_browser_timing_footer, add_custom_parameter, diff --git a/tests/agent_features/test_attribute.py b/tests/agent_features/test_attribute.py index edfffae2f..985cf1f81 100644 --- a/tests/agent_features/test_attribute.py +++ b/tests/agent_features/test_attribute.py @@ -27,9 +27,9 @@ from testing_support.fixtures import (override_application_settings, validate_attributes, validate_attributes_complete, - validate_custom_parameters, validate_agent_attribute_types) + validate_agent_attribute_types) from testing_support.sample_applications import fully_featured_app - +from testing_support.validators.validate_custom_parameters import validate_custom_parameters # Python 3 lacks longs diff --git a/tests/agent_features/test_browser.py b/tests/agent_features/test_browser.py index 98ad22192..944d649ac 100644 --- a/tests/agent_features/test_browser.py +++ b/tests/agent_features/test_browser.py @@ -18,9 +18,9 @@ import six -from testing_support.fixtures import (override_application_settings, - validate_custom_parameters) +from testing_support.fixtures import override_application_settings from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_custom_parameters import validate_custom_parameters from newrelic.api.application import application_settings from newrelic.api.transaction import (get_browser_timing_header, get_browser_timing_footer, add_custom_parameter, diff --git a/tests/agent_features/test_high_security_mode.py b/tests/agent_features/test_high_security_mode.py index fd6065b91..3f6dbdef0 100644 --- a/tests/agent_features/test_high_security_mode.py +++ b/tests/agent_features/test_high_security_mode.py @@ -24,11 +24,11 @@ validate_attributes_complete, validate_custom_event_count, validate_custom_event_in_application_stats_engine, - validate_custom_parameters, validate_non_transaction_error_event, validate_request_params_omitted, validate_tt_segment_params, ) +from testing_support.validators.validate_custom_parameters import validate_custom_parameters from testing_support.validators.validate_transaction_errors import validate_transaction_errors from newrelic.api.application import application_instance as application from newrelic.api.background_task import background_task diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index fc53fc895..000804d92 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -734,36 +734,36 @@ def _capture_transaction_metrics(wrapped, instance, args, kwargs): # return _validate_application_errors -def validate_custom_parameters(required_params=None, forgone_params=None): - required_params = required_params or [] - forgone_params = forgone_params or [] +# def validate_custom_parameters(required_params=None, forgone_params=None): +# required_params = required_params or [] +# forgone_params = forgone_params or [] - @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") - @catch_background_exceptions - def _validate_custom_parameters(wrapped, instance, args, kwargs): - def _bind_params(transaction, *args, **kwargs): - return transaction +# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") +# @catch_background_exceptions +# def _validate_custom_parameters(wrapped, instance, args, kwargs): +# def _bind_params(transaction, *args, **kwargs): +# return transaction - transaction = _bind_params(*args, **kwargs) +# transaction = _bind_params(*args, **kwargs) - # these are pre-destination applied attributes, so they may not - # actually end up in a transaction/error trace, we are merely testing - # for presence on the TransactionNode +# # these are pre-destination applied attributes, so they may not +# # actually end up in a transaction/error trace, we are merely testing +# # for presence on the TransactionNode - attrs = {} - for attr in transaction.user_attributes: - attrs[attr.name] = attr.value +# attrs = {} +# for attr in transaction.user_attributes: +# attrs[attr.name] = attr.value - for name, value in required_params: - assert name in attrs, "name=%r, params=%r" % (name, attrs) - assert attrs[name] == value, "name=%r, value=%r, params=%r" % (name, value, attrs) +# for name, value in required_params: +# assert name in attrs, "name=%r, params=%r" % (name, attrs) +# assert attrs[name] == value, "name=%r, value=%r, params=%r" % (name, value, attrs) - for name, value in forgone_params: - assert name not in attrs, "name=%r, params=%r" % (name, attrs) +# for name, value in forgone_params: +# assert name not in attrs, "name=%r, params=%r" % (name, attrs) - return wrapped(*args, **kwargs) +# return wrapped(*args, **kwargs) - return _validate_custom_parameters +# return _validate_custom_parameters def validate_synthetics_event(required_attrs=None, forgone_attrs=None, should_exist=True): diff --git a/tests/testing_support/validators/validate_custom_parameters.py b/tests/testing_support/validators/validate_custom_parameters.py new file mode 100644 index 000000000..9dc92fb12 --- /dev/null +++ b/tests/testing_support/validators/validate_custom_parameters.py @@ -0,0 +1,48 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from newrelic.common.object_wrapper import transient_function_wrapper +from testing_support.fixtures import catch_background_exceptions + + +def validate_custom_parameters(required_params=None, forgone_params=None): + required_params = required_params or [] + forgone_params = forgone_params or [] + + @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") + @catch_background_exceptions + def _validate_custom_parameters(wrapped, instance, args, kwargs): + def _bind_params(transaction, *args, **kwargs): + return transaction + + transaction = _bind_params(*args, **kwargs) + + # these are pre-destination applied attributes, so they may not + # actually end up in a transaction/error trace, we are merely testing + # for presence on the TransactionNode + + attrs = {} + for attr in transaction.user_attributes: + attrs[attr.name] = attr.value + + for name, value in required_params: + assert name in attrs, "name=%r, params=%r" % (name, attrs) + assert attrs[name] == value, "name=%r, value=%r, params=%r" % (name, value, attrs) + + for name, value in forgone_params: + assert name not in attrs, "name=%r, params=%r" % (name, attrs) + + return wrapped(*args, **kwargs) + + return _validate_custom_parameters \ No newline at end of file From 76ee5a4b43059eaac77a9eb4c8036c5928f9fb57 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Tue, 30 Aug 2022 17:36:16 -0700 Subject: [PATCH 08/23] Move validate_synthetics_event into validators directory --- tests/agent_features/test_synthetics.py | 2 +- tests/testing_support/fixtures.py | 80 +++++++++---------- .../validators/validate_synthetics_event.py | 71 ++++++++++++++++ 3 files changed, 112 insertions(+), 41 deletions(-) create mode 100644 tests/testing_support/validators/validate_synthetics_event.py diff --git a/tests/agent_features/test_synthetics.py b/tests/agent_features/test_synthetics.py index cdf02e3e4..ec7b78e96 100644 --- a/tests/agent_features/test_synthetics.py +++ b/tests/agent_features/test_synthetics.py @@ -19,10 +19,10 @@ cat_enabled, make_synthetics_header, override_application_settings, - validate_synthetics_event, validate_synthetics_transaction_trace, ) +from testing_support.validators.validate_synthetics_event import validate_synthetics_event from newrelic.api.web_transaction import web_transaction from newrelic.api.wsgi_application import wsgi_application from newrelic.common.encoding_utils import deobfuscate, json_decode diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index 000804d92..ed83244e3 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -766,56 +766,56 @@ def _capture_transaction_metrics(wrapped, instance, args, kwargs): # return _validate_custom_parameters -def validate_synthetics_event(required_attrs=None, forgone_attrs=None, should_exist=True): - required_attrs = required_attrs or [] - forgone_attrs = forgone_attrs or [] - failed = [] +# def validate_synthetics_event(required_attrs=None, forgone_attrs=None, should_exist=True): +# required_attrs = required_attrs or [] +# forgone_attrs = forgone_attrs or [] +# failed = [] - @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") - def _validate_synthetics_event(wrapped, instance, args, kwargs): - result = wrapped(*args, **kwargs) +# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") +# def _validate_synthetics_event(wrapped, instance, args, kwargs): +# result = wrapped(*args, **kwargs) - try: - if not should_exist: - assert instance.synthetics_events == [] - else: - assert len(instance.synthetics_events) == 1 - event = instance.synthetics_events[0] - assert event is not None - assert len(event) == 3 +# try: +# if not should_exist: +# assert instance.synthetics_events == [] +# else: +# assert len(instance.synthetics_events) == 1 +# event = instance.synthetics_events[0] +# assert event is not None +# assert len(event) == 3 - def _flatten(event): - result = {} - for elem in event: - for k, v in elem.items(): - result[k] = v - return result +# def _flatten(event): +# result = {} +# for elem in event: +# for k, v in elem.items(): +# result[k] = v +# return result - flat_event = _flatten(event) +# flat_event = _flatten(event) - assert "nr.guid" in flat_event, "name=%r, event=%r" % ("nr.guid", flat_event) +# assert "nr.guid" in flat_event, "name=%r, event=%r" % ("nr.guid", flat_event) - for name, value in required_attrs: - assert name in flat_event, "name=%r, event=%r" % (name, flat_event) - assert flat_event[name] == value, "name=%r, value=%r, event=%r" % (name, value, flat_event) +# for name, value in required_attrs: +# assert name in flat_event, "name=%r, event=%r" % (name, flat_event) +# assert flat_event[name] == value, "name=%r, value=%r, event=%r" % (name, value, flat_event) - for name, value in forgone_attrs: - assert name not in flat_event, "name=%r, value=%r, event=%r" % (name, value, flat_event) - except Exception as e: - failed.append(e) +# for name, value in forgone_attrs: +# assert name not in flat_event, "name=%r, value=%r, event=%r" % (name, value, flat_event) +# except Exception as e: +# failed.append(e) - return result +# return result - @function_wrapper - def wrapper(wrapped, instance, args, kwargs): - _new_wrapper = _validate_synthetics_event(wrapped) - result = _new_wrapper(*args, **kwargs) - if failed: - e = failed.pop() - raise e - return result +# @function_wrapper +# def wrapper(wrapped, instance, args, kwargs): +# _new_wrapper = _validate_synthetics_event(wrapped) +# result = _new_wrapper(*args, **kwargs) +# if failed: +# e = failed.pop() +# raise e +# return result - return wrapper +# return wrapper def validate_transaction_event_attributes(required_params=None, forgone_params=None, exact_attrs=None, index=-1): diff --git a/tests/testing_support/validators/validate_synthetics_event.py b/tests/testing_support/validators/validate_synthetics_event.py new file mode 100644 index 000000000..221cf7e6e --- /dev/null +++ b/tests/testing_support/validators/validate_synthetics_event.py @@ -0,0 +1,71 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from newrelic.common.object_wrapper import ( + function_wrapper, + transient_function_wrapper, +) + +def validate_synthetics_event(required_attrs=None, forgone_attrs=None, should_exist=True): + required_attrs = required_attrs or [] + forgone_attrs = forgone_attrs or [] + failed = [] + + @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") + def _validate_synthetics_event(wrapped, instance, args, kwargs): + result = wrapped(*args, **kwargs) + + try: + if not should_exist: + assert instance.synthetics_events == [] + else: + assert len(instance.synthetics_events) == 1 + event = instance.synthetics_events[0] + assert event is not None + assert len(event) == 3 + + def _flatten(event): + result = {} + for elem in event: + for k, v in elem.items(): + result[k] = v + return result + + flat_event = _flatten(event) + + assert "nr.guid" in flat_event, "name=%r, event=%r" % ("nr.guid", flat_event) + + for name, value in required_attrs: + assert name in flat_event, "name=%r, event=%r" % (name, flat_event) + assert flat_event[name] == value, "name=%r, value=%r, event=%r" % (name, value, flat_event) + + for name, value in forgone_attrs: + assert name not in flat_event, "name=%r, value=%r, event=%r" % (name, value, flat_event) + except Exception as e: + failed.append(e) + + return result + + @function_wrapper + def wrapper(wrapped, instance, args, kwargs): + _new_wrapper = _validate_synthetics_event(wrapped) + result = _new_wrapper(*args, **kwargs) + if failed: + e = failed.pop() + raise e + return result + + return wrapper + From f47c397013e069a214b70adecc3c4a545aed0753 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Wed, 31 Aug 2022 16:37:35 -0700 Subject: [PATCH 09/23] Move validate_transaction_event_attributes into validators directory --- .../test_asgi_w3c_trace_context.py | 5 +- .../test_distributed_tracing.py | 3 +- .../agent_features/test_w3c_trace_context.py | 4 +- tests/cross_agent/test_distributed_tracing.py | 2 +- tests/cross_agent/test_lambda_event_source.py | 4 +- tests/cross_agent/test_w3c_trace_context.py | 2 +- tests/framework_aiohttp/test_server.py | 2 +- tests/framework_grpc/test_server.py | 3 +- tests/framework_tornado/test_inbound_cat.py | 3 +- tests/testing_support/fixtures.py | 50 ++++++++--------- .../validate_transaction_event_attributes.py | 53 +++++++++++++++++++ 11 files changed, 93 insertions(+), 38 deletions(-) create mode 100644 tests/testing_support/validators/validate_transaction_event_attributes.py diff --git a/tests/agent_features/test_asgi_w3c_trace_context.py b/tests/agent_features/test_asgi_w3c_trace_context.py index 234e08409..8cec2eb7a 100644 --- a/tests/agent_features/test_asgi_w3c_trace_context.py +++ b/tests/agent_features/test_asgi_w3c_trace_context.py @@ -19,12 +19,11 @@ from newrelic.api.asgi_application import asgi_application from testing_support.asgi_testing import AsgiTest -from testing_support.fixtures import (override_application_settings, - validate_transaction_event_attributes) +from testing_support.fixtures import override_application_settings from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_span_events import ( validate_span_events) - +from testing_support.validators.validate_transaction_event_attributes import validate_transaction_event_attributes @asgi_application() async def target_asgi_application(scope, receive, send): diff --git a/tests/agent_features/test_distributed_tracing.py b/tests/agent_features/test_distributed_tracing.py index aed7de100..7f795573a 100644 --- a/tests/agent_features/test_distributed_tracing.py +++ b/tests/agent_features/test_distributed_tracing.py @@ -26,9 +26,10 @@ from newrelic.api.wsgi_application import wsgi_application from testing_support.fixtures import (override_application_settings, - validate_attributes, validate_transaction_event_attributes, + validate_attributes, validate_error_event_attributes) from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_event_attributes import validate_transaction_event_attributes distributed_trace_intrinsics = ['guid', 'traceId', 'priority', 'sampled'] inbound_payload_intrinsics = ['parent.type', 'parent.app', 'parent.account', diff --git a/tests/agent_features/test_w3c_trace_context.py b/tests/agent_features/test_w3c_trace_context.py index 7143e0f46..726cf011a 100644 --- a/tests/agent_features/test_w3c_trace_context.py +++ b/tests/agent_features/test_w3c_trace_context.py @@ -19,11 +19,11 @@ from newrelic.api.transaction import current_transaction from newrelic.api.external_trace import ExternalTrace from newrelic.api.wsgi_application import wsgi_application -from testing_support.fixtures import (override_application_settings, - validate_transaction_event_attributes) +from testing_support.fixtures import override_application_settings from testing_support.validators.validate_span_events import ( validate_span_events) from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_event_attributes import validate_transaction_event_attributes @wsgi_application() def target_wsgi_application(environ, start_response): diff --git a/tests/cross_agent/test_distributed_tracing.py b/tests/cross_agent/test_distributed_tracing.py index 7b0be1ca2..0ff46eea2 100644 --- a/tests/cross_agent/test_distributed_tracing.py +++ b/tests/cross_agent/test_distributed_tracing.py @@ -23,11 +23,11 @@ from newrelic.common.object_wrapper import transient_function_wrapper from testing_support.fixtures import (override_application_settings, - validate_transaction_event_attributes, validate_error_event_attributes, validate_attributes) from testing_support.validators.validate_span_events import ( validate_span_events) from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_event_attributes import validate_transaction_event_attributes CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) JSON_DIR = os.path.normpath(os.path.join(CURRENT_DIR, 'fixtures', diff --git a/tests/cross_agent/test_lambda_event_source.py b/tests/cross_agent/test_lambda_event_source.py index 3a90aec58..511294cf6 100644 --- a/tests/cross_agent/test_lambda_event_source.py +++ b/tests/cross_agent/test_lambda_event_source.py @@ -17,8 +17,8 @@ import pytest from newrelic.api.lambda_handler import lambda_handler -from testing_support.fixtures import (override_application_settings, - validate_transaction_event_attributes) +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_event_attributes import validate_transaction_event_attributes CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) FIXTURE_DIR = os.path.normpath(os.path.join(CURRENT_DIR, 'fixtures')) diff --git a/tests/cross_agent/test_w3c_trace_context.py b/tests/cross_agent/test_w3c_trace_context.py index efc13c25d..05f157f7b 100644 --- a/tests/cross_agent/test_w3c_trace_context.py +++ b/tests/cross_agent/test_w3c_trace_context.py @@ -24,10 +24,10 @@ from testing_support.validators.validate_span_events import ( validate_span_events) from testing_support.fixtures import (override_application_settings, - validate_transaction_event_attributes, validate_attributes) from newrelic.common.encoding_utils import W3CTraceState from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_event_attributes import validate_transaction_event_attributes CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) JSON_DIR = os.path.normpath(os.path.join(CURRENT_DIR, 'fixtures', diff --git a/tests/framework_aiohttp/test_server.py b/tests/framework_aiohttp/test_server.py index 4f0347df1..ac7cd7d31 100644 --- a/tests/framework_aiohttp/test_server.py +++ b/tests/framework_aiohttp/test_server.py @@ -18,12 +18,12 @@ from newrelic.core.config import global_settings from testing_support.fixtures import ( - validate_transaction_event_attributes, count_transactions, override_generic_settings, override_application_settings, override_ignore_status_codes) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_event_attributes import validate_transaction_event_attributes version_info = tuple(int(_) for _ in aiohttp.__version__.split('.')[:2]) diff --git a/tests/framework_grpc/test_server.py b/tests/framework_grpc/test_server.py index 92ec9c4b3..534d78005 100644 --- a/tests/framework_grpc/test_server.py +++ b/tests/framework_grpc/test_server.py @@ -19,11 +19,12 @@ from _test_common import create_request, wait_for_transaction_completion from newrelic.core.config import global_settings from testing_support.fixtures import ( - validate_transaction_event_attributes, override_application_settings, + override_application_settings, override_generic_settings, function_not_called) from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_transaction_event_attributes import validate_transaction_event_attributes def select_python_version(py2, py3): return six.PY3 and py3 or py2 diff --git a/tests/framework_tornado/test_inbound_cat.py b/tests/framework_tornado/test_inbound_cat.py index c399f70d5..44fbf2933 100644 --- a/tests/framework_tornado/test_inbound_cat.py +++ b/tests/framework_tornado/test_inbound_cat.py @@ -15,8 +15,9 @@ import json import pytest from testing_support.fixtures import (make_cross_agent_headers, - override_application_settings, validate_transaction_event_attributes) + override_application_settings) from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_event_attributes import validate_transaction_event_attributes ENCODING_KEY = '1234567890123456789012345678901234567890' diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index ed83244e3..b6cbcf102 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -818,38 +818,38 @@ def _capture_transaction_metrics(wrapped, instance, args, kwargs): # return wrapper -def validate_transaction_event_attributes(required_params=None, forgone_params=None, exact_attrs=None, index=-1): - required_params = required_params or {} - forgone_params = forgone_params or {} - exact_attrs = exact_attrs or {} +# def validate_transaction_event_attributes(required_params=None, forgone_params=None, exact_attrs=None, index=-1): +# required_params = required_params or {} +# forgone_params = forgone_params or {} +# exact_attrs = exact_attrs or {} - captured_events = [] +# captured_events = [] - @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") - def _capture_transaction_events(wrapped, instance, args, kwargs): - try: - result = wrapped(*args, **kwargs) - except: - raise - else: - event_data = instance.transaction_events - captured_events.append(event_data) - return result +# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") +# def _capture_transaction_events(wrapped, instance, args, kwargs): +# try: +# result = wrapped(*args, **kwargs) +# except: +# raise +# else: +# event_data = instance.transaction_events +# captured_events.append(event_data) +# return result - @function_wrapper - def _validate_transaction_event_attributes(wrapped, instance, args, kwargs): - _new_wrapper = _capture_transaction_events(wrapped) - result = _new_wrapper(*args, **kwargs) +# @function_wrapper +# def _validate_transaction_event_attributes(wrapped, instance, args, kwargs): +# _new_wrapper = _capture_transaction_events(wrapped) +# result = _new_wrapper(*args, **kwargs) - assert captured_events, "No events captured" - event_data = captured_events[index] - captured_events[:] = [] +# assert captured_events, "No events captured" +# event_data = captured_events[index] +# captured_events[:] = [] - check_event_attributes(event_data, required_params, forgone_params, exact_attrs) +# check_event_attributes(event_data, required_params, forgone_params, exact_attrs) - return result +# return result - return _validate_transaction_event_attributes +# return _validate_transaction_event_attributes def check_event_attributes(event_data, required_params=None, forgone_params=None, exact_attrs=None): diff --git a/tests/testing_support/validators/validate_transaction_event_attributes.py b/tests/testing_support/validators/validate_transaction_event_attributes.py new file mode 100644 index 000000000..7ef8c0629 --- /dev/null +++ b/tests/testing_support/validators/validate_transaction_event_attributes.py @@ -0,0 +1,53 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from newrelic.common.object_wrapper import ( + function_wrapper, + transient_function_wrapper, +) +from testing_support.fixtures import check_event_attributes + +def validate_transaction_event_attributes(required_params=None, forgone_params=None, exact_attrs=None, index=-1): + required_params = required_params or {} + forgone_params = forgone_params or {} + exact_attrs = exact_attrs or {} + + captured_events = [] + + @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") + def _capture_transaction_events(wrapped, instance, args, kwargs): + try: + result = wrapped(*args, **kwargs) + except: + raise + else: + event_data = instance.transaction_events + captured_events.append(event_data) + return result + + @function_wrapper + def _validate_transaction_event_attributes(wrapped, instance, args, kwargs): + _new_wrapper = _capture_transaction_events(wrapped) + result = _new_wrapper(*args, **kwargs) + + assert captured_events, "No events captured" + event_data = captured_events[index] + captured_events[:] = [] + + check_event_attributes(event_data, required_params, forgone_params, exact_attrs) + + return result + + return _validate_transaction_event_attributes \ No newline at end of file From f3423dbfba001ee40bae06376a4b4778d79755e1 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Tue, 6 Sep 2022 12:58:48 -0700 Subject: [PATCH 10/23] Move validate_non_transaction_error_event into validators directory --- tests/agent_features/test_error_events.py | 4 +- .../agent_features/test_high_security_mode.py | 13 ++- tests/testing_support/fixtures.py | 108 +++++++++--------- .../validate_non_transaction_error_event.py | 71 ++++++++++++ 4 files changed, 139 insertions(+), 57 deletions(-) create mode 100644 tests/testing_support/validators/validate_non_transaction_error_event.py diff --git a/tests/agent_features/test_error_events.py b/tests/agent_features/test_error_events.py index d93f9908b..99b3935be 100644 --- a/tests/agent_features/test_error_events.py +++ b/tests/agent_features/test_error_events.py @@ -23,10 +23,12 @@ override_application_settings, reset_core_stats_engine, validate_error_event_sample_data, - validate_non_transaction_error_event, validate_transaction_error_event_count, ) from testing_support.sample_applications import fully_featured_app +from testing_support.validators.validate_non_transaction_error_event import ( + validate_non_transaction_error_event, +) from newrelic.api.application import application_instance as application from newrelic.api.application import application_settings diff --git a/tests/agent_features/test_high_security_mode.py b/tests/agent_features/test_high_security_mode.py index 3f6dbdef0..6c093d151 100644 --- a/tests/agent_features/test_high_security_mode.py +++ b/tests/agent_features/test_high_security_mode.py @@ -24,12 +24,19 @@ validate_attributes_complete, validate_custom_event_count, validate_custom_event_in_application_stats_engine, - validate_non_transaction_error_event, validate_request_params_omitted, validate_tt_segment_params, ) -from testing_support.validators.validate_custom_parameters import validate_custom_parameters -from testing_support.validators.validate_transaction_errors import validate_transaction_errors +from testing_support.validators.validate_custom_parameters import ( + validate_custom_parameters, +) +from testing_support.validators.validate_non_transaction_error_event import ( + validate_non_transaction_error_event, +) +from testing_support.validators.validate_transaction_errors import ( + validate_transaction_errors, +) + from newrelic.api.application import application_instance as application from newrelic.api.background_task import background_task from newrelic.api.function_trace import FunctionTrace diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index b6cbcf102..bd90d2c50 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -65,8 +65,9 @@ ) from newrelic.core.config import apply_config_setting, flatten_settings, global_settings from newrelic.core.database_utils import SQLConnections -#from newrelic.core.internal_metrics import InternalTraceContext -#from newrelic.core.stats_engine import CustomMetrics + +# from newrelic.core.internal_metrics import InternalTraceContext +# from newrelic.core.stats_engine import CustomMetrics from newrelic.network.exceptions import RetryDataForRequest from newrelic.packages import six @@ -889,56 +890,56 @@ def check_event_attributes(event_data, required_params=None, forgone_params=None assert intrinsics[param] == value, ((param, value), intrinsics) -def validate_non_transaction_error_event(required_intrinsics=None, num_errors=1, required_user=None, forgone_user=None): - """Validate error event data for a single error occurring outside of a - transaction. - """ - required_intrinsics = required_intrinsics or {} - required_user = required_user or {} - forgone_user = forgone_user or [] +# def validate_non_transaction_error_event(required_intrinsics=None, num_errors=1, required_user=None, forgone_user=None): +# """Validate error event data for a single error occurring outside of a +# transaction. +# """ +# required_intrinsics = required_intrinsics or {} +# required_user = required_user or {} +# forgone_user = forgone_user or [] - @function_wrapper - def _validate_non_transaction_error_event(wrapped, instace, args, kwargs): +# @function_wrapper +# def _validate_non_transaction_error_event(wrapped, instace, args, kwargs): - try: - result = wrapped(*args, **kwargs) - except: - raise - else: +# try: +# result = wrapped(*args, **kwargs) +# except: +# raise +# else: - stats = core_application_stats_engine(None) +# stats = core_application_stats_engine(None) - assert stats.error_events.num_seen == num_errors - for event in stats.error_events: +# assert stats.error_events.num_seen == num_errors +# for event in stats.error_events: - assert len(event) == 3 # [intrinsic, user, agent attributes] +# assert len(event) == 3 # [intrinsic, user, agent attributes] - intrinsics = event[0] +# intrinsics = event[0] - # The following attributes are all required, and also the only - # intrinsic attributes that can be included in an error event - # recorded outside of a transaction +# # The following attributes are all required, and also the only +# # intrinsic attributes that can be included in an error event +# # recorded outside of a transaction - assert intrinsics["type"] == "TransactionError" - assert intrinsics["transactionName"] is None - assert intrinsics["error.class"] == required_intrinsics["error.class"] - assert intrinsics["error.message"].startswith(required_intrinsics["error.message"]) - assert intrinsics["error.expected"] == required_intrinsics["error.expected"] - now = time.time() - assert isinstance(intrinsics["timestamp"], int) - assert intrinsics["timestamp"] <= 1000.0 * now - - user_params = event[1] - for name, value in required_user.items(): - assert name in user_params, "name=%r, params=%r" % (name, user_params) - assert user_params[name] == value, "name=%r, value=%r, params=%r" % (name, value, user_params) - - for param in forgone_user: - assert param not in user_params +# assert intrinsics["type"] == "TransactionError" +# assert intrinsics["transactionName"] is None +# assert intrinsics["error.class"] == required_intrinsics["error.class"] +# assert intrinsics["error.message"].startswith(required_intrinsics["error.message"]) +# assert intrinsics["error.expected"] == required_intrinsics["error.expected"] +# now = time.time() +# assert isinstance(intrinsics["timestamp"], int) +# assert intrinsics["timestamp"] <= 1000.0 * now - return result +# user_params = event[1] +# for name, value in required_user.items(): +# assert name in user_params, "name=%r, params=%r" % (name, user_params) +# assert user_params[name] == value, "name=%r, value=%r, params=%r" % (name, value, user_params) + +# for param in forgone_user: +# assert param not in user_params - return _validate_non_transaction_error_event +# return result + +# return _validate_non_transaction_error_event def validate_application_error_trace_count(num_errors): @@ -2434,25 +2435,25 @@ def _override_ignore_status_codes(wrapped, instance, args, kwargs): return _override_ignore_status_codes -def code_coverage_fixture(source=['newrelic']): - @pytest.fixture(scope='session') +def code_coverage_fixture(source=["newrelic"]): + @pytest.fixture(scope="session") def _code_coverage_fixture(request): if not source: return - if os.environ.get('GITHUB_ACTIONS') is not None: + if os.environ.get("GITHUB_ACTIONS") is not None: return from coverage import coverage - env_directory = os.environ.get('TOX_ENVDIR', None) + env_directory = os.environ.get("TOX_ENVDIR", None) if env_directory is not None: - coverage_directory = os.path.join(env_directory, 'htmlcov') - xml_report = os.path.join(env_directory, 'coverage.xml') + coverage_directory = os.path.join(env_directory, "htmlcov") + xml_report = os.path.join(env_directory, "coverage.xml") else: - coverage_directory = 'htmlcov' - xml_report = 'coverage.xml' + coverage_directory = "htmlcov" + xml_report = "coverage.xml" def finalize(): cov.stop() @@ -2469,18 +2470,19 @@ def finalize(): def reset_core_stats_engine(): """Reset the StatsEngine and custom StatsEngine of the core application.""" + @function_wrapper def _reset_core_stats_engine(wrapped, instance, args, kwargs): api_application = application_instance() api_name = api_application.name core_application = api_application._agent.application(api_name) - + stats = core_application._stats_engine stats.reset_stats(stats.settings) - + custom_stats = core_application._stats_custom_engine custom_stats.reset_stats(custom_stats.settings) - + return wrapped(*args, **kwargs) return _reset_core_stats_engine diff --git a/tests/testing_support/validators/validate_non_transaction_error_event.py b/tests/testing_support/validators/validate_non_transaction_error_event.py new file mode 100644 index 000000000..dc97d7a42 --- /dev/null +++ b/tests/testing_support/validators/validate_non_transaction_error_event.py @@ -0,0 +1,71 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from time import time + +from testing_support.fixtures import core_application_stats_engine + +from newrelic.common.object_wrapper import function_wrapper + + +def validate_non_transaction_error_event(required_intrinsics=None, num_errors=1, required_user=None, forgone_user=None): + """Validate error event data for a single error occurring outside of a + transaction. + """ + required_intrinsics = required_intrinsics or {} + required_user = required_user or {} + forgone_user = forgone_user or [] + + @function_wrapper + def _validate_non_transaction_error_event(wrapped, instace, args, kwargs): + + try: + result = wrapped(*args, **kwargs) + except: + raise + else: + + stats = core_application_stats_engine(None) + + assert stats.error_events.num_seen == num_errors + for event in stats.error_events: + + assert len(event) == 3 # [intrinsic, user, agent attributes] + + intrinsics = event[0] + + # The following attributes are all required, and also the only + # intrinsic attributes that can be included in an error event + # recorded outside of a transaction + + assert intrinsics["type"] == "TransactionError" + assert intrinsics["transactionName"] is None + assert intrinsics["error.class"] == required_intrinsics["error.class"] + assert intrinsics["error.message"].startswith(required_intrinsics["error.message"]) + assert intrinsics["error.expected"] == required_intrinsics["error.expected"] + now = time.time() + assert isinstance(intrinsics["timestamp"], int) + assert intrinsics["timestamp"] <= 1000.0 * now + + user_params = event[1] + for name, value in required_user.items(): + assert name in user_params, "name=%r, params=%r" % (name, user_params) + assert user_params[name] == value, "name=%r, value=%r, params=%r" % (name, value, user_params) + + for param in forgone_user: + assert param not in user_params + + return result + + return _validate_non_transaction_error_event From 1bbb0471e26ec289642c1cb041aa0a3fb5d7311e Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Tue, 6 Sep 2022 13:03:41 -0700 Subject: [PATCH 11/23] Move validate_application_error_trace_count into validators directory --- tests/agent_features/test_notice_error.py | 12 ++++-- tests/testing_support/fixtures.py | 30 +++++++------- .../validate_application_error_trace_count.py | 39 +++++++++++++++++++ 3 files changed, 63 insertions(+), 18 deletions(-) create mode 100644 tests/testing_support/validators/validate_application_error_trace_count.py diff --git a/tests/agent_features/test_notice_error.py b/tests/agent_features/test_notice_error.py index a4509e215..1bdcb3419 100644 --- a/tests/agent_features/test_notice_error.py +++ b/tests/agent_features/test_notice_error.py @@ -20,13 +20,19 @@ override_application_settings, reset_core_stats_engine, validate_application_error_event_count, - validate_application_error_trace_count, validate_transaction_error_event_count, validate_transaction_error_trace_count, ) +from testing_support.validators.validate_application_error_trace_count import ( + validate_application_error_trace_count, +) +from testing_support.validators.validate_application_errors import ( + validate_application_errors, +) +from testing_support.validators.validate_transaction_errors import ( + validate_transaction_errors, +) -from testing_support.validators.validate_application_errors import validate_application_errors -from testing_support.validators.validate_transaction_errors import validate_transaction_errors from newrelic.api.application import application_instance as application from newrelic.api.application import application_settings from newrelic.api.background_task import background_task diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index bd90d2c50..493d1a7c5 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -942,26 +942,26 @@ def check_event_attributes(event_data, required_params=None, forgone_params=None # return _validate_non_transaction_error_event -def validate_application_error_trace_count(num_errors): - """Validate error event data for a single error occurring outside of a - transaction. - """ +# def validate_application_error_trace_count(num_errors): +# """Validate error event data for a single error occurring outside of a +# transaction. +# """ - @function_wrapper - def _validate_application_error_trace_count(wrapped, instace, args, kwargs): +# @function_wrapper +# def _validate_application_error_trace_count(wrapped, instace, args, kwargs): - try: - result = wrapped(*args, **kwargs) - except: - raise - else: +# try: +# result = wrapped(*args, **kwargs) +# except: +# raise +# else: - stats = core_application_stats_engine(None) - assert len(stats.error_data()) == num_errors +# stats = core_application_stats_engine(None) +# assert len(stats.error_data()) == num_errors - return result +# return result - return _validate_application_error_trace_count +# return _validate_application_error_trace_count def validate_application_error_event_count(num_errors): diff --git a/tests/testing_support/validators/validate_application_error_trace_count.py b/tests/testing_support/validators/validate_application_error_trace_count.py new file mode 100644 index 000000000..d700ea5eb --- /dev/null +++ b/tests/testing_support/validators/validate_application_error_trace_count.py @@ -0,0 +1,39 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from testing_support.fixtures import core_application_stats_engine + +from newrelic.common.object_wrapper import function_wrapper + + +def validate_application_error_trace_count(num_errors): + """Validate error event data for a single error occurring outside of a + transaction. + """ + + @function_wrapper + def _validate_application_error_trace_count(wrapped, instace, args, kwargs): + + try: + result = wrapped(*args, **kwargs) + except: + raise + else: + + stats = core_application_stats_engine(None) + assert len(stats.error_data()) == num_errors + + return result + + return _validate_application_error_trace_count From 140cfaad9d0d7eadd069b7524c99f783482089ca Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Tue, 6 Sep 2022 13:10:28 -0700 Subject: [PATCH 12/23] Move validate_application_error_event_count into validators directory --- tests/agent_features/test_notice_error.py | 4 +- tests/testing_support/fixtures.py | 30 +++++++------- .../validate_application_error_event_count.py | 39 +++++++++++++++++++ 3 files changed, 57 insertions(+), 16 deletions(-) create mode 100644 tests/testing_support/validators/validate_application_error_event_count.py diff --git a/tests/agent_features/test_notice_error.py b/tests/agent_features/test_notice_error.py index 1bdcb3419..913ee9289 100644 --- a/tests/agent_features/test_notice_error.py +++ b/tests/agent_features/test_notice_error.py @@ -19,10 +19,12 @@ error_is_saved, override_application_settings, reset_core_stats_engine, - validate_application_error_event_count, validate_transaction_error_event_count, validate_transaction_error_trace_count, ) +from testing_support.validators.validate_application_error_event_count import ( + validate_application_error_event_count, +) from testing_support.validators.validate_application_error_trace_count import ( validate_application_error_trace_count, ) diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index 493d1a7c5..8a7b80b75 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -964,26 +964,26 @@ def check_event_attributes(event_data, required_params=None, forgone_params=None # return _validate_application_error_trace_count -def validate_application_error_event_count(num_errors): - """Validate error event data for a single error occurring outside of a - transaction. - """ +# def validate_application_error_event_count(num_errors): +# """Validate error event data for a single error occurring outside of a +# transaction. +# """ - @function_wrapper - def _validate_application_error_event_count(wrapped, instace, args, kwargs): +# @function_wrapper +# def _validate_application_error_event_count(wrapped, instace, args, kwargs): - try: - result = wrapped(*args, **kwargs) - except: - raise - else: +# try: +# result = wrapped(*args, **kwargs) +# except: +# raise +# else: - stats = core_application_stats_engine(None) - assert len(list(stats.error_events)) == num_errors +# stats = core_application_stats_engine(None) +# assert len(list(stats.error_events)) == num_errors - return result +# return result - return _validate_application_error_event_count +# return _validate_application_error_event_count def validate_synthetics_transaction_trace(required_params=None, forgone_params=None, should_exist=True): diff --git a/tests/testing_support/validators/validate_application_error_event_count.py b/tests/testing_support/validators/validate_application_error_event_count.py new file mode 100644 index 000000000..8812ed7ed --- /dev/null +++ b/tests/testing_support/validators/validate_application_error_event_count.py @@ -0,0 +1,39 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from testing_support.fixtures import core_application_stats_engine + +from newrelic.common.object_wrapper import function_wrapper + + +def validate_application_error_event_count(num_errors): + """Validate error event data for a single error occurring outside of a + transaction. + """ + + @function_wrapper + def _validate_application_error_event_count(wrapped, instace, args, kwargs): + + try: + result = wrapped(*args, **kwargs) + except: + raise + else: + + stats = core_application_stats_engine(None) + assert len(list(stats.error_events)) == num_errors + + return result + + return _validate_application_error_event_count From d22a5e2b15d1b198aa3eaf63a618bd5e83e90b7d Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Tue, 6 Sep 2022 13:15:41 -0700 Subject: [PATCH 13/23] Move validate_synthetics_transaction_trace into validators directory --- tests/agent_features/test_synthetics.py | 6 +- tests/testing_support/fixtures.py | 72 +++++++++---------- .../validate_synthetics_transaction_trace.py | 67 +++++++++++++++++ 3 files changed, 108 insertions(+), 37 deletions(-) create mode 100644 tests/testing_support/validators/validate_synthetics_transaction_trace.py diff --git a/tests/agent_features/test_synthetics.py b/tests/agent_features/test_synthetics.py index ec7b78e96..2e08144cc 100644 --- a/tests/agent_features/test_synthetics.py +++ b/tests/agent_features/test_synthetics.py @@ -19,10 +19,14 @@ cat_enabled, make_synthetics_header, override_application_settings, +) +from testing_support.validators.validate_synthetics_event import ( + validate_synthetics_event, +) +from testing_support.validators.validate_synthetics_transaction_trace import ( validate_synthetics_transaction_trace, ) -from testing_support.validators.validate_synthetics_event import validate_synthetics_event from newrelic.api.web_transaction import web_transaction from newrelic.api.wsgi_application import wsgi_application from newrelic.common.encoding_utils import deobfuscate, json_decode diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index 8a7b80b75..738986d41 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -986,54 +986,54 @@ def check_event_attributes(event_data, required_params=None, forgone_params=None # return _validate_application_error_event_count -def validate_synthetics_transaction_trace(required_params=None, forgone_params=None, should_exist=True): - required_params = required_params or {} - forgone_params = forgone_params or {} +# def validate_synthetics_transaction_trace(required_params=None, forgone_params=None, should_exist=True): +# required_params = required_params or {} +# forgone_params = forgone_params or {} - @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") - def _validate_synthetics_transaction_trace(wrapped, instance, args, kwargs): - try: - result = wrapped(*args, **kwargs) - except: - raise - else: +# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") +# def _validate_synthetics_transaction_trace(wrapped, instance, args, kwargs): +# try: +# result = wrapped(*args, **kwargs) +# except: +# raise +# else: - # Now that transaction has been recorded, generate - # a transaction trace +# # Now that transaction has been recorded, generate +# # a transaction trace - connections = SQLConnections() - trace_data = instance.transaction_trace_data(connections) +# connections = SQLConnections() +# trace_data = instance.transaction_trace_data(connections) - # Check that synthetics resource id is in TT header +# # Check that synthetics resource id is in TT header - header = trace_data[0] - header_key = "synthetics_resource_id" +# header = trace_data[0] +# header_key = "synthetics_resource_id" - if should_exist: - assert header_key in required_params - assert header[9] == required_params[header_key], "name=%r, header=%r" % (header_key, header) - else: - assert header[9] is None +# if should_exist: +# assert header_key in required_params +# assert header[9] == required_params[header_key], "name=%r, header=%r" % (header_key, header) +# else: +# assert header[9] is None - # Check that synthetics ids are in TT custom params +# # Check that synthetics ids are in TT custom params - pack_data = unpack_field(trace_data[0][4]) - tt_intrinsics = pack_data[0][4]["intrinsics"] +# pack_data = unpack_field(trace_data[0][4]) +# tt_intrinsics = pack_data[0][4]["intrinsics"] - for name in required_params: - assert name in tt_intrinsics, "name=%r, intrinsics=%r" % (name, tt_intrinsics) - assert tt_intrinsics[name] == required_params[name], "name=%r, value=%r, intrinsics=%r" % ( - name, - required_params[name], - tt_intrinsics, - ) +# for name in required_params: +# assert name in tt_intrinsics, "name=%r, intrinsics=%r" % (name, tt_intrinsics) +# assert tt_intrinsics[name] == required_params[name], "name=%r, value=%r, intrinsics=%r" % ( +# name, +# required_params[name], +# tt_intrinsics, +# ) - for name in forgone_params: - assert name not in tt_intrinsics, "name=%r, intrinsics=%r" % (name, tt_intrinsics) +# for name in forgone_params: +# assert name not in tt_intrinsics, "name=%r, intrinsics=%r" % (name, tt_intrinsics) - return result +# return result - return _validate_synthetics_transaction_trace +# return _validate_synthetics_transaction_trace def validate_tt_collector_json( diff --git a/tests/testing_support/validators/validate_synthetics_transaction_trace.py b/tests/testing_support/validators/validate_synthetics_transaction_trace.py new file mode 100644 index 000000000..7227d0327 --- /dev/null +++ b/tests/testing_support/validators/validate_synthetics_transaction_trace.py @@ -0,0 +1,67 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from newrelic.common.encoding_utils import unpack_field +from newrelic.common.object_wrapper import transient_function_wrapper +from newrelic.core.database_utils import SQLConnections + + +def validate_synthetics_transaction_trace(required_params=None, forgone_params=None, should_exist=True): + required_params = required_params or {} + forgone_params = forgone_params or {} + + @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") + def _validate_synthetics_transaction_trace(wrapped, instance, args, kwargs): + try: + result = wrapped(*args, **kwargs) + except: + raise + else: + + # Now that transaction has been recorded, generate + # a transaction trace + + connections = SQLConnections() + trace_data = instance.transaction_trace_data(connections) + + # Check that synthetics resource id is in TT header + + header = trace_data[0] + header_key = "synthetics_resource_id" + + if should_exist: + assert header_key in required_params + assert header[9] == required_params[header_key], "name=%r, header=%r" % (header_key, header) + else: + assert header[9] is None + + # Check that synthetics ids are in TT custom params + + pack_data = unpack_field(trace_data[0][4]) + tt_intrinsics = pack_data[0][4]["intrinsics"] + + for name in required_params: + assert name in tt_intrinsics, "name=%r, intrinsics=%r" % (name, tt_intrinsics) + assert tt_intrinsics[name] == required_params[name], "name=%r, value=%r, intrinsics=%r" % ( + name, + required_params[name], + tt_intrinsics, + ) + + for name in forgone_params: + assert name not in tt_intrinsics, "name=%r, intrinsics=%r" % (name, tt_intrinsics) + + return result + + return _validate_synthetics_transaction_trace From 3fbd623ad18cc541bc24ba2b898c037eedda8f35 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Mon, 19 Sep 2022 12:20:35 -0700 Subject: [PATCH 14/23] Move validate_tt_collector_json to validators directory --- .../agent_features/test_collector_payloads.py | 45 ++- tests/datastore_aioredis/test_trace_node.py | 10 +- tests/datastore_aredis/test_trace_node.py | 77 ++--- tests/datastore_asyncpg/test_query.py | 10 +- .../test_trace_node.py | 64 ++-- tests/datastore_psycopg2/test_trace_node.py | 60 ++-- tests/datastore_redis/test_trace_node.py | 76 ++-- .../test_pika_async_connection_consume.py | 327 ++++++++++-------- .../test_pika_blocking_connection_consume.py | 213 +++++++----- ...a_blocking_connection_consume_generator.py | 219 ++++++------ tests/messagebroker_pika/test_pika_produce.py | 14 +- tests/testing_support/fixtures.py | 303 ++++++++-------- .../validators/validate_tt_collector_json.py | 184 ++++++++++ 13 files changed, 932 insertions(+), 670 deletions(-) create mode 100644 tests/testing_support/validators/validate_tt_collector_json.py diff --git a/tests/agent_features/test_collector_payloads.py b/tests/agent_features/test_collector_payloads.py index 17b46ce49..76c72517e 100644 --- a/tests/agent_features/test_collector_payloads.py +++ b/tests/agent_features/test_collector_payloads.py @@ -14,17 +14,24 @@ import pytest import webtest - -from testing_support.fixtures import (validate_error_trace_collector_json, - validate_tt_collector_json, validate_transaction_event_collector_json, - validate_error_event_collector_json, - validate_custom_event_collector_json, override_application_settings) - -from testing_support.sample_applications import (simple_app, - simple_exceptional_app, simple_custom_event_app) - -from testing_support.validators.validate_log_event_collector_json import validate_log_event_collector_json - +from testing_support.fixtures import ( + override_application_settings, + validate_custom_event_collector_json, + validate_error_event_collector_json, + validate_error_trace_collector_json, + validate_transaction_event_collector_json, +) +from testing_support.sample_applications import ( + simple_app, + simple_custom_event_app, + simple_exceptional_app, +) +from testing_support.validators.validate_log_event_collector_json import ( + validate_log_event_collector_json, +) +from testing_support.validators.validate_tt_collector_json import ( + validate_tt_collector_json, +) exceptional_application = webtest.TestApp(simple_exceptional_app) normal_application = webtest.TestApp(simple_app) @@ -34,7 +41,7 @@ @validate_error_trace_collector_json() def test_error_trace_json(): try: - exceptional_application.get('/') + exceptional_application.get("/") except ValueError: pass @@ -42,34 +49,34 @@ def test_error_trace_json(): @validate_error_event_collector_json() def test_error_event_json(): try: - exceptional_application.get('/') + exceptional_application.get("/") except ValueError: pass @validate_tt_collector_json() def test_transaction_trace_json(): - normal_application.get('/') + normal_application.get("/") @validate_tt_collector_json(exclude_request_uri=True) -@override_application_settings({'attributes.exclude': set(('request.uri',))}) +@override_application_settings({"attributes.exclude": set(("request.uri",))}) def test_transaction_trace_json_no_request_uri(): - normal_application.get('/') + normal_application.get("/") @validate_transaction_event_collector_json() def test_transaction_event_json(): - normal_application.get('/') + normal_application.get("/") @validate_custom_event_collector_json() def test_custom_event_json(): - custom_event_application.get('/') + custom_event_application.get("/") @pytest.mark.xfail(reason="Unwritten validator") @validate_log_event_collector_json def test_log_event_json(): - normal_application.get('/') + normal_application.get("/") raise NotImplementedError("Fix my validator") diff --git a/tests/datastore_aioredis/test_trace_node.py b/tests/datastore_aioredis/test_trace_node.py index fb1ac8545..1fdd650f5 100644 --- a/tests/datastore_aioredis/test_trace_node.py +++ b/tests/datastore_aioredis/test_trace_node.py @@ -14,11 +14,13 @@ import aioredis import pytest - -from conftest import event_loop, loop, AIOREDIS_VERSION -from testing_support.fixtures import validate_tt_collector_json, override_application_settings -from testing_support.util import instance_hostname +from conftest import AIOREDIS_VERSION, event_loop from testing_support.db_settings import redis_settings +from testing_support.fixtures import override_application_settings +from testing_support.util import instance_hostname +from testing_support.validators.validate_tt_collector_json import ( + validate_tt_collector_json, +) from newrelic.api.background_task import background_task diff --git a/tests/datastore_aredis/test_trace_node.py b/tests/datastore_aredis/test_trace_node.py index 9741bfbd6..a4c58cebd 100644 --- a/tests/datastore_aredis/test_trace_node.py +++ b/tests/datastore_aredis/test_trace_node.py @@ -13,12 +13,14 @@ # limitations under the License. import aredis +from testing_support.db_settings import redis_settings -from testing_support.fixture.event_loop import event_loop as loop -from testing_support.fixtures import (validate_tt_collector_json, - override_application_settings) +# from testing_support.fixture.event_loop import event_loop as loop +from testing_support.fixtures import override_application_settings from testing_support.util import instance_hostname -from testing_support.db_settings import redis_settings +from testing_support.validators.validate_tt_collector_json import ( + validate_tt_collector_json, +) from newrelic.api.background_task import background_task @@ -28,100 +30,93 @@ # Settings _enable_instance_settings = { - 'datastore_tracer.instance_reporting.enabled': True, - 'datastore_tracer.database_name_reporting.enabled': True, + "datastore_tracer.instance_reporting.enabled": True, + "datastore_tracer.database_name_reporting.enabled": True, } _disable_instance_settings = { - 'datastore_tracer.instance_reporting.enabled': False, - 'datastore_tracer.database_name_reporting.enabled': False, + "datastore_tracer.instance_reporting.enabled": False, + "datastore_tracer.database_name_reporting.enabled": False, } _instance_only_settings = { - 'datastore_tracer.instance_reporting.enabled': True, - 'datastore_tracer.database_name_reporting.enabled': False, + "datastore_tracer.instance_reporting.enabled": True, + "datastore_tracer.database_name_reporting.enabled": False, } _database_only_settings = { - 'datastore_tracer.instance_reporting.enabled': False, - 'datastore_tracer.database_name_reporting.enabled': True, + "datastore_tracer.instance_reporting.enabled": False, + "datastore_tracer.database_name_reporting.enabled": True, } # Expected parameters _enabled_required = { - 'host': instance_hostname(DB_SETTINGS['host']), - 'port_path_or_id': str(DB_SETTINGS['port']), - 'db.instance': str(DATABASE_NUMBER), + "host": instance_hostname(DB_SETTINGS["host"]), + "port_path_or_id": str(DB_SETTINGS["port"]), + "db.instance": str(DATABASE_NUMBER), } _enabled_forgone = {} _disabled_required = {} _disabled_forgone = { - 'host': 'VALUE NOT USED', - 'port_path_or_id': 'VALUE NOT USED', - 'db.instance': 'VALUE NOT USED', + "host": "VALUE NOT USED", + "port_path_or_id": "VALUE NOT USED", + "db.instance": "VALUE NOT USED", } _instance_only_required = { - 'host': instance_hostname(DB_SETTINGS['host']), - 'port_path_or_id': str(DB_SETTINGS['port']), + "host": instance_hostname(DB_SETTINGS["host"]), + "port_path_or_id": str(DB_SETTINGS["port"]), } _instance_only_forgone = { - 'db.instance': str(DATABASE_NUMBER), + "db.instance": str(DATABASE_NUMBER), } _database_only_required = { - 'db.instance': str(DATABASE_NUMBER), + "db.instance": str(DATABASE_NUMBER), } _database_only_forgone = { - 'host': 'VALUE NOT USED', - 'port_path_or_id': 'VALUE NOT USED', + "host": "VALUE NOT USED", + "port_path_or_id": "VALUE NOT USED", } # Query + async def _exercise_db(): - client = aredis.StrictRedis(host=DB_SETTINGS['host'], - port=DB_SETTINGS['port'], db=DATABASE_NUMBER) + client = aredis.StrictRedis(host=DB_SETTINGS["host"], port=DB_SETTINGS["port"], db=DATABASE_NUMBER) - await client.set('key', 'value') - await client.get('key') + await client.set("key", "value") + await client.get("key") - await client.execute_command('CLIENT', 'LIST', parse='LIST') + await client.execute_command("CLIENT", "LIST", parse="LIST") # Tests + @override_application_settings(_enable_instance_settings) -@validate_tt_collector_json( - datastore_params=_enabled_required, - datastore_forgone_params=_enabled_forgone) +@validate_tt_collector_json(datastore_params=_enabled_required, datastore_forgone_params=_enabled_forgone) @background_task() def test_trace_node_datastore_params_enable_instance(loop): loop.run_until_complete(_exercise_db()) @override_application_settings(_disable_instance_settings) -@validate_tt_collector_json( - datastore_params=_disabled_required, - datastore_forgone_params=_disabled_forgone) +@validate_tt_collector_json(datastore_params=_disabled_required, datastore_forgone_params=_disabled_forgone) @background_task() def test_trace_node_datastore_params_disable_instance(loop): loop.run_until_complete(_exercise_db()) @override_application_settings(_instance_only_settings) -@validate_tt_collector_json( - datastore_params=_instance_only_required, - datastore_forgone_params=_instance_only_forgone) +@validate_tt_collector_json(datastore_params=_instance_only_required, datastore_forgone_params=_instance_only_forgone) @background_task() def test_trace_node_datastore_params_instance_only(loop): loop.run_until_complete(_exercise_db()) @override_application_settings(_database_only_settings) -@validate_tt_collector_json( - datastore_params=_database_only_required, - datastore_forgone_params=_database_only_forgone) +@validate_tt_collector_json(datastore_params=_database_only_required, datastore_forgone_params=_database_only_forgone) @background_task() def test_trace_node_datastore_params_database_only(loop): loop.run_until_complete(_exercise_db()) diff --git a/tests/datastore_asyncpg/test_query.py b/tests/datastore_asyncpg/test_query.py index a952e062a..838ced61d 100644 --- a/tests/datastore_asyncpg/test_query.py +++ b/tests/datastore_asyncpg/test_query.py @@ -12,17 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. -import asyncio import os -import random from io import BytesIO import asyncpg import pytest from testing_support.db_settings import postgresql_settings -from testing_support.fixtures import validate_tt_collector_json -from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from testing_support.util import instance_hostname +from testing_support.validators.validate_transaction_metrics import ( + validate_transaction_metrics, +) +from testing_support.validators.validate_tt_collector_json import ( + validate_tt_collector_json, +) from newrelic.api.background_task import background_task diff --git a/tests/datastore_elasticsearch/test_trace_node.py b/tests/datastore_elasticsearch/test_trace_node.py index 65e773340..445b4a4eb 100644 --- a/tests/datastore_elasticsearch/test_trace_node.py +++ b/tests/datastore_elasticsearch/test_trace_node.py @@ -13,77 +13,81 @@ # limitations under the License. from elasticsearch import Elasticsearch - -from testing_support.fixtures import (validate_tt_collector_json, - override_application_settings, validate_tt_parenting) from testing_support.db_settings import elasticsearch_settings +from testing_support.fixtures import ( + override_application_settings, + validate_tt_parenting, +) from testing_support.util import instance_hostname +from testing_support.validators.validate_tt_collector_json import ( + validate_tt_collector_json, +) from newrelic.api.background_task import background_task ES_SETTINGS = elasticsearch_settings()[0] -ES_URL = 'http://%s:%s' % (ES_SETTINGS['host'], ES_SETTINGS['port']) +ES_URL = "http://%s:%s" % (ES_SETTINGS["host"], ES_SETTINGS["port"]) # Settings _enable_instance_settings = { - 'datastore_tracer.instance_reporting.enabled': True, - 'datastore_tracer.database_name_reporting.enabled': True, + "datastore_tracer.instance_reporting.enabled": True, + "datastore_tracer.database_name_reporting.enabled": True, } _disable_instance_settings = { - 'datastore_tracer.instance_reporting.enabled': False, - 'datastore_tracer.database_name_reporting.enabled': False, + "datastore_tracer.instance_reporting.enabled": False, + "datastore_tracer.database_name_reporting.enabled": False, } _instance_only_settings = { - 'datastore_tracer.instance_reporting.enabled': True, - 'datastore_tracer.database_name_reporting.enabled': False, + "datastore_tracer.instance_reporting.enabled": True, + "datastore_tracer.database_name_reporting.enabled": False, } # Expected parameters _enabled_required = { - 'host': instance_hostname(ES_SETTINGS['host']), - 'port_path_or_id': str(ES_SETTINGS['port']), + "host": instance_hostname(ES_SETTINGS["host"]), + "port_path_or_id": str(ES_SETTINGS["port"]), } _enabled_forgone = { - 'db.instance': 'VALUE NOT USED', + "db.instance": "VALUE NOT USED", } _disabled_required = {} _disabled_forgone = { - 'host': 'VALUE NOT USED', - 'port_path_or_id': 'VALUE NOT USED', - 'db.instance': 'VALUE NOT USED', + "host": "VALUE NOT USED", + "port_path_or_id": "VALUE NOT USED", + "db.instance": "VALUE NOT USED", } _instance_only_required = { - 'host': instance_hostname(ES_SETTINGS['host']), - 'port_path_or_id': str(ES_SETTINGS['port']), + "host": instance_hostname(ES_SETTINGS["host"]), + "port_path_or_id": str(ES_SETTINGS["port"]), } _instance_only_forgone = { - 'db.instance': 'VALUE NOT USED', + "db.instance": "VALUE NOT USED", } _tt_parenting = ( - 'TransactionNode', [ - ('DatastoreNode', []), + "TransactionNode", + [ + ("DatastoreNode", []), ], ) # Query + def _exercise_es(es): - es.index(index='contacts', doc_type='person', - body={'name': 'Joe Tester', 'age': 25, 'title': 'QA Master'}, id=1) + es.index(index="contacts", doc_type="person", body={"name": "Joe Tester", "age": 25, "title": "QA Master"}, id=1) # Tests + @override_application_settings(_enable_instance_settings) -@validate_tt_collector_json( - datastore_params=_enabled_required, - datastore_forgone_params=_enabled_forgone) +@validate_tt_collector_json(datastore_params=_enabled_required, datastore_forgone_params=_enabled_forgone) @validate_tt_parenting(_tt_parenting) @background_task() def test_trace_node_datastore_params_enable_instance(): @@ -92,9 +96,7 @@ def test_trace_node_datastore_params_enable_instance(): @override_application_settings(_disable_instance_settings) -@validate_tt_collector_json( - datastore_params=_disabled_required, - datastore_forgone_params=_disabled_forgone) +@validate_tt_collector_json(datastore_params=_disabled_required, datastore_forgone_params=_disabled_forgone) @validate_tt_parenting(_tt_parenting) @background_task() def test_trace_node_datastore_params_disable_instance(): @@ -103,9 +105,7 @@ def test_trace_node_datastore_params_disable_instance(): @override_application_settings(_instance_only_settings) -@validate_tt_collector_json( - datastore_params=_instance_only_required, - datastore_forgone_params=_instance_only_forgone) +@validate_tt_collector_json(datastore_params=_instance_only_required, datastore_forgone_params=_instance_only_forgone) @validate_tt_parenting(_tt_parenting) @background_task() def test_trace_node_datastore_params_instance_only(): diff --git a/tests/datastore_psycopg2/test_trace_node.py b/tests/datastore_psycopg2/test_trace_node.py index b9cd45788..9bfbcf42b 100644 --- a/tests/datastore_psycopg2/test_trace_node.py +++ b/tests/datastore_psycopg2/test_trace_node.py @@ -13,72 +13,78 @@ # limitations under the License. import psycopg2 - -from testing_support.fixtures import (validate_tt_collector_json, - override_application_settings, validate_tt_parenting) +from testing_support.fixtures import ( + override_application_settings, + validate_tt_parenting, +) from testing_support.util import instance_hostname +from testing_support.validators.validate_tt_collector_json import ( + validate_tt_collector_json, +) from utils import DB_SETTINGS from newrelic.api.background_task import background_task - # Settings _enable_instance_settings = { - 'datastore_tracer.instance_reporting.enabled': True, - 'datastore_tracer.database_name_reporting.enabled': True, + "datastore_tracer.instance_reporting.enabled": True, + "datastore_tracer.database_name_reporting.enabled": True, } _disable_instance_settings = { - 'datastore_tracer.instance_reporting.enabled': False, - 'datastore_tracer.database_name_reporting.enabled': False, + "datastore_tracer.instance_reporting.enabled": False, + "datastore_tracer.database_name_reporting.enabled": False, } # Expected parameters _enabled_required = { - 'host': instance_hostname(DB_SETTINGS['host']), - 'port_path_or_id': str(DB_SETTINGS['port']), - 'db.instance': DB_SETTINGS['name'], + "host": instance_hostname(DB_SETTINGS["host"]), + "port_path_or_id": str(DB_SETTINGS["port"]), + "db.instance": DB_SETTINGS["name"], } _enabled_forgone = {} _disabled_required = {} _disabled_forgone = { - 'host': 'VALUE NOT USED', - 'port_path_or_id': 'VALUE NOT USED', - 'db.instance': 'VALUE NOT USED', + "host": "VALUE NOT USED", + "port_path_or_id": "VALUE NOT USED", + "db.instance": "VALUE NOT USED", } _tt_parenting = ( - 'TransactionNode', [ - ('FunctionNode', []), - ('DatabaseNode', []), + "TransactionNode", + [ + ("FunctionNode", []), + ("DatabaseNode", []), ], ) # Query + def _exercise_db(): connection = psycopg2.connect( - database=DB_SETTINGS['name'], user=DB_SETTINGS['user'], - password=DB_SETTINGS['password'], host=DB_SETTINGS['host'], - port=DB_SETTINGS['port']) + database=DB_SETTINGS["name"], + user=DB_SETTINGS["user"], + password=DB_SETTINGS["password"], + host=DB_SETTINGS["host"], + port=DB_SETTINGS["port"], + ) try: cursor = connection.cursor() - cursor.execute("""SELECT setting from pg_settings where name=%s""", - ('server_version',)) + cursor.execute("""SELECT setting from pg_settings where name=%s""", ("server_version",)) finally: connection.close() # Tests + @override_application_settings(_enable_instance_settings) -@validate_tt_collector_json( - datastore_params=_enabled_required, - datastore_forgone_params=_enabled_forgone) +@validate_tt_collector_json(datastore_params=_enabled_required, datastore_forgone_params=_enabled_forgone) @validate_tt_parenting(_tt_parenting) @background_task() def test_trace_node_datastore_params_enable_instance(): @@ -86,9 +92,7 @@ def test_trace_node_datastore_params_enable_instance(): @override_application_settings(_disable_instance_settings) -@validate_tt_collector_json( - datastore_params=_disabled_required, - datastore_forgone_params=_disabled_forgone) +@validate_tt_collector_json(datastore_params=_disabled_required, datastore_forgone_params=_disabled_forgone) @validate_tt_parenting(_tt_parenting) @background_task() def test_trace_node_datastore_params_disable_instance(): diff --git a/tests/datastore_redis/test_trace_node.py b/tests/datastore_redis/test_trace_node.py index 39b7763ba..cc0d59919 100644 --- a/tests/datastore_redis/test_trace_node.py +++ b/tests/datastore_redis/test_trace_node.py @@ -13,11 +13,12 @@ # limitations under the License. import redis - -from testing_support.fixtures import (validate_tt_collector_json, - override_application_settings) -from testing_support.util import instance_hostname from testing_support.db_settings import redis_settings +from testing_support.fixtures import override_application_settings +from testing_support.util import instance_hostname +from testing_support.validators.validate_tt_collector_json import ( + validate_tt_collector_json, +) from newrelic.api.background_task import background_task @@ -27,100 +28,93 @@ # Settings _enable_instance_settings = { - 'datastore_tracer.instance_reporting.enabled': True, - 'datastore_tracer.database_name_reporting.enabled': True, + "datastore_tracer.instance_reporting.enabled": True, + "datastore_tracer.database_name_reporting.enabled": True, } _disable_instance_settings = { - 'datastore_tracer.instance_reporting.enabled': False, - 'datastore_tracer.database_name_reporting.enabled': False, + "datastore_tracer.instance_reporting.enabled": False, + "datastore_tracer.database_name_reporting.enabled": False, } _instance_only_settings = { - 'datastore_tracer.instance_reporting.enabled': True, - 'datastore_tracer.database_name_reporting.enabled': False, + "datastore_tracer.instance_reporting.enabled": True, + "datastore_tracer.database_name_reporting.enabled": False, } _database_only_settings = { - 'datastore_tracer.instance_reporting.enabled': False, - 'datastore_tracer.database_name_reporting.enabled': True, + "datastore_tracer.instance_reporting.enabled": False, + "datastore_tracer.database_name_reporting.enabled": True, } # Expected parameters _enabled_required = { - 'host': instance_hostname(DB_SETTINGS['host']), - 'port_path_or_id': str(DB_SETTINGS['port']), - 'db.instance': str(DATABASE_NUMBER), + "host": instance_hostname(DB_SETTINGS["host"]), + "port_path_or_id": str(DB_SETTINGS["port"]), + "db.instance": str(DATABASE_NUMBER), } _enabled_forgone = {} _disabled_required = {} _disabled_forgone = { - 'host': 'VALUE NOT USED', - 'port_path_or_id': 'VALUE NOT USED', - 'db.instance': 'VALUE NOT USED', + "host": "VALUE NOT USED", + "port_path_or_id": "VALUE NOT USED", + "db.instance": "VALUE NOT USED", } _instance_only_required = { - 'host': instance_hostname(DB_SETTINGS['host']), - 'port_path_or_id': str(DB_SETTINGS['port']), + "host": instance_hostname(DB_SETTINGS["host"]), + "port_path_or_id": str(DB_SETTINGS["port"]), } _instance_only_forgone = { - 'db.instance': str(DATABASE_NUMBER), + "db.instance": str(DATABASE_NUMBER), } _database_only_required = { - 'db.instance': str(DATABASE_NUMBER), + "db.instance": str(DATABASE_NUMBER), } _database_only_forgone = { - 'host': 'VALUE NOT USED', - 'port_path_or_id': 'VALUE NOT USED', + "host": "VALUE NOT USED", + "port_path_or_id": "VALUE NOT USED", } # Query + def _exercise_db(): - client = redis.StrictRedis(host=DB_SETTINGS['host'], - port=DB_SETTINGS['port'], db=DATABASE_NUMBER) + client = redis.StrictRedis(host=DB_SETTINGS["host"], port=DB_SETTINGS["port"], db=DATABASE_NUMBER) - client.set('key', 'value') - client.get('key') + client.set("key", "value") + client.get("key") - client.execute_command('CLIENT', 'LIST', parse='LIST') + client.execute_command("CLIENT", "LIST", parse="LIST") # Tests + @override_application_settings(_enable_instance_settings) -@validate_tt_collector_json( - datastore_params=_enabled_required, - datastore_forgone_params=_enabled_forgone) +@validate_tt_collector_json(datastore_params=_enabled_required, datastore_forgone_params=_enabled_forgone) @background_task() def test_trace_node_datastore_params_enable_instance(): _exercise_db() @override_application_settings(_disable_instance_settings) -@validate_tt_collector_json( - datastore_params=_disabled_required, - datastore_forgone_params=_disabled_forgone) +@validate_tt_collector_json(datastore_params=_disabled_required, datastore_forgone_params=_disabled_forgone) @background_task() def test_trace_node_datastore_params_disable_instance(): _exercise_db() @override_application_settings(_instance_only_settings) -@validate_tt_collector_json( - datastore_params=_instance_only_required, - datastore_forgone_params=_instance_only_forgone) +@validate_tt_collector_json(datastore_params=_instance_only_required, datastore_forgone_params=_instance_only_forgone) @background_task() def test_trace_node_datastore_params_instance_only(): _exercise_db() @override_application_settings(_database_only_settings) -@validate_tt_collector_json( - datastore_params=_database_only_required, - datastore_forgone_params=_database_only_forgone) +@validate_tt_collector_json(datastore_params=_database_only_required, datastore_forgone_params=_database_only_forgone) @background_task() def test_trace_node_datastore_params_database_only(): _exercise_db() diff --git a/tests/messagebroker_pika/test_pika_async_connection_consume.py b/tests/messagebroker_pika/test_pika_async_connection_consume.py index 7edf6b644..4e44c7ed7 100644 --- a/tests/messagebroker_pika/test_pika_async_connection_consume.py +++ b/tests/messagebroker_pika/test_pika_async_connection_consume.py @@ -12,39 +12,57 @@ # See the License for the specific language governing permissions and # limitations under the License. -from minversion import pika_version_info -from compat import basic_consume import functools + import pika -from pika.adapters.tornado_connection import TornadoConnection import pytest import six import tornado +from compat import basic_consume +from conftest import ( + BODY, + CORRELATION_ID, + EXCHANGE, + EXCHANGE_2, + HEADERS, + QUEUE, + QUEUE_2, + REPLY_TO, +) +from minversion import pika_version_info +from pika.adapters.tornado_connection import TornadoConnection +from testing_support.db_settings import rabbitmq_settings +from testing_support.fixtures import ( + capture_transaction_metrics, + function_not_called, + override_application_settings, +) +from testing_support.validators.validate_code_level_metrics import ( + validate_code_level_metrics, +) +from testing_support.validators.validate_transaction_metrics import ( + validate_transaction_metrics, +) +from testing_support.validators.validate_tt_collector_json import ( + validate_tt_collector_json, +) from newrelic.api.background_task import background_task -from conftest import (QUEUE, QUEUE_2, EXCHANGE, EXCHANGE_2, CORRELATION_ID, - REPLY_TO, HEADERS, BODY) -from testing_support.fixtures import (capture_transaction_metrics, - validate_tt_collector_json, - function_not_called, override_application_settings) -from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics -from testing_support.db_settings import rabbitmq_settings -from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics - DB_SETTINGS = rabbitmq_settings()[0] _message_broker_tt_params = { - 'queue_name': QUEUE, - 'routing_key': QUEUE, - 'correlation_id': CORRELATION_ID, - 'reply_to': REPLY_TO, - 'headers': HEADERS.copy(), + "queue_name": QUEUE, + "routing_key": QUEUE, + "correlation_id": CORRELATION_ID, + "reply_to": REPLY_TO, + "headers": HEADERS.copy(), } # Tornado's IO loop is not configurable in versions 5.x and up try: + class MyIOLoop(tornado.ioloop.IOLoop.configured_class()): def handle_callback_exception(self, *args, **kwargs): raise @@ -55,38 +73,44 @@ def handle_callback_exception(self, *args, **kwargs): connection_classes = [pika.SelectConnection, TornadoConnection] -parametrized_connection = pytest.mark.parametrize('ConnectionClass', - connection_classes) +parametrized_connection = pytest.mark.parametrize("ConnectionClass", connection_classes) _test_select_conn_basic_get_inside_txn_metrics = [ - ('MessageBroker/RabbitMQ/Exchange/Produce/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/%s' % EXCHANGE, 1), + ("MessageBroker/RabbitMQ/Exchange/Produce/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/%s" % EXCHANGE, 1), ] if six.PY3: _test_select_conn_basic_get_inside_txn_metrics.append( - (('Function/test_pika_async_connection_consume:' - 'test_async_connection_basic_get_inside_txn.' - '.on_message'), 1)) + ( + ( + "Function/test_pika_async_connection_consume:" + "test_async_connection_basic_get_inside_txn." + ".on_message" + ), + 1, + ) + ) else: - _test_select_conn_basic_get_inside_txn_metrics.append( - ('Function/test_pika_async_connection_consume:on_message', 1)) + _test_select_conn_basic_get_inside_txn_metrics.append(("Function/test_pika_async_connection_consume:on_message", 1)) @parametrized_connection -@pytest.mark.parametrize('callback_as_partial', [True, False]) -@validate_code_level_metrics("test_pika_async_connection_consume" + (".test_async_connection_basic_get_inside_txn." if six.PY3 else ""), "on_message") +@pytest.mark.parametrize("callback_as_partial", [True, False]) +@validate_code_level_metrics( + "test_pika_async_connection_consume" + (".test_async_connection_basic_get_inside_txn." if six.PY3 else ""), + "on_message", +) @validate_transaction_metrics( - ('test_pika_async_connection_consume:' - 'test_async_connection_basic_get_inside_txn'), - scoped_metrics=_test_select_conn_basic_get_inside_txn_metrics, - rollup_metrics=_test_select_conn_basic_get_inside_txn_metrics, - background_task=True) + ("test_pika_async_connection_consume:" "test_async_connection_basic_get_inside_txn"), + scoped_metrics=_test_select_conn_basic_get_inside_txn_metrics, + rollup_metrics=_test_select_conn_basic_get_inside_txn_metrics, + background_task=True, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() -def test_async_connection_basic_get_inside_txn(producer, ConnectionClass, - callback_as_partial): +def test_async_connection_basic_get_inside_txn(producer, ConnectionClass, callback_as_partial): def on_message(channel, method_frame, header_frame, body): assert method_frame assert body == BODY @@ -104,9 +128,7 @@ def on_open_channel(channel): def on_open_connection(connection): connection.channel(on_open_callback=on_open_channel) - connection = ConnectionClass( - pika.ConnectionParameters(DB_SETTINGS['host']), - on_open_callback=on_open_connection) + connection = ConnectionClass(pika.ConnectionParameters(DB_SETTINGS["host"]), on_open_callback=on_open_connection) try: connection.ioloop.start() @@ -117,9 +139,8 @@ def on_open_connection(connection): @parametrized_connection -@pytest.mark.parametrize('callback_as_partial', [True, False]) -def test_select_connection_basic_get_outside_txn(producer, ConnectionClass, - callback_as_partial): +@pytest.mark.parametrize("callback_as_partial", [True, False]) +def test_select_connection_basic_get_outside_txn(producer, ConnectionClass, callback_as_partial): metrics_list = [] @capture_transaction_metrics(metrics_list) @@ -142,8 +163,8 @@ def on_open_connection(connection): connection.channel(on_open_callback=on_open_channel) connection = ConnectionClass( - pika.ConnectionParameters(DB_SETTINGS['host']), - on_open_callback=on_open_connection) + pika.ConnectionParameters(DB_SETTINGS["host"]), on_open_callback=on_open_connection + ) try: connection.ioloop.start() @@ -160,25 +181,24 @@ def on_open_connection(connection): _test_select_conn_basic_get_inside_txn_no_callback_metrics = [ - ('MessageBroker/RabbitMQ/Exchange/Produce/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/%s' % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Produce/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/%s" % EXCHANGE, None), ] @pytest.mark.skipif( - condition=pika_version_info[0] > 0, - reason='pika 1.0 removed the ability to use basic_get with callback=None') + condition=pika_version_info[0] > 0, reason="pika 1.0 removed the ability to use basic_get with callback=None" +) @parametrized_connection @validate_transaction_metrics( - ('test_pika_async_connection_consume:' - 'test_async_connection_basic_get_inside_txn_no_callback'), + ("test_pika_async_connection_consume:" "test_async_connection_basic_get_inside_txn_no_callback"), scoped_metrics=_test_select_conn_basic_get_inside_txn_no_callback_metrics, rollup_metrics=_test_select_conn_basic_get_inside_txn_no_callback_metrics, - background_task=True) + background_task=True, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() -def test_async_connection_basic_get_inside_txn_no_callback(producer, - ConnectionClass): +def test_async_connection_basic_get_inside_txn_no_callback(producer, ConnectionClass): def on_open_channel(channel): channel.basic_get(callback=None, queue=QUEUE) channel.close() @@ -188,9 +208,7 @@ def on_open_channel(channel): def on_open_connection(connection): connection.channel(on_open_callback=on_open_channel) - connection = ConnectionClass( - pika.ConnectionParameters(DB_SETTINGS['host']), - on_open_callback=on_open_connection) + connection = ConnectionClass(pika.ConnectionParameters(DB_SETTINGS["host"]), on_open_callback=on_open_connection) try: connection.ioloop.start() @@ -201,27 +219,26 @@ def on_open_connection(connection): _test_async_connection_basic_get_empty_metrics = [ - ('MessageBroker/RabbitMQ/Exchange/Produce/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/%s' % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Produce/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/%s" % EXCHANGE, None), ] @parametrized_connection -@pytest.mark.parametrize('callback_as_partial', [True, False]) +@pytest.mark.parametrize("callback_as_partial", [True, False]) @validate_transaction_metrics( - ('test_pika_async_connection_consume:' - 'test_async_connection_basic_get_empty'), - scoped_metrics=_test_async_connection_basic_get_empty_metrics, - rollup_metrics=_test_async_connection_basic_get_empty_metrics, - background_task=True) + ("test_pika_async_connection_consume:" "test_async_connection_basic_get_empty"), + scoped_metrics=_test_async_connection_basic_get_empty_metrics, + rollup_metrics=_test_async_connection_basic_get_empty_metrics, + background_task=True, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() -def test_async_connection_basic_get_empty(ConnectionClass, - callback_as_partial): - QUEUE = 'test_async_empty' +def test_async_connection_basic_get_empty(ConnectionClass, callback_as_partial): + QUEUE = "test_async_empty" def on_message(channel, method_frame, header_frame, body): - assert False, body.decode('UTF-8') + assert False, body.decode("UTF-8") if callback_as_partial: on_message = functools.partial(on_message) @@ -235,9 +252,7 @@ def on_open_channel(channel): def on_open_connection(connection): connection.channel(on_open_callback=on_open_channel) - connection = ConnectionClass( - pika.ConnectionParameters(DB_SETTINGS['host']), - on_open_callback=on_open_connection) + connection = ConnectionClass(pika.ConnectionParameters(DB_SETTINGS["host"]), on_open_callback=on_open_connection) try: connection.ioloop.start() @@ -248,33 +263,42 @@ def on_open_connection(connection): _test_select_conn_basic_consume_in_txn_metrics = [ - ('MessageBroker/RabbitMQ/Exchange/Produce/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/%s' % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Produce/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/%s" % EXCHANGE, None), ] if six.PY3: _test_select_conn_basic_consume_in_txn_metrics.append( - (('Function/test_pika_async_connection_consume:' - 'test_async_connection_basic_consume_inside_txn.' - '.on_message'), 1)) + ( + ( + "Function/test_pika_async_connection_consume:" + "test_async_connection_basic_consume_inside_txn." + ".on_message" + ), + 1, + ) + ) else: - _test_select_conn_basic_consume_in_txn_metrics.append( - ('Function/test_pika_async_connection_consume:on_message', 1)) + _test_select_conn_basic_consume_in_txn_metrics.append(("Function/test_pika_async_connection_consume:on_message", 1)) @parametrized_connection @validate_transaction_metrics( - ('test_pika_async_connection_consume:' - 'test_async_connection_basic_consume_inside_txn'), - scoped_metrics=_test_select_conn_basic_consume_in_txn_metrics, - rollup_metrics=_test_select_conn_basic_consume_in_txn_metrics, - background_task=True) -@validate_code_level_metrics("test_pika_async_connection_consume" + (".test_async_connection_basic_consume_inside_txn." if six.PY3 else ""), "on_message") + ("test_pika_async_connection_consume:" "test_async_connection_basic_consume_inside_txn"), + scoped_metrics=_test_select_conn_basic_consume_in_txn_metrics, + rollup_metrics=_test_select_conn_basic_consume_in_txn_metrics, + background_task=True, +) +@validate_code_level_metrics( + "test_pika_async_connection_consume" + + (".test_async_connection_basic_consume_inside_txn." if six.PY3 else ""), + "on_message", +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() def test_async_connection_basic_consume_inside_txn(producer, ConnectionClass): def on_message(channel, method_frame, header_frame, body): - assert hasattr(method_frame, '_nr_start_time') + assert hasattr(method_frame, "_nr_start_time") assert body == BODY channel.basic_ack(method_frame.delivery_tag) channel.close() @@ -287,9 +311,7 @@ def on_open_channel(channel): def on_open_connection(connection): connection.channel(on_open_callback=on_open_channel) - connection = ConnectionClass( - pika.ConnectionParameters(DB_SETTINGS['host']), - on_open_callback=on_open_connection) + connection = ConnectionClass(pika.ConnectionParameters(DB_SETTINGS["host"]), on_open_callback=on_open_connection) try: connection.ioloop.start() @@ -300,46 +322,67 @@ def on_open_connection(connection): _test_select_conn_basic_consume_two_exchanges = [ - ('MessageBroker/RabbitMQ/Exchange/Produce/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Produce/Named/%s' % EXCHANGE_2, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/%s' % EXCHANGE_2, None), + ("MessageBroker/RabbitMQ/Exchange/Produce/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Produce/Named/%s" % EXCHANGE_2, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/%s" % EXCHANGE_2, None), ] if six.PY3: _test_select_conn_basic_consume_two_exchanges.append( - (('Function/test_pika_async_connection_consume:' - 'test_async_connection_basic_consume_two_exchanges.' - '.on_message_1'), 1)) + ( + ( + "Function/test_pika_async_connection_consume:" + "test_async_connection_basic_consume_two_exchanges." + ".on_message_1" + ), + 1, + ) + ) _test_select_conn_basic_consume_two_exchanges.append( - (('Function/test_pika_async_connection_consume:' - 'test_async_connection_basic_consume_two_exchanges.' - '.on_message_2'), 1)) + ( + ( + "Function/test_pika_async_connection_consume:" + "test_async_connection_basic_consume_two_exchanges." + ".on_message_2" + ), + 1, + ) + ) else: _test_select_conn_basic_consume_two_exchanges.append( - ('Function/test_pika_async_connection_consume:on_message_1', 1)) + ("Function/test_pika_async_connection_consume:on_message_1", 1) + ) _test_select_conn_basic_consume_two_exchanges.append( - ('Function/test_pika_async_connection_consume:on_message_2', 1)) + ("Function/test_pika_async_connection_consume:on_message_2", 1) + ) @parametrized_connection @validate_transaction_metrics( - ('test_pika_async_connection_consume:' - 'test_async_connection_basic_consume_two_exchanges'), - scoped_metrics=_test_select_conn_basic_consume_two_exchanges, - rollup_metrics=_test_select_conn_basic_consume_two_exchanges, - background_task=True) -@validate_code_level_metrics("test_pika_async_connection_consume" + (".test_async_connection_basic_consume_two_exchanges." if six.PY3 else ""), "on_message_1") -@validate_code_level_metrics("test_pika_async_connection_consume" + (".test_async_connection_basic_consume_two_exchanges." if six.PY3 else ""), "on_message_2") + ("test_pika_async_connection_consume:" "test_async_connection_basic_consume_two_exchanges"), + scoped_metrics=_test_select_conn_basic_consume_two_exchanges, + rollup_metrics=_test_select_conn_basic_consume_two_exchanges, + background_task=True, +) +@validate_code_level_metrics( + "test_pika_async_connection_consume" + + (".test_async_connection_basic_consume_two_exchanges." if six.PY3 else ""), + "on_message_1", +) +@validate_code_level_metrics( + "test_pika_async_connection_consume" + + (".test_async_connection_basic_consume_two_exchanges." if six.PY3 else ""), + "on_message_2", +) @background_task() -def test_async_connection_basic_consume_two_exchanges(producer, producer_2, - ConnectionClass): +def test_async_connection_basic_consume_two_exchanges(producer, producer_2, ConnectionClass): global events_received events_received = 0 def on_message_1(channel, method_frame, header_frame, body): channel.basic_ack(method_frame.delivery_tag) - assert hasattr(method_frame, '_nr_start_time') + assert hasattr(method_frame, "_nr_start_time") assert body == BODY global events_received @@ -352,7 +395,7 @@ def on_message_1(channel, method_frame, header_frame, body): def on_message_2(channel, method_frame, header_frame, body): channel.basic_ack(method_frame.delivery_tag) - assert hasattr(method_frame, '_nr_start_time') + assert hasattr(method_frame, "_nr_start_time") assert body == BODY global events_received @@ -370,9 +413,7 @@ def on_open_channel(channel): def on_open_connection(connection): connection.channel(on_open_callback=on_open_channel) - connection = ConnectionClass( - pika.ConnectionParameters(DB_SETTINGS['host']), - on_open_callback=on_open_connection) + connection = ConnectionClass(pika.ConnectionParameters(DB_SETTINGS["host"]), on_open_callback=on_open_connection) try: connection.ioloop.start() @@ -383,12 +424,11 @@ def on_open_connection(connection): # This should not create a transaction -@function_not_called('newrelic.core.stats_engine', - 'StatsEngine.record_transaction') -@override_application_settings({'debug.record_transaction_failure': True}) +@function_not_called("newrelic.core.stats_engine", "StatsEngine.record_transaction") +@override_application_settings({"debug.record_transaction_failure": True}) def test_tornado_connection_basic_consume_outside_transaction(producer): def on_message(channel, method_frame, header_frame, body): - assert hasattr(method_frame, '_nr_start_time') + assert hasattr(method_frame, "_nr_start_time") assert body == BODY channel.basic_ack(method_frame.delivery_tag) channel.close() @@ -401,9 +441,7 @@ def on_open_channel(channel): def on_open_connection(connection): connection.channel(on_open_callback=on_open_channel) - connection = TornadoConnection( - pika.ConnectionParameters(DB_SETTINGS['host']), - on_open_callback=on_open_connection) + connection = TornadoConnection(pika.ConnectionParameters(DB_SETTINGS["host"]), on_open_callback=on_open_connection) try: connection.ioloop.start() @@ -414,31 +452,44 @@ def on_open_connection(connection): if six.PY3: - _txn_name = ('test_pika_async_connection_consume:' - 'test_select_connection_basic_consume_outside_transaction.' - '.on_message') + _txn_name = ( + "test_pika_async_connection_consume:" + "test_select_connection_basic_consume_outside_transaction." + ".on_message" + ) _test_select_connection_consume_outside_txn_metrics = [ - (('Function/test_pika_async_connection_consume:' - 'test_select_connection_basic_consume_outside_transaction.' - '.on_message'), None)] + ( + ( + "Function/test_pika_async_connection_consume:" + "test_select_connection_basic_consume_outside_transaction." + ".on_message" + ), + None, + ) + ] else: - _txn_name = ( - 'test_pika_async_connection_consume:on_message') + _txn_name = "test_pika_async_connection_consume:on_message" _test_select_connection_consume_outside_txn_metrics = [ - ('Function/test_pika_async_connection_consume:on_message', None)] + ("Function/test_pika_async_connection_consume:on_message", None) + ] # This should create a transaction @validate_transaction_metrics( - _txn_name, - scoped_metrics=_test_select_connection_consume_outside_txn_metrics, - rollup_metrics=_test_select_connection_consume_outside_txn_metrics, - background_task=True, - group='Message/RabbitMQ/Exchange/%s' % EXCHANGE) -@validate_code_level_metrics("test_pika_async_connection_consume" + (".test_select_connection_basic_consume_outside_transaction." if six.PY3 else ""), "on_message") + _txn_name, + scoped_metrics=_test_select_connection_consume_outside_txn_metrics, + rollup_metrics=_test_select_connection_consume_outside_txn_metrics, + background_task=True, + group="Message/RabbitMQ/Exchange/%s" % EXCHANGE, +) +@validate_code_level_metrics( + "test_pika_async_connection_consume" + + (".test_select_connection_basic_consume_outside_transaction." if six.PY3 else ""), + "on_message", +) def test_select_connection_basic_consume_outside_transaction(producer): def on_message(channel, method_frame, header_frame, body): - assert hasattr(method_frame, '_nr_start_time') + assert hasattr(method_frame, "_nr_start_time") assert body == BODY channel.basic_ack(method_frame.delivery_tag) channel.close() @@ -452,8 +503,8 @@ def on_open_connection(connection): connection.channel(on_open_callback=on_open_channel) connection = pika.SelectConnection( - pika.ConnectionParameters(DB_SETTINGS['host']), - on_open_callback=on_open_connection) + pika.ConnectionParameters(DB_SETTINGS["host"]), on_open_callback=on_open_connection + ) try: connection.ioloop.start() diff --git a/tests/messagebroker_pika/test_pika_blocking_connection_consume.py b/tests/messagebroker_pika/test_pika_blocking_connection_consume.py index c96d42d98..7b41674a2 100644 --- a/tests/messagebroker_pika/test_pika_blocking_connection_consume.py +++ b/tests/messagebroker_pika/test_pika_blocking_connection_consume.py @@ -12,52 +12,56 @@ # See the License for the specific language governing permissions and # limitations under the License. -from compat import basic_consume import functools +import os + import pika import pytest import six -import os +from compat import basic_consume +from conftest import BODY, CORRELATION_ID, EXCHANGE, HEADERS, QUEUE, REPLY_TO +from testing_support.db_settings import rabbitmq_settings +from testing_support.fixtures import capture_transaction_metrics +from testing_support.validators.validate_code_level_metrics import ( + validate_code_level_metrics, +) +from testing_support.validators.validate_transaction_metrics import ( + validate_transaction_metrics, +) +from testing_support.validators.validate_tt_collector_json import ( + validate_tt_collector_json, +) from newrelic.api.background_task import background_task from newrelic.api.transaction import end_of_transaction -from conftest import QUEUE, EXCHANGE, CORRELATION_ID, REPLY_TO, HEADERS, BODY -from testing_support.fixtures import (capture_transaction_metrics, - validate_tt_collector_json) -from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics -from testing_support.db_settings import rabbitmq_settings -from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics - DB_SETTINGS = rabbitmq_settings()[0] _message_broker_tt_params = { - 'queue_name': QUEUE, - 'routing_key': QUEUE, - 'correlation_id': CORRELATION_ID, - 'reply_to': REPLY_TO, - 'headers': HEADERS.copy(), + "queue_name": QUEUE, + "routing_key": QUEUE, + "correlation_id": CORRELATION_ID, + "reply_to": REPLY_TO, + "headers": HEADERS.copy(), } _test_blocking_connection_basic_get_metrics = [ - ('MessageBroker/RabbitMQ/Exchange/Produce/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/%s' % EXCHANGE, 1), - (('Function/pika.adapters.blocking_connection:' - '_CallbackResult.set_value_once'), 1) + ("MessageBroker/RabbitMQ/Exchange/Produce/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/%s" % EXCHANGE, 1), + (("Function/pika.adapters.blocking_connection:" "_CallbackResult.set_value_once"), 1), ] @validate_transaction_metrics( - ('test_pika_blocking_connection_consume:' - 'test_blocking_connection_basic_get'), - scoped_metrics=_test_blocking_connection_basic_get_metrics, - rollup_metrics=_test_blocking_connection_basic_get_metrics, - background_task=True) + ("test_pika_blocking_connection_consume:" "test_blocking_connection_basic_get"), + scoped_metrics=_test_blocking_connection_basic_get_metrics, + rollup_metrics=_test_blocking_connection_basic_get_metrics, + background_task=True, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() def test_blocking_connection_basic_get(producer): - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() method_frame, _, _ = channel.basic_get(QUEUE) assert method_frame @@ -65,23 +69,22 @@ def test_blocking_connection_basic_get(producer): _test_blocking_connection_basic_get_empty_metrics = [ - ('MessageBroker/RabbitMQ/Exchange/Produce/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/%s' % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Produce/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/%s" % EXCHANGE, None), ] @validate_transaction_metrics( - ('test_pika_blocking_connection_consume:' - 'test_blocking_connection_basic_get_empty'), - scoped_metrics=_test_blocking_connection_basic_get_empty_metrics, - rollup_metrics=_test_blocking_connection_basic_get_empty_metrics, - background_task=True) + ("test_pika_blocking_connection_consume:" "test_blocking_connection_basic_get_empty"), + scoped_metrics=_test_blocking_connection_basic_get_empty_metrics, + rollup_metrics=_test_blocking_connection_basic_get_empty_metrics, + background_task=True, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() def test_blocking_connection_basic_get_empty(): - QUEUE = 'test_blocking_empty-%s' % os.getpid() - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + QUEUE = "test_blocking_empty-%s" % os.getpid() + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() channel.queue_declare(queue=QUEUE) @@ -97,8 +100,7 @@ def test_blocking_connection_basic_get_outside_transaction(producer): @capture_transaction_metrics(metrics_list) def test_basic_get(): - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() channel.queue_declare(queue=QUEUE) @@ -114,46 +116,57 @@ def test_basic_get(): _test_blocking_conn_basic_consume_no_txn_metrics = [ - ('MessageBroker/RabbitMQ/Exchange/Produce/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/%s' % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Produce/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/%s" % EXCHANGE, None), ] if six.PY3: - _txn_name = ('test_pika_blocking_connection_consume:' - 'test_blocking_connection_basic_consume_outside_transaction.' - '.on_message') + _txn_name = ( + "test_pika_blocking_connection_consume:" + "test_blocking_connection_basic_consume_outside_transaction." + ".on_message" + ) _test_blocking_conn_basic_consume_no_txn_metrics.append( - (('Function/test_pika_blocking_connection_consume:' - 'test_blocking_connection_basic_consume_outside_transaction.' - '.on_message'), None)) + ( + ( + "Function/test_pika_blocking_connection_consume:" + "test_blocking_connection_basic_consume_outside_transaction." + ".on_message" + ), + None, + ) + ) else: - _txn_name = ('test_pika_blocking_connection_consume:' - 'on_message') + _txn_name = "test_pika_blocking_connection_consume:" "on_message" _test_blocking_conn_basic_consume_no_txn_metrics.append( - ('Function/test_pika_blocking_connection_consume:on_message', None)) + ("Function/test_pika_blocking_connection_consume:on_message", None) + ) -@pytest.mark.parametrize('as_partial', [True, False]) -@validate_code_level_metrics("test_pika_blocking_connection_consume" + (".test_blocking_connection_basic_consume_outside_transaction." if six.PY3 else ""), "on_message") +@pytest.mark.parametrize("as_partial", [True, False]) +@validate_code_level_metrics( + "test_pika_blocking_connection_consume" + + (".test_blocking_connection_basic_consume_outside_transaction." if six.PY3 else ""), + "on_message", +) @validate_transaction_metrics( - _txn_name, - scoped_metrics=_test_blocking_conn_basic_consume_no_txn_metrics, - rollup_metrics=_test_blocking_conn_basic_consume_no_txn_metrics, - background_task=True, - group='Message/RabbitMQ/Exchange/%s' % EXCHANGE) + _txn_name, + scoped_metrics=_test_blocking_conn_basic_consume_no_txn_metrics, + rollup_metrics=_test_blocking_conn_basic_consume_no_txn_metrics, + background_task=True, + group="Message/RabbitMQ/Exchange/%s" % EXCHANGE, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) -def test_blocking_connection_basic_consume_outside_transaction(producer, - as_partial): +def test_blocking_connection_basic_consume_outside_transaction(producer, as_partial): def on_message(channel, method_frame, header_frame, body): - assert hasattr(method_frame, '_nr_start_time') + assert hasattr(method_frame, "_nr_start_time") assert body == BODY channel.stop_consuming() if as_partial: on_message = functools.partial(on_message) - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() basic_consume(channel, QUEUE, on_message) @@ -165,41 +178,51 @@ def on_message(channel, method_frame, header_frame, body): _test_blocking_conn_basic_consume_in_txn_metrics = [ - ('MessageBroker/RabbitMQ/Exchange/Produce/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/%s' % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Produce/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/%s" % EXCHANGE, None), ] if six.PY3: _test_blocking_conn_basic_consume_in_txn_metrics.append( - (('Function/test_pika_blocking_connection_consume:' - 'test_blocking_connection_basic_consume_inside_txn.' - '.on_message'), 1)) + ( + ( + "Function/test_pika_blocking_connection_consume:" + "test_blocking_connection_basic_consume_inside_txn." + ".on_message" + ), + 1, + ) + ) else: _test_blocking_conn_basic_consume_in_txn_metrics.append( - ('Function/test_pika_blocking_connection_consume:on_message', 1)) + ("Function/test_pika_blocking_connection_consume:on_message", 1) + ) -@pytest.mark.parametrize('as_partial', [True, False]) -@validate_code_level_metrics("test_pika_blocking_connection_consume" + (".test_blocking_connection_basic_consume_inside_txn." if six.PY3 else ""), "on_message") +@pytest.mark.parametrize("as_partial", [True, False]) +@validate_code_level_metrics( + "test_pika_blocking_connection_consume" + + (".test_blocking_connection_basic_consume_inside_txn." if six.PY3 else ""), + "on_message", +) @validate_transaction_metrics( - ('test_pika_blocking_connection_consume:' - 'test_blocking_connection_basic_consume_inside_txn'), - scoped_metrics=_test_blocking_conn_basic_consume_in_txn_metrics, - rollup_metrics=_test_blocking_conn_basic_consume_in_txn_metrics, - background_task=True) + ("test_pika_blocking_connection_consume:" "test_blocking_connection_basic_consume_inside_txn"), + scoped_metrics=_test_blocking_conn_basic_consume_in_txn_metrics, + rollup_metrics=_test_blocking_conn_basic_consume_in_txn_metrics, + background_task=True, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() def test_blocking_connection_basic_consume_inside_txn(producer, as_partial): def on_message(channel, method_frame, header_frame, body): - assert hasattr(method_frame, '_nr_start_time') + assert hasattr(method_frame, "_nr_start_time") assert body == BODY channel.stop_consuming() if as_partial: on_message = functools.partial(on_message) - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() basic_consume(channel, QUEUE, on_message) try: @@ -210,33 +233,40 @@ def on_message(channel, method_frame, header_frame, body): _test_blocking_conn_basic_consume_stopped_txn_metrics = [ - ('MessageBroker/RabbitMQ/Exchange/Produce/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/%s' % EXCHANGE, None), - ('OtherTransaction/Message/RabbitMQ/Exchange/Named/%s' % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Produce/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/%s" % EXCHANGE, None), + ("OtherTransaction/Message/RabbitMQ/Exchange/Named/%s" % EXCHANGE, None), ] if six.PY3: _test_blocking_conn_basic_consume_stopped_txn_metrics.append( - (('Function/test_pika_blocking_connection_consume:' - 'test_blocking_connection_basic_consume_stopped_txn.' - '.on_message'), None)) + ( + ( + "Function/test_pika_blocking_connection_consume:" + "test_blocking_connection_basic_consume_stopped_txn." + ".on_message" + ), + None, + ) + ) else: _test_blocking_conn_basic_consume_stopped_txn_metrics.append( - ('Function/test_pika_blocking_connection_consume:on_message', None)) + ("Function/test_pika_blocking_connection_consume:on_message", None) + ) -@pytest.mark.parametrize('as_partial', [True, False]) +@pytest.mark.parametrize("as_partial", [True, False]) @validate_transaction_metrics( - ('test_pika_blocking_connection_consume:' - 'test_blocking_connection_basic_consume_stopped_txn'), - scoped_metrics=_test_blocking_conn_basic_consume_stopped_txn_metrics, - rollup_metrics=_test_blocking_conn_basic_consume_stopped_txn_metrics, - background_task=True) + ("test_pika_blocking_connection_consume:" "test_blocking_connection_basic_consume_stopped_txn"), + scoped_metrics=_test_blocking_conn_basic_consume_stopped_txn_metrics, + rollup_metrics=_test_blocking_conn_basic_consume_stopped_txn_metrics, + background_task=True, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() def test_blocking_connection_basic_consume_stopped_txn(producer, as_partial): def on_message(channel, method_frame, header_frame, body): - assert hasattr(method_frame, '_nr_start_time') + assert hasattr(method_frame, "_nr_start_time") assert body == BODY channel.stop_consuming() @@ -245,8 +275,7 @@ def on_message(channel, method_frame, header_frame, body): if as_partial: on_message = functools.partial(on_message) - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() basic_consume(channel, QUEUE, on_message) try: diff --git a/tests/messagebroker_pika/test_pika_blocking_connection_consume_generator.py b/tests/messagebroker_pika/test_pika_blocking_connection_consume_generator.py index 4fff11487..816b28323 100644 --- a/tests/messagebroker_pika/test_pika_blocking_connection_consume_generator.py +++ b/tests/messagebroker_pika/test_pika_blocking_connection_consume_generator.py @@ -13,65 +13,66 @@ # limitations under the License. import pika +from conftest import BODY, CORRELATION_ID, EXCHANGE, HEADERS, QUEUE, REPLY_TO +from testing_support.db_settings import rabbitmq_settings +from testing_support.validators.validate_transaction_metrics import ( + validate_transaction_metrics, +) +from testing_support.validators.validate_tt_collector_json import ( + validate_tt_collector_json, +) from newrelic.api.background_task import background_task -from conftest import QUEUE, EXCHANGE, CORRELATION_ID, REPLY_TO, HEADERS, BODY -from testing_support.fixtures import validate_tt_collector_json -from testing_support.db_settings import rabbitmq_settings -from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics - DB_SETTINGS = rabbitmq_settings()[0] _message_broker_tt_params = { - 'queue_name': QUEUE, - 'routing_key': QUEUE, - 'correlation_id': CORRELATION_ID, - 'reply_to': REPLY_TO, - 'headers': HEADERS.copy(), + "queue_name": QUEUE, + "routing_key": QUEUE, + "correlation_id": CORRELATION_ID, + "reply_to": REPLY_TO, + "headers": HEADERS.copy(), } _test_blocking_connection_consume_metrics = [ - ('MessageBroker/RabbitMQ/Exchange/Produce/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/Unknown', None), + ("MessageBroker/RabbitMQ/Exchange/Produce/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/Unknown", None), ] @validate_transaction_metrics( - ('test_pika_blocking_connection_consume_generator:' - 'test_blocking_connection_consume_break'), - scoped_metrics=_test_blocking_connection_consume_metrics, - rollup_metrics=_test_blocking_connection_consume_metrics, - background_task=True) + ("test_pika_blocking_connection_consume_generator:" "test_blocking_connection_consume_break"), + scoped_metrics=_test_blocking_connection_consume_metrics, + rollup_metrics=_test_blocking_connection_consume_metrics, + background_task=True, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() def test_blocking_connection_consume_break(producer): - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() for method_frame, properties, body in channel.consume(QUEUE): - assert hasattr(method_frame, '_nr_start_time') + assert hasattr(method_frame, "_nr_start_time") assert body == BODY break @validate_transaction_metrics( - ('test_pika_blocking_connection_consume_generator:' - 'test_blocking_connection_consume_connection_close'), - scoped_metrics=_test_blocking_connection_consume_metrics, - rollup_metrics=_test_blocking_connection_consume_metrics, - background_task=True) + ("test_pika_blocking_connection_consume_generator:" "test_blocking_connection_consume_connection_close"), + scoped_metrics=_test_blocking_connection_consume_metrics, + rollup_metrics=_test_blocking_connection_consume_metrics, + background_task=True, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() def test_blocking_connection_consume_connection_close(producer): - connection = pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) + connection = pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) channel = connection.channel() try: for method_frame, properties, body in channel.consume(QUEUE): - assert hasattr(method_frame, '_nr_start_time') + assert hasattr(method_frame, "_nr_start_time") assert body == BODY channel.close() connection.close() @@ -82,16 +83,15 @@ def test_blocking_connection_consume_connection_close(producer): @validate_transaction_metrics( - ('test_pika_blocking_connection_consume_generator:' - 'test_blocking_connection_consume_timeout'), - scoped_metrics=_test_blocking_connection_consume_metrics, - rollup_metrics=_test_blocking_connection_consume_metrics, - background_task=True) + ("test_pika_blocking_connection_consume_generator:" "test_blocking_connection_consume_timeout"), + scoped_metrics=_test_blocking_connection_consume_metrics, + rollup_metrics=_test_blocking_connection_consume_metrics, + background_task=True, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() def test_blocking_connection_consume_timeout(producer): - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() for result in channel.consume(QUEUE, inactivity_timeout=0.01): @@ -99,7 +99,7 @@ def test_blocking_connection_consume_timeout(producer): if result and any(result): method_frame, properties, body = result channel.basic_ack(method_frame.delivery_tag) - assert hasattr(method_frame, '_nr_start_time') + assert hasattr(method_frame, "_nr_start_time") assert body == BODY else: # timeout hit! @@ -107,16 +107,15 @@ def test_blocking_connection_consume_timeout(producer): @validate_transaction_metrics( - ('test_pika_blocking_connection_consume_generator:' - 'test_blocking_connection_consume_exception_in_for_loop'), - scoped_metrics=_test_blocking_connection_consume_metrics, - rollup_metrics=_test_blocking_connection_consume_metrics, - background_task=True) + ("test_pika_blocking_connection_consume_generator:" "test_blocking_connection_consume_exception_in_for_loop"), + scoped_metrics=_test_blocking_connection_consume_metrics, + rollup_metrics=_test_blocking_connection_consume_metrics, + background_task=True, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() def test_blocking_connection_consume_exception_in_for_loop(producer): - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() try: @@ -128,29 +127,28 @@ def test_blocking_connection_consume_exception_in_for_loop(producer): # Expected error pass except Exception as e: - assert False, 'Wrong exception was raised: %s' % e + assert False, "Wrong exception was raised: %s" % e else: - assert False, 'No exception was raised!' + assert False, "No exception was raised!" _test_blocking_connection_consume_empty_metrics = [ - ('MessageBroker/RabbitMQ/Exchange/Produce/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/Unknown', None), + ("MessageBroker/RabbitMQ/Exchange/Produce/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/Unknown", None), ] @validate_transaction_metrics( - ('test_pika_blocking_connection_consume_generator:' - 'test_blocking_connection_consume_exception_in_generator'), - scoped_metrics=_test_blocking_connection_consume_empty_metrics, - rollup_metrics=_test_blocking_connection_consume_empty_metrics, - background_task=True) + ("test_pika_blocking_connection_consume_generator:" "test_blocking_connection_consume_exception_in_generator"), + scoped_metrics=_test_blocking_connection_consume_empty_metrics, + rollup_metrics=_test_blocking_connection_consume_empty_metrics, + background_task=True, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() def test_blocking_connection_consume_exception_in_generator(): - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() try: @@ -161,29 +159,28 @@ def test_blocking_connection_consume_exception_in_generator(): # Expected error pass except Exception as e: - assert False, 'Wrong exception was raised: %s' % e + assert False, "Wrong exception was raised: %s" % e else: - assert False, 'No exception was raised!' + assert False, "No exception was raised!" _test_blocking_connection_consume_many_metrics = [ - ('MessageBroker/RabbitMQ/Exchange/Produce/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/%s' % EXCHANGE, None), - ('MessageBroker/RabbitMQ/Exchange/Consume/Named/Unknown', None), + ("MessageBroker/RabbitMQ/Exchange/Produce/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/%s" % EXCHANGE, None), + ("MessageBroker/RabbitMQ/Exchange/Consume/Named/Unknown", None), ] @validate_transaction_metrics( - ('test_pika_blocking_connection_consume_generator:' - 'test_blocking_connection_consume_many'), - scoped_metrics=_test_blocking_connection_consume_many_metrics, - rollup_metrics=_test_blocking_connection_consume_many_metrics, - background_task=True) + ("test_pika_blocking_connection_consume_generator:" "test_blocking_connection_consume_many"), + scoped_metrics=_test_blocking_connection_consume_many_metrics, + rollup_metrics=_test_blocking_connection_consume_many_metrics, + background_task=True, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() def test_blocking_connection_consume_many(produce_five): - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() consumed = 0 @@ -196,22 +193,21 @@ def test_blocking_connection_consume_many(produce_five): @validate_transaction_metrics( - ('test_pika_blocking_connection_consume_generator:' - 'test_blocking_connection_consume_using_methods'), - scoped_metrics=_test_blocking_connection_consume_metrics, - rollup_metrics=_test_blocking_connection_consume_metrics, - background_task=True) + ("test_pika_blocking_connection_consume_generator:" "test_blocking_connection_consume_using_methods"), + scoped_metrics=_test_blocking_connection_consume_metrics, + rollup_metrics=_test_blocking_connection_consume_metrics, + background_task=True, +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) @background_task() def test_blocking_connection_consume_using_methods(producer): - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() consumer = channel.consume(QUEUE, inactivity_timeout=0.01) method, properties, body = next(consumer) - assert hasattr(method, '_nr_start_time') + assert hasattr(method, "_nr_start_time") assert body == BODY result = next(consumer) @@ -224,28 +220,28 @@ def test_blocking_connection_consume_using_methods(producer): pass else: # this is not - assert False, 'No exception was raised!' + assert False, "No exception was raised!" result = consumer.close() assert result is None @validate_transaction_metrics( - 'Named/%s' % EXCHANGE, - scoped_metrics=_test_blocking_connection_consume_metrics, - rollup_metrics=_test_blocking_connection_consume_metrics, - background_task=True, - group='Message/RabbitMQ/Exchange') + "Named/%s" % EXCHANGE, + scoped_metrics=_test_blocking_connection_consume_metrics, + rollup_metrics=_test_blocking_connection_consume_metrics, + background_task=True, + group="Message/RabbitMQ/Exchange", +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) def test_blocking_connection_consume_outside_txn(producer): - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() consumer = channel.consume(QUEUE) try: for method_frame, properties, body in consumer: - assert hasattr(method_frame, '_nr_start_time') + assert hasattr(method_frame, "_nr_start_time") assert body == BODY break finally: @@ -254,26 +250,24 @@ def test_blocking_connection_consume_outside_txn(producer): def test_blocking_connection_consume_many_outside_txn(produce_five): - @validate_transaction_metrics( - 'Named/%s' % EXCHANGE, - scoped_metrics=_test_blocking_connection_consume_metrics, - rollup_metrics=_test_blocking_connection_consume_metrics, - background_task=True, - group='Message/RabbitMQ/Exchange') - @validate_tt_collector_json( - message_broker_params=_message_broker_tt_params) + "Named/%s" % EXCHANGE, + scoped_metrics=_test_blocking_connection_consume_metrics, + rollup_metrics=_test_blocking_connection_consume_metrics, + background_task=True, + group="Message/RabbitMQ/Exchange", + ) + @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) def consume_it(consumer, up_next=None): if up_next is None: method_frame, properties, body = next(consumer) else: method_frame, properties, body = up_next - assert hasattr(method_frame, '_nr_start_time') + assert hasattr(method_frame, "_nr_start_time") assert body == BODY return next(consumer) - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() consumer = channel.consume(QUEUE) @@ -288,21 +282,21 @@ def consume_it(consumer, up_next=None): @validate_transaction_metrics( - 'Named/%s' % EXCHANGE, - scoped_metrics=_test_blocking_connection_consume_metrics, - rollup_metrics=_test_blocking_connection_consume_metrics, - background_task=True, - group='Message/RabbitMQ/Exchange') + "Named/%s" % EXCHANGE, + scoped_metrics=_test_blocking_connection_consume_metrics, + rollup_metrics=_test_blocking_connection_consume_metrics, + background_task=True, + group="Message/RabbitMQ/Exchange", +) @validate_tt_collector_json(message_broker_params=_message_broker_tt_params) def test_blocking_connection_consume_using_methods_outside_txn(producer): - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() consumer = channel.consume(QUEUE, inactivity_timeout=0.01) method, properties, body = next(consumer) - assert hasattr(method, '_nr_start_time') + assert hasattr(method, "_nr_start_time") assert body == BODY result = next(consumer) @@ -315,22 +309,21 @@ def test_blocking_connection_consume_using_methods_outside_txn(producer): pass else: # this is not - assert False, 'No exception was raised!' + assert False, "No exception was raised!" result = consumer.close() assert result is None @validate_transaction_metrics( - ('test_pika_blocking_connection_consume_generator:' - 'test_blocking_connection_consume_exception_on_creation'), - scoped_metrics=_test_blocking_connection_consume_empty_metrics, - rollup_metrics=_test_blocking_connection_consume_empty_metrics, - background_task=True) + ("test_pika_blocking_connection_consume_generator:" "test_blocking_connection_consume_exception_on_creation"), + scoped_metrics=_test_blocking_connection_consume_empty_metrics, + rollup_metrics=_test_blocking_connection_consume_empty_metrics, + background_task=True, +) @background_task() def test_blocking_connection_consume_exception_on_creation(): - with pika.BlockingConnection( - pika.ConnectionParameters(DB_SETTINGS['host'])) as connection: + with pika.BlockingConnection(pika.ConnectionParameters(DB_SETTINGS["host"])) as connection: channel = connection.channel() try: @@ -340,4 +333,4 @@ def test_blocking_connection_consume_exception_on_creation(): pass else: # this is not - assert False, 'TypeError was not raised' + assert False, "TypeError was not raised" diff --git a/tests/messagebroker_pika/test_pika_produce.py b/tests/messagebroker_pika/test_pika_produce.py index 0960159fa..dbc9af030 100644 --- a/tests/messagebroker_pika/test_pika_produce.py +++ b/tests/messagebroker_pika/test_pika_produce.py @@ -15,14 +15,16 @@ import pika import pytest from testing_support.db_settings import rabbitmq_settings -from testing_support.fixtures import ( - override_application_settings, - validate_tt_collector_json, -) +from testing_support.fixtures import override_application_settings from testing_support.validators.validate_messagebroker_headers import ( validate_messagebroker_headers, ) -from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_metrics import ( + validate_transaction_metrics, +) +from testing_support.validators.validate_tt_collector_json import ( + validate_tt_collector_json, +) from newrelic.api.background_task import background_task from newrelic.api.transaction import current_transaction @@ -46,7 +48,7 @@ def cache_pika_headers(wrapped, instance, args, kwargs): QUEUE = "test-pika-queue" CORRELATION_ID = "testingpika" REPLY_TO = "testing" -HEADERS = {u"MYHEADER": u"pikatest"} +HEADERS = {"MYHEADER": "pikatest"} _message_broker_tt_included_params = { "routing_key": QUEUE, diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index 738986d41..268d7506a 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -54,7 +54,6 @@ transient_function_wrapper, wrap_function_wrapper, ) -from newrelic.common.system_info import LOCALHOST_EQUIVALENTS from newrelic.config import initialize from newrelic.core.agent import shutdown_agent from newrelic.core.attribute import create_attributes @@ -89,12 +88,12 @@ def _environ_as_bool(name, default=False): return flag -def _lookup_string_table(name, string_table, default=None): - try: - index = int(name.lstrip("`")) - return string_table[index] - except ValueError: - return default +# def _lookup_string_table(name, string_table, default=None): +# try: +# index = int(name.lstrip("`")) +# return string_table[index] +# except ValueError: +# return default if _environ_as_bool("NEW_RELIC_HIGH_SECURITY"): @@ -1036,161 +1035,161 @@ def check_event_attributes(event_data, required_params=None, forgone_params=None # return _validate_synthetics_transaction_trace -def validate_tt_collector_json( - required_params=None, - forgone_params=None, - should_exist=True, - datastore_params=None, - datastore_forgone_params=None, - message_broker_params=None, - message_broker_forgone_params=None, - exclude_request_uri=False, -): - """make assertions based off the cross-agent spec on transaction traces""" - required_params = required_params or {} - forgone_params = forgone_params or {} - datastore_params = datastore_params or {} - datastore_forgone_params = datastore_forgone_params or {} - message_broker_params = message_broker_params or {} - message_broker_forgone_params = message_broker_forgone_params or [] +# def validate_tt_collector_json( +# required_params=None, +# forgone_params=None, +# should_exist=True, +# datastore_params=None, +# datastore_forgone_params=None, +# message_broker_params=None, +# message_broker_forgone_params=None, +# exclude_request_uri=False, +# ): +# """make assertions based off the cross-agent spec on transaction traces""" +# required_params = required_params or {} +# forgone_params = forgone_params or {} +# datastore_params = datastore_params or {} +# datastore_forgone_params = datastore_forgone_params or {} +# message_broker_params = message_broker_params or {} +# message_broker_forgone_params = message_broker_forgone_params or [] - @function_wrapper - def _validate_wrapper(wrapped, instance, args, kwargs): +# @function_wrapper +# def _validate_wrapper(wrapped, instance, args, kwargs): - traces_recorded = [] +# traces_recorded = [] - @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") - def _validate_tt_collector_json(wrapped, instance, args, kwargs): +# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") +# def _validate_tt_collector_json(wrapped, instance, args, kwargs): - result = wrapped(*args, **kwargs) +# result = wrapped(*args, **kwargs) - # Now that transaction has been recorded, generate - # a transaction trace +# # Now that transaction has been recorded, generate +# # a transaction trace - connections = SQLConnections() - trace_data = instance.transaction_trace_data(connections) - traces_recorded.append(trace_data) +# connections = SQLConnections() +# trace_data = instance.transaction_trace_data(connections) +# traces_recorded.append(trace_data) - return result +# return result - def _validate_trace(trace): - assert isinstance(trace[0], float) # absolute start time (ms) - assert isinstance(trace[1], float) # duration (ms) - assert trace[0] > 0 # absolute time (ms) - assert isinstance(trace[2], six.string_types) # transaction name - if trace[2].startswith("WebTransaction"): - if exclude_request_uri: - assert trace[3] is None # request url - else: - assert isinstance(trace[3], six.string_types) - # query parameters should not be captured - assert "?" not in trace[3] - - # trace details -- python agent always uses condensed trace array - - trace_details, string_table = unpack_field(trace[4]) - assert len(trace_details) == 5 - assert isinstance(trace_details[0], float) # start time (ms) - - # the next two items should be empty dicts, old parameters stuff, - # placeholders for now - - assert isinstance(trace_details[1], dict) - assert len(trace_details[1]) == 0 - assert isinstance(trace_details[2], dict) - assert len(trace_details[2]) == 0 - - # root node in slot 3 - - root_node = trace_details[3] - assert isinstance(root_node[0], float) # entry timestamp - assert isinstance(root_node[1], float) # exit timestamp - assert root_node[2] == "ROOT" - assert isinstance(root_node[3], dict) - assert len(root_node[3]) == 0 # spec shows empty (for root) - children = root_node[4] - assert isinstance(children, list) - - # there are two optional items at the end of trace segments, - # class name that segment is in, and method name function is in; - # Python agent does not use these (only Java does) - - # let's just test the first child - trace_segment = children[0] - assert isinstance(trace_segment[0], float) # entry timestamp - assert isinstance(trace_segment[1], float) # exit timestamp - assert isinstance(trace_segment[2], six.string_types) # scope - assert isinstance(trace_segment[3], dict) # request params - assert isinstance(trace_segment[4], list) # children - - assert trace_segment[0] >= root_node[0] # trace starts after root - - def _check_params_and_start_time(node): - children = node[4] - for child in children: - assert child[0] >= node[0] # child started after parent - _check_params_and_start_time(child) - - params = node[3] - assert isinstance(params, dict) - - # We should always report exclusive_duration_millis on a - # segment. This allows us to override exclusive time - # calculations on APM. - assert "exclusive_duration_millis" in params - assert isinstance(params["exclusive_duration_millis"], float) - - segment_name = _lookup_string_table(node[2], string_table, default=node[2]) - if segment_name.startswith("Datastore"): - for key in datastore_params: - assert key in params, key - assert params[key] == datastore_params[key] - for key in datastore_forgone_params: - assert key not in params, key - - # if host is reported, it cannot be localhost - if "host" in params: - assert params["host"] not in LOCALHOST_EQUIVALENTS - - elif segment_name.startswith("MessageBroker"): - for key in message_broker_params: - assert key in params, key - assert params[key] == message_broker_params[key] - for key in message_broker_forgone_params: - assert key not in params, key - - _check_params_and_start_time(trace_segment) - - attributes = trace_details[4] - - assert "intrinsics" in attributes - assert "userAttributes" in attributes - assert "agentAttributes" in attributes - - assert isinstance(trace[5], six.string_types) # GUID - assert trace[6] is None # reserved for future use - assert trace[7] is False # deprecated force persist flag - - # x-ray session ID - - assert trace[8] is None - - # Synthetics ID - - assert trace[9] is None or isinstance(trace[9], six.string_types) - - assert isinstance(string_table, list) - for name in string_table: - assert isinstance(name, six.string_types) # metric name +# def _validate_trace(trace): +# assert isinstance(trace[0], float) # absolute start time (ms) +# assert isinstance(trace[1], float) # duration (ms) +# assert trace[0] > 0 # absolute time (ms) +# assert isinstance(trace[2], six.string_types) # transaction name +# if trace[2].startswith("WebTransaction"): +# if exclude_request_uri: +# assert trace[3] is None # request url +# else: +# assert isinstance(trace[3], six.string_types) +# # query parameters should not be captured +# assert "?" not in trace[3] - _new_wrapper = _validate_tt_collector_json(wrapped) - val = _new_wrapper(*args, **kwargs) - trace_data = traces_recorded.pop() - trace = trace_data[0] # 1st trace - _validate_trace(trace) - return val +# # trace details -- python agent always uses condensed trace array - return _validate_wrapper +# trace_details, string_table = unpack_field(trace[4]) +# assert len(trace_details) == 5 +# assert isinstance(trace_details[0], float) # start time (ms) + +# # the next two items should be empty dicts, old parameters stuff, +# # placeholders for now + +# assert isinstance(trace_details[1], dict) +# assert len(trace_details[1]) == 0 +# assert isinstance(trace_details[2], dict) +# assert len(trace_details[2]) == 0 + +# # root node in slot 3 + +# root_node = trace_details[3] +# assert isinstance(root_node[0], float) # entry timestamp +# assert isinstance(root_node[1], float) # exit timestamp +# assert root_node[2] == "ROOT" +# assert isinstance(root_node[3], dict) +# assert len(root_node[3]) == 0 # spec shows empty (for root) +# children = root_node[4] +# assert isinstance(children, list) + +# # there are two optional items at the end of trace segments, +# # class name that segment is in, and method name function is in; +# # Python agent does not use these (only Java does) + +# # let's just test the first child +# trace_segment = children[0] +# assert isinstance(trace_segment[0], float) # entry timestamp +# assert isinstance(trace_segment[1], float) # exit timestamp +# assert isinstance(trace_segment[2], six.string_types) # scope +# assert isinstance(trace_segment[3], dict) # request params +# assert isinstance(trace_segment[4], list) # children + +# assert trace_segment[0] >= root_node[0] # trace starts after root + +# def _check_params_and_start_time(node): +# children = node[4] +# for child in children: +# assert child[0] >= node[0] # child started after parent +# _check_params_and_start_time(child) + +# params = node[3] +# assert isinstance(params, dict) + +# # We should always report exclusive_duration_millis on a +# # segment. This allows us to override exclusive time +# # calculations on APM. +# assert "exclusive_duration_millis" in params +# assert isinstance(params["exclusive_duration_millis"], float) + +# segment_name = _lookup_string_table(node[2], string_table, default=node[2]) +# if segment_name.startswith("Datastore"): +# for key in datastore_params: +# assert key in params, key +# assert params[key] == datastore_params[key] +# for key in datastore_forgone_params: +# assert key not in params, key + +# # if host is reported, it cannot be localhost +# if "host" in params: +# assert params["host"] not in LOCALHOST_EQUIVALENTS + +# elif segment_name.startswith("MessageBroker"): +# for key in message_broker_params: +# assert key in params, key +# assert params[key] == message_broker_params[key] +# for key in message_broker_forgone_params: +# assert key not in params, key + +# _check_params_and_start_time(trace_segment) + +# attributes = trace_details[4] + +# assert "intrinsics" in attributes +# assert "userAttributes" in attributes +# assert "agentAttributes" in attributes + +# assert isinstance(trace[5], six.string_types) # GUID +# assert trace[6] is None # reserved for future use +# assert trace[7] is False # deprecated force persist flag + +# # x-ray session ID + +# assert trace[8] is None + +# # Synthetics ID + +# assert trace[9] is None or isinstance(trace[9], six.string_types) + +# assert isinstance(string_table, list) +# for name in string_table: +# assert isinstance(name, six.string_types) # metric name + +# _new_wrapper = _validate_tt_collector_json(wrapped) +# val = _new_wrapper(*args, **kwargs) +# trace_data = traces_recorded.pop() +# trace = trace_data[0] # 1st trace +# _validate_trace(trace) +# return val + +# return _validate_wrapper def validate_transaction_trace_attributes( diff --git a/tests/testing_support/validators/validate_tt_collector_json.py b/tests/testing_support/validators/validate_tt_collector_json.py new file mode 100644 index 000000000..85e393280 --- /dev/null +++ b/tests/testing_support/validators/validate_tt_collector_json.py @@ -0,0 +1,184 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from newrelic.common.encoding_utils import unpack_field +from newrelic.common.object_wrapper import function_wrapper, transient_function_wrapper +from newrelic.common.system_info import LOCALHOST_EQUIVALENTS +from newrelic.core.database_utils import SQLConnections +from newrelic.packages import six + + +def _lookup_string_table(name, string_table, default=None): + try: + index = int(name.lstrip("`")) + return string_table[index] + except ValueError: + return default + + +def validate_tt_collector_json( + required_params=None, + forgone_params=None, + should_exist=True, + datastore_params=None, + datastore_forgone_params=None, + message_broker_params=None, + message_broker_forgone_params=None, + exclude_request_uri=False, +): + """make assertions based off the cross-agent spec on transaction traces""" + required_params = required_params or {} + forgone_params = forgone_params or {} + datastore_params = datastore_params or {} + datastore_forgone_params = datastore_forgone_params or {} + message_broker_params = message_broker_params or {} + message_broker_forgone_params = message_broker_forgone_params or [] + + @function_wrapper + def _validate_wrapper(wrapped, instance, args, kwargs): + + traces_recorded = [] + + @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") + def _validate_tt_collector_json(wrapped, instance, args, kwargs): + + result = wrapped(*args, **kwargs) + + # Now that transaction has been recorded, generate + # a transaction trace + + connections = SQLConnections() + trace_data = instance.transaction_trace_data(connections) + traces_recorded.append(trace_data) + + return result + + def _validate_trace(trace): + assert isinstance(trace[0], float) # absolute start time (ms) + assert isinstance(trace[1], float) # duration (ms) + assert trace[0] > 0 # absolute time (ms) + assert isinstance(trace[2], six.string_types) # transaction name + if trace[2].startswith("WebTransaction"): + if exclude_request_uri: + assert trace[3] is None # request url + else: + assert isinstance(trace[3], six.string_types) + # query parameters should not be captured + assert "?" not in trace[3] + + # trace details -- python agent always uses condensed trace array + + trace_details, string_table = unpack_field(trace[4]) + assert len(trace_details) == 5 + assert isinstance(trace_details[0], float) # start time (ms) + + # the next two items should be empty dicts, old parameters stuff, + # placeholders for now + + assert isinstance(trace_details[1], dict) + assert len(trace_details[1]) == 0 + assert isinstance(trace_details[2], dict) + assert len(trace_details[2]) == 0 + + # root node in slot 3 + + root_node = trace_details[3] + assert isinstance(root_node[0], float) # entry timestamp + assert isinstance(root_node[1], float) # exit timestamp + assert root_node[2] == "ROOT" + assert isinstance(root_node[3], dict) + assert len(root_node[3]) == 0 # spec shows empty (for root) + children = root_node[4] + assert isinstance(children, list) + + # there are two optional items at the end of trace segments, + # class name that segment is in, and method name function is in; + # Python agent does not use these (only Java does) + + # let's just test the first child + trace_segment = children[0] + assert isinstance(trace_segment[0], float) # entry timestamp + assert isinstance(trace_segment[1], float) # exit timestamp + assert isinstance(trace_segment[2], six.string_types) # scope + assert isinstance(trace_segment[3], dict) # request params + assert isinstance(trace_segment[4], list) # children + + assert trace_segment[0] >= root_node[0] # trace starts after root + + def _check_params_and_start_time(node): + children = node[4] + for child in children: + assert child[0] >= node[0] # child started after parent + _check_params_and_start_time(child) + + params = node[3] + assert isinstance(params, dict) + + # We should always report exclusive_duration_millis on a + # segment. This allows us to override exclusive time + # calculations on APM. + assert "exclusive_duration_millis" in params + assert isinstance(params["exclusive_duration_millis"], float) + + segment_name = _lookup_string_table(node[2], string_table, default=node[2]) + if segment_name.startswith("Datastore"): + for key in datastore_params: + assert key in params, key + assert params[key] == datastore_params[key] + for key in datastore_forgone_params: + assert key not in params, key + + # if host is reported, it cannot be localhost + if "host" in params: + assert params["host"] not in LOCALHOST_EQUIVALENTS + + elif segment_name.startswith("MessageBroker"): + for key in message_broker_params: + assert key in params, key + assert params[key] == message_broker_params[key] + for key in message_broker_forgone_params: + assert key not in params, key + + _check_params_and_start_time(trace_segment) + + attributes = trace_details[4] + + assert "intrinsics" in attributes + assert "userAttributes" in attributes + assert "agentAttributes" in attributes + + assert isinstance(trace[5], six.string_types) # GUID + assert trace[6] is None # reserved for future use + assert trace[7] is False # deprecated force persist flag + + # x-ray session ID + + assert trace[8] is None + + # Synthetics ID + + assert trace[9] is None or isinstance(trace[9], six.string_types) + + assert isinstance(string_table, list) + for name in string_table: + assert isinstance(name, six.string_types) # metric name + + _new_wrapper = _validate_tt_collector_json(wrapped) + val = _new_wrapper(*args, **kwargs) + trace_data = traces_recorded.pop() + trace = trace_data[0] # 1st trace + _validate_trace(trace) + return val + + return _validate_wrapper From 6ce729d017feff431a44ab3854b1fb18f36af082 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Mon, 19 Sep 2022 16:58:35 -0700 Subject: [PATCH 15/23] Move validate_transaction_trace_attributes into validator directory --- .../test_attributes_in_action.py | 6 +- .../test_event_loop_wait_time.py | 10 +- tests/agent_features/test_lambda_handler.py | 279 +++---- tests/agent_features/test_span_events.py | 731 +++++++++--------- ...n_event_data_and_some_browser_stuff_too.py | 272 +++---- tests/agent_features/test_wsgi_attributes.py | 8 +- tests/datastore_aredis/test_trace_node.py | 11 +- tests/framework_aiohttp/test_server_cat.py | 173 +++-- tests/framework_sanic/test_application.py | 310 ++++---- .../framework_sanic/test_cross_application.py | 150 ++-- tests/framework_tornado/test_server.py | 219 +++--- tests/testing_support/fixtures.py | 68 +- .../validate_transaction_trace_attributes.py | 69 ++ 13 files changed, 1256 insertions(+), 1050 deletions(-) create mode 100644 tests/testing_support/validators/validate_transaction_trace_attributes.py diff --git a/tests/agent_features/test_attributes_in_action.py b/tests/agent_features/test_attributes_in_action.py index 31c5d625d..3dde59b0f 100644 --- a/tests/agent_features/test_attributes_in_action.py +++ b/tests/agent_features/test_attributes_in_action.py @@ -25,10 +25,14 @@ validate_error_event_attributes_outside_transaction, validate_error_trace_attributes_outside_transaction, validate_transaction_error_trace_attributes, +) +from testing_support.validators.validate_span_events import validate_span_events +from testing_support.validators.validate_transaction_event_attributes import ( validate_transaction_event_attributes, +) +from testing_support.validators.validate_transaction_trace_attributes import ( validate_transaction_trace_attributes, ) -from testing_support.validators.validate_span_events import validate_span_events from newrelic.api.application import application_instance as application from newrelic.api.message_transaction import message_transaction diff --git a/tests/agent_features/test_event_loop_wait_time.py b/tests/agent_features/test_event_loop_wait_time.py index f93e78c23..c5af1e9dd 100644 --- a/tests/agent_features/test_event_loop_wait_time.py +++ b/tests/agent_features/test_event_loop_wait_time.py @@ -16,13 +16,17 @@ import time import pytest -from testing_support.fixtures import ( - override_application_settings, +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_event_attributes import ( validate_transaction_event_attributes, +) +from testing_support.validators.validate_transaction_metrics import ( + validate_transaction_metrics, +) +from testing_support.validators.validate_transaction_trace_attributes import ( validate_transaction_trace_attributes, ) -from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics from newrelic.api.background_task import background_task from newrelic.api.function_trace import FunctionTrace, function_trace from newrelic.api.transaction import current_transaction diff --git a/tests/agent_features/test_lambda_handler.py b/tests/agent_features/test_lambda_handler.py index 4ff932e36..27240a3cc 100644 --- a/tests/agent_features/test_lambda_handler.py +++ b/tests/agent_features/test_lambda_handler.py @@ -13,11 +13,17 @@ # limitations under the License. import functools -import pytest from copy import deepcopy -from testing_support.fixtures import (override_application_settings, - validate_transaction_trace_attributes, - validate_transaction_event_attributes) + +import pytest +from testing_support.fixtures import override_application_settings +from testing_support.validators.validate_transaction_event_attributes import ( + validate_transaction_event_attributes, +) +from testing_support.validators.validate_transaction_trace_attributes import ( + validate_transaction_trace_attributes, +) + import newrelic.api.lambda_handler as lambda_handler @@ -27,7 +33,7 @@ @pytest.fixture(autouse=True) def force_cold_start_status(request): try: - is_cold_start = request.getfixturevalue('is_cold') + is_cold_start = request.getfixturevalue("is_cold") lambda_handler.COLD_START_RECORDED = not is_cold_start except Exception: lambda_handler.COLD_START_RECORDED = True @@ -36,63 +42,65 @@ def force_cold_start_status(request): @lambda_handler.lambda_handler() def handler(event, context): return { - 'statusCode': '200', - 'body': '{}', - 'headers': { - 'Content-Type': 'application/json', - 'Content-Length': 2, + "statusCode": "200", + "body": "{}", + "headers": { + "Content-Type": "application/json", + "Content-Length": 2, }, } _override_settings = { - 'attributes.include': ['request.parameters.*', 'request.headers.*'], + "attributes.include": ["request.parameters.*", "request.headers.*"], } _expected_attributes = { - 'agent': [ - 'aws.requestId', - 'aws.lambda.arn', - 'request.method', - 'request.uri', - 'response.status', - 'response.headers.contentType', - 'response.headers.contentLength', + "agent": [ + "aws.requestId", + "aws.lambda.arn", + "request.method", + "request.uri", + "response.status", + "response.headers.contentType", + "response.headers.contentLength", ], - 'user': [], - 'intrinsic': [], + "user": [], + "intrinsic": [], } _exact_attrs = { - 'agent': { - 'request.parameters.foo': 'bar', - 'request.headers.host': 'myhost', + "agent": { + "request.parameters.foo": "bar", + "request.headers.host": "myhost", }, - 'user': {}, - 'intrinsic': {} + "user": {}, + "intrinsic": {}, } empty_event = {} firehose_event = { - "records": [{ - "recordId": "495469866831355442", - "data": "SGVsbG8sIHRoaXMgaXMgYSB0ZXN0IDEyMy4=", - "approximateArrivalTimestamp": 1495072949453 - }], + "records": [ + { + "recordId": "495469866831355442", + "data": "SGVsbG8sIHRoaXMgaXMgYSB0ZXN0IDEyMy4=", + "approximateArrivalTimestamp": 1495072949453, + } + ], "region": "us-west-2", "deliveryStreamArn": "arn:aws:kinesis:EXAMPLE", - "invocationId": "invocationIdExample" + "invocationId": "invocationIdExample", } class Context(object): - aws_request_id = 'cookies' - invoked_function_arn = 'arn' - function_name = 'cats' - function_version = '$LATEST' + aws_request_id = "cookies" + invoked_function_arn = "arn" + function_name = "cats" + function_version = "$LATEST" memory_limit_in_mb = 128 -@pytest.mark.parametrize('is_cold', (False, True)) +@pytest.mark.parametrize("is_cold", (False, True)) def test_lambda_transaction_attributes(is_cold, monkeypatch): # setup copies of the attribute lists for this test only _forgone_params = {} @@ -101,36 +109,32 @@ def test_lambda_transaction_attributes(is_cold, monkeypatch): # if we have a cold start, then we should see aws.lambda.coldStart=True if is_cold: - _exact['agent']['aws.lambda.coldStart'] = True - _expected['agent'].append('aws.lambda.coldStart') + _exact["agent"]["aws.lambda.coldStart"] = True + _expected["agent"].append("aws.lambda.coldStart") # otherwise, then we need to make sure that we don't see it at all else: - _forgone_params = { - 'agent': ['aws.lambda.coldStart'], - 'user': [], - 'intrinsic': [] - } + _forgone_params = {"agent": ["aws.lambda.coldStart"], "user": [], "intrinsic": []} - @validate_transaction_trace_attributes( - required_params=_expected, - forgone_params=_forgone_params) + @validate_transaction_trace_attributes(required_params=_expected, forgone_params=_forgone_params) @validate_transaction_event_attributes( - required_params=_expected, - forgone_params=_forgone_params, - exact_attrs=_exact) + required_params=_expected, forgone_params=_forgone_params, exact_attrs=_exact + ) @override_application_settings(_override_settings) def _test(): - monkeypatch.setenv('AWS_REGION', 'earth') - handler({ - 'httpMethod': 'GET', - 'path': '/', - 'headers': { - 'HOST': 'myhost', + monkeypatch.setenv("AWS_REGION", "earth") + handler( + { + "httpMethod": "GET", + "path": "/", + "headers": { + "HOST": "myhost", + }, + "queryStringParameters": {"foo": "bar"}, + "multiValueQueryStringParameters": {"foo": ["bar"]}, }, - 'queryStringParameters': {'foo': 'bar'}, - 'multiValueQueryStringParameters': {'foo': ['bar']}, - }, Context) + Context, + ) _test() @@ -139,23 +143,26 @@ def _test(): @validate_transaction_event_attributes(_expected_attributes) @override_application_settings(_override_settings) def test_lambda_malformed_api_gateway_payload(monkeypatch): - monkeypatch.setenv('AWS_REGION', 'earth') - handler({ - 'httpMethod': 'GET', - 'path': '/', - 'headers': {}, - 'queryStringParameters': 42, - 'multiValueQueryStringParameters': 42, - }, Context) + monkeypatch.setenv("AWS_REGION", "earth") + handler( + { + "httpMethod": "GET", + "path": "/", + "headers": {}, + "queryStringParameters": 42, + "multiValueQueryStringParameters": 42, + }, + Context, + ) _malformed_request_attributes = { - 'agent': [ - 'aws.requestId', - 'aws.lambda.arn', + "agent": [ + "aws.requestId", + "aws.lambda.arn", ], - 'user': [], - 'intrinsic': [], + "user": [], + "intrinsic": [], } @@ -163,23 +170,26 @@ def test_lambda_malformed_api_gateway_payload(monkeypatch): @validate_transaction_event_attributes(_malformed_request_attributes) @override_application_settings(_override_settings) def test_lambda_malformed_request_headers(): - handler({ - 'httpMethod': 'GET', - 'path': '/', - 'headers': None, - }, Context) + handler( + { + "httpMethod": "GET", + "path": "/", + "headers": None, + }, + Context, + ) _malformed_response_attributes = { - 'agent': [ - 'aws.requestId', - 'aws.lambda.arn', - 'request.method', - 'request.uri', - 'response.status', + "agent": [ + "aws.requestId", + "aws.lambda.arn", + "request.method", + "request.uri", + "response.status", ], - 'user': [], - 'intrinsic': [], + "user": [], + "intrinsic": [], } @@ -187,33 +197,35 @@ def test_lambda_malformed_request_headers(): @validate_transaction_event_attributes(_malformed_response_attributes) @override_application_settings(_override_settings) def test_lambda_malformed_response_headers(): - @lambda_handler.lambda_handler() def handler(event, context): return { - 'statusCode': 200, - 'body': '{}', - 'headers': None, + "statusCode": 200, + "body": "{}", + "headers": None, } - handler({ - 'httpMethod': 'GET', - 'path': '/', - 'headers': {}, - }, Context) + handler( + { + "httpMethod": "GET", + "path": "/", + "headers": {}, + }, + Context, + ) _no_status_code_response = { - 'agent': [ - 'aws.requestId', - 'aws.lambda.arn', - 'request.method', - 'request.uri', - 'response.headers.contentType', - 'response.headers.contentLength', + "agent": [ + "aws.requestId", + "aws.lambda.arn", + "request.method", + "request.uri", + "response.headers.contentType", + "response.headers.contentLength", ], - 'user': [], - 'intrinsic': [], + "user": [], + "intrinsic": [], } @@ -221,53 +233,51 @@ def handler(event, context): @validate_transaction_event_attributes(_no_status_code_response) @override_application_settings(_override_settings) def test_lambda_no_status_code_response(): - @lambda_handler.lambda_handler() def handler(event, context): return { - 'body': '{}', - 'headers': { - 'Content-Type': 'application/json', - 'Content-Length': 2, + "body": "{}", + "headers": { + "Content-Type": "application/json", + "Content-Length": 2, }, } - handler({ - 'httpMethod': 'GET', - 'path': '/', - 'headers': {}, - }, Context) + handler( + { + "httpMethod": "GET", + "path": "/", + "headers": {}, + }, + Context, + ) -@pytest.mark.parametrize('event,arn', ( - (empty_event, None), - (firehose_event, 'arn:aws:kinesis:EXAMPLE'))) +@pytest.mark.parametrize("event,arn", ((empty_event, None), (firehose_event, "arn:aws:kinesis:EXAMPLE"))) def test_lambda_event_source_arn_attribute(event, arn): if arn is None: _exact = None _expected = None _forgone = { - 'user': [], 'intrinsic': [], - 'agent': ['aws.lambda.eventSource.arn'], + "user": [], + "intrinsic": [], + "agent": ["aws.lambda.eventSource.arn"], } else: _exact = { - 'user': {}, 'intrinsic': {}, - 'agent': {'aws.lambda.eventSource.arn': arn}, + "user": {}, + "intrinsic": {}, + "agent": {"aws.lambda.eventSource.arn": arn}, } _expected = { - 'user': [], 'intrinsic': [], - 'agent': ['aws.lambda.eventSource.arn'], + "user": [], + "intrinsic": [], + "agent": ["aws.lambda.eventSource.arn"], } _forgone = None - @validate_transaction_trace_attributes( - required_params=_expected, - forgone_params=_forgone) - @validate_transaction_event_attributes( - required_params=_expected, - forgone_params=_forgone, - exact_attrs=_exact) + @validate_transaction_trace_attributes(required_params=_expected, forgone_params=_forgone) + @validate_transaction_event_attributes(required_params=_expected, forgone_params=_forgone, exact_attrs=_exact) @override_application_settings(_override_settings) def _test(): handler(event, Context) @@ -275,10 +285,13 @@ def _test(): _test() -@pytest.mark.parametrize('api', ( - lambda_handler.lambda_handler, - functools.partial(lambda_handler.LambdaHandlerWrapper, handler), -)) +@pytest.mark.parametrize( + "api", + ( + lambda_handler.lambda_handler, + functools.partial(lambda_handler.LambdaHandlerWrapper, handler), + ), +) def test_deprecation_warnings(api): with pytest.deprecated_call(): api() diff --git a/tests/agent_features/test_span_events.py b/tests/agent_features/test_span_events.py index 4c4eecc69..211c0a20c 100644 --- a/tests/agent_features/test_span_events.py +++ b/tests/agent_features/test_span_events.py @@ -12,15 +12,24 @@ # See the License for the specific language governing permissions and # limitations under the License. -import pytest import sys -from newrelic.api.transaction import current_transaction -from newrelic.api.time_trace import (current_trace, - add_custom_span_attribute, notice_error) -from newrelic.api.background_task import background_task -from newrelic.common.object_names import callable_name +import pytest +from testing_support.fixtures import ( + dt_enabled, + function_not_called, + override_application_settings, + validate_tt_segment_params, +) +from testing_support.validators.validate_span_events import validate_span_events +from testing_support.validators.validate_transaction_event_attributes import ( + validate_transaction_event_attributes, +) +from testing_support.validators.validate_transaction_metrics import ( + validate_transaction_metrics, +) +from newrelic.api.background_task import background_task from newrelic.api.database_trace import DatabaseTrace from newrelic.api.datastore_trace import DatastoreTrace from newrelic.api.external_trace import ExternalTrace @@ -28,82 +37,73 @@ from newrelic.api.memcache_trace import MemcacheTrace from newrelic.api.message_trace import MessageTrace from newrelic.api.solr_trace import SolrTrace - -from testing_support.fixtures import (override_application_settings, - function_not_called, validate_tt_segment_params, - dt_enabled, - validate_transaction_event_attributes) -from testing_support.validators.validate_span_events import ( - validate_span_events) -from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from newrelic.api.time_trace import ( + add_custom_span_attribute, + current_trace, + notice_error, +) +from newrelic.api.transaction import current_transaction +from newrelic.common.object_names import callable_name ERROR = ValueError("whoops") ERROR_NAME = callable_name(ERROR) -@pytest.mark.parametrize('dt_enabled', (True, False)) -@pytest.mark.parametrize('span_events_enabled', (True, False)) -@pytest.mark.parametrize('txn_sampled', (True, False)) +@pytest.mark.parametrize("dt_enabled", (True, False)) +@pytest.mark.parametrize("span_events_enabled", (True, False)) +@pytest.mark.parametrize("txn_sampled", (True, False)) def test_span_events(dt_enabled, span_events_enabled, txn_sampled): - guid = 'dbb536c53b749e0b' - sentinel_guid = '0687e0c371ea2c4e' - function_guid = '482439c52de807ee' - transaction_name = 'OtherTransaction/Function/transaction' + guid = "dbb536c53b749e0b" + sentinel_guid = "0687e0c371ea2c4e" + function_guid = "482439c52de807ee" + transaction_name = "OtherTransaction/Function/transaction" priority = 0.5 - @function_trace(name='child') + @function_trace(name="child") def child(): pass - @function_trace(name='function') + @function_trace(name="function") def function(): current_trace().guid = function_guid child() - _settings = { - 'distributed_tracing.enabled': dt_enabled, - 'span_events.enabled': span_events_enabled - } + _settings = {"distributed_tracing.enabled": dt_enabled, "span_events.enabled": span_events_enabled} count = 0 if dt_enabled and span_events_enabled and txn_sampled: count = 1 exact_intrinsics_common = { - 'type': 'Span', - 'transactionId': guid, - 'sampled': txn_sampled, - 'priority': priority, - 'category': 'generic', + "type": "Span", + "transactionId": guid, + "sampled": txn_sampled, + "priority": priority, + "category": "generic", } - expected_intrinsics = ('timestamp', 'duration') + expected_intrinsics = ("timestamp", "duration") exact_intrinsics_root = exact_intrinsics_common.copy() - exact_intrinsics_root['name'] = 'Function/transaction' - exact_intrinsics_root['transaction.name'] = transaction_name - exact_intrinsics_root['nr.entryPoint'] = True + exact_intrinsics_root["name"] = "Function/transaction" + exact_intrinsics_root["transaction.name"] = transaction_name + exact_intrinsics_root["nr.entryPoint"] = True exact_intrinsics_function = exact_intrinsics_common.copy() - exact_intrinsics_function['name'] = 'Function/function' - exact_intrinsics_function['parentId'] = sentinel_guid + exact_intrinsics_function["name"] = "Function/function" + exact_intrinsics_function["parentId"] = sentinel_guid exact_intrinsics_child = exact_intrinsics_common.copy() - exact_intrinsics_child['name'] = 'Function/child' - exact_intrinsics_child['parentId'] = function_guid - - @validate_span_events(count=count, - expected_intrinsics=['nr.entryPoint']) - @validate_span_events(count=count, - exact_intrinsics=exact_intrinsics_root, - expected_intrinsics=expected_intrinsics) - @validate_span_events(count=count, - exact_intrinsics=exact_intrinsics_function, - expected_intrinsics=expected_intrinsics) - @validate_span_events(count=count, - exact_intrinsics=exact_intrinsics_child, - expected_intrinsics=expected_intrinsics) + exact_intrinsics_child["name"] = "Function/child" + exact_intrinsics_child["parentId"] = function_guid + + @validate_span_events(count=count, expected_intrinsics=["nr.entryPoint"]) + @validate_span_events(count=count, exact_intrinsics=exact_intrinsics_root, expected_intrinsics=expected_intrinsics) + @validate_span_events( + count=count, exact_intrinsics=exact_intrinsics_function, expected_intrinsics=expected_intrinsics + ) + @validate_span_events(count=count, exact_intrinsics=exact_intrinsics_child, expected_intrinsics=expected_intrinsics) @override_application_settings(_settings) - @background_task(name='transaction') + @background_task(name="transaction") def _test(): # Force intrinsics txn = current_transaction() @@ -117,22 +117,27 @@ def _test(): _test() -@pytest.mark.parametrize('trace_type,args', ( - (DatabaseTrace, ('select * from foo', )), - (DatastoreTrace, ('db_product', 'db_target', 'db_operation')), - (ExternalTrace, ('lib', 'url')), - (FunctionTrace, ('name', )), - (MemcacheTrace, ('command', )), - (MessageTrace, ('lib', 'operation', 'dst_type', 'dst_name')), - (SolrTrace, ('lib', 'command')), -)) +@pytest.mark.parametrize( + "trace_type,args", + ( + (DatabaseTrace, ("select * from foo",)), + (DatastoreTrace, ("db_product", "db_target", "db_operation")), + (ExternalTrace, ("lib", "url")), + (FunctionTrace, ("name",)), + (MemcacheTrace, ("command",)), + (MessageTrace, ("lib", "operation", "dst_type", "dst_name")), + (SolrTrace, ("lib", "command")), + ), +) def test_each_span_type(trace_type, args): @validate_span_events(count=2) - @override_application_settings({ - 'distributed_tracing.enabled': True, - 'span_events.enabled': True, - }) - @background_task(name='test_each_span_type') + @override_application_settings( + { + "distributed_tracing.enabled": True, + "span_events.enabled": True, + } + ) + @background_task(name="test_each_span_type") def _test(): transaction = current_transaction() @@ -144,37 +149,37 @@ def _test(): _test() -@pytest.mark.parametrize('sql,sql_format,expected', ( - pytest.param( - 'a' * 2001, - 'raw', - ''.join(['a'] * 1997 + ['...']), - id='truncate'), - pytest.param( - 'a' * 2000, - 'raw', - ''.join(['a'] * 2000), - id='no_truncate'), - pytest.param( - 'select * from %s' % ''.join(['?'] * 2000), - 'obfuscated', - 'select * from %s...' % ( - ''.join(['?'] * (2000 - len('select * from ') - 3))), - id='truncate_obfuscated'), - pytest.param('select 1', 'off', ''), - pytest.param('select 1', 'raw', 'select 1'), - pytest.param('select 1', 'obfuscated', 'select ?'), -)) +@pytest.mark.parametrize( + "sql,sql_format,expected", + ( + pytest.param("a" * 2001, "raw", "".join(["a"] * 1997 + ["..."]), id="truncate"), + pytest.param("a" * 2000, "raw", "".join(["a"] * 2000), id="no_truncate"), + pytest.param( + "select * from %s" % "".join(["?"] * 2000), + "obfuscated", + "select * from %s..." % ("".join(["?"] * (2000 - len("select * from ") - 3))), + id="truncate_obfuscated", + ), + pytest.param("select 1", "off", ""), + pytest.param("select 1", "raw", "select 1"), + pytest.param("select 1", "obfuscated", "select ?"), + ), +) def test_database_db_statement_format(sql, sql_format, expected): - @validate_span_events(count=1, exact_agents={ - 'db.statement': expected, - }) - @override_application_settings({ - 'distributed_tracing.enabled': True, - 'span_events.enabled': True, - 'transaction_tracer.record_sql': sql_format, - }) - @background_task(name='test_database_db_statement_format') + @validate_span_events( + count=1, + exact_agents={ + "db.statement": expected, + }, + ) + @override_application_settings( + { + "distributed_tracing.enabled": True, + "span_events.enabled": True, + "transaction_tracer.record_sql": sql_format, + } + ) + @background_task(name="test_database_db_statement_format") def _test(): transaction = current_transaction() transaction._sampled = True @@ -187,115 +192,130 @@ def _test(): @validate_span_events( count=1, - exact_intrinsics={'category': 'datastore'}, - unexpected_agents=['db.statement'], + exact_intrinsics={"category": "datastore"}, + unexpected_agents=["db.statement"], +) +@override_application_settings( + { + "distributed_tracing.enabled": True, + "span_events.enabled": True, + "span_events.attributes.exclude": ["db.statement"], + } ) -@override_application_settings({ - 'distributed_tracing.enabled': True, - 'span_events.enabled': True, - 'span_events.attributes.exclude': ['db.statement'], -}) -@background_task(name='test_database_db_statement_exclude') +@background_task(name="test_database_db_statement_exclude") def test_database_db_statement_exclude(): transaction = current_transaction() transaction._sampled = True - with DatabaseTrace('select 1'): + with DatabaseTrace("select 1"): pass -@pytest.mark.parametrize('trace_type,args,attrs', ( - (DatastoreTrace, ('db_product', 'db_target', 'db_operation'), {"db.collection": "db_target", "db.operation": "db_operation"}), - (DatabaseTrace, ("select 1 from db_table",), {"db.collection": "db_table", "db.statement": "select ? from db_table"}), -)) +@pytest.mark.parametrize( + "trace_type,args,attrs", + ( + ( + DatastoreTrace, + ("db_product", "db_target", "db_operation"), + {"db.collection": "db_target", "db.operation": "db_operation"}, + ), + ( + DatabaseTrace, + ("select 1 from db_table",), + {"db.collection": "db_table", "db.statement": "select ? from db_table"}, + ), + ), +) def test_datastore_database_trace_attrs(trace_type, args, attrs): @validate_span_events( count=1, exact_agents=attrs, ) - @override_application_settings({ - 'distributed_tracing.enabled': True, - 'span_events.enabled': True, - }) - @background_task(name='test_database_db_statement_exclude') + @override_application_settings( + { + "distributed_tracing.enabled": True, + "span_events.enabled": True, + } + ) + @background_task(name="test_database_db_statement_exclude") def test(): transaction = current_transaction() transaction._sampled = True with trace_type(*args): pass - + test() -@pytest.mark.parametrize('exclude_url', (True, False)) +@pytest.mark.parametrize("exclude_url", (True, False)) def test_external_spans(exclude_url): override_settings = { - 'distributed_tracing.enabled': True, - 'span_events.enabled': True, + "distributed_tracing.enabled": True, + "span_events.enabled": True, } if exclude_url: - override_settings['span_events.attributes.exclude'] = ['http.url'] + override_settings["span_events.attributes.exclude"] = ["http.url"] exact_agents = {} - unexpected_agents = ['http.url'] + unexpected_agents = ["http.url"] else: - exact_agents = {'http.url': 'http://example.com/foo'} + exact_agents = {"http.url": "http://example.com/foo"} unexpected_agents = [] @validate_span_events( count=1, exact_intrinsics={ - 'name': 'External/example.com/library/get', - 'type': 'Span', - 'sampled': True, - - 'category': 'http', - 'span.kind': 'client', - 'component': 'library', - 'http.method': 'get', + "name": "External/example.com/library/get", + "type": "Span", + "sampled": True, + "category": "http", + "span.kind": "client", + "component": "library", + "http.method": "get", }, exact_agents=exact_agents, unexpected_agents=unexpected_agents, - expected_intrinsics=('priority',), + expected_intrinsics=("priority",), ) @override_application_settings(override_settings) - @background_task(name='test_external_spans') + @background_task(name="test_external_spans") def _test(): transaction = current_transaction() transaction._sampled = True - with ExternalTrace( - library='library', - url='http://example.com/foo?secret=123', - method='get'): + with ExternalTrace(library="library", url="http://example.com/foo?secret=123", method="get"): pass _test() -@pytest.mark.parametrize('kwarg_override,attr_override', ( - ({'url': 'a' * 256}, {'http.url': 'a' * 255}), - ({'library': 'a' * 256}, {'component': 'a' * 255}), - ({'method': 'a' * 256}, {'http.method': 'a' * 255}), -)) -@override_application_settings({ - 'distributed_tracing.enabled': True, - 'span_events.enabled': True, -}) +@pytest.mark.parametrize( + "kwarg_override,attr_override", + ( + ({"url": "a" * 256}, {"http.url": "a" * 255}), + ({"library": "a" * 256}, {"component": "a" * 255}), + ({"method": "a" * 256}, {"http.method": "a" * 255}), + ), +) +@override_application_settings( + { + "distributed_tracing.enabled": True, + "span_events.enabled": True, + } +) def test_external_span_limits(kwarg_override, attr_override): exact_intrinsics = { - 'type': 'Span', - 'sampled': True, - - 'category': 'http', - 'span.kind': 'client', - 'component': 'library', - 'http.method': 'get', + "type": "Span", + "sampled": True, + "category": "http", + "span.kind": "client", + "component": "library", + "http.method": "get", } exact_agents = { - 'http.url': 'http://example.com/foo', + "http.url": "http://example.com/foo", } for attr_name, attr_value in attr_override.items(): if attr_name in exact_agents: @@ -304,9 +324,9 @@ def test_external_span_limits(kwarg_override, attr_override): exact_intrinsics[attr_name] = attr_value kwargs = { - 'library': 'library', - 'url': 'http://example.com/foo?secret=123', - 'method': 'get', + "library": "library", + "url": "http://example.com/foo?secret=123", + "method": "get", } kwargs.update(kwarg_override) @@ -314,9 +334,9 @@ def test_external_span_limits(kwarg_override, attr_override): count=1, exact_intrinsics=exact_intrinsics, exact_agents=exact_agents, - expected_intrinsics=('priority',), + expected_intrinsics=("priority",), ) - @background_task(name='test_external_spans') + @background_task(name="test_external_spans") def _test(): transaction = current_transaction() transaction._sampled = True @@ -327,32 +347,34 @@ def _test(): _test() -@pytest.mark.parametrize('kwarg_override,attribute_override', ( - ({'host': 'a' * 256}, - {'peer.hostname': 'a' * 255, 'peer.address': 'a' * 255}), - ({'port_path_or_id': 'a' * 256, 'host': 'a'}, - {'peer.hostname': 'a', 'peer.address': 'a:' + 'a' * 253}), - ({'database_name': 'a' * 256}, {'db.instance': 'a' * 255}), -)) -@override_application_settings({ - 'distributed_tracing.enabled': True, - 'span_events.enabled': True, -}) +@pytest.mark.parametrize( + "kwarg_override,attribute_override", + ( + ({"host": "a" * 256}, {"peer.hostname": "a" * 255, "peer.address": "a" * 255}), + ({"port_path_or_id": "a" * 256, "host": "a"}, {"peer.hostname": "a", "peer.address": "a:" + "a" * 253}), + ({"database_name": "a" * 256}, {"db.instance": "a" * 255}), + ), +) +@override_application_settings( + { + "distributed_tracing.enabled": True, + "span_events.enabled": True, + } +) def test_datastore_span_limits(kwarg_override, attribute_override): exact_intrinsics = { - 'type': 'Span', - 'sampled': True, - - 'category': 'datastore', - 'span.kind': 'client', - 'component': 'library', + "type": "Span", + "sampled": True, + "category": "datastore", + "span.kind": "client", + "component": "library", } exact_agents = { - 'db.instance': 'db', - 'peer.hostname': 'foo', - 'peer.address': 'foo:1234', + "db.instance": "db", + "peer.hostname": "foo", + "peer.address": "foo:1234", } for k, v in attribute_override.items(): @@ -362,22 +384,22 @@ def test_datastore_span_limits(kwarg_override, attribute_override): exact_intrinsics[k] = v kwargs = { - 'product': 'library', - 'target': 'table', - 'operation': 'operation', - 'host': 'foo', - 'port_path_or_id': 1234, - 'database_name': 'db', + "product": "library", + "target": "table", + "operation": "operation", + "host": "foo", + "port_path_or_id": 1234, + "database_name": "db", } kwargs.update(kwarg_override) @validate_span_events( count=1, exact_intrinsics=exact_intrinsics, - expected_intrinsics=('priority',), + expected_intrinsics=("priority",), exact_agents=exact_agents, ) - @background_task(name='test_external_spans') + @background_task(name="test_external_spans") def _test(): transaction = current_transaction() transaction._sampled = True @@ -388,10 +410,9 @@ def _test(): _test() -@pytest.mark.parametrize('collect_span_events', (False, True)) -@pytest.mark.parametrize('span_events_enabled', (False, True)) -def test_collect_span_events_override(collect_span_events, - span_events_enabled): +@pytest.mark.parametrize("collect_span_events", (False, True)) +@pytest.mark.parametrize("span_events_enabled", (False, True)) +def test_collect_span_events_override(collect_span_events, span_events_enabled): if collect_span_events and span_events_enabled: spans_expected = True @@ -401,63 +422,64 @@ def test_collect_span_events_override(collect_span_events, span_count = 2 if spans_expected else 0 @validate_span_events(count=span_count) - @override_application_settings({ - 'transaction_tracer.enabled': False, - 'distributed_tracing.enabled': True, - 'span_events.enabled': span_events_enabled, - 'collect_span_events': collect_span_events - }) - @background_task(name='test_collect_span_events_override') + @override_application_settings( + { + "transaction_tracer.enabled": False, + "distributed_tracing.enabled": True, + "span_events.enabled": span_events_enabled, + "collect_span_events": collect_span_events, + } + ) + @background_task(name="test_collect_span_events_override") def _test(): transaction = current_transaction() transaction._sampled = True - with FunctionTrace('span_generator'): + with FunctionTrace("span_generator"): pass if not spans_expected: - _test = function_not_called( - 'newrelic.core.attribute', - 'resolve_agent_attributes')(_test) + _test = function_not_called("newrelic.core.attribute", "resolve_agent_attributes")(_test) _test() -@pytest.mark.parametrize('include_attribues', (True, False)) +@pytest.mark.parametrize("include_attribues", (True, False)) def test_span_event_agent_attributes(include_attribues): override_settings = { - 'distributed_tracing.enabled': True, - 'span_events.enabled': True, + "distributed_tracing.enabled": True, + "span_events.enabled": True, } if include_attribues: count = 1 - override_settings['attributes.include'] = ['*'] + override_settings["attributes.include"] = ["*"] else: count = 0 @override_application_settings(override_settings) + @validate_span_events(count=count, expected_agents=["webfrontend.queue.seconds"]) @validate_span_events( - count=count, expected_agents=['webfrontend.queue.seconds']) - @validate_span_events( - count=count, - exact_agents={'trace1_a': 'foobar', 'trace1_b': 'barbaz'}, - unexpected_agents=['trace2_a', 'trace2_b']) + count=count, + exact_agents={"trace1_a": "foobar", "trace1_b": "barbaz"}, + unexpected_agents=["trace2_a", "trace2_b"], + ) @validate_span_events( - count=count, - exact_agents={'trace2_a': 'foobar', 'trace2_b': 'barbaz'}, - unexpected_agents=['trace1_a', 'trace1_b']) - @background_task(name='test_span_event_agent_attributes') + count=count, + exact_agents={"trace2_a": "foobar", "trace2_b": "barbaz"}, + unexpected_agents=["trace1_a", "trace1_b"], + ) + @background_task(name="test_span_event_agent_attributes") def _test(): transaction = current_transaction() transaction.queue_start = 1.0 transaction._sampled = True - with FunctionTrace('trace1') as trace_1: - trace_1._add_agent_attribute('trace1_a', 'foobar') - trace_1._add_agent_attribute('trace1_b', 'barbaz') - with FunctionTrace('trace2') as trace_2: - trace_2._add_agent_attribute('trace2_a', 'foobar') - trace_2._add_agent_attribute('trace2_b', 'barbaz') + with FunctionTrace("trace1") as trace_1: + trace_1._add_agent_attribute("trace1_a", "foobar") + trace_1._add_agent_attribute("trace1_b", "barbaz") + with FunctionTrace("trace2") as trace_2: + trace_2._add_agent_attribute("trace2_a", "foobar") + trace_2._add_agent_attribute("trace2_b", "barbaz") _test() @@ -470,31 +492,36 @@ def __exit__(self, *args): pass -@pytest.mark.parametrize('trace_type,args', ( - (DatabaseTrace, ('select * from foo', )), - (DatastoreTrace, ('db_product', 'db_target', 'db_operation')), - (ExternalTrace, ('lib', 'url')), - (FunctionTrace, ('name', )), - (MemcacheTrace, ('command', )), - (MessageTrace, ('lib', 'operation', 'dst_type', 'dst_name')), - (SolrTrace, ('lib', 'command')), - (FakeTrace, ()), -)) -@pytest.mark.parametrize('exclude_attributes', (True, False)) +@pytest.mark.parametrize( + "trace_type,args", + ( + (DatabaseTrace, ("select * from foo",)), + (DatastoreTrace, ("db_product", "db_target", "db_operation")), + (ExternalTrace, ("lib", "url")), + (FunctionTrace, ("name",)), + (MemcacheTrace, ("command",)), + (MessageTrace, ("lib", "operation", "dst_type", "dst_name")), + (SolrTrace, ("lib", "command")), + (FakeTrace, ()), + ), +) +@pytest.mark.parametrize("exclude_attributes", (True, False)) def test_span_event_user_attributes(trace_type, args, exclude_attributes): _settings = { - 'distributed_tracing.enabled': True, - 'span_events.enabled': True, + "distributed_tracing.enabled": True, + "span_events.enabled": True, } - forgone_params = ['invalid_value', ] - expected_params = {'trace1_a': 'foobar', 'trace1_b': 'barbaz'} + forgone_params = [ + "invalid_value", + ] + expected_params = {"trace1_a": "foobar", "trace1_b": "barbaz"} # We expect user_attributes to be included by default if exclude_attributes: count = 0 - _settings['attributes.exclude'] = ['*'] - forgone_params.extend(('trace1_a', 'trace1_b')) + _settings["attributes.exclude"] = ["*"] + forgone_params.extend(("trace1_a", "trace1_b")) expected_trace_params = {} else: expected_trace_params = expected_params @@ -504,44 +531,44 @@ def test_span_event_user_attributes(trace_type, args, exclude_attributes): @validate_span_events( count=count, exact_users=expected_params, - unexpected_users=forgone_params,) - @validate_tt_segment_params(exact_params=expected_trace_params, - forgone_params=forgone_params) - @background_task(name='test_span_event_user_attributes') + unexpected_users=forgone_params, + ) + @validate_tt_segment_params(exact_params=expected_trace_params, forgone_params=forgone_params) + @background_task(name="test_span_event_user_attributes") def _test(): transaction = current_transaction() transaction._sampled = True with trace_type(*args): - add_custom_span_attribute('trace1_a', 'foobar') - add_custom_span_attribute('trace1_b', 'barbaz') - add_custom_span_attribute('invalid_value', sys.maxsize + 1) + add_custom_span_attribute("trace1_a", "foobar") + add_custom_span_attribute("trace1_b", "barbaz") + add_custom_span_attribute("invalid_value", sys.maxsize + 1) _test() -@validate_span_events(count=1, exact_users={'foo': 'b'}) +@validate_span_events(count=1, exact_users={"foo": "b"}) @dt_enabled -@background_task(name='test_span_user_attribute_overrides_transaction_attribute') +@background_task(name="test_span_user_attribute_overrides_transaction_attribute") def test_span_user_attribute_overrides_transaction_attribute(): transaction = current_transaction() - transaction.add_custom_parameter('foo', 'a') - add_custom_span_attribute('foo', 'b') - transaction.add_custom_parameter('foo', 'c') + transaction.add_custom_parameter("foo", "a") + add_custom_span_attribute("foo", "b") + transaction.add_custom_parameter("foo", "c") -@override_application_settings({'attributes.include': '*'}) -@validate_span_events(count=1, exact_agents={'foo': 'b'}) +@override_application_settings({"attributes.include": "*"}) +@validate_span_events(count=1, exact_agents={"foo": "b"}) @dt_enabled -@background_task(name='test_span_agent_attribute_overrides_transaction_attribute') +@background_task(name="test_span_agent_attribute_overrides_transaction_attribute") def test_span_agent_attribute_overrides_transaction_attribute(): transaction = current_transaction() trace = current_trace() - transaction._add_agent_attribute('foo', 'a') - trace._add_agent_attribute('foo', 'b') - transaction._add_agent_attribute('foo', 'c') + transaction._add_agent_attribute("foo", "a") + trace._add_agent_attribute("foo", "b") + transaction._add_agent_attribute("foo", "c") def test_span_custom_attribute_limit(): @@ -556,71 +583,69 @@ def test_span_custom_attribute_limit(): for i in range(128): if i < 64: - span_custom_attrs.append('span_attr%i' % i) - txn_custom_attrs.append('txn_attr%i' % i) + span_custom_attrs.append("span_attr%i" % i) + txn_custom_attrs.append("txn_attr%i" % i) unexpected_txn_attrs.extend(span_custom_attrs) span_custom_attrs.extend(txn_custom_attrs[:64]) - expected_txn_attrs = {'user': txn_custom_attrs, 'agent': [], - 'intrinsic': []} - expected_absent_txn_attrs = {'agent': [], - 'user': unexpected_txn_attrs, - 'intrinsic': []} - - @override_application_settings({'attributes.include': '*'}) - @validate_transaction_event_attributes(expected_txn_attrs, - expected_absent_txn_attrs) - @validate_span_events(count=1, - expected_users=span_custom_attrs, - unexpected_users=txn_custom_attrs[64:]) + expected_txn_attrs = {"user": txn_custom_attrs, "agent": [], "intrinsic": []} + expected_absent_txn_attrs = {"agent": [], "user": unexpected_txn_attrs, "intrinsic": []} + + @override_application_settings({"attributes.include": "*"}) + @validate_transaction_event_attributes(expected_txn_attrs, expected_absent_txn_attrs) + @validate_span_events(count=1, expected_users=span_custom_attrs, unexpected_users=txn_custom_attrs[64:]) @dt_enabled - @background_task(name='test_span_attribute_limit') + @background_task(name="test_span_attribute_limit") def _test(): transaction = current_transaction() for i in range(128): - transaction.add_custom_parameter('txn_attr%i' % i, 'txnValue') + transaction.add_custom_parameter("txn_attr%i" % i, "txnValue") if i < 64: - add_custom_span_attribute('span_attr%i' % i, 'spanValue') + add_custom_span_attribute("span_attr%i" % i, "spanValue") + _test() _span_event_metrics = [("Supportability/SpanEvent/Errors/Dropped", None)] -@pytest.mark.parametrize('trace_type,args', ( - (DatabaseTrace, ('select * from foo', )), - (DatastoreTrace, ('db_product', 'db_target', 'db_operation')), - (ExternalTrace, ('lib', 'url')), - (FunctionTrace, ('name', )), - (MemcacheTrace, ('command', )), - (MessageTrace, ('lib', 'operation', 'dst_type', 'dst_name')), - (SolrTrace, ('lib', 'command')), - (FakeTrace, ()), -)) +@pytest.mark.parametrize( + "trace_type,args", + ( + (DatabaseTrace, ("select * from foo",)), + (DatastoreTrace, ("db_product", "db_target", "db_operation")), + (ExternalTrace, ("lib", "url")), + (FunctionTrace, ("name",)), + (MemcacheTrace, ("command",)), + (MessageTrace, ("lib", "operation", "dst_type", "dst_name")), + (SolrTrace, ("lib", "command")), + (FakeTrace, ()), + ), +) def test_span_event_error_attributes_notice_error(trace_type, args): _settings = { - 'distributed_tracing.enabled': True, - 'span_events.enabled': True, + "distributed_tracing.enabled": True, + "span_events.enabled": True, } error = ValueError("whoops") exact_agents = { - 'error.class': callable_name(error), - 'error.message': 'whoops', + "error.class": callable_name(error), + "error.message": "whoops", } @override_application_settings(_settings) @validate_transaction_metrics( - 'test_span_event_error_attributes_notice_error', - background_task=True, - rollup_metrics=_span_event_metrics) + "test_span_event_error_attributes_notice_error", background_task=True, rollup_metrics=_span_event_metrics + ) @validate_span_events( count=1, - exact_agents=exact_agents,) - @background_task(name='test_span_event_error_attributes_notice_error') + exact_agents=exact_agents, + ) + @background_task(name="test_span_event_error_attributes_notice_error") def _test(): transaction = current_transaction() transaction._sampled = True @@ -634,36 +659,39 @@ def _test(): _test() -@pytest.mark.parametrize('trace_type,args', ( - (DatabaseTrace, ('select * from foo', )), - (DatastoreTrace, ('db_product', 'db_target', 'db_operation')), - (ExternalTrace, ('lib', 'url')), - (FunctionTrace, ('name', )), - (MemcacheTrace, ('command', )), - (MessageTrace, ('lib', 'operation', 'dst_type', 'dst_name')), - (SolrTrace, ('lib', 'command')), -)) +@pytest.mark.parametrize( + "trace_type,args", + ( + (DatabaseTrace, ("select * from foo",)), + (DatastoreTrace, ("db_product", "db_target", "db_operation")), + (ExternalTrace, ("lib", "url")), + (FunctionTrace, ("name",)), + (MemcacheTrace, ("command",)), + (MessageTrace, ("lib", "operation", "dst_type", "dst_name")), + (SolrTrace, ("lib", "command")), + ), +) def test_span_event_error_attributes_observed(trace_type, args): error = ValueError("whoops") exact_agents = { - 'error.class': callable_name(error), - 'error.message': 'whoops', + "error.class": callable_name(error), + "error.message": "whoops", } # Verify errors are not recorded since notice_error is not called - rollups = [('Errors/all', None)] + _span_event_metrics + rollups = [("Errors/all", None)] + _span_event_metrics @dt_enabled @validate_transaction_metrics( - 'test_span_event_error_attributes_observed', - background_task=True, - rollup_metrics=rollups) + "test_span_event_error_attributes_observed", background_task=True, rollup_metrics=rollups + ) @validate_span_events( count=1, - exact_agents=exact_agents,) - @background_task(name='test_span_event_error_attributes_observed') + exact_agents=exact_agents, + ) + @background_task(name="test_span_event_error_attributes_observed") def _test(): try: with trace_type(*args): @@ -674,20 +702,22 @@ def _test(): _test() -@pytest.mark.parametrize('trace_type,args', ( - (DatabaseTrace, ('select * from foo', )), - (DatastoreTrace, ('db_product', 'db_target', 'db_operation')), - (ExternalTrace, ('lib', 'url')), - (FunctionTrace, ('name', )), - (MemcacheTrace, ('command', )), - (MessageTrace, ('lib', 'operation', 'dst_type', 'dst_name')), - (SolrTrace, ('lib', 'command')), - (FakeTrace, ()), -)) +@pytest.mark.parametrize( + "trace_type,args", + ( + (DatabaseTrace, ("select * from foo",)), + (DatastoreTrace, ("db_product", "db_target", "db_operation")), + (ExternalTrace, ("lib", "url")), + (FunctionTrace, ("name",)), + (MemcacheTrace, ("command",)), + (MessageTrace, ("lib", "operation", "dst_type", "dst_name")), + (SolrTrace, ("lib", "command")), + (FakeTrace, ()), + ), +) @dt_enabled -@validate_span_events(count=1, - exact_agents={'error.class': ERROR_NAME, 'error.message': 'whoops'}) -@background_task(name='test_span_event_notice_error_overrides_observed') +@validate_span_events(count=1, exact_agents={"error.class": ERROR_NAME, "error.message": "whoops"}) +@background_task(name="test_span_event_notice_error_overrides_observed") def test_span_event_notice_error_overrides_observed(trace_type, args): try: with trace_type(*args): @@ -700,21 +730,24 @@ def test_span_event_notice_error_overrides_observed(trace_type, args): pass -@pytest.mark.parametrize('trace_type,args', ( - (DatabaseTrace, ('select * from foo', )), - (DatastoreTrace, ('db_product', 'db_target', 'db_operation')), - (ExternalTrace, ('lib', 'url')), - (FunctionTrace, ('name', )), - (MemcacheTrace, ('command', )), - (MessageTrace, ('lib', 'operation', 'dst_type', 'dst_name')), - (SolrTrace, ('lib', 'command')), - (FakeTrace, ()), -)) -@override_application_settings({'error_collector.enabled': False}) -@validate_span_events(count=0, expected_agents=['error.class']) -@validate_span_events(count=0, expected_agents=['error.message']) +@pytest.mark.parametrize( + "trace_type,args", + ( + (DatabaseTrace, ("select * from foo",)), + (DatastoreTrace, ("db_product", "db_target", "db_operation")), + (ExternalTrace, ("lib", "url")), + (FunctionTrace, ("name",)), + (MemcacheTrace, ("command",)), + (MessageTrace, ("lib", "operation", "dst_type", "dst_name")), + (SolrTrace, ("lib", "command")), + (FakeTrace, ()), + ), +) +@override_application_settings({"error_collector.enabled": False}) +@validate_span_events(count=0, expected_agents=["error.class"]) +@validate_span_events(count=0, expected_agents=["error.message"]) @dt_enabled -@background_task(name='test_span_event_errors_disabled') +@background_task(name="test_span_event_errors_disabled") def test_span_event_errors_disabled(trace_type, args): with trace_type(*args): try: @@ -726,32 +759,34 @@ def test_span_event_errors_disabled(trace_type, args): _metrics = [("Supportability/SpanEvent/Errors/Dropped", 2)] -@pytest.mark.parametrize('trace_type,args', ( - (FunctionTrace, ('name', )), - (FakeTrace, ()), -)) +@pytest.mark.parametrize( + "trace_type,args", + ( + (FunctionTrace, ("name",)), + (FakeTrace, ()), + ), +) def test_span_event_multiple_errors(trace_type, args): _settings = { - 'distributed_tracing.enabled': True, - 'span_events.enabled': True, + "distributed_tracing.enabled": True, + "span_events.enabled": True, } error = ValueError("whoops") exact_agents = { - 'error.class': callable_name(error), - 'error.message': 'whoops', + "error.class": callable_name(error), + "error.message": "whoops", "error.expected": False, } @override_application_settings(_settings) @validate_span_events( count=1, - exact_agents=exact_agents,) - @validate_transaction_metrics("test_span_event_multiple_errors", - background_task=True, - rollup_metrics=_metrics) - @background_task(name='test_span_event_multiple_errors') + exact_agents=exact_agents, + ) + @validate_transaction_metrics("test_span_event_multiple_errors", background_task=True, rollup_metrics=_metrics) + @background_task(name="test_span_event_multiple_errors") def _test(): transaction = current_transaction() transaction._sampled = True diff --git a/tests/agent_features/test_transaction_event_data_and_some_browser_stuff_too.py b/tests/agent_features/test_transaction_event_data_and_some_browser_stuff_too.py index a99fc1cdd..c2e22b68a 100644 --- a/tests/agent_features/test_transaction_event_data_and_some_browser_stuff_too.py +++ b/tests/agent_features/test_transaction_event_data_and_some_browser_stuff_too.py @@ -13,36 +13,39 @@ # limitations under the License. import json + import webtest +from testing_support.fixtures import ( + override_application_settings, + validate_transaction_event_sample_data, +) +from testing_support.sample_applications import ( + fully_featured_app, + user_attributes_added, +) +from testing_support.validators.validate_transaction_event_attributes import ( + validate_transaction_event_attributes, +) from newrelic.api.application import application_settings from newrelic.api.background_task import background_task - from newrelic.common.encoding_utils import deobfuscate from newrelic.common.object_wrapper import transient_function_wrapper -from testing_support.fixtures import (override_application_settings, - validate_transaction_event_sample_data, - validate_transaction_event_attributes) -from testing_support.sample_applications import (fully_featured_app, - user_attributes_added) - - fully_featured_application = webtest.TestApp(fully_featured_app) _user_attributes = user_attributes_added() -#====================== Test cases ==================================== +# ====================== Test cases ==================================== -_test_capture_attributes_enabled_settings = { - 'browser_monitoring.attributes.enabled': True } +_test_capture_attributes_enabled_settings = {"browser_monitoring.attributes.enabled": True} _intrinsic_attributes = { - 'name': 'WebTransaction/Uri/', - 'port': 80, + "name": "WebTransaction/Uri/", + "port": 80, } -@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, - required_user_attrs=_user_attributes) + +@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, required_user_attrs=_user_attributes) @override_application_settings(_test_capture_attributes_enabled_settings) def test_capture_attributes_enabled(): settings = application_settings() @@ -52,7 +55,7 @@ def test_capture_attributes_enabled(): assert settings.js_agent_loader - response = fully_featured_application.get('/') + response = fully_featured_application.get("/") header = response.html.html.head.script.string content = response.html.html.body.p.string @@ -60,25 +63,23 @@ def test_capture_attributes_enabled(): # Validate actual body content. - assert content == 'RESPONSE' + assert content == "RESPONSE" # We no longer are in control of the JS contents of the header so # just check to make sure it contains at least the magic string # 'NREUM'. - assert header.find('NREUM') != -1 + assert header.find("NREUM") != -1 # Now validate the various fields of the footer related to analytics. # The fields are held by a JSON dictionary. - data = json.loads(footer.split('NREUM.info=')[1]) + data = json.loads(footer.split("NREUM.info=")[1]) obfuscation_key = settings.license_key[:13] - attributes = json.loads(deobfuscate(data['atts'], - obfuscation_key)) - user_attrs = attributes['u'] - + attributes = json.loads(deobfuscate(data["atts"], obfuscation_key)) + user_attrs = attributes["u"] # When you round-trip through json encoding and json decoding, you # always end up with unicode (unicode in Python 2, str in Python 3.) @@ -90,22 +91,18 @@ def test_capture_attributes_enabled(): browser_attributes = _user_attributes.copy() - browser_attributes['bytes'] = u'bytes-value' - browser_attributes['invalid-utf8'] = _user_attributes[ - 'invalid-utf8'].decode('latin-1') - browser_attributes['multibyte-utf8'] = _user_attributes[ - 'multibyte-utf8'].decode('latin-1') + browser_attributes["bytes"] = "bytes-value" + browser_attributes["invalid-utf8"] = _user_attributes["invalid-utf8"].decode("latin-1") + browser_attributes["multibyte-utf8"] = _user_attributes["multibyte-utf8"].decode("latin-1") for attr, value in browser_attributes.items(): - assert user_attrs[attr] == value, ( - "attribute %r expected %r, found %r" % - (attr, value, user_attrs[attr])) + assert user_attrs[attr] == value, "attribute %r expected %r, found %r" % (attr, value, user_attrs[attr]) + + +_test_no_attributes_recorded_settings = {"browser_monitoring.attributes.enabled": True} -_test_no_attributes_recorded_settings = { - 'browser_monitoring.attributes.enabled': True } -@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, - required_user_attrs={}) +@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, required_user_attrs={}) @override_application_settings(_test_no_attributes_recorded_settings) def test_no_attributes_recorded(): settings = application_settings() @@ -115,8 +112,7 @@ def test_no_attributes_recorded(): assert settings.js_agent_loader - response = fully_featured_application.get('/', extra_environ={ - 'record_attributes': 'FALSE'}) + response = fully_featured_application.get("/", extra_environ={"record_attributes": "FALSE"}) header = response.html.html.head.script.string content = response.html.html.body.p.string @@ -124,32 +120,33 @@ def test_no_attributes_recorded(): # Validate actual body content. - assert content == 'RESPONSE' + assert content == "RESPONSE" # We no longer are in control of the JS contents of the header so # just check to make sure it contains at least the magic string # 'NREUM'. - assert header.find('NREUM') != -1 + assert header.find("NREUM") != -1 # Now validate the various fields of the footer related to analytics. # The fields are held by a JSON dictionary. - data = json.loads(footer.split('NREUM.info=')[1]) + data = json.loads(footer.split("NREUM.info=")[1]) # As we are not recording any user or agent attributes, we should not # actually have an entry at all in the footer. - assert 'atts' not in data + assert "atts" not in data + _test_analytic_events_capture_attributes_disabled_settings = { - 'transaction_events.attributes.enabled': False, - 'browser_monitoring.attributes.enabled': True } + "transaction_events.attributes.enabled": False, + "browser_monitoring.attributes.enabled": True, +} -@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, - required_user_attrs={}) -@override_application_settings( - _test_analytic_events_capture_attributes_disabled_settings) + +@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, required_user_attrs={}) +@override_application_settings(_test_analytic_events_capture_attributes_disabled_settings) def test_analytic_events_capture_attributes_disabled(): settings = application_settings() @@ -162,7 +159,7 @@ def test_analytic_events_capture_attributes_disabled(): assert settings.js_agent_loader - response = fully_featured_application.get('/') + response = fully_featured_application.get("/") header = response.html.html.head.script.string content = response.html.html.body.p.string @@ -170,23 +167,23 @@ def test_analytic_events_capture_attributes_disabled(): # Validate actual body content. - assert content == 'RESPONSE' + assert content == "RESPONSE" # We no longer are in control of the JS contents of the header so # just check to make sure it contains at least the magic string # 'NREUM'. - assert header.find('NREUM') != -1 + assert header.find("NREUM") != -1 # Now validate that attributes are present, since browser monitoring should # be enabled. - data = json.loads(footer.split('NREUM.info=')[1]) + data = json.loads(footer.split("NREUM.info=")[1]) + + assert "atts" in data - assert 'atts' in data -@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, - required_user_attrs=_user_attributes) +@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, required_user_attrs=_user_attributes) def test_capture_attributes_default(): settings = application_settings() @@ -195,7 +192,7 @@ def test_capture_attributes_default(): assert settings.js_agent_loader - response = fully_featured_application.get('/') + response = fully_featured_application.get("/") header = response.html.html.head.script.string content = response.html.html.body.p.string @@ -203,32 +200,29 @@ def test_capture_attributes_default(): # Validate actual body content. - assert content == 'RESPONSE' + assert content == "RESPONSE" # We no longer are in control of the JS contents of the header so # just check to make sure it contains at least the magic string # 'NREUM'. - assert header.find('NREUM') != -1 + assert header.find("NREUM") != -1 # Now validate that attributes are not present, since should # be disabled. - data = json.loads(footer.split('NREUM.info=')[1]) + data = json.loads(footer.split("NREUM.info=")[1]) - assert 'atts' not in data + assert "atts" not in data -_test_analytic_events_background_task_settings = { - 'browser_monitoring.attributes.enabled': True } -_intrinsic_attributes = { - 'name': 'OtherTransaction/Uri/' -} +_test_analytic_events_background_task_settings = {"browser_monitoring.attributes.enabled": True} + +_intrinsic_attributes = {"name": "OtherTransaction/Uri/"} -@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, - required_user_attrs=_user_attributes) -@override_application_settings( - _test_analytic_events_background_task_settings) + +@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, required_user_attrs=_user_attributes) +@override_application_settings(_test_analytic_events_background_task_settings) def test_analytic_events_background_task(): settings = application_settings() @@ -240,20 +234,17 @@ def test_analytic_events_background_task(): assert settings.js_agent_loader - response = fully_featured_application.get('/', extra_environ={ - 'newrelic.set_background_task': True}) + response = fully_featured_application.get("/", extra_environ={"newrelic.set_background_task": True}) assert response.html.html.head.script is None -_test_capture_attributes_disabled_settings = { - 'browser_monitoring.attributes.enabled': False } -_intrinsic_attributes = { - 'name': 'WebTransaction/Uri/' -} +_test_capture_attributes_disabled_settings = {"browser_monitoring.attributes.enabled": False} + +_intrinsic_attributes = {"name": "WebTransaction/Uri/"} -@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, - required_user_attrs=_user_attributes) + +@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, required_user_attrs=_user_attributes) @override_application_settings(_test_capture_attributes_disabled_settings) def test_capture_attributes_disabled(): settings = application_settings() @@ -263,7 +254,7 @@ def test_capture_attributes_disabled(): assert settings.js_agent_loader - response = fully_featured_application.get('/') + response = fully_featured_application.get("/") header = response.html.html.head.script.string content = response.html.html.body.p.string @@ -271,30 +262,33 @@ def test_capture_attributes_disabled(): # Validate actual body content. - assert content == 'RESPONSE' + assert content == "RESPONSE" # We no longer are in control of the JS contents of the header so # just check to make sure it contains at least the magic string # 'NREUM'. - assert header.find('NREUM') != -1 + assert header.find("NREUM") != -1 # Now validate that attributes are not present, since should # be disabled. - data = json.loads(footer.split('NREUM.info=')[1]) + data = json.loads(footer.split("NREUM.info=")[1]) + + assert "atts" not in data - assert 'atts' not in data -@transient_function_wrapper('newrelic.core.stats_engine', - 'SampledDataSet.add') +@transient_function_wrapper("newrelic.core.stats_engine", "SampledDataSet.add") def validate_no_analytics_sample_data(wrapped, instance, args, kwargs): - assert False, 'Should not be recording analytic event.' + assert False, "Should not be recording analytic event." return wrapped(*args, **kwargs) + _test_collect_analytic_events_disabled_settings = { - 'collect_analytics_events': False, - 'browser_monitoring.attributes.enabled': True } + "collect_analytics_events": False, + "browser_monitoring.attributes.enabled": True, +} + @validate_no_analytics_sample_data @override_application_settings(_test_collect_analytic_events_disabled_settings) @@ -308,7 +302,7 @@ def test_collect_analytic_events_disabled(): assert settings.js_agent_loader - response = fully_featured_application.get('/') + response = fully_featured_application.get("/") header = response.html.html.head.script.string content = response.html.html.body.p.string @@ -316,24 +310,27 @@ def test_collect_analytic_events_disabled(): # Validate actual body content. - assert content == 'RESPONSE' + assert content == "RESPONSE" # We no longer are in control of the JS contents of the header so # just check to make sure it contains at least the magic string # 'NREUM'. - assert header.find('NREUM') != -1 + assert header.find("NREUM") != -1 # Now validate that attributes are present, since should # be enabled. - data = json.loads(footer.split('NREUM.info=')[1]) + data = json.loads(footer.split("NREUM.info=")[1]) + + assert "atts" in data - assert 'atts' in data _test_analytic_events_disabled_settings = { - 'transaction_events.enabled': False, - 'browser_monitoring.attributes.enabled': True } + "transaction_events.enabled": False, + "browser_monitoring.attributes.enabled": True, +} + @validate_no_analytics_sample_data @override_application_settings(_test_analytic_events_disabled_settings) @@ -348,7 +345,7 @@ def test_analytic_events_disabled(): assert settings.js_agent_loader - response = fully_featured_application.get('/') + response = fully_featured_application.get("/") header = response.html.html.head.script.string content = response.html.html.body.p.string @@ -356,25 +353,26 @@ def test_analytic_events_disabled(): # Validate actual body content. - assert content == 'RESPONSE' + assert content == "RESPONSE" # We no longer are in control of the JS contents of the header so # just check to make sure it contains at least the magic string # 'NREUM'. - assert header.find('NREUM') != -1 + assert header.find("NREUM") != -1 # Now validate that attributes are present, since should # be enabled. - data = json.loads(footer.split('NREUM.info=')[1]) + data = json.loads(footer.split("NREUM.info=")[1]) + + assert "atts" in data - assert 'atts' in data # -------------- Test call counts in analytic events ---------------- -@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, - required_user_attrs=_user_attributes) + +@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, required_user_attrs=_user_attributes) def test_no_database_or_external_attributes_in_analytics(): """Make no external calls or database calls in the transaction and check if the analytic event doesn't have the databaseCallCount, databaseDuration, @@ -385,7 +383,7 @@ def test_no_database_or_external_attributes_in_analytics(): assert settings.browser_monitoring.enabled - response = fully_featured_application.get('/') + response = fully_featured_application.get("/") # Validation of analytic data happens in the decorator. @@ -393,15 +391,16 @@ def test_no_database_or_external_attributes_in_analytics(): # Validate actual body content. - assert content == 'RESPONSE' + assert content == "RESPONSE" + _intrinsic_attributes = { - 'name': 'WebTransaction/Uri/db', - 'databaseCallCount': 2, + "name": "WebTransaction/Uri/db", + "databaseCallCount": 2, } -@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, - required_user_attrs=_user_attributes) + +@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, required_user_attrs=_user_attributes) def test_database_attributes_in_analytics(): """Make database calls in the transaction and check if the analytic event has the databaseCallCount and databaseDuration attributes. @@ -412,9 +411,9 @@ def test_database_attributes_in_analytics(): assert settings.browser_monitoring.enabled test_environ = { - 'db' : '2', + "db": "2", } - response = fully_featured_application.get('/db', extra_environ=test_environ) + response = fully_featured_application.get("/db", extra_environ=test_environ) # Validation of analytic data happens in the decorator. @@ -422,15 +421,16 @@ def test_database_attributes_in_analytics(): # Validate actual body content. - assert content == 'RESPONSE' + assert content == "RESPONSE" + _intrinsic_attributes = { - 'name': 'WebTransaction/Uri/ext', - 'externalCallCount': 2, + "name": "WebTransaction/Uri/ext", + "externalCallCount": 2, } -@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, - required_user_attrs=_user_attributes) + +@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, required_user_attrs=_user_attributes) def test_external_attributes_in_analytics(): """Make external calls in the transaction and check if the analytic event has the externalCallCount and externalDuration attributes. @@ -441,10 +441,9 @@ def test_external_attributes_in_analytics(): assert settings.browser_monitoring.enabled test_environ = { - 'external' : '2', + "external": "2", } - response = fully_featured_application.get('/ext', - extra_environ=test_environ) + response = fully_featured_application.get("/ext", extra_environ=test_environ) # Validation of analytic data happens in the decorator. @@ -452,16 +451,17 @@ def test_external_attributes_in_analytics(): # Validate actual body content. - assert content == 'RESPONSE' + assert content == "RESPONSE" + _intrinsic_attributes = { - 'name': 'WebTransaction/Uri/dbext', - 'databaseCallCount': 2, - 'externalCallCount': 2, + "name": "WebTransaction/Uri/dbext", + "databaseCallCount": 2, + "externalCallCount": 2, } -@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, - required_user_attrs=_user_attributes) + +@validate_transaction_event_sample_data(required_attrs=_intrinsic_attributes, required_user_attrs=_user_attributes) def test_database_and_external_attributes_in_analytics(): """Make external calls and database calls in the transaction and check if the analytic event has the databaseCallCount, databaseDuration, @@ -473,11 +473,10 @@ def test_database_and_external_attributes_in_analytics(): assert settings.browser_monitoring.enabled test_environ = { - 'db' : '2', - 'external' : '2', + "db": "2", + "external": "2", } - response = fully_featured_application.get('/dbext', - extra_environ=test_environ) + response = fully_featured_application.get("/dbext", extra_environ=test_environ) # Validation of analytic data happens in the decorator. @@ -485,24 +484,25 @@ def test_database_and_external_attributes_in_analytics(): # Validate actual body content. - assert content == 'RESPONSE' + assert content == "RESPONSE" + # -------------- Test background tasks ---------------- _expected_attributes = { - 'user': [], - 'agent': [], - 'intrinsic' : ('name', 'duration', 'type', 'timestamp', 'totalTime'), + "user": [], + "agent": [], + "intrinsic": ("name", "duration", "type", "timestamp", "totalTime"), } _expected_absent_attributes = { - 'user': ('foo'), - 'agent': ('response.status', 'request.method'), - 'intrinsic': ('port'), + "user": ("foo"), + "agent": ("response.status", "request.method"), + "intrinsic": ("port"), } -@validate_transaction_event_attributes(_expected_attributes, - _expected_absent_attributes) + +@validate_transaction_event_attributes(_expected_attributes, _expected_absent_attributes) @background_task() def test_background_task_intrinsics_has_no_port(): pass diff --git a/tests/agent_features/test_wsgi_attributes.py b/tests/agent_features/test_wsgi_attributes.py index 0f7f7d6f2..7543e45d8 100644 --- a/tests/agent_features/test_wsgi_attributes.py +++ b/tests/agent_features/test_wsgi_attributes.py @@ -18,9 +18,11 @@ override_application_settings, validate_error_event_attributes, validate_transaction_error_trace_attributes, - validate_transaction_event_attributes, ) from testing_support.sample_applications import fully_featured_app +from testing_support.validators.validate_transaction_event_attributes import ( + validate_transaction_event_attributes, +) WSGI_ATTRIBUTES = [ "wsgi.input.seconds", @@ -44,6 +46,4 @@ @override_application_settings({"attributes.include": ["*"]}) @dt_enabled def test_wsgi_attributes(): - app.post_json( - "/", {"foo": "bar"}, extra_environ={"n_errors": "1", "err_message": "oops"} - ) + app.post_json("/", {"foo": "bar"}, extra_environ={"n_errors": "1", "err_message": "oops"}) diff --git a/tests/datastore_aredis/test_trace_node.py b/tests/datastore_aredis/test_trace_node.py index a4c58cebd..9d5d86162 100644 --- a/tests/datastore_aredis/test_trace_node.py +++ b/tests/datastore_aredis/test_trace_node.py @@ -14,8 +14,7 @@ import aredis from testing_support.db_settings import redis_settings - -# from testing_support.fixture.event_loop import event_loop as loop +from testing_support.fixture.event_loop import event_loop as loop # noqa: F401 from testing_support.fixtures import override_application_settings from testing_support.util import instance_hostname from testing_support.validators.validate_tt_collector_json import ( @@ -97,26 +96,26 @@ async def _exercise_db(): @override_application_settings(_enable_instance_settings) @validate_tt_collector_json(datastore_params=_enabled_required, datastore_forgone_params=_enabled_forgone) @background_task() -def test_trace_node_datastore_params_enable_instance(loop): +def test_trace_node_datastore_params_enable_instance(loop): # noqa: F811 loop.run_until_complete(_exercise_db()) @override_application_settings(_disable_instance_settings) @validate_tt_collector_json(datastore_params=_disabled_required, datastore_forgone_params=_disabled_forgone) @background_task() -def test_trace_node_datastore_params_disable_instance(loop): +def test_trace_node_datastore_params_disable_instance(loop): # noqa: F811 loop.run_until_complete(_exercise_db()) @override_application_settings(_instance_only_settings) @validate_tt_collector_json(datastore_params=_instance_only_required, datastore_forgone_params=_instance_only_forgone) @background_task() -def test_trace_node_datastore_params_instance_only(loop): +def test_trace_node_datastore_params_instance_only(loop): # noqa: F811 loop.run_until_complete(_exercise_db()) @override_application_settings(_database_only_settings) @validate_tt_collector_json(datastore_params=_database_only_required, datastore_forgone_params=_database_only_forgone) @background_task() -def test_trace_node_datastore_params_database_only(loop): +def test_trace_node_datastore_params_database_only(loop): # noqa: F811 loop.run_until_complete(_exercise_db()) diff --git a/tests/framework_aiohttp/test_server_cat.py b/tests/framework_aiohttp/test_server_cat.py index a09fa6b79..e668bed65 100644 --- a/tests/framework_aiohttp/test_server_cat.py +++ b/tests/framework_aiohttp/test_server_cat.py @@ -14,45 +14,53 @@ import asyncio import json + import pytest +from testing_support.fixtures import ( + make_cross_agent_headers, + override_application_settings, + validate_analytics_catmap_data, +) +from testing_support.validators.validate_transaction_event_attributes import ( + validate_transaction_event_attributes, +) -from newrelic.common.object_wrapper import transient_function_wrapper from newrelic.common.encoding_utils import deobfuscate -from testing_support.fixtures import (override_application_settings, - make_cross_agent_headers, validate_analytics_catmap_data, - validate_transaction_event_attributes) +from newrelic.common.object_wrapper import transient_function_wrapper -ENCODING_KEY = '1234567890123456789012345678901234567890' +ENCODING_KEY = "1234567890123456789012345678901234567890" test_uris = [ - ('/error?hello=world', '_target_application:error'), - ('/coro?hello=world', '_target_application:index'), - ('/class?hello=world', '_target_application:HelloWorldView._respond'), + ("/error?hello=world", "_target_application:error"), + ("/coro?hello=world", "_target_application:index"), + ("/class?hello=world", "_target_application:HelloWorldView._respond"), ] def record_aiohttp1_raw_headers(raw_headers): try: - import aiohttp.protocol + import aiohttp.protocol # noqa: F401 except ImportError: + def pass_through(function): return function + return pass_through - @transient_function_wrapper('aiohttp.protocol', 'HttpParser.parse_headers') + @transient_function_wrapper("aiohttp.protocol", "HttpParser.parse_headers") def recorder(wrapped, instance, args, kwargs): def _bind_params(lines): return lines lines = _bind_params(*args, **kwargs) for line in lines: - line = line.decode('utf-8') + line = line.decode("utf-8") # This is the request, not the response - if line.startswith('GET'): + if line.startswith("GET"): break - if ':' in line: - key, value = line.split(':', maxsplit=1) + if ":" in line: + key, value = line.split(":", maxsplit=1) raw_headers[key.strip()] = value.strip() return wrapped(*args, **kwargs) @@ -61,59 +69,62 @@ def _bind_params(lines): @pytest.mark.parametrize( - 'inbound_payload,expected_intrinsics,forgone_intrinsics,cat_id', [ - - # Valid payload from trusted account - (["b854df4feb2b1f06", False, "7e249074f277923d", "5d2957be"], - {"nr.referringTransactionGuid": "b854df4feb2b1f06", - "nr.tripId": "7e249074f277923d", - "nr.referringPathHash": "5d2957be"}, - [], - '1#1'), - - # Valid payload from an untrusted account - (["b854df4feb2b1f06", False, "7e249074f277923d", "5d2957be"], - {}, - ['nr.referringTransactionGuid', 'nr.tripId', 'nr.referringPathHash'], - '80#1'), -]) -@pytest.mark.parametrize('method', ['GET']) -@pytest.mark.parametrize('uri,metric_name', test_uris) -def test_cat_headers(method, uri, metric_name, inbound_payload, - expected_intrinsics, forgone_intrinsics, cat_id, aiohttp_app): + "inbound_payload,expected_intrinsics,forgone_intrinsics,cat_id", + [ + # Valid payload from trusted account + ( + ["b854df4feb2b1f06", False, "7e249074f277923d", "5d2957be"], + { + "nr.referringTransactionGuid": "b854df4feb2b1f06", + "nr.tripId": "7e249074f277923d", + "nr.referringPathHash": "5d2957be", + }, + [], + "1#1", + ), + # Valid payload from an untrusted account + ( + ["b854df4feb2b1f06", False, "7e249074f277923d", "5d2957be"], + {}, + ["nr.referringTransactionGuid", "nr.tripId", "nr.referringPathHash"], + "80#1", + ), + ], +) +@pytest.mark.parametrize("method", ["GET"]) +@pytest.mark.parametrize("uri,metric_name", test_uris) +def test_cat_headers( + method, uri, metric_name, inbound_payload, expected_intrinsics, forgone_intrinsics, cat_id, aiohttp_app +): _raw_headers = {} @asyncio.coroutine def fetch(): - headers = make_cross_agent_headers(inbound_payload, ENCODING_KEY, - cat_id) - resp = yield from aiohttp_app.client.request(method, uri, - headers=headers) + headers = make_cross_agent_headers(inbound_payload, ENCODING_KEY, cat_id) + resp = yield from aiohttp_app.client.request(method, uri, headers=headers) if _raw_headers: raw_headers = _raw_headers else: - raw_headers = {k.decode('utf-8'): v.decode('utf-8') - for k, v in resp.raw_headers} + raw_headers = {k.decode("utf-8"): v.decode("utf-8") for k, v in resp.raw_headers} if expected_intrinsics: # test valid CAT response header - assert 'X-NewRelic-App-Data' in raw_headers + assert "X-NewRelic-App-Data" in raw_headers - app_data = json.loads(deobfuscate( - raw_headers['X-NewRelic-App-Data'], ENCODING_KEY)) + app_data = json.loads(deobfuscate(raw_headers["X-NewRelic-App-Data"], ENCODING_KEY)) assert app_data[0] == cat_id - assert app_data[1] == ('WebTransaction/Function/%s' % metric_name) + assert app_data[1] == ("WebTransaction/Function/%s" % metric_name) else: - assert 'X-NewRelic-App-Data' not in resp.headers + assert "X-NewRelic-App-Data" not in resp.headers _custom_settings = { - 'cross_process_id': '1#1', - 'encoding_key': ENCODING_KEY, - 'trusted_account_ids': [1], - 'cross_application_tracer.enabled': True, - 'distributed_tracing.enabled': False, + "cross_process_id": "1#1", + "encoding_key": ENCODING_KEY, + "trusted_account_ids": [1], + "cross_application_tracer.enabled": True, + "distributed_tracing.enabled": False, } # NOTE: the logic-flow of this test can be a bit confusing. @@ -125,9 +136,11 @@ def fetch(): # is received and subsequently processed. that code is # a fixture from conftest.py/_target_application.py - @validate_analytics_catmap_data('WebTransaction/Function/%s' % metric_name, - expected_attributes=expected_intrinsics, - non_expected_attributes=forgone_intrinsics) + @validate_analytics_catmap_data( + "WebTransaction/Function/%s" % metric_name, + expected_attributes=expected_intrinsics, + non_expected_attributes=forgone_intrinsics, + ) @override_application_settings(_custom_settings) @record_aiohttp1_raw_headers(_raw_headers) def _test(): @@ -136,8 +149,8 @@ def _test(): _test() -account_id = '33' -primary_application_id = '2827902' +account_id = "33" +primary_application_id = "2827902" inbound_payload = { "v": [0, 1], @@ -150,14 +163,14 @@ def _test(): "sa": True, "ti": 1518469636035, "tr": "d6b4ba0c3a712ca", - "ty": "App" - } + "ty": "App", + }, } expected_attributes = { - 'agent': [], - 'user': [], - 'intrinsic': { + "agent": [], + "user": [], + "intrinsic": { "traceId": "d6b4ba0c3a712ca", "priority": 1.234567, "sampled": True, @@ -166,32 +179,29 @@ def _test(): "parent.account": account_id, "parent.transportType": "HTTP", "parentId": "e8b91a159289ff74", - "parentSpanId": "7d3efb1b173fecfa" - } + "parentSpanId": "7d3efb1b173fecfa", + }, } unexpected_attributes = { - 'agent': [], - 'user': [], - 'intrinsic': [ - "grandparentId", "cross_process_id", "nr.tripId", "nr.pathHash" - ] + "agent": [], + "user": [], + "intrinsic": ["grandparentId", "cross_process_id", "nr.tripId", "nr.pathHash"], } -@pytest.mark.parametrize('uri,metric_name', test_uris) +@pytest.mark.parametrize("uri,metric_name", test_uris) def test_distributed_tracing_headers(uri, metric_name, aiohttp_app): @asyncio.coroutine def fetch(): - headers = {'newrelic': json.dumps(inbound_payload)} - resp = yield from aiohttp_app.client.request('GET', uri, - headers=headers) + headers = {"newrelic": json.dumps(inbound_payload)} + resp = yield from aiohttp_app.client.request("GET", uri, headers=headers) # better cat does not send a response in the headers - assert 'newrelic' not in resp.headers + assert "newrelic" not in resp.headers # old-cat headers should not be in the response - assert 'X-NewRelic-App-Data' not in resp.headers + assert "X-NewRelic-App-Data" not in resp.headers # NOTE: the logic-flow of this test can be a bit confusing. # the override settings and attribute validation occur @@ -202,14 +212,15 @@ def fetch(): # is received and subsequently processed. that code is # a fixture from conftest.py/_target_application.py - @validate_transaction_event_attributes( - expected_attributes, unexpected_attributes) - @override_application_settings({ - 'account_id': '33', - 'trusted_account_key': '33', - 'primary_application_id': primary_application_id, - 'distributed_tracing.enabled': True - }) + @validate_transaction_event_attributes(expected_attributes, unexpected_attributes) + @override_application_settings( + { + "account_id": "33", + "trusted_account_key": "33", + "primary_application_id": primary_application_id, + "distributed_tracing.enabled": True, + } + ) def _test(): aiohttp_app.loop.run_until_complete(fetch()) diff --git a/tests/framework_sanic/test_application.py b/tests/framework_sanic/test_application.py index ccb0dec67..d1dc135b4 100644 --- a/tests/framework_sanic/test_application.py +++ b/tests/framework_sanic/test_application.py @@ -12,143 +12,158 @@ # See the License for the specific language governing permissions and # limitations under the License. +from collections import deque + import pytest import sanic - -from newrelic.core.config import global_settings -from collections import deque +from testing_support.fixtures import ( + function_not_called, + override_application_settings, + override_generic_settings, + override_ignore_status_codes, +) +from testing_support.validators.validate_code_level_metrics import ( + validate_code_level_metrics, +) +from testing_support.validators.validate_transaction_errors import ( + validate_transaction_errors, +) +from testing_support.validators.validate_transaction_event_attributes import ( + validate_transaction_event_attributes, +) +from testing_support.validators.validate_transaction_metrics import ( + validate_transaction_metrics, +) from newrelic.api.application import application_instance -from newrelic.api.transaction import Transaction from newrelic.api.external_trace import ExternalTrace +from newrelic.api.transaction import Transaction +from newrelic.core.config import global_settings -from testing_support.fixtures import ( - override_application_settings, - validate_transaction_event_attributes, - override_ignore_status_codes, override_generic_settings, - function_not_called) -from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics -from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics -from testing_support.validators.validate_transaction_errors import validate_transaction_errors - -sanic_21 = int(sanic.__version__.split('.', 1)[0]) >= 21 +sanic_21 = int(sanic.__version__.split(".", 1)[0]) >= 21 BASE_METRICS = [ - ('Function/_target_application:index', 1), - ('Function/_target_application:request_middleware', 1 if int(sanic.__version__.split('.', 1)[0]) > 18 else 2), + ("Function/_target_application:index", 1), + ("Function/_target_application:request_middleware", 1 if int(sanic.__version__.split(".", 1)[0]) > 18 else 2), ] FRAMEWORK_METRICS = [ - ('Python/Framework/Sanic/%s' % sanic.__version__, 1), + ("Python/Framework/Sanic/%s" % sanic.__version__, 1), ] -BASE_ATTRS = ['response.status', 'response.headers.contentType', - 'response.headers.contentLength'] +BASE_ATTRS = ["response.status", "response.headers.contentType", "response.headers.contentLength"] validate_base_transaction_event_attr = validate_transaction_event_attributes( - required_params={'agent': BASE_ATTRS, 'user': [], 'intrinsic': []}, + required_params={"agent": BASE_ATTRS, "user": [], "intrinsic": []}, ) @validate_code_level_metrics("_target_application", "index") @validate_transaction_metrics( - '_target_application:index', + "_target_application:index", scoped_metrics=BASE_METRICS, rollup_metrics=BASE_METRICS + FRAMEWORK_METRICS, ) @validate_base_transaction_event_attr def test_simple_request(app): - response = app.fetch('get', '/') + response = app.fetch("get", "/") assert response.status == 200 -@function_not_called('newrelic.core.stats_engine', - 'StatsEngine.record_transaction') +@function_not_called("newrelic.core.stats_engine", "StatsEngine.record_transaction") def test_websocket(app): - headers = {'upgrade': 'WebSocket'} - response = app.fetch('get', '/', headers=headers) + headers = {"upgrade": "WebSocket"} + response = app.fetch("get", "/", headers=headers) assert response.status == 200 -@pytest.mark.parametrize('method', ( - 'get', - 'post', - 'put', - 'patch', - 'delete', -)) +@pytest.mark.parametrize( + "method", + ( + "get", + "post", + "put", + "patch", + "delete", + ), +) def test_method_view(app, method): - metric_name = 'Function/_target_application:MethodView.' + method + metric_name = "Function/_target_application:MethodView." + method @validate_code_level_metrics("_target_application.MethodView", method) @validate_transaction_metrics( - '_target_application:MethodView.' + method, + "_target_application:MethodView." + method, scoped_metrics=[(metric_name, 1)], rollup_metrics=[(metric_name, 1)], ) @validate_base_transaction_event_attr def _test(): - response = app.fetch(method, '/method_view') + response = app.fetch(method, "/method_view") assert response.status == 200 _test() DT_METRICS = [ - ('Supportability/DistributedTrace/AcceptPayload/Success', None), - ('Supportability/TraceContext/TraceParent/Accept/Success', 1), + ("Supportability/DistributedTrace/AcceptPayload/Success", None), + ("Supportability/TraceContext/TraceParent/Accept/Success", 1), ] @validate_transaction_metrics( - '_target_application:index', + "_target_application:index", scoped_metrics=BASE_METRICS, rollup_metrics=BASE_METRICS + DT_METRICS + FRAMEWORK_METRICS, ) @validate_base_transaction_event_attr -@override_application_settings({ - 'distributed_tracing.enabled': True, -}) +@override_application_settings( + { + "distributed_tracing.enabled": True, + } +) def test_inbound_distributed_trace(app): transaction = Transaction(application_instance()) dt_headers = ExternalTrace.generate_request_headers(transaction) - response = app.fetch('get', '/', headers=dict(dt_headers)) + response = app.fetch("get", "/", headers=dict(dt_headers)) assert response.status == 200 + _params = ["error"] if not sanic_21: - _params.append('write_response_error') -@pytest.mark.parametrize('endpoint', _params) + _params.append("write_response_error") + + +@pytest.mark.parametrize("endpoint", _params) def test_recorded_error(app, endpoint): ERROR_METRICS = [ - ('Function/_target_application:%s' % endpoint, 1), + ("Function/_target_application:%s" % endpoint, 1), ] - @validate_transaction_errors(errors=['builtins:ValueError']) + @validate_transaction_errors(errors=["builtins:ValueError"]) @validate_base_transaction_event_attr @validate_transaction_metrics( - '_target_application:%s' % endpoint, + "_target_application:%s" % endpoint, scoped_metrics=ERROR_METRICS, rollup_metrics=ERROR_METRICS + FRAMEWORK_METRICS, ) def _test(): - if endpoint == 'write_response_error': + if endpoint == "write_response_error": with pytest.raises(ValueError): - response = app.fetch('get', '/' + endpoint) + response = app.fetch("get", "/" + endpoint) else: - response = app.fetch('get', '/' + endpoint) + response = app.fetch("get", "/" + endpoint) assert response.status == 500 _test() NOT_FOUND_METRICS = [ - ('Function/_target_application:not_found', 1), + ("Function/_target_application:not_found", 1), ] @validate_transaction_metrics( - '_target_application:not_found', + "_target_application:not_found", scoped_metrics=NOT_FOUND_METRICS, rollup_metrics=NOT_FOUND_METRICS + FRAMEWORK_METRICS, ) @@ -156,88 +171,90 @@ def _test(): @override_ignore_status_codes([404]) @validate_transaction_errors(errors=[]) def test_ignored_by_status_error(app): - response = app.fetch('get', '/404') + response = app.fetch("get", "/404") assert response.status == 404 DOUBLE_ERROR_METRICS = [ - ('Function/_target_application:zero_division_error', 1), + ("Function/_target_application:zero_division_error", 1), ] @validate_transaction_metrics( - '_target_application:zero_division_error', + "_target_application:zero_division_error", scoped_metrics=DOUBLE_ERROR_METRICS, rollup_metrics=DOUBLE_ERROR_METRICS, ) -@validate_transaction_errors( - errors=['builtins:ValueError', 'builtins:ZeroDivisionError']) +@validate_transaction_errors(errors=["builtins:ValueError", "builtins:ZeroDivisionError"]) def test_error_raised_in_error_handler(app): # Because of a bug in Sanic versions <0.8.0, the response.status value is # inconsistent. Rather than assert the status value, we rely on the # transaction errors validator to confirm the application acted as we'd # expect it to. - app.fetch('get', '/zero') + app.fetch("get", "/zero") -STREAMING_ATTRS = ['response.status', 'response.headers.contentType'] +STREAMING_ATTRS = ["response.status", "response.headers.contentType"] STREAMING_METRICS = [ - ('Function/_target_application:streaming', 1), + ("Function/_target_application:streaming", 1), ] @validate_code_level_metrics("_target_application", "streaming") @validate_transaction_metrics( - '_target_application:streaming', + "_target_application:streaming", scoped_metrics=STREAMING_METRICS, rollup_metrics=STREAMING_METRICS, ) @validate_transaction_event_attributes( - required_params={'agent': STREAMING_ATTRS, 'user': [], 'intrinsic': []}, + required_params={"agent": STREAMING_ATTRS, "user": [], "intrinsic": []}, ) def test_streaming_response(app): # streaming responses do not have content-length headers - response = app.fetch('get', '/streaming') + response = app.fetch("get", "/streaming") assert response.status == 200 ERROR_IN_ERROR_TESTS = [ - ('/sync-error', '_target_application:sync_error', - [('Function/_target_application:sync_error', 1), - ('Function/_target_application:handle_custom_exception_sync', 1)], - ['_target_application:CustomExceptionSync', - 'sanic.exceptions:SanicException']), - - ('/async-error', '_target_application:async_error', - [('Function/_target_application:async_error', 1), - ('Function/_target_application:handle_custom_exception_async', 1)], - ['_target_application:CustomExceptionAsync']), + ( + "/sync-error", + "_target_application:sync_error", + [ + ("Function/_target_application:sync_error", 1), + ("Function/_target_application:handle_custom_exception_sync", 1), + ], + ["_target_application:CustomExceptionSync", "sanic.exceptions:SanicException"], + ), + ( + "/async-error", + "_target_application:async_error", + [ + ("Function/_target_application:async_error", 1), + ("Function/_target_application:handle_custom_exception_async", 1), + ], + ["_target_application:CustomExceptionAsync"], + ), ] -@pytest.mark.parametrize('url,metric_name,metrics,errors', - ERROR_IN_ERROR_TESTS) -@pytest.mark.parametrize('nr_enabled', (True, False)) -def test_errors_in_error_handlers( - nr_enabled, app, url, metric_name, metrics, errors): +@pytest.mark.parametrize("url,metric_name,metrics,errors", ERROR_IN_ERROR_TESTS) +@pytest.mark.parametrize("nr_enabled", (True, False)) +def test_errors_in_error_handlers(nr_enabled, app, url, metric_name, metrics, errors): settings = global_settings() - @override_generic_settings(settings, {'enabled': nr_enabled}) + @override_generic_settings(settings, {"enabled": nr_enabled}) def _test(): # Because of a bug in Sanic versions <0.8.0, the response.status value # is inconsistent. Rather than assert the status value, we rely on the # transaction errors validator to confirm the application acted as we'd # expect it to. - app.fetch('get', url) + app.fetch("get", url) if nr_enabled: _test = validate_transaction_errors(errors=errors)(_test) - _test = validate_transaction_metrics(metric_name, - scoped_metrics=metrics, - rollup_metrics=metrics)(_test) + _test = validate_transaction_metrics(metric_name, scoped_metrics=metrics, rollup_metrics=metrics)(_test) else: - _test = function_not_called('newrelic.core.stats_engine', - 'StatsEngine.record_transaction')(_test) + _test = function_not_called("newrelic.core.stats_engine", "StatsEngine.record_transaction")(_test) _test() @@ -245,63 +262,82 @@ def _test(): def test_no_transaction_when_nr_disabled(app): settings = global_settings() - @function_not_called('newrelic.core.stats_engine', - 'StatsEngine.record_transaction') - @override_generic_settings(settings, {'enabled': False}) + @function_not_called("newrelic.core.stats_engine", "StatsEngine.record_transaction") + @override_generic_settings(settings, {"enabled": False}) def _test(): - app.fetch('GET', '/') + app.fetch("GET", "/") _test() async def async_returning_middleware(*args, **kwargs): from sanic.response import json - return json({'oops': 'I returned it again'}) + + return json({"oops": "I returned it again"}) def sync_returning_middleware(*args, **kwargs): from sanic.response import json - return json({'oops': 'I returned it again'}) + + return json({"oops": "I returned it again"}) def sync_failing_middleware(*args, **kwargs): from sanic.exceptions import SanicException - raise SanicException('Everything is ok', status_code=200) - - -@pytest.mark.parametrize('middleware,attach_to,metric_name,transaction_name', [ - (async_returning_middleware, 'request', - 'test_application:async_returning_middleware', - 'test_application:async_returning_middleware'), - (sync_returning_middleware, 'request', - 'test_application:sync_returning_middleware', - 'test_application:sync_returning_middleware'), - (sync_failing_middleware, 'request', - 'test_application:sync_failing_middleware', - 'test_application:sync_failing_middleware'), - (async_returning_middleware, 'response', - 'test_application:async_returning_middleware', - '_target_application:index'), - (sync_returning_middleware, 'response', - 'test_application:sync_returning_middleware', - '_target_application:index'), -]) -def test_returning_middleware(app, middleware, attach_to, metric_name, - transaction_name): + + raise SanicException("Everything is ok", status_code=200) + + +@pytest.mark.parametrize( + "middleware,attach_to,metric_name,transaction_name", + [ + ( + async_returning_middleware, + "request", + "test_application:async_returning_middleware", + "test_application:async_returning_middleware", + ), + ( + sync_returning_middleware, + "request", + "test_application:sync_returning_middleware", + "test_application:sync_returning_middleware", + ), + ( + sync_failing_middleware, + "request", + "test_application:sync_failing_middleware", + "test_application:sync_failing_middleware", + ), + ( + async_returning_middleware, + "response", + "test_application:async_returning_middleware", + "_target_application:index", + ), + ( + sync_returning_middleware, + "response", + "test_application:sync_returning_middleware", + "_target_application:index", + ), + ], +) +def test_returning_middleware(app, middleware, attach_to, metric_name, transaction_name): metrics = [ - ('Function/%s' % metric_name, 1), + ("Function/%s" % metric_name, 1), ] @validate_code_level_metrics(*metric_name.split(":")) @validate_transaction_metrics( - transaction_name, - scoped_metrics=metrics, - rollup_metrics=metrics, + transaction_name, + scoped_metrics=metrics, + rollup_metrics=metrics, ) @validate_base_transaction_event_attr def _test(): - response = app.fetch('get', '/') + response = app.fetch("get", "/") assert response.status == 200 original_request_middleware = deque(app.app.request_middleware) @@ -320,17 +356,17 @@ def error_middleware(*args, **kwargs): def test_errors_in_middleware(app): - metrics = [('Function/test_application:error_middleware', 1)] + metrics = [("Function/test_application:error_middleware", 1)] @validate_transaction_metrics( - 'test_application:error_middleware', - scoped_metrics=metrics, - rollup_metrics=metrics, + "test_application:error_middleware", + scoped_metrics=metrics, + rollup_metrics=metrics, ) @validate_base_transaction_event_attr - @validate_transaction_errors(errors=['builtins:ValueError']) + @validate_transaction_errors(errors=["builtins:ValueError"]) def _test(): - response = app.fetch('get', '/') + response = app.fetch("get", "/") assert response.status == 500 original_request_middleware = deque(app.app.request_middleware) @@ -359,31 +395,39 @@ def _test(): ) @validate_transaction_errors(errors=[]) def test_blueprint_middleware(app): - response = app.fetch('get', '/blueprint') + response = app.fetch("get", "/blueprint") assert response.status == 200 def test_unknown_route(app): import sanic + sanic_version = [int(x) for x in sanic.__version__.split(".")] - _tx_name = "_target_application:CustomRouter.get" if sanic_version[0] < 21 else "_target_application:request_middleware" - + _tx_name = ( + "_target_application:CustomRouter.get" if sanic_version[0] < 21 else "_target_application:request_middleware" + ) + @validate_transaction_metrics(_tx_name) def _test(): - response = app.fetch('get', '/what-route') + response = app.fetch("get", "/what-route") assert response.status == 404 - - _test() + + _test() + def test_bad_method(app): import sanic + sanic_version = [int(x) for x in sanic.__version__.split(".")] - _tx_name = "_target_application:CustomRouter.get" if sanic_version[0] < 21 else "_target_application:request_middleware" + _tx_name = ( + "_target_application:CustomRouter.get" if sanic_version[0] < 21 else "_target_application:request_middleware" + ) @validate_transaction_metrics(_tx_name) @override_ignore_status_codes([405]) @validate_transaction_errors(errors=[]) def _test(): - response = app.fetch('post', '/') + response = app.fetch("post", "/") assert response.status == 405 + _test() diff --git a/tests/framework_sanic/test_cross_application.py b/tests/framework_sanic/test_cross_application.py index 55e5a3578..31dc3b9b9 100644 --- a/tests/framework_sanic/test_cross_application.py +++ b/tests/framework_sanic/test_cross_application.py @@ -13,30 +13,38 @@ # limitations under the License. import json -import pytest -import re import random + +# import re import string -from newrelic.common.encoding_utils import deobfuscate +import pytest +from testing_support.fixtures import ( + make_cross_agent_headers, + override_application_settings, + validate_analytics_catmap_data, +) +from testing_support.validators.validate_transaction_event_attributes import ( + validate_transaction_event_attributes, +) +from testing_support.validators.validate_transaction_metrics import ( + validate_transaction_metrics, +) + from newrelic.api.application import application_instance from newrelic.api.external_trace import ExternalTrace from newrelic.api.transaction import Transaction - -from testing_support.fixtures import (override_application_settings, - make_cross_agent_headers, validate_analytics_catmap_data, - validate_transaction_event_attributes) -from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from newrelic.common.encoding_utils import deobfuscate BASE_METRICS = [ - ('Function/_target_application:index', 1), + ("Function/_target_application:index", 1), ] DT_METRICS = [ - ('Supportability/DistributedTrace/AcceptPayload/Success', None), - ('Supportability/TraceContext/TraceParent/Accept/Success', 1), + ("Supportability/DistributedTrace/AcceptPayload/Success", None), + ("Supportability/TraceContext/TraceParent/Accept/Success", 1), ] -BASE_ATTRS = ['response.status', 'response.headers.contentType', - 'response.headers.contentLength'] +BASE_ATTRS = ["response.status", "response.headers.contentType", "response.headers.contentLength"] + def raw_headers(response): try: @@ -50,62 +58,69 @@ def raw_headers(response): @validate_transaction_metrics( - '_target_application:index', + "_target_application:index", scoped_metrics=BASE_METRICS, rollup_metrics=BASE_METRICS + DT_METRICS, ) -@override_application_settings({ - 'distributed_tracing.enabled': True, -}) +@override_application_settings( + { + "distributed_tracing.enabled": True, + } +) @validate_transaction_event_attributes( - required_params={'agent': BASE_ATTRS, 'user': [], 'intrinsic': []}, + required_params={"agent": BASE_ATTRS, "user": [], "intrinsic": []}, ) def test_inbound_distributed_trace(app): transaction = Transaction(application_instance()) dt_headers = ExternalTrace.generate_request_headers(transaction) - response = app.fetch('get', '/', headers=dict(dt_headers)) + response = app.fetch("get", "/", headers=dict(dt_headers)) assert response.status == 200 -ENCODING_KEY = "".join(random.choice(string.ascii_lowercase) for _ in range(40)) +ENCODING_KEY = "".join(random.choice(string.ascii_lowercase) for _ in range(40)) # nosec _cat_response_header_urls_to_test = ( - ('/', '_target_application:index'), - ('/streaming', '_target_application:streaming'), - ('/error', '_target_application:error'), + ("/", "_target_application:index"), + ("/streaming", "_target_application:streaming"), + ("/error", "_target_application:error"), ) _custom_settings = { - 'cross_process_id': '1#1', - 'encoding_key': ENCODING_KEY, - 'trusted_account_ids': [1], - 'cross_application_tracer.enabled': True, - 'distributed_tracing.enabled': False, + "cross_process_id": "1#1", + "encoding_key": ENCODING_KEY, + "trusted_account_ids": [1], + "cross_application_tracer.enabled": True, + "distributed_tracing.enabled": False, } @pytest.mark.parametrize( - 'inbound_payload,expected_intrinsics,forgone_intrinsics,cat_id', [ - - # Valid payload from trusted account - (['b854df4feb2b1f06', False, '7e249074f277923d', '5d2957be'], - {'nr.referringTransactionGuid': 'b854df4feb2b1f06', - 'nr.tripId': '7e249074f277923d', - 'nr.referringPathHash': '5d2957be'}, - [], - '1#1'), - - # Valid payload from an untrusted account - (['b854df4feb2b1f06', False, '7e249074f277923d', '5d2957be'], - {}, - ['nr.referringTransactionGuid', 'nr.tripId', 'nr.referringPathHash'], - '80#1'), -]) -@pytest.mark.parametrize('url,metric_name', _cat_response_header_urls_to_test) -def test_cat_response_headers(app, inbound_payload, expected_intrinsics, - forgone_intrinsics, cat_id, url, metric_name): + "inbound_payload,expected_intrinsics,forgone_intrinsics,cat_id", + [ + # Valid payload from trusted account + ( + ["b854df4feb2b1f06", False, "7e249074f277923d", "5d2957be"], + { + "nr.referringTransactionGuid": "b854df4feb2b1f06", + "nr.tripId": "7e249074f277923d", + "nr.referringPathHash": "5d2957be", + }, + [], + "1#1", + ), + # Valid payload from an untrusted account + ( + ["b854df4feb2b1f06", False, "7e249074f277923d", "5d2957be"], + {}, + ["nr.referringTransactionGuid", "nr.tripId", "nr.referringPathHash"], + "80#1", + ), + ], +) +@pytest.mark.parametrize("url,metric_name", _cat_response_header_urls_to_test) +def test_cat_response_headers(app, inbound_payload, expected_intrinsics, forgone_intrinsics, cat_id, url, metric_name): _base_metrics = [ - ('Function/%s' % metric_name, 1), + ("Function/%s" % metric_name, 1), ] @validate_transaction_metrics( @@ -114,39 +129,36 @@ def test_cat_response_headers(app, inbound_payload, expected_intrinsics, rollup_metrics=_base_metrics, ) @validate_analytics_catmap_data( - 'WebTransaction/Function/%s' % metric_name, - expected_attributes=expected_intrinsics, - non_expected_attributes=forgone_intrinsics) + "WebTransaction/Function/%s" % metric_name, + expected_attributes=expected_intrinsics, + non_expected_attributes=forgone_intrinsics, + ) @override_application_settings(_custom_settings) def _test(): - cat_headers = make_cross_agent_headers(inbound_payload, ENCODING_KEY, - cat_id) - response = app.fetch('get', url, headers=dict(cat_headers)) + cat_headers = make_cross_agent_headers(inbound_payload, ENCODING_KEY, cat_id) + response = app.fetch("get", url, headers=dict(cat_headers)) if expected_intrinsics: # test valid CAT response header - assert b'X-NewRelic-App-Data' in raw_headers(response) + assert b"X-NewRelic-App-Data" in raw_headers(response) cat_response_header = response.headers.get("X-NewRelic-App-Data", None) - app_data = json.loads(deobfuscate(cat_response_header, - ENCODING_KEY)) + app_data = json.loads(deobfuscate(cat_response_header, ENCODING_KEY)) assert app_data[0] == cat_id - assert app_data[1] == ('WebTransaction/Function/%s' % metric_name) + assert app_data[1] == ("WebTransaction/Function/%s" % metric_name) else: - assert b'X-NewRelic-App-Data' not in raw_headers(response) + assert b"X-NewRelic-App-Data" not in raw_headers(response) _test() @override_application_settings(_custom_settings) def test_cat_response_custom_header(app): - inbound_payload = ['b854df4feb2b1f06', False, '7e249074f277923d', - '5d2957be'] - cat_id = '1#1' - custom_header_value = b'my-custom-header-value' - cat_headers = make_cross_agent_headers(inbound_payload, ENCODING_KEY, - cat_id) - - response = app.fetch('get', '/custom-header/%s/%s' % ( - 'X-NewRelic-App-Data', custom_header_value), - headers=dict(cat_headers)) + inbound_payload = ["b854df4feb2b1f06", False, "7e249074f277923d", "5d2957be"] + cat_id = "1#1" + custom_header_value = b"my-custom-header-value" + cat_headers = make_cross_agent_headers(inbound_payload, ENCODING_KEY, cat_id) + + response = app.fetch( + "get", "/custom-header/%s/%s" % ("X-NewRelic-App-Data", custom_header_value), headers=dict(cat_headers) + ) assert custom_header_value in raw_headers(response), raw_headers(response) diff --git a/tests/framework_tornado/test_server.py b/tests/framework_tornado/test_server.py index 57eb8b576..ffeae3685 100644 --- a/tests/framework_tornado/test_server.py +++ b/tests/framework_tornado/test_server.py @@ -13,42 +13,56 @@ # limitations under the License. import pytest -from newrelic.core.config import global_settings from testing_support.fixtures import ( - override_generic_settings, function_not_called, - validate_transaction_event_attributes, - override_ignore_status_codes, - override_application_settings) + function_not_called, + override_application_settings, + override_generic_settings, + override_ignore_status_codes, +) +from testing_support.validators.validate_code_level_metrics import ( + validate_code_level_metrics, +) from testing_support.validators.validate_transaction_count import ( - validate_transaction_count) -from testing_support.validators.validate_code_level_metrics import validate_code_level_metrics -from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics -from testing_support.validators.validate_transaction_errors import validate_transaction_errors - -@pytest.mark.parametrize('uri,name,metrics, method_metric', ( - # ('/native-simple', '_target_application:NativeSimpleHandler.get', None, - # True), - # ('/simple', '_target_application:SimpleHandler.get', None, True), - ('/call-simple', '_target_application:CallSimpleHandler.get', None, True), - ('/super-simple', '_target_application:SuperSimpleHandler.get', None, - True), - ('/coro', '_target_application:CoroHandler.get', None, False), - ('/fake-coro', '_target_application:FakeCoroHandler.get', None, False), - ('/coro-throw', '_target_application:CoroThrowHandler.get', None, False), - ('/init', '_target_application:InitializeHandler.get', None, True), - ('/multi-trace', '_target_application:MultiTraceHandler.get', - [('Function/trace', 2)], True), -)) -@override_application_settings({'attributes.include': ['request.*']}) + validate_transaction_count, +) +from testing_support.validators.validate_transaction_errors import ( + validate_transaction_errors, +) +from testing_support.validators.validate_transaction_event_attributes import ( + validate_transaction_event_attributes, +) +from testing_support.validators.validate_transaction_metrics import ( + validate_transaction_metrics, +) + +from newrelic.core.config import global_settings + + +@pytest.mark.parametrize( + "uri,name,metrics, method_metric", + ( + # ('/native-simple', '_target_application:NativeSimpleHandler.get', None, + # True), + # ('/simple', '_target_application:SimpleHandler.get', None, True), + ("/call-simple", "_target_application:CallSimpleHandler.get", None, True), + ("/super-simple", "_target_application:SuperSimpleHandler.get", None, True), + ("/coro", "_target_application:CoroHandler.get", None, False), + ("/fake-coro", "_target_application:FakeCoroHandler.get", None, False), + ("/coro-throw", "_target_application:CoroThrowHandler.get", None, False), + ("/init", "_target_application:InitializeHandler.get", None, True), + ("/multi-trace", "_target_application:MultiTraceHandler.get", [("Function/trace", 2)], True), + ), +) +@override_application_settings({"attributes.include": ["request.*"]}) def test_server(app, uri, name, metrics, method_metric): - FRAMEWORK_METRIC = 'Python/Framework/Tornado/%s' % app.tornado_version - METHOD_METRIC = 'Function/%s' % name + FRAMEWORK_METRIC = "Python/Framework/Tornado/%s" % app.tornado_version + METHOD_METRIC = "Function/%s" % name metrics = metrics or [] metrics.append((FRAMEWORK_METRIC, 1)) metrics.append((METHOD_METRIC, 1 if method_metric else None)) - host = '127.0.0.1:' + str(app.get_http_port()) + host = "127.0.0.1:" + str(app.get_http_port()) namespace, func_name = name.split(".") namespace = namespace.replace(":", ".") @@ -57,21 +71,21 @@ def test_server(app, uri, name, metrics, method_metric): rollup_metrics=metrics, ) @validate_transaction_event_attributes( - required_params={ - 'agent': ('response.headers.contentType',), - 'user': (), 'intrinsic': ()}, + required_params={"agent": ("response.headers.contentType",), "user": (), "intrinsic": ()}, exact_attrs={ - 'agent': {'request.headers.contentType': '1234', - 'request.headers.host': host, - 'request.method': 'GET', - 'request.uri': uri, - 'response.status': '200'}, - 'user': {}, - 'intrinsic': {'port': app.get_http_port()}, + "agent": { + "request.headers.contentType": "1234", + "request.headers.host": host, + "request.method": "GET", + "request.uri": uri, + "response.status": "200", + }, + "user": {}, + "intrinsic": {"port": app.get_http_port()}, }, ) def _test(): - response = app.fetch(uri, headers=(('Content-Type', '1234'),)) + response = app.fetch(uri, headers=(("Content-Type", "1234"),)) assert response.code == 200 if method_metric: @@ -80,33 +94,31 @@ def _test(): _test() -@pytest.mark.parametrize('uri,name,metrics,method_metric', ( - ('/native-simple', '_target_application:NativeSimpleHandler.get', None, - True), - ('/simple', '_target_application:SimpleHandler.get', None, True), - ('/call-simple', '_target_application:CallSimpleHandler.get', None, True), - ('/super-simple', '_target_application:SuperSimpleHandler.get', None, - True), - ('/coro', '_target_application:CoroHandler.get', None, False), - ('/fake-coro', '_target_application:FakeCoroHandler.get', None, False), - ('/coro-throw', '_target_application:CoroThrowHandler.get', None, False), - ('/init', '_target_application:InitializeHandler.get', None, True), - ('/ensure-future', - '_target_application:EnsureFutureHandler.get', - [('Function/trace', None)], True), - ('/multi-trace', '_target_application:MultiTraceHandler.get', - [('Function/trace', 2)], True), -)) +@pytest.mark.parametrize( + "uri,name,metrics,method_metric", + ( + ("/native-simple", "_target_application:NativeSimpleHandler.get", None, True), + ("/simple", "_target_application:SimpleHandler.get", None, True), + ("/call-simple", "_target_application:CallSimpleHandler.get", None, True), + ("/super-simple", "_target_application:SuperSimpleHandler.get", None, True), + ("/coro", "_target_application:CoroHandler.get", None, False), + ("/fake-coro", "_target_application:FakeCoroHandler.get", None, False), + ("/coro-throw", "_target_application:CoroThrowHandler.get", None, False), + ("/init", "_target_application:InitializeHandler.get", None, True), + ("/ensure-future", "_target_application:EnsureFutureHandler.get", [("Function/trace", None)], True), + ("/multi-trace", "_target_application:MultiTraceHandler.get", [("Function/trace", 2)], True), + ), +) def test_concurrent_inbound_requests(app, uri, name, metrics, method_metric): from tornado import gen - FRAMEWORK_METRIC = 'Python/Framework/Tornado/%s' % app.tornado_version - METHOD_METRIC = 'Function/%s' % name + FRAMEWORK_METRIC = "Python/Framework/Tornado/%s" % app.tornado_version + METHOD_METRIC = "Function/%s" % name metrics = metrics or [] metrics.append((FRAMEWORK_METRIC, 1)) metrics.append((METHOD_METRIC, 1 if method_metric else None)) - + namespace, func_name = name.split(".") namespace = namespace.replace(":", ".") @@ -128,85 +140,91 @@ def _test(): _test() + @validate_code_level_metrics("_target_application.CrashHandler", "get") -@validate_transaction_metrics('_target_application:CrashHandler.get') -@validate_transaction_errors(['builtins:ValueError']) +@validate_transaction_metrics("_target_application:CrashHandler.get") +@validate_transaction_errors(["builtins:ValueError"]) def test_exceptions_are_recorded(app): - response = app.fetch('/crash') + response = app.fetch("/crash") assert response.code == 500 -@pytest.mark.parametrize('nr_enabled,ignore_status_codes', [ - (True, [405]), - (True, []), - (False, None), -]) +@pytest.mark.parametrize( + "nr_enabled,ignore_status_codes", + [ + (True, [405]), + (True, []), + (False, None), + ], +) def test_unsupported_method(app, nr_enabled, ignore_status_codes): - def _test(): - response = app.fetch('/simple', - method='TEAPOT', body=b'', allow_nonstandard_methods=True) + response = app.fetch("/simple", method="TEAPOT", body=b"", allow_nonstandard_methods=True) assert response.code == 405 if nr_enabled: _test = override_ignore_status_codes(ignore_status_codes)(_test) - _test = validate_transaction_metrics( - '_target_application:SimpleHandler')(_test) + _test = validate_transaction_metrics("_target_application:SimpleHandler")(_test) if ignore_status_codes: _test = validate_transaction_errors(errors=[])(_test) else: - _test = validate_transaction_errors( - errors=['tornado.web:HTTPError'])(_test) + _test = validate_transaction_errors(errors=["tornado.web:HTTPError"])(_test) else: settings = global_settings() - _test = override_generic_settings(settings, {'enabled': False})(_test) + _test = override_generic_settings(settings, {"enabled": False})(_test) _test() @validate_transaction_errors(errors=[]) -@validate_transaction_metrics('tornado.web:ErrorHandler') +@validate_transaction_metrics("tornado.web:ErrorHandler") @validate_transaction_event_attributes( - required_params={'agent': (), 'user': (), 'intrinsic': ()}, + required_params={"agent": (), "user": (), "intrinsic": ()}, exact_attrs={ - 'agent': {'request.uri': '/does-not-exist'}, - 'user': {}, - 'intrinsic': {}, + "agent": {"request.uri": "/does-not-exist"}, + "user": {}, + "intrinsic": {}, }, ) def test_not_found(app): - response = app.fetch('/does-not-exist') + response = app.fetch("/does-not-exist") assert response.code == 404 -@override_generic_settings(global_settings(), { - 'enabled': False, -}) -@function_not_called('newrelic.core.stats_engine', - 'StatsEngine.record_transaction') +@override_generic_settings( + global_settings(), + { + "enabled": False, + }, +) +@function_not_called("newrelic.core.stats_engine", "StatsEngine.record_transaction") def test_nr_disabled(app): - response = app.fetch('/simple') + response = app.fetch("/simple") assert response.code == 200 -@pytest.mark.parametrize('uri,name', ( - ('/web-socket', '_target_application:WebSocketHandler'), - ('/call-web-socket', '_target_application:WebNestedHandler'), -)) +@pytest.mark.parametrize( + "uri,name", + ( + ("/web-socket", "_target_application:WebSocketHandler"), + ("/call-web-socket", "_target_application:WebNestedHandler"), + ), +) def test_web_socket(uri, name, app): import asyncio + from tornado.websocket import websocket_connect namespace, func_name = name.split(":") @validate_transaction_metrics( name, - rollup_metrics=[('Function/%s' % name, None)], + rollup_metrics=[("Function/%s" % name, None)], ) @validate_code_level_metrics(namespace, func_name) def _test(): - url = app.get_url(uri).replace('http', 'ws') + url = app.get_url(uri).replace("http", "ws") @asyncio.coroutine def _connect(): @@ -219,14 +237,14 @@ def _connect(): def connect(): return app.io_loop.run_sync(_connect) - @function_not_called('newrelic.core.stats_engine', - 'StatsEngine.record_transaction') + @function_not_called("newrelic.core.stats_engine", "StatsEngine.record_transaction") def call(call): @asyncio.coroutine def _call(): yield from conn.write_message("test") resp = yield from conn.read_message() assert resp == "hello test" + app.io_loop.run_sync(_call) conn = connect() @@ -236,13 +254,10 @@ def _call(): _test() -LOOP_TIME_METRICS = ( - ('EventLoop/Wait/' - 'WebTransaction/Function/_target_application:BlockingHandler.get', 1), -) +LOOP_TIME_METRICS = (("EventLoop/Wait/" "WebTransaction/Function/_target_application:BlockingHandler.get", 1),) -@pytest.mark.parametrize('yield_before_finish', (True, False)) +@pytest.mark.parametrize("yield_before_finish", (True, False)) @validate_transaction_metrics( "_target_application:BlockingHandler.get", scoped_metrics=LOOP_TIME_METRICS, @@ -251,9 +266,9 @@ def test_io_loop_blocking_time(app, yield_before_finish): from tornado import gen if yield_before_finish: - url = app.get_url('/block-with-yield/2') + url = app.get_url("/block-with-yield/2") else: - url = app.get_url('/block/2') + url = app.get_url("/block/2") coros = (app.http_client.fetch(url) for _ in range(2)) responses = app.io_loop.run_sync(lambda: gen.multi(coros)) diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index 268d7506a..0dbdf5272 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -1192,54 +1192,54 @@ def check_event_attributes(event_data, required_params=None, forgone_params=None # return _validate_wrapper -def validate_transaction_trace_attributes( - required_params=None, forgone_params=None, should_exist=True, url=None, index=-1 -): - required_params = required_params or {} - forgone_params = forgone_params or {} +# def validate_transaction_trace_attributes( +# required_params=None, forgone_params=None, should_exist=True, url=None, index=-1 +# ): +# required_params = required_params or {} +# forgone_params = forgone_params or {} - trace_data = [] +# trace_data = [] - @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") - def _validate_transaction_trace_attributes(wrapped, instance, args, kwargs): +# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") +# def _validate_transaction_trace_attributes(wrapped, instance, args, kwargs): - result = wrapped(*args, **kwargs) +# result = wrapped(*args, **kwargs) - # Now that transaction has been recorded, generate - # a transaction trace +# # Now that transaction has been recorded, generate +# # a transaction trace - connections = SQLConnections() - _trace_data = instance.transaction_trace_data(connections) - trace_data.append(_trace_data) +# connections = SQLConnections() +# _trace_data = instance.transaction_trace_data(connections) +# trace_data.append(_trace_data) - return result +# return result - @function_wrapper - def wrapper(wrapped, instance, args, kwargs): - _new_wrapper = _validate_transaction_trace_attributes(wrapped) - result = _new_wrapper(*args, **kwargs) +# @function_wrapper +# def wrapper(wrapped, instance, args, kwargs): +# _new_wrapper = _validate_transaction_trace_attributes(wrapped) +# result = _new_wrapper(*args, **kwargs) - _trace_data = trace_data[index] - trace_data[:] = [] +# _trace_data = trace_data[index] +# trace_data[:] = [] - if url is not None: - trace_url = _trace_data[0][3] - assert url == trace_url +# if url is not None: +# trace_url = _trace_data[0][3] +# assert url == trace_url - pack_data = unpack_field(_trace_data[0][4]) - assert len(pack_data) == 2 - assert len(pack_data[0]) == 5 - parameters = pack_data[0][4] +# pack_data = unpack_field(_trace_data[0][4]) +# assert len(pack_data) == 2 +# assert len(pack_data[0]) == 5 +# parameters = pack_data[0][4] - assert "intrinsics" in parameters - assert "userAttributes" in parameters - assert "agentAttributes" in parameters +# assert "intrinsics" in parameters +# assert "userAttributes" in parameters +# assert "agentAttributes" in parameters - check_attributes(parameters, required_params, forgone_params) +# check_attributes(parameters, required_params, forgone_params) - return result +# return result - return wrapper +# return wrapper def validate_transaction_error_trace_attributes(required_params=None, forgone_params=None, exact_attrs=None): diff --git a/tests/testing_support/validators/validate_transaction_trace_attributes.py b/tests/testing_support/validators/validate_transaction_trace_attributes.py new file mode 100644 index 000000000..dafe9b920 --- /dev/null +++ b/tests/testing_support/validators/validate_transaction_trace_attributes.py @@ -0,0 +1,69 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from testing_support.fixtures import check_attributes + +from newrelic.common.encoding_utils import unpack_field +from newrelic.common.object_wrapper import function_wrapper, transient_function_wrapper +from newrelic.core.database_utils import SQLConnections + + +def validate_transaction_trace_attributes( + required_params=None, forgone_params=None, should_exist=True, url=None, index=-1 +): + required_params = required_params or {} + forgone_params = forgone_params or {} + + trace_data = [] + + @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") + def _validate_transaction_trace_attributes(wrapped, instance, args, kwargs): + + result = wrapped(*args, **kwargs) + + # Now that transaction has been recorded, generate + # a transaction trace + + connections = SQLConnections() + _trace_data = instance.transaction_trace_data(connections) + trace_data.append(_trace_data) + + return result + + @function_wrapper + def wrapper(wrapped, instance, args, kwargs): + _new_wrapper = _validate_transaction_trace_attributes(wrapped) + result = _new_wrapper(*args, **kwargs) + + _trace_data = trace_data[index] + trace_data[:] = [] + + if url is not None: + trace_url = _trace_data[0][3] + assert url == trace_url + + pack_data = unpack_field(_trace_data[0][4]) + assert len(pack_data) == 2 + assert len(pack_data[0]) == 5 + parameters = pack_data[0][4] + + assert "intrinsics" in parameters + assert "userAttributes" in parameters + assert "agentAttributes" in parameters + + check_attributes(parameters, required_params, forgone_params) + + return result + + return wrapper From 40d343b5153abac35565efb57c946726885b381e Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Mon, 19 Sep 2022 17:29:12 -0700 Subject: [PATCH 16/23] Move validate_transaction_error_trace_attributes into validator directory --- .../test_attributes_in_action.py | 4 +- .../test_ignore_expected_errors.py | 39 +++++++-------- tests/agent_features/test_wsgi_attributes.py | 4 +- tests/testing_support/fixtures.py | 46 ++++++++--------- ...date_transaction_error_trace_attributes.py | 49 +++++++++++++++++++ 5 files changed, 96 insertions(+), 46 deletions(-) create mode 100644 tests/testing_support/validators/validate_transaction_error_trace_attributes.py diff --git a/tests/agent_features/test_attributes_in_action.py b/tests/agent_features/test_attributes_in_action.py index 3dde59b0f..aff846d0b 100644 --- a/tests/agent_features/test_attributes_in_action.py +++ b/tests/agent_features/test_attributes_in_action.py @@ -24,9 +24,11 @@ validate_error_event_attributes, validate_error_event_attributes_outside_transaction, validate_error_trace_attributes_outside_transaction, - validate_transaction_error_trace_attributes, ) from testing_support.validators.validate_span_events import validate_span_events +from testing_support.validators.validate_transaction_error_trace_attributes import ( + validate_transaction_error_trace_attributes, +) from testing_support.validators.validate_transaction_event_attributes import ( validate_transaction_event_attributes, ) diff --git a/tests/agent_features/test_ignore_expected_errors.py b/tests/agent_features/test_ignore_expected_errors.py index f2cd8861a..162424755 100644 --- a/tests/agent_features/test_ignore_expected_errors.py +++ b/tests/agent_features/test_ignore_expected_errors.py @@ -19,11 +19,20 @@ validate_error_event_attributes_outside_transaction, validate_error_event_sample_data, validate_error_trace_attributes_outside_transaction, +) +from testing_support.validators.validate_time_metrics_outside_transaction import ( + validate_time_metrics_outside_transaction, +) +from testing_support.validators.validate_transaction_error_trace_attributes import ( validate_transaction_error_trace_attributes, ) -from testing_support.validators.validate_time_metrics_outside_transaction import validate_time_metrics_outside_transaction -from testing_support.validators.validate_transaction_errors import validate_transaction_errors -from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics +from testing_support.validators.validate_transaction_errors import ( + validate_transaction_errors, +) +from testing_support.validators.validate_transaction_metrics import ( + validate_transaction_metrics, +) + from newrelic.api.application import application_instance from newrelic.api.background_task import background_task from newrelic.api.time_trace import notice_error @@ -36,12 +45,8 @@ # Settings presets # Error classes settings -expected_runtime_error_settings = { - "error_collector.expected_classes": [_runtime_error_name] -} -ignore_runtime_error_settings = { - "error_collector.ignore_classes": [_runtime_error_name] -} +expected_runtime_error_settings = {"error_collector.expected_classes": [_runtime_error_name]} +ignore_runtime_error_settings = {"error_collector.ignore_classes": [_runtime_error_name]} # Status code settings expected_status_code_settings = {"error_collector.expected_status_codes": [418]} @@ -140,9 +145,7 @@ def _test(): @pytest.mark.parametrize("settings,expected", error_trace_settings_matrix) @pytest.mark.parametrize("override_expected", override_expected_matrix) -def test_error_trace_attributes_inside_transaction( - settings, expected, override_expected -): +def test_error_trace_attributes_inside_transaction(settings, expected, override_expected): expected = override_expected if override_expected is not None else expected error_trace_attributes = { @@ -164,9 +167,7 @@ def _test(): @pytest.mark.parametrize("settings,expected", error_trace_settings_matrix) @pytest.mark.parametrize("override_expected", override_expected_matrix) -def test_error_trace_attributes_outside_transaction( - settings, expected, override_expected -): +def test_error_trace_attributes_outside_transaction(settings, expected, override_expected): expected = override_expected if override_expected is not None else expected error_trace_attributes = { @@ -181,9 +182,7 @@ def test_error_trace_attributes_outside_transaction( } @reset_core_stats_engine() - @validate_error_trace_attributes_outside_transaction( - _runtime_error_name, exact_attrs=error_trace_attributes - ) + @validate_error_trace_attributes_outside_transaction(_runtime_error_name, exact_attrs=error_trace_attributes) @override_application_settings(settings) def _test(): exercise(override_expected) @@ -205,9 +204,7 @@ def test_error_metrics_inside_transaction(expected): ("ErrorsExpected/all", expected_metrics_count), ] - @validate_transaction_metrics( - "test", background_task=True, rollup_metrics=metrics_payload - ) + @validate_transaction_metrics("test", background_task=True, rollup_metrics=metrics_payload) @background_task(name="test") def _test(): exercise(expected) diff --git a/tests/agent_features/test_wsgi_attributes.py b/tests/agent_features/test_wsgi_attributes.py index 7543e45d8..e90410b6d 100644 --- a/tests/agent_features/test_wsgi_attributes.py +++ b/tests/agent_features/test_wsgi_attributes.py @@ -17,9 +17,11 @@ dt_enabled, override_application_settings, validate_error_event_attributes, - validate_transaction_error_trace_attributes, ) from testing_support.sample_applications import fully_featured_app +from testing_support.validators.validate_transaction_error_trace_attributes import ( + validate_transaction_error_trace_attributes, +) from testing_support.validators.validate_transaction_event_attributes import ( validate_transaction_event_attributes, ) diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index 0dbdf5272..47c031b38 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -1242,35 +1242,35 @@ def check_event_attributes(event_data, required_params=None, forgone_params=None # return wrapper -def validate_transaction_error_trace_attributes(required_params=None, forgone_params=None, exact_attrs=None): - """Check the error trace for attributes, expect only one error to be - present in the transaction. - """ - required_params = required_params or {} - forgone_params = forgone_params or {} - exact_attrs = exact_attrs or {} +# def validate_transaction_error_trace_attributes(required_params=None, forgone_params=None, exact_attrs=None): +# """Check the error trace for attributes, expect only one error to be +# present in the transaction. +# """ +# required_params = required_params or {} +# forgone_params = forgone_params or {} +# exact_attrs = exact_attrs or {} - @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") - def _validate_transaction_error_trace(wrapped, instance, args, kwargs): - try: - result = wrapped(*args, **kwargs) - except: - raise - else: +# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") +# def _validate_transaction_error_trace(wrapped, instance, args, kwargs): +# try: +# result = wrapped(*args, **kwargs) +# except: +# raise +# else: - error_data = instance.error_data() +# error_data = instance.error_data() - # there should be only one error - assert len(error_data) == 1 - traced_error = error_data[0] +# # there should be only one error +# assert len(error_data) == 1 +# traced_error = error_data[0] - check_error_attributes( - traced_error.parameters, required_params, forgone_params, exact_attrs, is_transaction=True - ) +# check_error_attributes( +# traced_error.parameters, required_params, forgone_params, exact_attrs, is_transaction=True +# ) - return result +# return result - return _validate_transaction_error_trace +# return _validate_transaction_error_trace def check_error_attributes( diff --git a/tests/testing_support/validators/validate_transaction_error_trace_attributes.py b/tests/testing_support/validators/validate_transaction_error_trace_attributes.py new file mode 100644 index 000000000..90734d348 --- /dev/null +++ b/tests/testing_support/validators/validate_transaction_error_trace_attributes.py @@ -0,0 +1,49 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from testing_support.fixtures import check_error_attributes + +from newrelic.common.object_wrapper import transient_function_wrapper + + +def validate_transaction_error_trace_attributes(required_params=None, forgone_params=None, exact_attrs=None): + """Check the error trace for attributes, expect only one error to be + present in the transaction. + """ + required_params = required_params or {} + forgone_params = forgone_params or {} + exact_attrs = exact_attrs or {} + + @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") + def _validate_transaction_error_trace(wrapped, instance, args, kwargs): + try: + result = wrapped(*args, **kwargs) + except: + raise + else: + + error_data = instance.error_data() + + # there should be only one error + assert len(error_data) == 1 + traced_error = error_data[0] + + check_error_attributes( + traced_error.parameters, required_params, forgone_params, exact_attrs, is_transaction=True + ) + + return result + + return _validate_transaction_error_trace From af378e07e3f6d165648ff8969be52c4cdfc9a7c7 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Mon, 19 Sep 2022 17:35:59 -0700 Subject: [PATCH 17/23] Move validate_error_trace_collector_json into validator directory --- .../agent_features/test_collector_payloads.py | 4 +- tests/testing_support/fixtures.py | 58 +++++++++---------- .../validate_error_trace_collector_json.py | 58 +++++++++++++++++++ 3 files changed, 90 insertions(+), 30 deletions(-) create mode 100644 tests/testing_support/validators/validate_error_trace_collector_json.py diff --git a/tests/agent_features/test_collector_payloads.py b/tests/agent_features/test_collector_payloads.py index 76c72517e..ebaddfaba 100644 --- a/tests/agent_features/test_collector_payloads.py +++ b/tests/agent_features/test_collector_payloads.py @@ -18,7 +18,6 @@ override_application_settings, validate_custom_event_collector_json, validate_error_event_collector_json, - validate_error_trace_collector_json, validate_transaction_event_collector_json, ) from testing_support.sample_applications import ( @@ -26,6 +25,9 @@ simple_custom_event_app, simple_exceptional_app, ) +from testing_support.validators.validate_error_trace_collector_json import ( + validate_error_trace_collector_json, +) from testing_support.validators.validate_log_event_collector_json import ( validate_log_event_collector_json, ) diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index 47c031b38..6397570d6 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -1330,43 +1330,43 @@ def check_attributes(parameters, required_params=None, forgone_params=None, exac assert intrinsics[param] == value, ((param, value), intrinsics) -def validate_error_trace_collector_json(): - @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") - def _validate_error_trace_collector_json(wrapped, instance, args, kwargs): - try: - result = wrapped(*args, **kwargs) - except: - raise - else: - errors = instance.error_data() +# def validate_error_trace_collector_json(): +# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") +# def _validate_error_trace_collector_json(wrapped, instance, args, kwargs): +# try: +# result = wrapped(*args, **kwargs) +# except: +# raise +# else: +# errors = instance.error_data() - # recreate what happens right before data is sent to the collector - # in data_collector.py via ApplicationSession.send_errors - agent_run_id = 666 - payload = (agent_run_id, errors) - collector_json = json_encode(payload) +# # recreate what happens right before data is sent to the collector +# # in data_collector.py via ApplicationSession.send_errors +# agent_run_id = 666 +# payload = (agent_run_id, errors) +# collector_json = json_encode(payload) - decoded_json = json.loads(collector_json) +# decoded_json = json.loads(collector_json) - assert decoded_json[0] == agent_run_id - err = decoded_json[1][0] - assert len(err) == 5 - assert isinstance(err[0], (int, float)) - assert isinstance(err[1], six.string_types) # path - assert isinstance(err[2], six.string_types) # error message - assert isinstance(err[3], six.string_types) # exception name - parameters = err[4] +# assert decoded_json[0] == agent_run_id +# err = decoded_json[1][0] +# assert len(err) == 5 +# assert isinstance(err[0], (int, float)) +# assert isinstance(err[1], six.string_types) # path +# assert isinstance(err[2], six.string_types) # error message +# assert isinstance(err[3], six.string_types) # exception name +# parameters = err[4] - parameter_fields = ["userAttributes", "stack_trace", "agentAttributes", "intrinsics"] +# parameter_fields = ["userAttributes", "stack_trace", "agentAttributes", "intrinsics"] - for field in parameter_fields: - assert field in parameters +# for field in parameter_fields: +# assert field in parameters - assert "request_uri" not in parameters +# assert "request_uri" not in parameters - return result +# return result - return _validate_error_trace_collector_json +# return _validate_error_trace_collector_json def validate_error_event_collector_json(num_errors=1): diff --git a/tests/testing_support/validators/validate_error_trace_collector_json.py b/tests/testing_support/validators/validate_error_trace_collector_json.py new file mode 100644 index 000000000..e4d14ee21 --- /dev/null +++ b/tests/testing_support/validators/validate_error_trace_collector_json.py @@ -0,0 +1,58 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json + +from newrelic.common.encoding_utils import json_encode +from newrelic.common.object_wrapper import transient_function_wrapper +from newrelic.packages import six + + +def validate_error_trace_collector_json(): + @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") + def _validate_error_trace_collector_json(wrapped, instance, args, kwargs): + try: + result = wrapped(*args, **kwargs) + except: + raise + else: + errors = instance.error_data() + + # recreate what happens right before data is sent to the collector + # in data_collector.py via ApplicationSession.send_errors + agent_run_id = 666 + payload = (agent_run_id, errors) + collector_json = json_encode(payload) + + decoded_json = json.loads(collector_json) + + assert decoded_json[0] == agent_run_id + err = decoded_json[1][0] + assert len(err) == 5 + assert isinstance(err[0], (int, float)) + assert isinstance(err[1], six.string_types) # path + assert isinstance(err[2], six.string_types) # error message + assert isinstance(err[3], six.string_types) # exception name + parameters = err[4] + + parameter_fields = ["userAttributes", "stack_trace", "agentAttributes", "intrinsics"] + + for field in parameter_fields: + assert field in parameters + + assert "request_uri" not in parameters + + return result + + return _validate_error_trace_collector_json From 3325cd57cff47d75b5e7816c6f5e2df91a190eea Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Tue, 20 Sep 2022 10:26:23 -0700 Subject: [PATCH 18/23] Move validate_error_event_collector_json into validator directory --- .../agent_features/test_collector_payloads.py | 4 +- tests/testing_support/fixtures.py | 898 +----------------- .../validate_error_event_collector_json.py | 69 ++ 3 files changed, 106 insertions(+), 865 deletions(-) create mode 100644 tests/testing_support/validators/validate_error_event_collector_json.py diff --git a/tests/agent_features/test_collector_payloads.py b/tests/agent_features/test_collector_payloads.py index ebaddfaba..072c9bcc8 100644 --- a/tests/agent_features/test_collector_payloads.py +++ b/tests/agent_features/test_collector_payloads.py @@ -17,7 +17,6 @@ from testing_support.fixtures import ( override_application_settings, validate_custom_event_collector_json, - validate_error_event_collector_json, validate_transaction_event_collector_json, ) from testing_support.sample_applications import ( @@ -25,6 +24,9 @@ simple_custom_event_app, simple_exceptional_app, ) +from testing_support.validators.validate_error_event_collector_json import ( + validate_error_event_collector_json, +) from testing_support.validators.validate_error_trace_collector_json import ( validate_error_trace_collector_json, ) diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index 6397570d6..7e3155e4e 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -385,194 +385,6 @@ def make_synthetics_header(account_id, resource_id, job_id, monitor_id, encoding return {"X-NewRelic-Synthetics": value} -# def validate_transaction_metrics( -# name, -# group="Function", -# background_task=False, -# scoped_metrics=None, -# rollup_metrics=None, -# custom_metrics=None, -# index=-1, -# ): -# scoped_metrics = scoped_metrics or [] -# rollup_metrics = rollup_metrics or [] -# custom_metrics = custom_metrics or [] - -# if background_task: -# unscoped_metrics = [ -# "OtherTransaction/all", -# "OtherTransaction/%s/%s" % (group, name), -# "OtherTransactionTotalTime", -# "OtherTransactionTotalTime/%s/%s" % (group, name), -# ] -# transaction_scope_name = "OtherTransaction/%s/%s" % (group, name) -# else: -# unscoped_metrics = [ -# "WebTransaction", -# "WebTransaction/%s/%s" % (group, name), -# "WebTransactionTotalTime", -# "WebTransactionTotalTime/%s/%s" % (group, name), -# "HttpDispatcher", -# ] -# transaction_scope_name = "WebTransaction/%s/%s" % (group, name) - -# @function_wrapper -# def _validate_wrapper(wrapped, instance, args, kwargs): - -# record_transaction_called = [] -# recorded_metrics = [] - -# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") -# @catch_background_exceptions -# def _validate_transaction_metrics(wrapped, instance, args, kwargs): -# record_transaction_called.append(True) -# try: -# result = wrapped(*args, **kwargs) -# except: -# raise -# else: -# metrics = instance.stats_table -# # Record a copy of the metric value so that the values aren't -# # merged in the future -# _metrics = {} -# for k, v in metrics.items(): -# _metrics[k] = copy.copy(v) -# recorded_metrics.append(_metrics) - -# return result - -# def _validate(metrics, name, scope, count): -# key = (name, scope) -# metric = metrics.get(key) - -# def _metrics_table(): -# out = [""] -# out.append("Expected: {0}: {1}".format(key, count)) -# for metric_key, metric_value in metrics.items(): -# out.append("{0}: {1}".format(metric_key, metric_value[0])) -# return "\n".join(out) - -# def _metric_details(): -# return "metric=%r, count=%r" % (key, metric.call_count) - -# if count is not None: -# assert metric is not None, _metrics_table() -# if count == "present": -# assert metric.call_count > 0, _metric_details() -# else: -# assert metric.call_count == count, _metric_details() - -# assert metric.total_call_time >= 0, (key, metric) -# assert metric.total_exclusive_call_time >= 0, (key, metric) -# assert metric.min_call_time >= 0, (key, metric) -# assert metric.sum_of_squares >= 0, (key, metric) - -# else: -# assert metric is None, _metrics_table() - -# _new_wrapper = _validate_transaction_metrics(wrapped) -# val = _new_wrapper(*args, **kwargs) -# assert record_transaction_called -# metrics = recorded_metrics[index] - -# record_transaction_called[:] = [] -# recorded_metrics[:] = [] - -# for unscoped_metric in unscoped_metrics: -# _validate(metrics, unscoped_metric, "", 1) - -# for scoped_name, scoped_count in scoped_metrics: -# _validate(metrics, scoped_name, transaction_scope_name, scoped_count) - -# for rollup_name, rollup_count in rollup_metrics: -# _validate(metrics, rollup_name, "", rollup_count) - -# for custom_name, custom_count in custom_metrics: -# _validate(metrics, custom_name, "", custom_count) - -# custom_metric_names = {name for name, _ in custom_metrics} -# for name, _ in metrics: -# if name not in custom_metric_names: -# assert not name.startswith("Supportability/api/"), name - -# return val - -# return _validate_wrapper - - -# def validate_time_metrics_outside_transaction(time_metrics=None, index=-1): -# time_metrics = time_metrics or [] - -# @function_wrapper -# def _validate_wrapper(wrapped, instance, args, kwargs): - -# record_time_metric_called = [] -# recorded_metrics = [] - -# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_time_metric") -# @catch_background_exceptions -# def _validate_transaction_metrics(wrapped, instance, args, kwargs): -# record_time_metric_called.append(True) -# try: -# result = wrapped(*args, **kwargs) -# except: -# raise -# else: -# metrics = instance.stats_table -# # Record a copy of the metric value so that the values aren't -# # merged in the future -# _metrics = {} -# for k, v in metrics.items(): -# _metrics[k] = copy.copy(v) -# recorded_metrics.append(_metrics) - -# return result - -# def _validate(metrics, name, count): -# key = (name, "") -# metric = metrics.get(key) - -# def _metrics_table(): -# out = [""] -# out.append("Expected: {0}: {1}".format(key, count)) -# for metric_key, metric_value in metrics.items(): -# out.append("{0}: {1}".format(metric_key, metric_value[0])) -# return "\n".join(out) - -# def _metric_details(): -# return "metric=%r, count=%r" % (key, metric.call_count) - -# if count is not None: -# assert metric is not None, _metrics_table() -# if count == "present": -# assert metric.call_count > 0, _metric_details() -# else: -# assert metric.call_count == count, _metric_details() - -# assert metric.total_call_time >= 0, (key, metric) -# assert metric.total_exclusive_call_time >= 0, (key, metric) -# assert metric.min_call_time >= 0, (key, metric) -# assert metric.sum_of_squares >= 0, (key, metric) - -# else: -# assert metric is None, _metrics_table() - -# _new_wrapper = _validate_transaction_metrics(wrapped) -# val = _new_wrapper(*args, **kwargs) -# assert record_time_metric_called -# metrics = recorded_metrics[index] - -# record_time_metric_called[:] = [] -# recorded_metrics[:] = [] - -# for time_metric, count in time_metrics: -# _validate(metrics, time_metric, count) - -# return val - -# return _validate_wrapper - - def capture_transaction_metrics(metrics_list, full_metrics=None): @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") @catch_background_exceptions @@ -594,264 +406,6 @@ def _capture_transaction_metrics(wrapped, instance, args, kwargs): return _capture_transaction_metrics -# def validate_internal_metrics(metrics=None): -# metrics = metrics or [] - -# def no_op(wrapped, instance, args, kwargs): -# pass - -# @function_wrapper -# def _validate_wrapper(wrapped, instance, args, kwargs): -# # Apply no-op wrappers to prevent new internal trace contexts from being started, preventing capture -# wrapped = transient_function_wrapper("newrelic.core.internal_metrics", "InternalTraceContext.__enter__")(no_op)(wrapped) -# wrapped = transient_function_wrapper("newrelic.core.internal_metrics", "InternalTraceContext.__exit__")(no_op)(wrapped) - -# captured_metrics = CustomMetrics() -# with InternalTraceContext(captured_metrics): -# result = wrapped(*args, **kwargs) -# captured_metrics = dict(captured_metrics.metrics()) - -# def _validate(name, count): -# metric = captured_metrics.get(name) - -# def _metrics_table(): -# return "metric=%r, metrics=%r" % (name, captured_metrics) - -# def _metric_details(): -# return "metric=%r, count=%r" % (name, metric.call_count) - -# if count is not None and count > 0: -# assert metric is not None, _metrics_table() -# if count == "present": -# assert metric.call_count > 0, _metric_details() -# else: -# assert metric.call_count == count, _metric_details() - -# else: -# assert metric is None, _metrics_table() - -# for metric, count in metrics: -# _validate(metric, count) - -# return result - -# return _validate_wrapper - - -# def validate_transaction_errors(errors=None, required_params=None, forgone_params=None): -# errors = errors or [] -# required_params = required_params or [] -# forgone_params = forgone_params or [] -# captured_errors = [] - -# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") -# @catch_background_exceptions -# def _capture_transaction_errors(wrapped, instance, args, kwargs): -# def _bind_params(transaction, *args, **kwargs): -# return transaction - -# transaction = _bind_params(*args, **kwargs) -# captured = transaction.errors - -# captured_errors.append(captured) - -# return wrapped(*args, **kwargs) - -# @function_wrapper -# def _validate_transaction_errors(wrapped, instance, args, kwargs): -# _new_wrapped = _capture_transaction_errors(wrapped) -# output = _new_wrapped(*args, **kwargs) - -# expected = sorted(errors) - -# if captured_errors: -# captured = captured_errors[0] -# else: -# captured = [] - -# if errors and isinstance(errors[0], (tuple, list)): -# compare_to = sorted([(e.type, e.message) for e in captured]) -# else: -# compare_to = sorted([e.type for e in captured]) - -# assert expected == compare_to, "expected=%r, captured=%r, errors=%r" % (expected, compare_to, captured) - -# for e in captured: -# assert e.span_id -# for name, value in required_params: -# assert name in e.custom_params, "name=%r, params=%r" % (name, e.custom_params) -# assert e.custom_params[name] == value, "name=%r, value=%r, params=%r" % ( -# name, -# value, -# e.custom_params, -# ) - -# for name, value in forgone_params: -# assert name not in e.custom_params, "name=%r, params=%r" % (name, e.custom_params) - -# return output - -# return _validate_transaction_errors - - -# def validate_application_errors(errors=None, required_params=None, forgone_params=None): -# errors = errors or [] -# required_params = required_params or [] -# forgone_params = forgone_params or [] - -# @function_wrapper -# def _validate_application_errors(wrapped, instace, args, kwargs): - -# try: -# result = wrapped(*args, **kwargs) -# except: -# raise -# else: - -# stats = core_application_stats_engine() - -# app_errors = stats.error_data() - -# expected = sorted(errors) -# captured = sorted([(e.type, e.message) for e in stats.error_data()]) - -# assert expected == captured, "expected=%r, captured=%r, errors=%r" % (expected, captured, app_errors) - -# for e in app_errors: -# for name, value in required_params: -# assert name in e.parameters["userAttributes"], "name=%r, params=%r" % (name, e.parameters) -# assert e.parameters["userAttributes"][name] == value, "name=%r, value=%r, params=%r" % ( -# name, -# value, -# e.parameters, -# ) - -# for name, value in forgone_params: -# assert name not in e.parameters["userAttributes"], "name=%r, params=%r" % (name, e.parameters) - -# return result - -# return _validate_application_errors - - -# def validate_custom_parameters(required_params=None, forgone_params=None): -# required_params = required_params or [] -# forgone_params = forgone_params or [] - -# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") -# @catch_background_exceptions -# def _validate_custom_parameters(wrapped, instance, args, kwargs): -# def _bind_params(transaction, *args, **kwargs): -# return transaction - -# transaction = _bind_params(*args, **kwargs) - -# # these are pre-destination applied attributes, so they may not -# # actually end up in a transaction/error trace, we are merely testing -# # for presence on the TransactionNode - -# attrs = {} -# for attr in transaction.user_attributes: -# attrs[attr.name] = attr.value - -# for name, value in required_params: -# assert name in attrs, "name=%r, params=%r" % (name, attrs) -# assert attrs[name] == value, "name=%r, value=%r, params=%r" % (name, value, attrs) - -# for name, value in forgone_params: -# assert name not in attrs, "name=%r, params=%r" % (name, attrs) - -# return wrapped(*args, **kwargs) - -# return _validate_custom_parameters - - -# def validate_synthetics_event(required_attrs=None, forgone_attrs=None, should_exist=True): -# required_attrs = required_attrs or [] -# forgone_attrs = forgone_attrs or [] -# failed = [] - -# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") -# def _validate_synthetics_event(wrapped, instance, args, kwargs): -# result = wrapped(*args, **kwargs) - -# try: -# if not should_exist: -# assert instance.synthetics_events == [] -# else: -# assert len(instance.synthetics_events) == 1 -# event = instance.synthetics_events[0] -# assert event is not None -# assert len(event) == 3 - -# def _flatten(event): -# result = {} -# for elem in event: -# for k, v in elem.items(): -# result[k] = v -# return result - -# flat_event = _flatten(event) - -# assert "nr.guid" in flat_event, "name=%r, event=%r" % ("nr.guid", flat_event) - -# for name, value in required_attrs: -# assert name in flat_event, "name=%r, event=%r" % (name, flat_event) -# assert flat_event[name] == value, "name=%r, value=%r, event=%r" % (name, value, flat_event) - -# for name, value in forgone_attrs: -# assert name not in flat_event, "name=%r, value=%r, event=%r" % (name, value, flat_event) -# except Exception as e: -# failed.append(e) - -# return result - -# @function_wrapper -# def wrapper(wrapped, instance, args, kwargs): -# _new_wrapper = _validate_synthetics_event(wrapped) -# result = _new_wrapper(*args, **kwargs) -# if failed: -# e = failed.pop() -# raise e -# return result - -# return wrapper - - -# def validate_transaction_event_attributes(required_params=None, forgone_params=None, exact_attrs=None, index=-1): -# required_params = required_params or {} -# forgone_params = forgone_params or {} -# exact_attrs = exact_attrs or {} - -# captured_events = [] - -# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") -# def _capture_transaction_events(wrapped, instance, args, kwargs): -# try: -# result = wrapped(*args, **kwargs) -# except: -# raise -# else: -# event_data = instance.transaction_events -# captured_events.append(event_data) -# return result - -# @function_wrapper -# def _validate_transaction_event_attributes(wrapped, instance, args, kwargs): -# _new_wrapper = _capture_transaction_events(wrapped) -# result = _new_wrapper(*args, **kwargs) - -# assert captured_events, "No events captured" -# event_data = captured_events[index] -# captured_events[:] = [] - -# check_event_attributes(event_data, required_params, forgone_params, exact_attrs) - -# return result - -# return _validate_transaction_event_attributes - - def check_event_attributes(event_data, required_params=None, forgone_params=None, exact_attrs=None): """Check the event attributes from a single (first) event in a SampledDataSet. If necessary, clear out previous errors from StatsEngine @@ -889,390 +443,6 @@ def check_event_attributes(event_data, required_params=None, forgone_params=None assert intrinsics[param] == value, ((param, value), intrinsics) -# def validate_non_transaction_error_event(required_intrinsics=None, num_errors=1, required_user=None, forgone_user=None): -# """Validate error event data for a single error occurring outside of a -# transaction. -# """ -# required_intrinsics = required_intrinsics or {} -# required_user = required_user or {} -# forgone_user = forgone_user or [] - -# @function_wrapper -# def _validate_non_transaction_error_event(wrapped, instace, args, kwargs): - -# try: -# result = wrapped(*args, **kwargs) -# except: -# raise -# else: - -# stats = core_application_stats_engine(None) - -# assert stats.error_events.num_seen == num_errors -# for event in stats.error_events: - -# assert len(event) == 3 # [intrinsic, user, agent attributes] - -# intrinsics = event[0] - -# # The following attributes are all required, and also the only -# # intrinsic attributes that can be included in an error event -# # recorded outside of a transaction - -# assert intrinsics["type"] == "TransactionError" -# assert intrinsics["transactionName"] is None -# assert intrinsics["error.class"] == required_intrinsics["error.class"] -# assert intrinsics["error.message"].startswith(required_intrinsics["error.message"]) -# assert intrinsics["error.expected"] == required_intrinsics["error.expected"] -# now = time.time() -# assert isinstance(intrinsics["timestamp"], int) -# assert intrinsics["timestamp"] <= 1000.0 * now - -# user_params = event[1] -# for name, value in required_user.items(): -# assert name in user_params, "name=%r, params=%r" % (name, user_params) -# assert user_params[name] == value, "name=%r, value=%r, params=%r" % (name, value, user_params) - -# for param in forgone_user: -# assert param not in user_params - -# return result - -# return _validate_non_transaction_error_event - - -# def validate_application_error_trace_count(num_errors): -# """Validate error event data for a single error occurring outside of a -# transaction. -# """ - -# @function_wrapper -# def _validate_application_error_trace_count(wrapped, instace, args, kwargs): - -# try: -# result = wrapped(*args, **kwargs) -# except: -# raise -# else: - -# stats = core_application_stats_engine(None) -# assert len(stats.error_data()) == num_errors - -# return result - -# return _validate_application_error_trace_count - - -# def validate_application_error_event_count(num_errors): -# """Validate error event data for a single error occurring outside of a -# transaction. -# """ - -# @function_wrapper -# def _validate_application_error_event_count(wrapped, instace, args, kwargs): - -# try: -# result = wrapped(*args, **kwargs) -# except: -# raise -# else: - -# stats = core_application_stats_engine(None) -# assert len(list(stats.error_events)) == num_errors - -# return result - -# return _validate_application_error_event_count - - -# def validate_synthetics_transaction_trace(required_params=None, forgone_params=None, should_exist=True): -# required_params = required_params or {} -# forgone_params = forgone_params or {} - -# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") -# def _validate_synthetics_transaction_trace(wrapped, instance, args, kwargs): -# try: -# result = wrapped(*args, **kwargs) -# except: -# raise -# else: - -# # Now that transaction has been recorded, generate -# # a transaction trace - -# connections = SQLConnections() -# trace_data = instance.transaction_trace_data(connections) - -# # Check that synthetics resource id is in TT header - -# header = trace_data[0] -# header_key = "synthetics_resource_id" - -# if should_exist: -# assert header_key in required_params -# assert header[9] == required_params[header_key], "name=%r, header=%r" % (header_key, header) -# else: -# assert header[9] is None - -# # Check that synthetics ids are in TT custom params - -# pack_data = unpack_field(trace_data[0][4]) -# tt_intrinsics = pack_data[0][4]["intrinsics"] - -# for name in required_params: -# assert name in tt_intrinsics, "name=%r, intrinsics=%r" % (name, tt_intrinsics) -# assert tt_intrinsics[name] == required_params[name], "name=%r, value=%r, intrinsics=%r" % ( -# name, -# required_params[name], -# tt_intrinsics, -# ) - -# for name in forgone_params: -# assert name not in tt_intrinsics, "name=%r, intrinsics=%r" % (name, tt_intrinsics) - -# return result - -# return _validate_synthetics_transaction_trace - - -# def validate_tt_collector_json( -# required_params=None, -# forgone_params=None, -# should_exist=True, -# datastore_params=None, -# datastore_forgone_params=None, -# message_broker_params=None, -# message_broker_forgone_params=None, -# exclude_request_uri=False, -# ): -# """make assertions based off the cross-agent spec on transaction traces""" -# required_params = required_params or {} -# forgone_params = forgone_params or {} -# datastore_params = datastore_params or {} -# datastore_forgone_params = datastore_forgone_params or {} -# message_broker_params = message_broker_params or {} -# message_broker_forgone_params = message_broker_forgone_params or [] - -# @function_wrapper -# def _validate_wrapper(wrapped, instance, args, kwargs): - -# traces_recorded = [] - -# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") -# def _validate_tt_collector_json(wrapped, instance, args, kwargs): - -# result = wrapped(*args, **kwargs) - -# # Now that transaction has been recorded, generate -# # a transaction trace - -# connections = SQLConnections() -# trace_data = instance.transaction_trace_data(connections) -# traces_recorded.append(trace_data) - -# return result - -# def _validate_trace(trace): -# assert isinstance(trace[0], float) # absolute start time (ms) -# assert isinstance(trace[1], float) # duration (ms) -# assert trace[0] > 0 # absolute time (ms) -# assert isinstance(trace[2], six.string_types) # transaction name -# if trace[2].startswith("WebTransaction"): -# if exclude_request_uri: -# assert trace[3] is None # request url -# else: -# assert isinstance(trace[3], six.string_types) -# # query parameters should not be captured -# assert "?" not in trace[3] - -# # trace details -- python agent always uses condensed trace array - -# trace_details, string_table = unpack_field(trace[4]) -# assert len(trace_details) == 5 -# assert isinstance(trace_details[0], float) # start time (ms) - -# # the next two items should be empty dicts, old parameters stuff, -# # placeholders for now - -# assert isinstance(trace_details[1], dict) -# assert len(trace_details[1]) == 0 -# assert isinstance(trace_details[2], dict) -# assert len(trace_details[2]) == 0 - -# # root node in slot 3 - -# root_node = trace_details[3] -# assert isinstance(root_node[0], float) # entry timestamp -# assert isinstance(root_node[1], float) # exit timestamp -# assert root_node[2] == "ROOT" -# assert isinstance(root_node[3], dict) -# assert len(root_node[3]) == 0 # spec shows empty (for root) -# children = root_node[4] -# assert isinstance(children, list) - -# # there are two optional items at the end of trace segments, -# # class name that segment is in, and method name function is in; -# # Python agent does not use these (only Java does) - -# # let's just test the first child -# trace_segment = children[0] -# assert isinstance(trace_segment[0], float) # entry timestamp -# assert isinstance(trace_segment[1], float) # exit timestamp -# assert isinstance(trace_segment[2], six.string_types) # scope -# assert isinstance(trace_segment[3], dict) # request params -# assert isinstance(trace_segment[4], list) # children - -# assert trace_segment[0] >= root_node[0] # trace starts after root - -# def _check_params_and_start_time(node): -# children = node[4] -# for child in children: -# assert child[0] >= node[0] # child started after parent -# _check_params_and_start_time(child) - -# params = node[3] -# assert isinstance(params, dict) - -# # We should always report exclusive_duration_millis on a -# # segment. This allows us to override exclusive time -# # calculations on APM. -# assert "exclusive_duration_millis" in params -# assert isinstance(params["exclusive_duration_millis"], float) - -# segment_name = _lookup_string_table(node[2], string_table, default=node[2]) -# if segment_name.startswith("Datastore"): -# for key in datastore_params: -# assert key in params, key -# assert params[key] == datastore_params[key] -# for key in datastore_forgone_params: -# assert key not in params, key - -# # if host is reported, it cannot be localhost -# if "host" in params: -# assert params["host"] not in LOCALHOST_EQUIVALENTS - -# elif segment_name.startswith("MessageBroker"): -# for key in message_broker_params: -# assert key in params, key -# assert params[key] == message_broker_params[key] -# for key in message_broker_forgone_params: -# assert key not in params, key - -# _check_params_and_start_time(trace_segment) - -# attributes = trace_details[4] - -# assert "intrinsics" in attributes -# assert "userAttributes" in attributes -# assert "agentAttributes" in attributes - -# assert isinstance(trace[5], six.string_types) # GUID -# assert trace[6] is None # reserved for future use -# assert trace[7] is False # deprecated force persist flag - -# # x-ray session ID - -# assert trace[8] is None - -# # Synthetics ID - -# assert trace[9] is None or isinstance(trace[9], six.string_types) - -# assert isinstance(string_table, list) -# for name in string_table: -# assert isinstance(name, six.string_types) # metric name - -# _new_wrapper = _validate_tt_collector_json(wrapped) -# val = _new_wrapper(*args, **kwargs) -# trace_data = traces_recorded.pop() -# trace = trace_data[0] # 1st trace -# _validate_trace(trace) -# return val - -# return _validate_wrapper - - -# def validate_transaction_trace_attributes( -# required_params=None, forgone_params=None, should_exist=True, url=None, index=-1 -# ): -# required_params = required_params or {} -# forgone_params = forgone_params or {} - -# trace_data = [] - -# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") -# def _validate_transaction_trace_attributes(wrapped, instance, args, kwargs): - -# result = wrapped(*args, **kwargs) - -# # Now that transaction has been recorded, generate -# # a transaction trace - -# connections = SQLConnections() -# _trace_data = instance.transaction_trace_data(connections) -# trace_data.append(_trace_data) - -# return result - -# @function_wrapper -# def wrapper(wrapped, instance, args, kwargs): -# _new_wrapper = _validate_transaction_trace_attributes(wrapped) -# result = _new_wrapper(*args, **kwargs) - -# _trace_data = trace_data[index] -# trace_data[:] = [] - -# if url is not None: -# trace_url = _trace_data[0][3] -# assert url == trace_url - -# pack_data = unpack_field(_trace_data[0][4]) -# assert len(pack_data) == 2 -# assert len(pack_data[0]) == 5 -# parameters = pack_data[0][4] - -# assert "intrinsics" in parameters -# assert "userAttributes" in parameters -# assert "agentAttributes" in parameters - -# check_attributes(parameters, required_params, forgone_params) - -# return result - -# return wrapper - - -# def validate_transaction_error_trace_attributes(required_params=None, forgone_params=None, exact_attrs=None): -# """Check the error trace for attributes, expect only one error to be -# present in the transaction. -# """ -# required_params = required_params or {} -# forgone_params = forgone_params or {} -# exact_attrs = exact_attrs or {} - -# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") -# def _validate_transaction_error_trace(wrapped, instance, args, kwargs): -# try: -# result = wrapped(*args, **kwargs) -# except: -# raise -# else: - -# error_data = instance.error_data() - -# # there should be only one error -# assert len(error_data) == 1 -# traced_error = error_data[0] - -# check_error_attributes( -# traced_error.parameters, required_params, forgone_params, exact_attrs, is_transaction=True -# ) - -# return result - -# return _validate_transaction_error_trace - - def check_error_attributes( parameters, required_params=None, forgone_params=None, exact_attrs=None, is_transaction=True ): @@ -1369,55 +539,55 @@ def check_attributes(parameters, required_params=None, forgone_params=None, exac # return _validate_error_trace_collector_json -def validate_error_event_collector_json(num_errors=1): - """Validate the format, types and number of errors of the data we - send to the collector for harvest. - """ +# def validate_error_event_collector_json(num_errors=1): +# """Validate the format, types and number of errors of the data we +# send to the collector for harvest. +# """ - @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") - def _validate_error_event_collector_json(wrapped, instance, args, kwargs): - try: - result = wrapped(*args, **kwargs) - except: - raise - else: +# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") +# def _validate_error_event_collector_json(wrapped, instance, args, kwargs): +# try: +# result = wrapped(*args, **kwargs) +# except: +# raise +# else: - samples = list(instance.error_events) - s_info = instance.error_events.sampling_info - agent_run_id = 666 +# samples = list(instance.error_events) +# s_info = instance.error_events.sampling_info +# agent_run_id = 666 - # emulate the payload used in data_collector.py +# # emulate the payload used in data_collector.py - payload = (agent_run_id, s_info, samples) - collector_json = json_encode(payload) +# payload = (agent_run_id, s_info, samples) +# collector_json = json_encode(payload) - decoded_json = json.loads(collector_json) +# decoded_json = json.loads(collector_json) - assert decoded_json[0] == agent_run_id +# assert decoded_json[0] == agent_run_id - sampling_info = decoded_json[1] +# sampling_info = decoded_json[1] - harvest_config = instance.settings.event_harvest_config - reservoir_size = harvest_config.harvest_limits.error_event_data +# harvest_config = instance.settings.event_harvest_config +# reservoir_size = harvest_config.harvest_limits.error_event_data - assert sampling_info["reservoir_size"] == reservoir_size - assert sampling_info["events_seen"] == num_errors +# assert sampling_info["reservoir_size"] == reservoir_size +# assert sampling_info["events_seen"] == num_errors - error_events = decoded_json[2] +# error_events = decoded_json[2] - assert len(error_events) == num_errors - for event in error_events: +# assert len(error_events) == num_errors +# for event in error_events: - # event is an array containing intrinsics, user-attributes, - # and agent-attributes +# # event is an array containing intrinsics, user-attributes, +# # and agent-attributes - assert len(event) == 3 - for d in event: - assert isinstance(d, dict) +# assert len(event) == 3 +# for d in event: +# assert isinstance(d, dict) - return result +# return result - return _validate_error_event_collector_json +# return _validate_error_event_collector_json def validate_transaction_event_collector_json(): diff --git a/tests/testing_support/validators/validate_error_event_collector_json.py b/tests/testing_support/validators/validate_error_event_collector_json.py new file mode 100644 index 000000000..44940818f --- /dev/null +++ b/tests/testing_support/validators/validate_error_event_collector_json.py @@ -0,0 +1,69 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json + +from newrelic.common.encoding_utils import json_encode +from newrelic.common.object_wrapper import transient_function_wrapper + + +def validate_error_event_collector_json(num_errors=1): + """Validate the format, types and number of errors of the data we + send to the collector for harvest. + """ + + @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") + def _validate_error_event_collector_json(wrapped, instance, args, kwargs): + try: + result = wrapped(*args, **kwargs) + except: + raise + else: + + samples = list(instance.error_events) + s_info = instance.error_events.sampling_info + agent_run_id = 666 + + # emulate the payload used in data_collector.py + + payload = (agent_run_id, s_info, samples) + collector_json = json_encode(payload) + + decoded_json = json.loads(collector_json) + + assert decoded_json[0] == agent_run_id + + sampling_info = decoded_json[1] + + harvest_config = instance.settings.event_harvest_config + reservoir_size = harvest_config.harvest_limits.error_event_data + + assert sampling_info["reservoir_size"] == reservoir_size + assert sampling_info["events_seen"] == num_errors + + error_events = decoded_json[2] + + assert len(error_events) == num_errors + for event in error_events: + + # event is an array containing intrinsics, user-attributes, + # and agent-attributes + + assert len(event) == 3 + for d in event: + assert isinstance(d, dict) + + return result + + return _validate_error_event_collector_json From b15f3cc9b291f3142b1bcb252c7e426fad11cee5 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Tue, 20 Sep 2022 10:33:41 -0700 Subject: [PATCH 19/23] Move validate_transaction_event_collector_json into validator directory --- .../agent_features/test_collector_payloads.py | 4 +- tests/testing_support/fixtures.py | 52 ++++++++--------- ...lidate_transaction_event_collector_json.py | 56 +++++++++++++++++++ 3 files changed, 85 insertions(+), 27 deletions(-) create mode 100644 tests/testing_support/validators/validate_transaction_event_collector_json.py diff --git a/tests/agent_features/test_collector_payloads.py b/tests/agent_features/test_collector_payloads.py index 072c9bcc8..0c1b2367c 100644 --- a/tests/agent_features/test_collector_payloads.py +++ b/tests/agent_features/test_collector_payloads.py @@ -17,7 +17,6 @@ from testing_support.fixtures import ( override_application_settings, validate_custom_event_collector_json, - validate_transaction_event_collector_json, ) from testing_support.sample_applications import ( simple_app, @@ -33,6 +32,9 @@ from testing_support.validators.validate_log_event_collector_json import ( validate_log_event_collector_json, ) +from testing_support.validators.validate_transaction_event_collector_json import ( + validate_transaction_event_collector_json, +) from testing_support.validators.validate_tt_collector_json import ( validate_tt_collector_json, ) diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index 7e3155e4e..7a807ebd7 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -590,42 +590,42 @@ def check_attributes(parameters, required_params=None, forgone_params=None, exac # return _validate_error_event_collector_json -def validate_transaction_event_collector_json(): - @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") - def _validate_transaction_event_collector_json(wrapped, instance, args, kwargs): - try: - result = wrapped(*args, **kwargs) - except: - raise - else: - samples = list(instance.transaction_events) +# def validate_transaction_event_collector_json(): +# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") +# def _validate_transaction_event_collector_json(wrapped, instance, args, kwargs): +# try: +# result = wrapped(*args, **kwargs) +# except: +# raise +# else: +# samples = list(instance.transaction_events) - # recreate what happens right before data is sent to the collector - # in data_collector.py during the harvest via analytic_event_data - agent_run_id = 666 - payload = (agent_run_id, samples) - collector_json = json_encode(payload) +# # recreate what happens right before data is sent to the collector +# # in data_collector.py during the harvest via analytic_event_data +# agent_run_id = 666 +# payload = (agent_run_id, samples) +# collector_json = json_encode(payload) - decoded_json = json.loads(collector_json) +# decoded_json = json.loads(collector_json) - assert decoded_json[0] == agent_run_id +# assert decoded_json[0] == agent_run_id - # list of events +# # list of events - events = decoded_json[1] +# events = decoded_json[1] - for event in events: +# for event in events: - # event is an array containing intrinsics, user-attributes, - # and agent-attributes +# # event is an array containing intrinsics, user-attributes, +# # and agent-attributes - assert len(event) == 3 - for d in event: - assert isinstance(d, dict) +# assert len(event) == 3 +# for d in event: +# assert isinstance(d, dict) - return result +# return result - return _validate_transaction_event_collector_json +# return _validate_transaction_event_collector_json def validate_custom_event_collector_json(num_events=1): diff --git a/tests/testing_support/validators/validate_transaction_event_collector_json.py b/tests/testing_support/validators/validate_transaction_event_collector_json.py new file mode 100644 index 000000000..765a3b8e0 --- /dev/null +++ b/tests/testing_support/validators/validate_transaction_event_collector_json.py @@ -0,0 +1,56 @@ +# Copyright 2010 New Relic, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json + +from newrelic.common.encoding_utils import json_encode +from newrelic.common.object_wrapper import transient_function_wrapper + + +def validate_transaction_event_collector_json(): + @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") + def _validate_transaction_event_collector_json(wrapped, instance, args, kwargs): + try: + result = wrapped(*args, **kwargs) + except: + raise + else: + samples = list(instance.transaction_events) + + # recreate what happens right before data is sent to the collector + # in data_collector.py during the harvest via analytic_event_data + agent_run_id = 666 + payload = (agent_run_id, samples) + collector_json = json_encode(payload) + + decoded_json = json.loads(collector_json) + + assert decoded_json[0] == agent_run_id + + # list of events + + events = decoded_json[1] + + for event in events: + + # event is an array containing intrinsics, user-attributes, + # and agent-attributes + + assert len(event) == 3 + for d in event: + assert isinstance(d, dict) + + return result + + return _validate_transaction_event_collector_json From 4ff75135a44fb057a383979193ae76ef49776286 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Fri, 11 Nov 2022 13:57:00 -0800 Subject: [PATCH 20/23] Fix import issues from merge --- tests/agent_features/test_span_events.py | 10 ++++++---- tests/datastore_aioredis/test_execute_command.py | 2 +- tests/datastore_aioredis/test_multiple_dbs.py | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/agent_features/test_span_events.py b/tests/agent_features/test_span_events.py index a723b4e2a..211c0a20c 100644 --- a/tests/agent_features/test_span_events.py +++ b/tests/agent_features/test_span_events.py @@ -19,19 +19,21 @@ dt_enabled, function_not_called, override_application_settings, - validate_transaction_event_attributes, - validate_transaction_metrics, validate_tt_segment_params, ) from testing_support.validators.validate_span_events import validate_span_events +from testing_support.validators.validate_transaction_event_attributes import ( + validate_transaction_event_attributes, +) +from testing_support.validators.validate_transaction_metrics import ( + validate_transaction_metrics, +) from newrelic.api.background_task import background_task from newrelic.api.database_trace import DatabaseTrace from newrelic.api.datastore_trace import DatastoreTrace from newrelic.api.external_trace import ExternalTrace from newrelic.api.function_trace import FunctionTrace, function_trace - -# from newrelic.api.graphql_trace import GraphQLOperationTrace, GraphQLResolverTrace from newrelic.api.memcache_trace import MemcacheTrace from newrelic.api.message_trace import MessageTrace from newrelic.api.solr_trace import SolrTrace diff --git a/tests/datastore_aioredis/test_execute_command.py b/tests/datastore_aioredis/test_execute_command.py index 7f178355e..51f7be008 100644 --- a/tests/datastore_aioredis/test_execute_command.py +++ b/tests/datastore_aioredis/test_execute_command.py @@ -15,7 +15,7 @@ import pytest # import aioredis -from conftest import AIOREDIS_VERSION, event_loop, loop # noqa +from conftest import AIOREDIS_VERSION, loop # noqa from testing_support.db_settings import redis_settings from testing_support.fixtures import override_application_settings from testing_support.util import instance_hostname diff --git a/tests/datastore_aioredis/test_multiple_dbs.py b/tests/datastore_aioredis/test_multiple_dbs.py index ba26254bc..61d99d3ae 100644 --- a/tests/datastore_aioredis/test_multiple_dbs.py +++ b/tests/datastore_aioredis/test_multiple_dbs.py @@ -14,7 +14,7 @@ import aioredis import pytest -from conftest import AIOREDIS_VERSION, event_loop, loop # noqa +from conftest import AIOREDIS_VERSION, loop # noqa from testing_support.db_settings import redis_settings from testing_support.fixtures import override_application_settings from testing_support.util import instance_hostname From 5c965402175bccbbfa0d5896476f475b6d8c03a1 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Fri, 11 Nov 2022 15:11:46 -0800 Subject: [PATCH 21/23] Fix some pylint errors --- tests/agent_features/test_event_loop_wait_time.py | 4 ++-- tests/agent_features/test_lambda_handler.py | 2 +- tests/agent_features/test_span_events.py | 14 +++++++------- tests/datastore_aioredis/test_execute_command.py | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/agent_features/test_event_loop_wait_time.py b/tests/agent_features/test_event_loop_wait_time.py index ac3fdd30b..69e6fc102 100644 --- a/tests/agent_features/test_event_loop_wait_time.py +++ b/tests/agent_features/test_event_loop_wait_time.py @@ -75,7 +75,7 @@ async def wait_for_loop(ready, done, times=1): ), ) def test_record_event_loop_wait(event_loop, blocking_transaction_active, event_loop_visibility_enabled): - import asyncio + # import asyncio metric_count = 2 if event_loop_visibility_enabled else None execute_attributes = {"intrinsic": ("eventLoopTime",), "agent": (), "user": ()} @@ -184,7 +184,7 @@ def test_blocking_task_on_different_loop(): def test_record_event_loop_wait_on_different_task(event_loop): - import asyncio + # import asyncio async def recorder(ready, wait): ready.set() diff --git a/tests/agent_features/test_lambda_handler.py b/tests/agent_features/test_lambda_handler.py index 27240a3cc..40b694407 100644 --- a/tests/agent_features/test_lambda_handler.py +++ b/tests/agent_features/test_lambda_handler.py @@ -24,7 +24,7 @@ validate_transaction_trace_attributes, ) -import newrelic.api.lambda_handler as lambda_handler +from newrelic.api import lambda_handler # NOTE: this fixture will force all tests in this file to assume that a cold diff --git a/tests/agent_features/test_span_events.py b/tests/agent_features/test_span_events.py index 211c0a20c..abd8249ca 100644 --- a/tests/agent_features/test_span_events.py +++ b/tests/agent_features/test_span_events.py @@ -413,11 +413,11 @@ def _test(): @pytest.mark.parametrize("collect_span_events", (False, True)) @pytest.mark.parametrize("span_events_enabled", (False, True)) def test_collect_span_events_override(collect_span_events, span_events_enabled): - - if collect_span_events and span_events_enabled: - spans_expected = True - else: - spans_expected = False + spans_expected = collect_span_events and span_events_enabled + # if collect_span_events and span_events_enabled: + # spans_expected = True + # else: + # spans_expected = False span_count = 2 if spans_expected else 0 @@ -723,9 +723,9 @@ def test_span_event_notice_error_overrides_observed(trace_type, args): with trace_type(*args): try: raise ERROR - except: + except Exception as exc: notice_error() - raise ValueError + raise ValueError from exc except ValueError: pass diff --git a/tests/datastore_aioredis/test_execute_command.py b/tests/datastore_aioredis/test_execute_command.py index 51f7be008..54851a659 100644 --- a/tests/datastore_aioredis/test_execute_command.py +++ b/tests/datastore_aioredis/test_execute_command.py @@ -15,7 +15,7 @@ import pytest # import aioredis -from conftest import AIOREDIS_VERSION, loop # noqa +from conftest import AIOREDIS_VERSION, loop # noqa # pylint: disable=E0611,W0611 from testing_support.db_settings import redis_settings from testing_support.fixtures import override_application_settings from testing_support.util import instance_hostname From c6253609e898436a8736733a93d65be0383ac39c Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Fri, 11 Nov 2022 15:31:40 -0800 Subject: [PATCH 22/23] Revert 'raise ValueError' to be PY2 compatible --- tests/agent_features/test_span_events.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/agent_features/test_span_events.py b/tests/agent_features/test_span_events.py index abd8249ca..655efee8c 100644 --- a/tests/agent_features/test_span_events.py +++ b/tests/agent_features/test_span_events.py @@ -723,9 +723,9 @@ def test_span_event_notice_error_overrides_observed(trace_type, args): with trace_type(*args): try: raise ERROR - except Exception as exc: + except Exception: notice_error() - raise ValueError from exc + raise ValueError # pylint: disable except ValueError: pass From db272fe678b9c78adcf9cda0f0fe02b8b301e4b1 Mon Sep 17 00:00:00 2001 From: Lalleh Rafeei Date: Mon, 28 Nov 2022 11:55:03 -0800 Subject: [PATCH 23/23] Delete commented lines --- tests/testing_support/fixtures.py | 136 ------------------------------ 1 file changed, 136 deletions(-) diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index 14fb38398..f642d1f6f 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -88,14 +88,6 @@ def _environ_as_bool(name, default=False): return flag -# def _lookup_string_table(name, string_table, default=None): -# try: -# index = int(name.lstrip("`")) -# return string_table[index] -# except ValueError: -# return default - - if _environ_as_bool("NEW_RELIC_HIGH_SECURITY"): DeveloperModeClient.RESPONSES["connect"]["high_security"] = True @@ -500,134 +492,6 @@ def check_attributes(parameters, required_params=None, forgone_params=None, exac assert intrinsics[param] == value, ((param, value), intrinsics) -# def validate_error_trace_collector_json(): -# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") -# def _validate_error_trace_collector_json(wrapped, instance, args, kwargs): -# try: -# result = wrapped(*args, **kwargs) -# except: -# raise -# else: -# errors = instance.error_data() - -# # recreate what happens right before data is sent to the collector -# # in data_collector.py via ApplicationSession.send_errors -# agent_run_id = 666 -# payload = (agent_run_id, errors) -# collector_json = json_encode(payload) - -# decoded_json = json.loads(collector_json) - -# assert decoded_json[0] == agent_run_id -# err = decoded_json[1][0] -# assert len(err) == 5 -# assert isinstance(err[0], (int, float)) -# assert isinstance(err[1], six.string_types) # path -# assert isinstance(err[2], six.string_types) # error message -# assert isinstance(err[3], six.string_types) # exception name -# parameters = err[4] - -# parameter_fields = ["userAttributes", "stack_trace", "agentAttributes", "intrinsics"] - -# for field in parameter_fields: -# assert field in parameters - -# assert "request_uri" not in parameters - -# return result - -# return _validate_error_trace_collector_json - - -# def validate_error_event_collector_json(num_errors=1): -# """Validate the format, types and number of errors of the data we -# send to the collector for harvest. -# """ - -# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") -# def _validate_error_event_collector_json(wrapped, instance, args, kwargs): -# try: -# result = wrapped(*args, **kwargs) -# except: -# raise -# else: - -# samples = list(instance.error_events) -# s_info = instance.error_events.sampling_info -# agent_run_id = 666 - -# # emulate the payload used in data_collector.py - -# payload = (agent_run_id, s_info, samples) -# collector_json = json_encode(payload) - -# decoded_json = json.loads(collector_json) - -# assert decoded_json[0] == agent_run_id - -# sampling_info = decoded_json[1] - -# harvest_config = instance.settings.event_harvest_config -# reservoir_size = harvest_config.harvest_limits.error_event_data - -# assert sampling_info["reservoir_size"] == reservoir_size -# assert sampling_info["events_seen"] == num_errors - -# error_events = decoded_json[2] - -# assert len(error_events) == num_errors -# for event in error_events: - -# # event is an array containing intrinsics, user-attributes, -# # and agent-attributes - -# assert len(event) == 3 -# for d in event: -# assert isinstance(d, dict) - -# return result - -# return _validate_error_event_collector_json - - -# def validate_transaction_event_collector_json(): -# @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") -# def _validate_transaction_event_collector_json(wrapped, instance, args, kwargs): -# try: -# result = wrapped(*args, **kwargs) -# except: -# raise -# else: -# samples = list(instance.transaction_events) - -# # recreate what happens right before data is sent to the collector -# # in data_collector.py during the harvest via analytic_event_data -# agent_run_id = 666 -# payload = (agent_run_id, samples) -# collector_json = json_encode(payload) - -# decoded_json = json.loads(collector_json) - -# assert decoded_json[0] == agent_run_id - -# # list of events - -# events = decoded_json[1] - -# for event in events: - -# # event is an array containing intrinsics, user-attributes, -# # and agent-attributes - -# assert len(event) == 3 -# for d in event: -# assert isinstance(d, dict) - -# return result - -# return _validate_transaction_event_collector_json - - def validate_custom_event_collector_json(num_events=1): """Validate the format, types and number of custom events."""