From 1986366b2a82ed7796c1362742588a5326b7c659 Mon Sep 17 00:00:00 2001 From: Timothy Pansino <11214426+TimPansino@users.noreply.github.com> Date: Thu, 16 Nov 2023 14:49:31 -0800 Subject: [PATCH] Revert "Synthetics Info Header Support (#896)" (#983) This reverts commit 398012772d3889701e1f0be51b6315a78b7592ee. --- newrelic/api/cat_header_mixin.py | 6 +- newrelic/api/message_trace.py | 1 - newrelic/api/transaction.py | 22 ----- newrelic/api/web_transaction.py | 39 +------- newrelic/common/encoding_utils.py | 43 -------- newrelic/core/transaction_node.py | 14 --- tests/agent_features/test_error_events.py | 15 +-- tests/agent_features/test_synthetics.py | 98 +++---------------- tests/agent_unittests/test_encoding_utils.py | 52 ---------- tests/agent_unittests/test_harvest_loop.py | 4 - tests/testing_support/external_fixtures.py | 74 ++++++-------- tests/testing_support/fixtures.py | 27 ----- .../validators/validate_synthetics_event.py | 4 +- 13 files changed, 54 insertions(+), 345 deletions(-) delete mode 100644 tests/agent_unittests/test_encoding_utils.py diff --git a/newrelic/api/cat_header_mixin.py b/newrelic/api/cat_header_mixin.py index b8251fdca1..fe5c0a71ff 100644 --- a/newrelic/api/cat_header_mixin.py +++ b/newrelic/api/cat_header_mixin.py @@ -22,7 +22,6 @@ class CatHeaderMixin(object): cat_transaction_key = 'X-NewRelic-Transaction' cat_appdata_key = 'X-NewRelic-App-Data' cat_synthetics_key = 'X-NewRelic-Synthetics' - cat_synthetics_info_key = 'X-NewRelic-Synthetics-Info' cat_metadata_key = 'x-newrelic-trace' cat_distributed_trace_key = 'newrelic' settings = None @@ -106,9 +105,8 @@ def generate_request_headers(cls, transaction): (cls.cat_transaction_key, encoded_transaction)) if transaction.synthetics_header: - nr_headers.append((cls.cat_synthetics_key, transaction.synthetics_header)) - if transaction.synthetics_info_header: - nr_headers.append((cls.cat_synthetics_info_key, transaction.synthetics_info_header)) + nr_headers.append( + (cls.cat_synthetics_key, transaction.synthetics_header)) return nr_headers diff --git a/newrelic/api/message_trace.py b/newrelic/api/message_trace.py index e0fa5956d0..f564c41cb4 100644 --- a/newrelic/api/message_trace.py +++ b/newrelic/api/message_trace.py @@ -27,7 +27,6 @@ class MessageTrace(CatHeaderMixin, TimeTrace): cat_transaction_key = "NewRelicTransaction" cat_appdata_key = "NewRelicAppData" cat_synthetics_key = "NewRelicSynthetics" - cat_synthetics_info_key = "NewRelicSyntheticsInfo" def __init__(self, library, operation, destination_type, destination_name, params=None, terminal=True, **kwargs): parent = kwargs.pop("parent", None) diff --git a/newrelic/api/transaction.py b/newrelic/api/transaction.py index bbe8f38522..988b56be6e 100644 --- a/newrelic/api/transaction.py +++ b/newrelic/api/transaction.py @@ -44,7 +44,6 @@ json_decode, json_encode, obfuscate, - snake_case, ) from newrelic.core.attribute import ( MAX_ATTRIBUTE_LENGTH, @@ -304,17 +303,10 @@ def __init__(self, application, enabled=None, source=None): self._alternate_path_hashes = {} self.is_part_of_cat = False - # Synthetics Header self.synthetics_resource_id = None self.synthetics_job_id = None self.synthetics_monitor_id = None self.synthetics_header = None - - # Synthetics Info Header - self.synthetics_type = None - self.synthetics_initiator = None - self.synthetics_attributes = None - self.synthetics_info_header = None self._custom_metrics = CustomMetrics() self._dimensional_metrics = DimensionalMetrics() @@ -611,10 +603,6 @@ def __exit__(self, exc, value, tb): synthetics_job_id=self.synthetics_job_id, synthetics_monitor_id=self.synthetics_monitor_id, synthetics_header=self.synthetics_header, - synthetics_type=self.synthetics_type, - synthetics_initiator=self.synthetics_initiator, - synthetics_attributes=self.synthetics_attributes, - synthetics_info_header=self.synthetics_info_header, is_part_of_cat=self.is_part_of_cat, trip_id=self.trip_id, path_hash=self.path_hash, @@ -852,16 +840,6 @@ def trace_intrinsics(self): i_attrs["synthetics_job_id"] = self.synthetics_job_id if self.synthetics_monitor_id: i_attrs["synthetics_monitor_id"] = self.synthetics_monitor_id - if self.synthetics_type: - i_attrs["synthetics_type"] = self.synthetics_type - if self.synthetics_initiator: - i_attrs["synthetics_initiator"] = self.synthetics_initiator - if self.synthetics_attributes: - # Add all synthetics attributes - for k, v in self.synthetics_attributes.items(): - if k: - i_attrs["synthetics_%s" % snake_case(k)] = v - if self.total_time: i_attrs["totalTime"] = self.total_time if self._loop_time: diff --git a/newrelic/api/web_transaction.py b/newrelic/api/web_transaction.py index 47155425e1..9749e26194 100644 --- a/newrelic/api/web_transaction.py +++ b/newrelic/api/web_transaction.py @@ -125,27 +125,6 @@ def _parse_synthetics_header(header): return synthetics -def _parse_synthetics_info_header(header): - # Return a dictionary of values from SyntheticsInfo header - # Returns empty dict, if version is not supported. - - synthetics_info = {} - version = None - - try: - version = int(header.get("version")) - - if version == 1: - synthetics_info['version'] = version - synthetics_info['type'] = header.get("type") - synthetics_info['initiator'] = header.get("initiator") - synthetics_info['attributes'] = header.get("attributes") - except Exception: - return - - return synthetics_info - - def _remove_query_string(url): url = ensure_str(url) out = urlparse.urlsplit(url) @@ -252,7 +231,6 @@ def _process_synthetics_header(self): settings.trusted_account_ids and \ settings.encoding_key: - # Synthetics Header encoded_header = self._request_headers.get('x-newrelic-synthetics') encoded_header = encoded_header and ensure_str(encoded_header) if not encoded_header: @@ -263,20 +241,11 @@ def _process_synthetics_header(self): settings.encoding_key) synthetics = _parse_synthetics_header(decoded_header) - # Synthetics Info Header - encoded_info_header = self._request_headers.get('x-newrelic-synthetics-info') - encoded_info_header = encoded_info_header and ensure_str(encoded_info_header) - - decoded_info_header = decode_newrelic_header( - encoded_info_header, - settings.encoding_key) - synthetics_info = _parse_synthetics_info_header(decoded_info_header) - if synthetics and \ synthetics['account_id'] in \ settings.trusted_account_ids: - # Save obfuscated headers, because we will pass them along + # Save obfuscated header, because we will pass it along # unchanged in all external requests. self.synthetics_header = encoded_header @@ -284,12 +253,6 @@ def _process_synthetics_header(self): self.synthetics_job_id = synthetics['job_id'] self.synthetics_monitor_id = synthetics['monitor_id'] - if synthetics_info: - self.synthetics_info_header = encoded_info_header - self.synthetics_type = synthetics_info['type'] - self.synthetics_initiator = synthetics_info['initiator'] - self.synthetics_attributes = synthetics_info['attributes'] - def _process_context_headers(self): # Process the New Relic cross process ID header and extract # the relevant details. diff --git a/newrelic/common/encoding_utils.py b/newrelic/common/encoding_utils.py index bee53df1a9..ef8624240f 100644 --- a/newrelic/common/encoding_utils.py +++ b/newrelic/common/encoding_utils.py @@ -571,46 +571,3 @@ def decode(cls, payload, tk): data['pr'] = None return data - - -def capitalize(string): - """Capitalize the first letter of a string.""" - if not string: - return string - elif len(string) == 1: - return string.capitalize() - else: - return "".join((string[0].upper(), string[1:])) - - -def camel_case(string, upper=False): - """ - Convert a string of snake case to camel case. - - Setting upper=True will capitalize the first letter. Defaults to False, where no change is made to the first letter. - """ - string = ensure_str(string) - split_string = list(string.split("_")) - - if len(split_string) < 2: - if upper: - return capitalize(string) - else: - return string - else: - if upper: - camel_cased_string = "".join([capitalize(substr) for substr in split_string]) - else: - camel_cased_string = split_string[0] + "".join([capitalize(substr) for substr in split_string[1:]]) - - return camel_cased_string - - -_snake_case_re = re.compile(r"([A-Z]+[a-z]*)") -def snake_case(string): - """Convert a string of camel case to snake case. Assumes no repeated runs of capital letters.""" - string = ensure_str(string) - if "_" in string: - return string # Don't touch strings that are already snake cased - - return "_".join([s for s in _snake_case_re.split(string) if s]).lower() diff --git a/newrelic/core/transaction_node.py b/newrelic/core/transaction_node.py index 74216f7df2..d63d7f9b65 100644 --- a/newrelic/core/transaction_node.py +++ b/newrelic/core/transaction_node.py @@ -22,7 +22,6 @@ import newrelic.core.error_collector import newrelic.core.trace_node -from newrelic.common.encoding_utils import camel_case from newrelic.common.streaming_utils import SpanProtoAttrs from newrelic.core.attribute import create_agent_attributes, create_user_attributes from newrelic.core.attribute_filter import ( @@ -77,10 +76,6 @@ "synthetics_job_id", "synthetics_monitor_id", "synthetics_header", - "synthetics_type", - "synthetics_initiator", - "synthetics_attributes", - "synthetics_info_header", "is_part_of_cat", "trip_id", "path_hash", @@ -591,15 +586,6 @@ def _event_intrinsics(self, stats_table): intrinsics["nr.syntheticsJobId"] = self.synthetics_job_id intrinsics["nr.syntheticsMonitorId"] = self.synthetics_monitor_id - if self.synthetics_type: - intrinsics["nr.syntheticsType"] = self.synthetics_type - intrinsics["nr.syntheticsInitiator"] = self.synthetics_initiator - if self.synthetics_attributes: - # Add all synthetics attributes - for k, v in self.synthetics_attributes.items(): - if k: - intrinsics["nr.synthetics%s" % camel_case(k, upper=True)] = v - def _add_call_time(source, target): # include time for keys previously added to stats table via # stats_engine.record_transaction diff --git a/tests/agent_features/test_error_events.py b/tests/agent_features/test_error_events.py index 2e648271d0..72bdb14f7c 100644 --- a/tests/agent_features/test_error_events.py +++ b/tests/agent_features/test_error_events.py @@ -20,7 +20,7 @@ from testing_support.fixtures import ( cat_enabled, make_cross_agent_headers, - make_synthetics_headers, + make_synthetics_header, override_application_settings, reset_core_stats_engine, validate_error_event_sample_data, @@ -43,9 +43,6 @@ SYNTHETICS_RESOURCE_ID = "09845779-16ef-4fa7-b7f2-44da8e62931c" SYNTHETICS_JOB_ID = "8c7dd3ba-4933-4cbb-b1ed-b62f511782f4" SYNTHETICS_MONITOR_ID = "dc452ae9-1a93-4ab5-8a33-600521e9cd00" -SYNTHETICS_TYPE = "scheduled" -SYNTHETICS_INITIATOR = "graphql" -SYNTHETICS_ATTRIBUTES = {"exampleAttribute": "1"} ERR_MESSAGE = "Transaction had bad value" ERROR = ValueError(ERR_MESSAGE) @@ -138,9 +135,6 @@ def test_transaction_error_cross_agent(): "nr.syntheticsResourceId": SYNTHETICS_RESOURCE_ID, "nr.syntheticsJobId": SYNTHETICS_JOB_ID, "nr.syntheticsMonitorId": SYNTHETICS_MONITOR_ID, - "nr.syntheticsType": SYNTHETICS_TYPE, - "nr.syntheticsInitiator": SYNTHETICS_INITIATOR, - "nr.syntheticsExampleAttribute": "1", } @@ -150,15 +144,12 @@ def test_transaction_error_with_synthetics(): "err_message": ERR_MESSAGE, } settings = application_settings() - headers = make_synthetics_headers( - settings.encoding_key, + headers = make_synthetics_header( settings.trusted_account_ids[0], SYNTHETICS_RESOURCE_ID, SYNTHETICS_JOB_ID, SYNTHETICS_MONITOR_ID, - SYNTHETICS_TYPE, - SYNTHETICS_INITIATOR, - SYNTHETICS_ATTRIBUTES, + settings.encoding_key, ) response = fully_featured_application.get("/", headers=headers, extra_environ=test_environ) diff --git a/tests/agent_features/test_synthetics.py b/tests/agent_features/test_synthetics.py index 350cab03f0..2e08144cc7 100644 --- a/tests/agent_features/test_synthetics.py +++ b/tests/agent_features/test_synthetics.py @@ -17,7 +17,7 @@ from testing_support.external_fixtures import validate_synthetics_external_trace_header from testing_support.fixtures import ( cat_enabled, - make_synthetics_headers, + make_synthetics_header, override_application_settings, ) from testing_support.validators.validate_synthetics_event import ( @@ -37,9 +37,6 @@ SYNTHETICS_RESOURCE_ID = "09845779-16ef-4fa7-b7f2-44da8e62931c" SYNTHETICS_JOB_ID = "8c7dd3ba-4933-4cbb-b1ed-b62f511782f4" SYNTHETICS_MONITOR_ID = "dc452ae9-1a93-4ab5-8a33-600521e9cd00" -SYNTHETICS_TYPE = "scheduled" -SYNTHETICS_INITIATOR = "graphql" -SYNTHETICS_ATTRIBUTES = {"exampleAttribute": "1"} _override_settings = { "encoding_key": ENCODING_KEY, @@ -48,19 +45,15 @@ } -def _make_synthetics_headers( +def _make_synthetics_header( version="1", account_id=ACCOUNT_ID, resource_id=SYNTHETICS_RESOURCE_ID, job_id=SYNTHETICS_JOB_ID, monitor_id=SYNTHETICS_MONITOR_ID, encoding_key=ENCODING_KEY, - info_version="1", - type_=SYNTHETICS_TYPE, - initiator=SYNTHETICS_INITIATOR, - attributes=SYNTHETICS_ATTRIBUTES, ): - return make_synthetics_headers(encoding_key, account_id, resource_id, job_id, monitor_id, type_, initiator, attributes, synthetics_version=version, synthetics_info_version=info_version) + return make_synthetics_header(account_id, resource_id, job_id, monitor_id, encoding_key, version) def decode_header(header, encoding_key=ENCODING_KEY): @@ -87,9 +80,6 @@ def target_wsgi_application(environ, start_response): ("nr.syntheticsResourceId", SYNTHETICS_RESOURCE_ID), ("nr.syntheticsJobId", SYNTHETICS_JOB_ID), ("nr.syntheticsMonitorId", SYNTHETICS_MONITOR_ID), - ("nr.syntheticsType", SYNTHETICS_TYPE), - ("nr.syntheticsInitiator", SYNTHETICS_INITIATOR), - ("nr.syntheticsExampleAttribute", "1"), ] _test_valid_synthetics_event_forgone = [] @@ -99,51 +89,21 @@ def target_wsgi_application(environ, start_response): ) @override_application_settings(_override_settings) def test_valid_synthetics_event(): - headers = _make_synthetics_headers() - response = target_application.get("/", headers=headers) - - -_test_valid_synthetics_event_without_info_required = [ - ("nr.syntheticsResourceId", SYNTHETICS_RESOURCE_ID), - ("nr.syntheticsJobId", SYNTHETICS_JOB_ID), - ("nr.syntheticsMonitorId", SYNTHETICS_MONITOR_ID), -] -_test_valid_synthetics_event_without_info_forgone = [ - "nr.syntheticsType", - "nr.syntheticsInitiator", - "nr.syntheticsExampleAttribute", -] - - -@validate_synthetics_event( - _test_valid_synthetics_event_without_info_required, _test_valid_synthetics_event_without_info_forgone, should_exist=True -) -@override_application_settings(_override_settings) -def test_valid_synthetics_event_without_info(): - headers = _make_synthetics_headers(type_=None, initiator=None, attributes=None) + headers = _make_synthetics_header() response = target_application.get("/", headers=headers) @validate_synthetics_event([], [], should_exist=False) @override_application_settings(_override_settings) def test_no_synthetics_event_unsupported_version(): - headers = _make_synthetics_headers(version="0") - response = target_application.get("/", headers=headers) - - -@validate_synthetics_event( - _test_valid_synthetics_event_without_info_required, _test_valid_synthetics_event_without_info_forgone, should_exist=True -) -@override_application_settings(_override_settings) -def test_synthetics_event_unsupported_info_version(): - headers = _make_synthetics_headers(info_version="0") + headers = _make_synthetics_header(version="0") response = target_application.get("/", headers=headers) @validate_synthetics_event([], [], should_exist=False) @override_application_settings(_override_settings) def test_no_synthetics_event_untrusted_account(): - headers = _make_synthetics_headers(account_id="999") + headers = _make_synthetics_header(account_id="999") response = target_application.get("/", headers=headers) @@ -151,20 +111,7 @@ def test_no_synthetics_event_untrusted_account(): @override_application_settings(_override_settings) def test_no_synthetics_event_mismatched_encoding_key(): encoding_key = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" - headers = _make_synthetics_headers(encoding_key=encoding_key) - response = target_application.get("/", headers=headers) - - -@validate_synthetics_event( - _test_valid_synthetics_event_without_info_required, _test_valid_synthetics_event_without_info_forgone, should_exist=True -) -@override_application_settings(_override_settings) -def test_synthetics_event_mismatched_info_encoding_key(): - encoding_key = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" - headers = { - "X-NewRelic-Synthetics": _make_synthetics_headers(type_=None)["X-NewRelic-Synthetics"], - "X-NewRelic-Synthetics-Info": _make_synthetics_headers(encoding_key=encoding_key)["X-NewRelic-Synthetics-Info"], - } + headers = _make_synthetics_header(encoding_key=encoding_key) response = target_application.get("/", headers=headers) @@ -172,9 +119,6 @@ def test_synthetics_event_mismatched_info_encoding_key(): "synthetics_resource_id": SYNTHETICS_RESOURCE_ID, "synthetics_job_id": SYNTHETICS_JOB_ID, "synthetics_monitor_id": SYNTHETICS_MONITOR_ID, - "synthetics_type": SYNTHETICS_TYPE, - "synthetics_initiator": SYNTHETICS_INITIATOR, - "synthetics_example_attribute": "1", } @@ -182,7 +126,7 @@ def test_synthetics_event_mismatched_info_encoding_key(): @validate_synthetics_transaction_trace(_test_valid_synthetics_tt_required) @override_application_settings(_override_settings) def test_valid_synthetics_in_transaction_trace(): - headers = _make_synthetics_headers() + headers = _make_synthetics_header() response = target_application.get("/", headers=headers) @@ -202,36 +146,26 @@ def test_no_synthetics_in_transaction_trace(): @validate_synthetics_event([], [], should_exist=False) @override_application_settings(_disabled_settings) def test_synthetics_disabled(): - headers = _make_synthetics_headers() + headers = _make_synthetics_header() response = target_application.get("/", headers=headers) -_external_synthetics_headers = _make_synthetics_headers() -_external_synthetics_header = _external_synthetics_headers["X-NewRelic-Synthetics"] -_external_synthetics_info_header = _external_synthetics_headers["X-NewRelic-Synthetics-Info"] +_external_synthetics_header = ("X-NewRelic-Synthetics", _make_synthetics_header()["X-NewRelic-Synthetics"]) @cat_enabled -@validate_synthetics_external_trace_header(_external_synthetics_header, _external_synthetics_info_header) +@validate_synthetics_external_trace_header(required_header=_external_synthetics_header, should_exist=True) @override_application_settings(_override_settings) def test_valid_synthetics_external_trace_header(): - headers = _make_synthetics_headers() - response = target_application.get("/", headers=headers) - - -@cat_enabled -@validate_synthetics_external_trace_header(_external_synthetics_header, None) -@override_application_settings(_override_settings) -def test_valid_synthetics_external_trace_header_without_info(): - headers = _make_synthetics_headers(type_=None) + headers = _make_synthetics_header() response = target_application.get("/", headers=headers) @cat_enabled -@validate_synthetics_external_trace_header(_external_synthetics_header, _external_synthetics_info_header) +@validate_synthetics_external_trace_header(required_header=_external_synthetics_header, should_exist=True) @override_application_settings(_override_settings) def test_valid_external_trace_header_with_byte_inbound_header(): - headers = _make_synthetics_headers() + headers = _make_synthetics_header() headers = {k.encode("utf-8"): v.encode("utf-8") for k, v in headers.items()} @web_transaction( @@ -244,7 +178,7 @@ def webapp(): webapp() -@validate_synthetics_external_trace_header(None, None) +@validate_synthetics_external_trace_header(should_exist=False) @override_application_settings(_override_settings) def test_no_synthetics_external_trace_header(): response = target_application.get("/") @@ -260,7 +194,7 @@ def _synthetics_limit_test(num_requests, num_events, num_transactions): # Send requests - headers = _make_synthetics_headers() + headers = _make_synthetics_header() for i in range(num_requests): response = target_application.get("/", headers=headers) diff --git a/tests/agent_unittests/test_encoding_utils.py b/tests/agent_unittests/test_encoding_utils.py deleted file mode 100644 index 397f2fa2ef..0000000000 --- a/tests/agent_unittests/test_encoding_utils.py +++ /dev/null @@ -1,52 +0,0 @@ -# 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 pytest - -from newrelic.common.encoding_utils import camel_case, snake_case - - -@pytest.mark.parametrize("input_,expected,upper", [ - ("", "", False), - ("", "", True), - ("my_string", "myString", False), - ("my_string", "MyString", True), - ("LeaveCase", "LeaveCase", False), - ("correctCase", "CorrectCase", True), - ("UPPERcaseLETTERS", "UPPERcaseLETTERS", False), - ("UPPERcaseLETTERS", "UPPERcaseLETTERS", True), - ("lowerCASEletters", "lowerCASEletters", False), - ("lowerCASEletters", "LowerCASEletters", True), - ("very_long_snake_string", "VeryLongSnakeString", True), - ("kebab-case", "kebab-case", False), -]) -def test_camel_case(input_, expected, upper): - output = camel_case(input_, upper=upper) - assert output == expected - - -@pytest.mark.parametrize("input_,expected", [ - ("", ""), - ("", ""), - ("my_string", "my_string"), - ("myString", "my_string"), - ("MyString", "my_string"), - ("UPPERcaseLETTERS", "uppercase_letters"), - ("lowerCASEletters", "lower_caseletters"), - ("VeryLongCamelString", "very_long_camel_string"), - ("kebab-case", "kebab-case"), -]) -def test_snake_case(input_, expected): - output = snake_case(input_) - assert output == expected diff --git a/tests/agent_unittests/test_harvest_loop.py b/tests/agent_unittests/test_harvest_loop.py index a3eaf7b5ff..15b67a81e1 100644 --- a/tests/agent_unittests/test_harvest_loop.py +++ b/tests/agent_unittests/test_harvest_loop.py @@ -143,10 +143,6 @@ def transaction_node(request): synthetics_job_id=None, synthetics_monitor_id=None, synthetics_header=None, - synthetics_type=None, - synthetics_initiator=None, - synthetics_attributes=None, - synthetics_info_header=None, is_part_of_cat=False, trip_id="4485b89db608aece", path_hash=None, diff --git a/tests/testing_support/external_fixtures.py b/tests/testing_support/external_fixtures.py index de746c38be..a968fe2d1e 100644 --- a/tests/testing_support/external_fixtures.py +++ b/tests/testing_support/external_fixtures.py @@ -51,10 +51,8 @@ def create_incoming_headers(transaction): return headers -def validate_synthetics_external_trace_header( - synthetics_header, - synthetics_info_header, - ): +def validate_synthetics_external_trace_header(required_header=(), + should_exist=True): @transient_function_wrapper('newrelic.core.stats_engine', 'StatsEngine.record_transaction') def _validate_synthetics_external_trace_header(wrapped, instance, @@ -69,46 +67,34 @@ def _bind_params(transaction, *args, **kwargs): except: raise else: - # XXX This validation routine is technically - # broken as the argument to record_transaction() - # is not actually an instance of the Transaction - # object. Instead it is a TransactionNode object. - # The static method generate_request_headers() is - # expecting a Transaction object and not - # TransactionNode. The latter provides attributes - # which are not updatable by the static method - # generate_request_headers(), which it wants to - # update, so would fail. For now what we do is use - # a little proxy wrapper so that updates do not - # fail. The use of this wrapper needs to be - # reviewed and a better way of achieving what is - # required found. - - class _Transaction(object): - def __init__(self, wrapped): - self.__wrapped__ = wrapped - - def __getattr__(self, name): - return getattr(self.__wrapped__, name, lambda *args, **kwargs: None) - - external_headers = ExternalTrace.generate_request_headers( - _Transaction(transaction)) - external_headers = {header[0]: header[1] for header in external_headers} - - if synthetics_header: - assert synthetics_header == external_headers["X-NewRelic-Synthetics"], ( - 'synthetics_header=%r, external_headers=%r' % ( - synthetics_header, external_headers)) - else: - assert "X-NewRelic-Synthetics" not in external_headers - - if synthetics_info_header: - assert synthetics_info_header == external_headers["X-NewRelic-Synthetics-Info"], ( - 'synthetics_info_header=%r, external_headers=%r' % ( - synthetics_info_header, external_headers)) - else: - assert "X-NewRelic-Synthetics-Info" not in external_headers - + if should_exist: + # XXX This validation routine is technically + # broken as the argument to record_transaction() + # is not actually an instance of the Transaction + # object. Instead it is a TransactionNode object. + # The static method generate_request_headers() is + # expecting a Transaction object and not + # TransactionNode. The latter provides attributes + # which are not updatable by the static method + # generate_request_headers(), which it wants to + # update, so would fail. For now what we do is use + # a little proxy wrapper so that updates do not + # fail. The use of this wrapper needs to be + # reviewed and a better way of achieving what is + # required found. + + class _Transaction(object): + def __init__(self, wrapped): + self.__wrapped__ = wrapped + + def __getattr__(self, name): + return getattr(self.__wrapped__, name) + + external_headers = ExternalTrace.generate_request_headers( + _Transaction(transaction)) + assert required_header in external_headers, ( + 'required_header=%r, ''external_headers=%r' % ( + required_header, external_headers)) return result diff --git a/tests/testing_support/fixtures.py b/tests/testing_support/fixtures.py index fab0150d52..883c3ec595 100644 --- a/tests/testing_support/fixtures.py +++ b/tests/testing_support/fixtures.py @@ -363,26 +363,12 @@ def make_cross_agent_headers(payload, encoding_key, cat_id): return {"X-NewRelic-Transaction": value, "X-NewRelic-ID": id_value} -def make_synthetics_headers(encoding_key, account_id, resource_id, job_id, monitor_id, type_, initiator, attributes, synthetics_version=1, synthetics_info_version=1): - headers = {} - headers.update(make_synthetics_header(account_id, resource_id, job_id, monitor_id, encoding_key, synthetics_version)) - if type_: - headers.update(make_synthetics_info_header(type_, initiator, attributes, encoding_key, synthetics_info_version)) - return headers - - def make_synthetics_header(account_id, resource_id, job_id, monitor_id, encoding_key, version=1): value = [version, account_id, resource_id, job_id, monitor_id] value = obfuscate(json_encode(value), encoding_key) return {"X-NewRelic-Synthetics": value} -def make_synthetics_info_header(type_, initiator, attributes, encoding_key, version=1): - value = {"version": version, "type": type_, "initiator": initiator, "attributes": attributes} - value = obfuscate(json_encode(value), encoding_key) - return {"X-NewRelic-Synthetics-Info": value} - - def capture_transaction_metrics(metrics_list, full_metrics=None): @transient_function_wrapper("newrelic.core.stats_engine", "StatsEngine.record_transaction") @catch_background_exceptions @@ -758,9 +744,6 @@ def _bind_params(transaction, *args, **kwargs): return _validate_error_event_sample_data -SYNTHETICS_INTRINSIC_ATTR_NAMES = set(["nr.syntheticsResourceId", "nr.syntheticsJobId", "nr.syntheticsMonitorId", "nr.syntheticsType", "nr.syntheticsInitiator"]) - - def _validate_event_attributes(intrinsics, user_attributes, required_intrinsics, required_user): now = time.time() assert isinstance(intrinsics["timestamp"], int) @@ -810,16 +793,6 @@ def _validate_event_attributes(intrinsics, user_attributes, required_intrinsics, assert intrinsics["nr.syntheticsResourceId"] == res_id assert intrinsics["nr.syntheticsJobId"] == job_id assert intrinsics["nr.syntheticsMonitorId"] == monitor_id - - if "nr.syntheticsType" in required_intrinsics: - type_ = required_intrinsics["nr.syntheticsType"] - initiator = required_intrinsics["nr.syntheticsInitiator"] - assert intrinsics["nr.syntheticsType"] == type_ - assert intrinsics["nr.syntheticsInitiator"] == initiator - - for k, v in required_intrinsics.items(): - if k.startswith("nr.synthetics") and k not in SYNTHETICS_INTRINSIC_ATTR_NAMES: - assert v == intrinsics[k] if "port" in required_intrinsics: assert intrinsics["port"] == required_intrinsics["port"] diff --git a/tests/testing_support/validators/validate_synthetics_event.py b/tests/testing_support/validators/validate_synthetics_event.py index bab176138d..221cf7e6ef 100644 --- a/tests/testing_support/validators/validate_synthetics_event.py +++ b/tests/testing_support/validators/validate_synthetics_event.py @@ -51,8 +51,8 @@ def _flatten(event): 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 in forgone_attrs: - assert name not in flat_event, "name=%r, event=%r" % (name, 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)