diff --git a/CHANGELOG.md b/CHANGELOG.md index a469d95194..5880769377 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ Support for Ruby versions 2.4 and 2.5 has been removed. The new minimum required Ruby version is now 2.6. [PR#3314](https://github.com/newrelic/newrelic-ruby-agent/pull/3314) +- **Breaking Change: Removal of Cross Application Tracing (CAT)** + + Previously, Cross Application Tracing (CAT) was deprecated in favor of Distributed Tracing. CAT functionality has now been removed. The configuration option `cross_application_tracer.enabled` has been removed. Public API methods `NewRelic::Agent::External.process_request_metadata`, `NewRelic::Agent::External.get_response_metadata`, `NewRelic::Agent::Transaction::ExternalRequestSegment#process_response_metadata`, and `NewRelic::Agent::Transaction::ExternalRequestSegment#get_request_metadata` have also been removed. [PR#3333](https://github.com/newrelic/newrelic-ruby-agent/pull/3333) + - **Feature: Add `logger` as a dependency** The `logger` gem is now listed as a dependency of the agent to ensure continued logging functionality and support for Ruby 4.0.0 and newer versions. [PR#3293](https://github.com/newrelic/newrelic-ruby-agent/pull/3293) diff --git a/lib/new_relic/agent.rb b/lib/new_relic/agent.rb index 8be8515669..d3458a2923 100644 --- a/lib/new_relic/agent.rb +++ b/lib/new_relic/agent.rb @@ -55,7 +55,6 @@ module Agent require 'new_relic/agent/rules_engine' require 'new_relic/agent/http_clients/uri_util' require 'new_relic/agent/system_info' - require 'new_relic/agent/external' require 'new_relic/agent/deprecator' require 'new_relic/agent/logging' require 'new_relic/agent/distributed_tracing' diff --git a/lib/new_relic/agent/configuration/default_source.rb b/lib/new_relic/agent/configuration/default_source.rb index 116d7afd48..0ac5cd2180 100644 --- a/lib/new_relic/agent/configuration/default_source.rb +++ b/lib/new_relic/agent/configuration/default_source.rb @@ -1127,18 +1127,6 @@ def self.enforce_fallback(allowed_values: nil, fallback: nil) :description => "If `true`, the agent will report source code level metrics for traced methods.\n\tSee: " \ 'https://docs.newrelic.com/docs/apm/agents/ruby-agent/features/ruby-codestream-integration/' }, - # Cross application tracer - :"cross_application_tracer.enabled" => { - :default => false, - :public => true, - :type => Boolean, - :allowed_from_server => true, - :deprecated => true, - :description => deprecated_description( - :'distributed_tracing.enabled', - ' If `true`, enables [cross-application tracing](/docs/agents/ruby-agent/features/cross-application-tracing-ruby/) when `distributed_tracing.enabled` is set to `false`.' - ) - }, # Custom attributes :'custom_attributes.enabled' => { :default => true, diff --git a/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb b/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb index b6ac885432..bb2a23e804 100644 --- a/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb +++ b/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb @@ -164,8 +164,7 @@ def valid_encoding_key? end def cross_application_tracer_enabled? - !NewRelic::Agent.config[:"distributed_tracing.enabled"] && - NewRelic::Agent.config[:"cross_application_tracer.enabled"] + false end def obfuscator diff --git a/lib/new_relic/agent/external.rb b/lib/new_relic/agent/external.rb deleted file mode 100644 index 499b596826..0000000000 --- a/lib/new_relic/agent/external.rb +++ /dev/null @@ -1,112 +0,0 @@ -# This file is distributed under New Relic's license terms. -# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details. -# frozen_string_literal: true - -require 'new_relic/agent/transaction/tracing' -require 'new_relic/agent/distributed_tracing/cross_app_tracing' -require 'new_relic/agent/distributed_tracing/cross_app_payload' - -module NewRelic - module Agent - # - # This module contains helper methods to facilitate - # instrumentation of external requests not directly supported by - # the Ruby agent. It is intended to be primarily used by authors - # of 3rd-party instrumentation. - # - # @api public - module External - extend self - - NON_HTTP_CAT_ID_HEADER = 'NewRelicID'.freeze - NON_HTTP_CAT_TXN_HEADER = 'NewRelicTransaction'.freeze - NON_HTTP_CAT_SYNTHETICS_HEADER = 'NewRelicSynthetics'.freeze - NON_HTTP_CAT_CONTENT_LENGTH = -1 - - # Process obfuscated +String+ identifying a calling application and transaction that is also running a - # New Relic agent and save information in current transaction for inclusion in a trace. The +String+ is - # generated by +get_request_metadata+ on the calling application. - # - # @param request_metadata [String] received obfuscated request metadata - # - # @!scope class - # @api public - # - def process_request_metadata(request_metadata) - NewRelic::Agent.record_api_supportability_metric(:process_request_metadata) - return unless CrossAppTracing.cross_app_enabled? - - state = NewRelic::Agent::Tracer.state - if transaction = state.current_transaction - rmd = ::JSON.parse(obfuscator.deobfuscate(request_metadata)) - - # handle/check ID - # - if id = rmd[NON_HTTP_CAT_ID_HEADER] and CrossAppTracing.trusted_valid_cross_app_id?(id) - # handle transaction info - # - if txn_info = rmd[NON_HTTP_CAT_TXN_HEADER] - payload = CrossAppPayload.new(id, transaction, txn_info) - transaction.distributed_tracer.cross_app_payload = payload - - CrossAppTracing.assign_intrinsic_transaction_attributes(state) - end - - # handle synthetics - # - if synth = rmd[NON_HTTP_CAT_SYNTHETICS_HEADER] - transaction.synthetics_payload = synth - transaction.raw_synthetics_header = obfuscator.obfuscate(::JSON.dump(synth)) - end - - else - NewRelic::Agent.logger.error("error processing request metadata: invalid/non-trusted ID: '#{id}'") - end - - nil - end - rescue => e - NewRelic::Agent.logger.error('error during process_request_metadata', e) - end - - # Obtain an obfuscated +String+ suitable for delivery across public networks that carries transaction - # information from this application to a calling application which is also running a New Relic agent. - # This +String+ can be processed by +process_response_metadata+ on the calling application. - # - # @return [String] obfuscated response metadata to send - # - # @!scope class - # @api public - # - def get_response_metadata - NewRelic::Agent.record_api_supportability_metric(:get_response_metadata) - return unless CrossAppTracing.cross_app_enabled? - - return unless (txn = Tracer.current_transaction) - return unless (payload = txn.distributed_tracer.cross_app_payload) - - # must freeze the name since we're responding with it - # - txn.freeze_name_and_execute_if_not_ignored do - # build response payload - # - rmd = { - NewRelicAppData: payload.as_json_array(NON_HTTP_CAT_CONTENT_LENGTH) - } - - # obfuscate the generated response metadata JSON - # - obfuscator.obfuscate(::JSON.dump(rmd)) - end - rescue => e - NewRelic::Agent.logger.error('error during get_response_metadata', e) - end - - private - - def obfuscator - CrossAppTracing.obfuscator - end - end - end -end diff --git a/lib/new_relic/agent/transaction/external_request_segment.rb b/lib/new_relic/agent/transaction/external_request_segment.rb index e0e23acaa6..bcfe7913ac 100644 --- a/lib/new_relic/agent/transaction/external_request_segment.rb +++ b/lib/new_relic/agent/transaction/external_request_segment.rb @@ -106,77 +106,6 @@ def cross_process_transaction_name # :nodoc: @app_data && @app_data[1] end - # Obtain an obfuscated +String+ suitable for delivery across public networks that identifies this application - # and transaction to another application which is also running a New Relic agent. This +String+ can be processed - # by +process_request_metadata+ on the receiving application. - # - # @return [String] obfuscated request metadata to send - # - # @api public - # - def get_request_metadata - NewRelic::Agent.record_api_supportability_metric(:get_request_metadata) - return unless CrossAppTracing.cross_app_enabled? - - if transaction - - # build hash of CAT metadata - # - rmd = { - NewRelicID: NewRelic::Agent.config[:cross_process_id], - NewRelicTransaction: [ - transaction.guid, - false, - transaction.distributed_tracer.cat_trip_id, - transaction.distributed_tracer.cat_path_hash - ] - } - - # flag cross app in the state so transaction knows to add bits to payload - # - transaction.distributed_tracer.is_cross_app_caller = true - - # add Synthetics header if we have it - # - rmd[:NewRelicSynthetics] = transaction.raw_synthetics_header if transaction.raw_synthetics_header - - # obfuscate the generated request metadata JSON - # - obfuscator.obfuscate(::JSON.dump(rmd)) - - end - rescue => e - NewRelic::Agent.logger.error('error during get_request_metadata', e) - end - - # Process obfuscated +String+ sent from a called application that is also running a New Relic agent and - # save information in current transaction for inclusion in a trace. This +String+ is generated by - # +get_response_metadata+ on the receiving application. - # - # @param response_metadata [String] received obfuscated response metadata - # - # @api public - # - def process_response_metadata(response_metadata) - NewRelic::Agent.record_api_supportability_metric(:process_response_metadata) - if transaction - app_data = ::JSON.parse(obfuscator.deobfuscate(response_metadata))[APP_DATA_KEY] - - # validate cross app id - # - if Array === app_data and CrossAppTracing.trusted_valid_cross_app_id?(app_data[0]) - @app_data = app_data - update_segment_name - else - NewRelic::Agent.logger.error('error processing response metadata: invalid/non-trusted ID') - end - end - - nil - rescue => e - NewRelic::Agent.logger.error('error during process_response_metadata', e) - end - def record_metrics add_unscoped_metrics super diff --git a/lib/new_relic/supportability_helper.rb b/lib/new_relic/supportability_helper.rb index 69309053fc..97a1167a3e 100644 --- a/lib/new_relic/supportability_helper.rb +++ b/lib/new_relic/supportability_helper.rb @@ -23,8 +23,6 @@ module SupportabilityHelper :disable_all_tracing, :disable_sql_recording, :drop_buffered_data, - :get_request_metadata, - :get_response_metadata, :get_transaction_name, :ignore_apdex, :ignore_enduser, @@ -39,8 +37,6 @@ module SupportabilityHelper :notice_sql, :notice_statement, :perform_action_with_newrelic_trace, - :process_request_metadata, - :process_response_metadata, :record_custom_event, :record_metric, :record_llm_feedback_event, diff --git a/test/multiverse/suites/agent_only/cross_application_tracing_test.rb b/test/multiverse/suites/agent_only/cross_application_tracing_test.rb deleted file mode 100644 index eec38cb0a1..0000000000 --- a/test/multiverse/suites/agent_only/cross_application_tracing_test.rb +++ /dev/null @@ -1,104 +0,0 @@ -# This file is distributed under New Relic's license terms. -# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details. -# frozen_string_literal: true - -require 'rack/test' -require 'fake_collector' -require './testing_app' -require 'new_relic/rack/agent_hooks' - -class CrossApplicationTracingTest < Minitest::Test - include MultiverseHelpers - setup_and_teardown_agent(:'cross_application_tracer.enabled' => true, - :'distributed_tracing.enabled' => false, - :cross_process_id => 'boo', - :encoding_key => "\0", - :trusted_account_ids => [1]) \ - do |collector| - collector.stub('connect', { - 'agent_run_id' => 666, - 'transaction_name_rules' => [{'match_expression' => 'ignored_transaction', - 'ignore' => true}] - }) - end - - include Rack::Test::Methods - - def app - Rack::Builder.app { run(TestingApp.new) } - end - - def test_cross_app_doesnt_modify_without_header - get('/') - - refute last_response.headers['X-NewRelic-App-Data'] - end - - def test_cross_app_doesnt_modify_with_invalid_header - get('/', nil, {'HTTP_X_NEWRELIC_ID' => NewRelic::Base64.encode64('otherjunk')}) - - refute last_response.headers['X-NewRelic-App-Data'] - end - - def test_cross_app_writes_out_information - get('/', nil, {'HTTP_X_NEWRELIC_ID' => NewRelic::Base64.encode64('1#234')}) - - refute_nil last_response.headers['X-NewRelic-App-Data'] - assert_metrics_recorded(['ClientApplication/1#234/all']) - end - - def test_cross_app_doesnt_modify_if_txn_is_ignored - get('/', {'transaction_name' => 'ignored_transaction'}, {'HTTP_X_NEWRELIC_ID' => NewRelic::Base64.encode64('1#234')}) - - refute last_response.headers['X-NewRelic-App-Data'] - end - - def test_cross_app_error_attaches_process_id_to_intrinsics - assert_raises(RuntimeError) do - get('/', {'fail' => 'true'}, {'HTTP_X_NEWRELIC_ID' => NewRelic::Base64.encode64('1#234')}) - end - - assert_includes attributes_for(last_traced_error, :intrinsic), :client_cross_process_id - end - - load_cross_agent_test('cat_map').each do |test_case| - # We only can do test cases here that don't involve outgoing calls - if !test_case['outboundRequests'] - if test_case['inboundPayload'] - request_headers = { - 'HTTP_X_NEWRELIC_ID' => NewRelic::Base64.encode64('1#234'), - 'HTTP_X_NEWRELIC_TRANSACTION' => json_dump_and_encode(test_case['inboundPayload']) - } - else - request_headers = {} - end - - define_method("test_#{test_case['name']}") do - txn_name_parts = test_case['transactionName'].split('/') - txn_category = txn_name_parts[0..1].join('/') - txn_name = txn_name_parts[2..-1].join('/') - - request_params = { - 'transaction_name' => txn_name, - 'transaction_category' => txn_category, - 'guid' => test_case['transactionGuid'] - } - - with_config('app_name' => test_case['appName'], - :'cross_application_tracer.enabled' => true, - :'distributed_tracing.enabled' => false) do - get '/', request_params, request_headers - end - - event = get_last_analytics_event - - assert_event_attributes( - event, - test_case['name'], - test_case['expectedIntrinsicFields'], - test_case['nonExpectedIntrinsicFields'] - ) - end - end - end -end diff --git a/test/multiverse/suites/rails/request_statistics_test.rb b/test/multiverse/suites/rails/request_statistics_test.rb index 37332f9a06..5a39c4aa84 100644 --- a/test/multiverse/suites/rails/request_statistics_test.rb +++ b/test/multiverse/suites/rails/request_statistics_test.rb @@ -94,36 +94,6 @@ def test_request_should_include_guid_if_cross_app end end - def test_request_should_include_referring_guid_if_needed - with_config(:'cross_application_tracer.enabled' => true, - :'distributed_tracing.enabled' => false, - :'analytics_events.enabled' => true, - :'cross_process_id' => 'boo', - :'encoding_key' => "\0", - :'trusted_account_ids' => [1]) do - rack_env = { - 'HTTP_X_NEWRELIC_ID' => NewRelic::Base64.encode64('1#234'), - 'HTTP_X_NEWRELIC_TRANSACTION' => NewRelic::Base64.encode64('["8badf00d",1]') - } - - get('/request_stats/cross_app_action', headers: rack_env) - - NewRelic::Agent.agent.send(:harvest_and_send_analytic_event_data) - - post = $collector.calls_for('analytic_event_data').first - - refute_nil(post) - assert_kind_of Array, post.events - assert_kind_of Array, post.events.first - - sample = post.events.first.first - - assert_kind_of Hash, sample - assert_kind_of String, sample['nr.guid'] - assert_equal('8badf00d', sample['nr.referringTransactionGuid']) - end - end - def test_custom_params_should_be_reported_with_events_and_coerced_to_safe_types with_config(:'analytics_events.enabled' => true) do 5.times { get('/request_stats/stats_action_with_custom_params') } diff --git a/test/new_relic/agent/external_test.rb b/test/new_relic/agent/external_test.rb deleted file mode 100644 index e555f8ca3f..0000000000 --- a/test/new_relic/agent/external_test.rb +++ /dev/null @@ -1,194 +0,0 @@ -# This file is distributed under New Relic's license terms. -# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details. -# frozen_string_literal: true - -require_relative '../../test_helper' -require 'new_relic/agent/external' - -module NewRelic - module Agent - class ExternalTest < Minitest::Test - TRANSACTION_GUID = 'BEC1BC64675138B9' - - def setup - NewRelic::Agent::Harvester.any_instance.stubs(:harvest_thread_enabled?).returns(false) - - @obfuscator = NewRelic::Agent::Obfuscator.new('jotorotoes') - NewRelic::Agent::CrossAppTracing.stubs(:obfuscator).returns(@obfuscator) - NewRelic::Agent::CrossAppTracing.stubs(:valid_encoding_key?).returns(true) - end - - def teardown - NewRelic::Agent.drop_buffered_data - end - - # --- process_request_metadata - - def test_process_request_metadata - with_config(cat_config) do - rmd = @obfuscator.obfuscate(::JSON.dump({ - NewRelicID: cat_config[:cross_process_id], - NewRelicTransaction: ['abc', false, 'def', 'ghi'] - })) - - in_transaction do |txn| - NewRelic::Agent::External.process_request_metadata(rmd) - ca_payload = txn.distributed_tracer.cross_app_payload - - assert_equal cat_config[:cross_process_id], ca_payload.id - assert_equal 'abc', ca_payload.referring_guid - assert_equal 'def', ca_payload.referring_trip_id - assert_equal 'ghi', ca_payload.referring_path_hash - end - end - end - - def test_process_request_metadata_with_synthetics - with_config(cat_config) do - raw_synth = @obfuscator.obfuscate(::JSON.dump('raw_synth')) - - rmd = @obfuscator.obfuscate(::JSON.dump({ - NewRelicID: cat_config[:cross_process_id], - NewRelicTransaction: ['abc', false, 'def', 'ghi'], - NewRelicSynthetics: 'raw_synth' - })) - - in_transaction do |txn| - NewRelic::Agent::External.process_request_metadata(rmd) - - assert_equal raw_synth, txn.raw_synthetics_header - assert_equal 'raw_synth', txn.synthetics_payload - end - end - end - - def test_process_request_metadata_not_in_transaction - with_config(cat_config) do - rmd = @obfuscator.obfuscate(::JSON.dump({ - NewRelicID: cat_config[:cross_process_id], - NewRelicTransaction: ['abc', false, 'def', 'ghi'], - NewRelicSynthetics: 'raw_synth' - })) - - l = with_array_logger { NewRelic::Agent::External.process_request_metadata(rmd) } - - assert_empty l.array, 'process_request_metadata should not log errors without a current transaction' - - refute Tracer.current_transaction - end - end - - def test_process_request_metadata_with_invalid_id - with_config(cat_config) do - rmd = @obfuscator.obfuscate(::JSON.dump({ - NewRelicID: 'bugz', - NewRelicTransaction: ['abc', false, 'def', 'ghi'], - NewRelicSynthetics: 'raw_synth' - })) - - in_transaction do |txn| - l = with_array_logger { NewRelic::Agent::External.process_request_metadata(rmd) } - - refute_empty l.array, 'process_request_metadata should log error on invalid ID' - assert_includes l.array.first, 'invalid/non-trusted ID' - - refute txn.distributed_tracer.cross_app_payload - end - end - end - - def test_process_request_metadata_with_non_trusted_id - with_config(cat_config) do - rmd = @obfuscator.obfuscate(::JSON.dump({ - NewRelicID: '190#666', - NewRelicTransaction: ['abc', false, 'def', 'ghi'], - NewRelicSynthetics: 'raw_synth' - })) - - in_transaction do |txn| - l = with_array_logger { NewRelic::Agent::External.process_request_metadata(rmd) } - - refute_empty l.array, 'process_request_metadata should log error on invalid ID' - assert_includes l.array.first, 'invalid/non-trusted ID' - - refute txn.distributed_tracer.cross_app_payload - end - end - end - - def test_process_request_metadata_cross_app_disabled - with_config(cat_config.merge(:'cross_application_tracer.enabled' => false)) do - rmd = @obfuscator.obfuscate(::JSON.dump({ - NewRelicID: cat_config[:cross_process_id], - NewRelicTransaction: ['abc', false, 'def', 'ghi'] - })) - - in_transaction do |txn| - l = with_array_logger { NewRelic::Agent::External.process_request_metadata(rmd) } - - assert_empty l.array, 'process_request_metadata should not log errors when cross app tracing is disabled' - - refute txn.distributed_tracer.cross_app_payload - end - end - end - - # --- get_response_metadata - - def test_get_response_metadata - with_config(cat_config) do - inbound_rmd = @obfuscator.obfuscate(::JSON.dump({ - NewRelicID: '1#666', - NewRelicTransaction: ['xyz', false, 'uvw', 'rst'] - })) - - in_transaction do |txn| - # simulate valid processed request metadata - NewRelic::Agent::External.process_request_metadata(inbound_rmd) - - rmd = NewRelic::Agent::External.get_response_metadata - - assert_instance_of String, rmd - rmd = @obfuscator.deobfuscate(rmd) - rmd = JSON.parse(rmd) - - assert_instance_of Hash, rmd - assert_instance_of Array, rmd['NewRelicAppData'] - - assert_equal '269975#22824', rmd['NewRelicAppData'][0] - assert_equal 'dummy', rmd['NewRelicAppData'][1] - assert_instance_of Float, rmd['NewRelicAppData'][2] - assert_instance_of Float, rmd['NewRelicAppData'][3] - assert_equal(-1, rmd['NewRelicAppData'][4]) - assert_equal txn.guid, rmd['NewRelicAppData'][5] - end - end - end - - def test_get_response_metadata_not_in_transaction - with_config(cat_config) do - refute NewRelic::Agent::External.get_response_metadata - end - end - - def test_get_response_metadata_without_valid_id - with_config(cat_config) do - in_transaction do |txn| - refute NewRelic::Agent::External.get_response_metadata - end - end - end - - # --- - - def cat_config - { - :'cross_application_tracer.enabled' => true, - :'distributed_tracing.enabled' => false, - :cross_process_id => '269975#22824', - :trusted_account_ids => [1, 269975] - } - end - end - end -end diff --git a/test/new_relic/agent/messaging_test.rb b/test/new_relic/agent/messaging_test.rb index b53cab78d8..bcb6306340 100644 --- a/test/new_relic/agent/messaging_test.rb +++ b/test/new_relic/agent/messaging_test.rb @@ -442,81 +442,6 @@ def test_segment_records_proper_metrics_for_consume ] end - def test_wrap_message_broker_consume_transaction_reads_cat_headers - guid = 'BEC1BC64675138B9' - cross_process_id = '321#123' - intrinsic_attributes = {client_cross_process_id: cross_process_id, referring_transaction_guid: guid} - obfuscated_id = nil - raw_txn_info = nil - obfuscated_txn_info = nil - - tap = mock('tap') - tap.expects(:tap) - - with_config(:"cross_application_tracer.enabled" => true, - :cross_process_id => cross_process_id, - :'distributed_tracing.enabled' => false, - :trusted_account_ids => [321], - :encoding_key => 'abc') do - in_transaction do |txn| - obfuscated_id = obfuscator.obfuscate(cross_process_id) - raw_txn_info = [guid, false, guid, txn.distributed_tracer.cat_path_hash] - obfuscated_txn_info = obfuscator.obfuscate(raw_txn_info.to_json) - end - - NewRelic::Agent::Messaging.wrap_message_broker_consume_transaction( - library: 'RabbitMQ', - destination_type: :exchange, - destination_name: 'Default', - headers: {'NewRelicID' => obfuscated_id, 'NewRelicTransaction' => obfuscated_txn_info} - ) do - txn = NewRelic::Agent::Tracer.current_transaction - payload = txn.distributed_tracer.cross_app_payload - - assert_equal cross_process_id, payload.id - assert_equal payload.referring_guid, raw_txn_info[0] - assert_equal payload.referring_trip_id, raw_txn_info[2] - assert_equal payload.referring_path_hash, raw_txn_info[3] - assert_equal txn.attributes.intrinsic_attributes_for(NewRelic::Agent::AttributeFilter::DST_TRANSACTION_TRACER), intrinsic_attributes - tap.tap - end - end - end - - def test_wrap_message_broker_consume_transaction_records_proper_metrics_with_cat - guid = 'BEC1BC64675138B9' - cross_process_id = '321#123' - obfuscated_id = nil - raw_txn_info = nil - obfuscated_txn_info = nil - - tap = mock('tap') - tap.expects(:tap) - - with_config(:"cross_application_tracer.enabled" => true, - :cross_process_id => cross_process_id, - :'distributed_tracing.enabled' => false, - :trusted_account_ids => [321], - :encoding_key => 'abc') do - in_transaction('test_txn') do |txn| - obfuscated_id = obfuscator.obfuscate(cross_process_id) - raw_txn_info = [guid, false, guid, txn.distributed_tracer.cat_path_hash] - obfuscated_txn_info = obfuscator.obfuscate(raw_txn_info.to_json) - end - - Messaging.wrap_message_broker_consume_transaction( - library: 'RabbitMQ', - destination_type: :exchange, - destination_name: 'Default', - headers: {'NewRelicID' => obfuscated_id, 'NewRelicTransaction' => obfuscated_txn_info} - ) do - tap.tap - end - - assert_metrics_recorded "ClientApplication/#{cross_process_id}/all" - end - end - def obfuscator NewRelic::Agent::CrossAppTracing.obfuscator end diff --git a/test/new_relic/agent/monitors/cross_app_monitor_test.rb b/test/new_relic/agent/monitors/cross_app_monitor_test.rb deleted file mode 100644 index 62c6a347b4..0000000000 --- a/test/new_relic/agent/monitors/cross_app_monitor_test.rb +++ /dev/null @@ -1,261 +0,0 @@ -# This file is distributed under New Relic's license terms. -# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details. -# frozen_string_literal: true - -require_relative '../../../test_helper' - -module NewRelic::Agent - class CrossAppMonitorTest < Minitest::Test - NEWRELIC_ID_HEADER = DistributedTracing::CrossAppMonitor::NEWRELIC_ID_HEADER_KEY - NEWRELIC_TXN_HEADER = DistributedTracing::CrossAppMonitor::NEWRELIC_TXN_HEADER_KEY - CONTENT_LENGTH_KEY = 'HTTP_CONTENT_LENGTH' - - AGENT_CROSS_APP_ID = 'qwerty' - REQUEST_CROSS_APP_ID = '42#1234' - TRANSACTION_GUID = '941B0E8001E444E8' - REF_TRANSACTION_GUID = '830092CDE59421D4' - - TRANSACTION_NAME = 'transaction' - QUEUE_TIME = 1.0 - APP_TIME = 2.0 - - ENCODING_KEY_NOOP = "\0" - TRUSTED_ACCOUNT_IDS = [42, 13] - - CROSS_APP_ID_POSITION = 0 - TRANSACTION_NAME_POSITION = 1 - QUEUE_TIME_POSITION = 2 - APP_TIME_POSITION = 3 - CONTENT_LENGTH_POSITION = 4 - - def setup - NewRelic::Agent.reset_config - NewRelic::Agent.drop_buffered_data - @events = EventListener.new - @response = {} - - @monitor = DistributedTracing::CrossAppMonitor.new(@events) - @config = { - :cross_process_id => AGENT_CROSS_APP_ID, - :encoding_key => ENCODING_KEY_NOOP, - :trusted_account_ids => TRUSTED_ACCOUNT_IDS, - :disable_harvest_thread => true, - :'cross_application_tracer.enabled' => true, - :'distributed_tracing.enabled' => false - } - - NewRelic::Agent.config.add_config_for_testing(@config) - @events.notify(:initial_configuration_complete) - end - - def teardown - NewRelic::Agent.config.remove_config(@config) - @events.clear - end - - # - # Tests - # - - def test_adds_response_header - Transaction.any_instance.stubs(:queue_time).returns(QUEUE_TIME) - - when_request_runs(for_id(REQUEST_CROSS_APP_ID), 'transaction', APP_TIME) - - assert_equal [AGENT_CROSS_APP_ID, TRANSACTION_NAME, QUEUE_TIME, APP_TIME, -1, TRANSACTION_GUID, false], unpacked_response - end - - def test_encodes_transaction_name - when_request_runs(for_id(REQUEST_CROSS_APP_ID), %("'goo), APP_TIME) - - assert_equal "\"'goo", unpacked_response[TRANSACTION_NAME_POSITION] - end - - def test_doesnt_write_response_header_if_id_blank - when_request_runs(for_id('')) - - assert_nil response_app_data - end - - def test_doesnt_write_response_header_if_untrusted_id - when_request_runs(for_id('4#1234')) - - assert_nil response_app_data - end - - def test_doesnt_write_response_header_if_improperly_formatted_id - when_request_runs(for_id('42')) - - assert_nil response_app_data - end - - def test_doesnt_add_header_if_no_id_in_request - when_request_runs({}) - - assert_nil response_app_data - end - - def test_doesnt_add_header_if_no_id_on_agent - with_config(:cross_process_id => '') do - when_request_runs - - assert_nil response_app_data - end - end - - def test_doesnt_add_header_if_config_disabled - with_config(:"cross_application_tracer.enabled" => false) do - when_request_runs - - assert_nil response_app_data - end - end - - def test_old_cat_enabled - with_config(:"cross_application_tracer.enabled" => true) do - assert_predicate CrossAppTracing, :cross_application_tracer_enabled? - end - end - - def test_old_cat_disabled - with_config(:"cross_application_tracer.enabled" => false) do - refute_predicate CrossAppTracing, :cross_application_tracer_enabled? - end - end - - def test_old_cat_disabled_when_better_cat_enabled - with_config(:"cross_application_tracer.enabled" => true, - :"distributed_tracing.enabled" => true) do - refute_predicate CrossAppTracing, :cross_application_tracer_enabled? - end - end - - def test_doesnt_add_header_if_missing_encoding_key - with_config(:encoding_key => '') do - when_request_runs - - assert_nil response_app_data - end - end - - def test_includes_content_length - when_request_runs(for_id(REQUEST_CROSS_APP_ID).merge(CONTENT_LENGTH_KEY => 3000)) - - assert_equal 3000, unpacked_response[CONTENT_LENGTH_POSITION] - end - - def test_finds_content_length_from_headers - request = {'HTTP_CONTENT_LENGTH' => 42} - - assert_equal(42, @monitor.send(:content_length_from_request, request)) - end - - def test_writes_attributes - txn = when_request_runs - - assert_equal REQUEST_CROSS_APP_ID, attributes_for(txn, :intrinsic)[:client_cross_process_id] - assert_equal REF_TRANSACTION_GUID, attributes_for(txn, :intrinsic)[:referring_transaction_guid] - end - - def test_writes_metric - when_request_runs - - assert_metrics_recorded(["ClientApplication/#{REQUEST_CROSS_APP_ID}/all"]) - end - - def test_doesnt_write_metric_if_id_blank - when_request_runs(for_id('')) - - assert_metrics_recorded_exclusive([ - 'transaction', - 'Supportability/API/drop_buffered_data', - 'OtherTransactionTotalTime', - 'OtherTransactionTotalTime/transaction', - 'Supportability/API/record_metric', - 'Supportability/Deprecated/cross_application_tracer' - ]) - end - - def test_setting_response_headers_freezes_transaction_name - in_transaction do - request = for_id(REQUEST_CROSS_APP_ID) - @events.notify(:before_call, request) - - refute_predicate Transaction.tl_current, :name_frozen? - @events.notify(:after_call, request, [200, @response, '']) - - assert_predicate Transaction.tl_current, :name_frozen? - end - end - - def test_listener_in_other_thread_has_correct_txn_state - t = Thread.new do - in_transaction('transaction') do - request = for_id(REQUEST_CROSS_APP_ID) - - @events.notify(:before_call, request) - # Fake out our GUID for easier comparison in tests - Transaction.tl_current.stubs(:guid).returns(TRANSACTION_GUID) - @events.notify(:after_call, request, [200, @response, '']) - end - end - - t.join - - assert_metrics_recorded(["ClientApplication/#{REQUEST_CROSS_APP_ID}/all"]) - end - - def test_path_hash - with_config(:app_name => 'test') do - h0 = @monitor.path_hash('23547', 0) - h1 = @monitor.path_hash('step1', 0) - h2 = @monitor.path_hash('step2', h1.to_i(16)) - h3 = @monitor.path_hash('step3', h2.to_i(16)) - h4 = @monitor.path_hash('step4', h3.to_i(16)) - - assert_equal('eaaec1df', h0) - assert_equal('2e9a0b02', h1) - assert_equal('01d3f0eb', h2) - assert_equal('9a1b45e5', h3) - assert_equal('e9eecfee', h4) - end - end - - # - # Helpers - # - - def when_request_runs(request = for_id(REQUEST_CROSS_APP_ID), name = 'transaction', duration = nil) - nr_freeze_process_time if duration - - in_transaction(name) do |txn| - @events.notify(:before_call, request) - # Fake out our GUID for easier comparison in tests - Transaction.tl_current.stubs(:guid).returns(TRANSACTION_GUID) - advance_process_time(duration) if duration - @events.notify(:after_call, request, [200, @response, '']) - txn - end - end - - def for_id(id) - encoded_id = id == '' ? '' : NewRelic::Base64.encode64(id) - encoded_txn_info = json_dump_and_encode([REF_TRANSACTION_GUID, false]) - - return { - NEWRELIC_ID_HEADER => encoded_id, - NEWRELIC_TXN_HEADER => encoded_txn_info - } - end - - def response_app_data - @response['X-NewRelic-App-Data'] - end - - def unpacked_response - return nil unless response_app_data - - ::JSON.load(NewRelic::Base64.decode64(response_app_data)) - end - end -end diff --git a/test/new_relic/agent/supportability_test.rb b/test/new_relic/agent/supportability_test.rb index b39095b050..93bf4f890f 100644 --- a/test/new_relic/agent/supportability_test.rb +++ b/test/new_relic/agent/supportability_test.rb @@ -227,50 +227,3 @@ def test_trace_execution_unscoped_records_supportability_metric assert_api_supportability_metric_recorded(:trace_execution_unscoped) end end - -class ExternalAPISupportabilityMetricsTest < Minitest::Test - def setup - NewRelic::Agent.manual_start - NewRelic::Agent.drop_buffered_data - @segment = NewRelic::Agent::Tracer.start_external_request_segment( - library: :foo, - uri: 'http://example.com/root/index', - procedure: :http - ) - super - end - - def teardown - @segment.finish - NewRelic::Agent.shutdown - super - end - - def assert_api_supportability_metric_recorded(method_name) - assert_metrics_recorded(["Supportability/API/#{method_name}"]) - end - - def test_get_request_metadata_records_supportability_metric - @segment.get_request_metadata - - assert_api_supportability_metric_recorded(:get_request_metadata) - end - - def test_process_request_metadata_records_supportability_metric - NewRelic::Agent::External.process_request_metadata('') - - assert_api_supportability_metric_recorded(:process_request_metadata) - end - - def test_get_response_metadata_records_supportability_metric - NewRelic::Agent::External.get_response_metadata - - assert_api_supportability_metric_recorded(:get_response_metadata) - end - - def test_process_response_metadata_records_supportability_metric - @segment.process_response_metadata('') - - assert_api_supportability_metric_recorded(:process_response_metadata) - end -end diff --git a/test/new_relic/agent/transaction/external_request_segment_test.rb b/test/new_relic/agent/transaction/external_request_segment_test.rb index 056e7ba9d4..c840c7a01d 100644 --- a/test/new_relic/agent/transaction/external_request_segment_test.rb +++ b/test/new_relic/agent/transaction/external_request_segment_test.rb @@ -206,40 +206,6 @@ def test_segment_records_noncat_metrics_without_valid_encoding_key end end - def test_segment_records_expected_metrics_for_cat_transaction - response = { - 'X-NewRelic-App-Data' => make_app_data_payload('1#1884', 'txn-name', 2, 8, 0, TRANSACTION_GUID) - } - - with_config(cat_config) do - in_transaction('test', :category => :controller) do |txn| - segment = Tracer.start_external_request_segment( - library: 'Net::HTTP', - uri: 'http://newrelic.com/blogs/index', - procedure: 'GET' - ) - segment.process_response_headers(response) - segment.finish - end - - expected_metrics = [ - 'ExternalTransaction/newrelic.com/1#1884/txn-name', - 'ExternalApp/newrelic.com/1#1884/all', - 'External/all', - 'External/newrelic.com/all', - 'External/allWeb', - ['ExternalTransaction/newrelic.com/1#1884/txn-name', 'test'] - ] - - if Agent.config[:'distributed_tracing.enabled'] - expected_metrics << 'DurationByCaller/Unknown/Unknown/Unknown/Unknown/all' - expected_metrics << 'DurationByCaller/Unknown/Unknown/Unknown/Unknown/allWeb' - end - - assert_metrics_recorded expected_metrics - end - end - def test_proper_metrics_recorded_for_distributed_trace_on_receiver with_config(:'distributed_tracing.enabled' => true, :trusted_account_key => 'trust_this!') do @@ -329,24 +295,6 @@ def test_proper_metrics_recorded_for_distributed_trace_on_receiver_when_error_oc end end - def test_segment_writes_outbound_request_headers - request = RequestWrapper.new - with_config(cat_config) do - in_transaction(:category => :controller) do - segment = Tracer.start_external_request_segment( - library: 'Net::HTTP', - uri: 'http://remotehost.com/blogs/index', - procedure: 'GET' - ) - segment.add_request_headers(request) - segment.finish - end - end - - assert request.headers.key?('X-NewRelic-ID'), 'Expected to find X-NewRelic-ID header' - assert request.headers.key?('X-NewRelic-Transaction'), 'Expected to find X-NewRelic-Transaction header' - end - def test_segment_writes_outbound_request_headers_for_trace_context request = RequestWrapper.new with_config(trace_context_config) do @@ -365,28 +313,6 @@ def test_segment_writes_outbound_request_headers_for_trace_context assert request.headers.key?('tracestate'), 'Expected to find tracestate header' end - def test_segment_writes_synthetics_header_for_synthetics_txn - synthetics_info_header = {'version' => '1', 'type' => 'automatedTest', 'initiator' => 'cli', 'attributes' => {'attribute1' => 'one'}} - request = RequestWrapper.new - with_config(cat_config) do - in_transaction(:category => :controller) do |txn| - txn.raw_synthetics_header = json_dump_and_encode([1, 42, 100, 200, 300]) - txn.raw_synthetics_info_header = synthetics_info_header - segment = Tracer.start_external_request_segment( - library: 'Net::HTTP', - uri: 'http://remotehost.com/blogs/index', - procedure: 'GET' - ) - segment.add_request_headers(request) - segment.finish - end - end - - assert request.headers.key?('X-NewRelic-Synthetics'), 'Expected to find X-NewRelic-Synthetics header' - assert request.headers.key?('X-NewRelic-Synthetics-Info'), 'Expected to find X-NewRelic-Synthetics-Info header' - assert_equal request.headers['X-NewRelic-Synthetics-Info'], synthetics_info_header - end - def test_add_request_headers_renames_segment_based_on_host_header request = RequestWrapper.new({'host' => 'anotherhost.local'}) with_config(cat_config) do @@ -406,29 +332,6 @@ def test_add_request_headers_renames_segment_based_on_host_header end end - def test_read_response_headers_decodes_valid_appdata - response = { - 'X-NewRelic-App-Data' => make_app_data_payload('1#1884', 'txn-name', 2, 8, 0, TRANSACTION_GUID) - } - - with_config(cat_config) do - in_transaction(:category => :controller) do |txn| - segment = Tracer.start_external_request_segment( - library: 'Net::HTTP', - uri: 'http://remotehost.com/blogs/index', - procedure: 'GET' - ) - segment.process_response_headers(response) - segment.finish - - assert_predicate segment, :cross_app_request? - assert_equal '1#1884', segment.cross_process_id - assert_equal 'txn-name', segment.cross_process_transaction_name - assert_equal 'BEC1BC64675138B9', segment.transaction_guid - end - end - end - # Can pass :status_code and any HTTP code in headers to alter # default 200 (OK) HTTP status code def with_external_segment(headers, config, segment_params) @@ -447,24 +350,6 @@ def with_external_segment(headers, config, segment_params) return [segment, http_response] end - def test_read_response_headers_ignores_invalid_appdata - headers = { - 'X-NewRelic-App-Data' => 'this#is#not#valid#appdata' - } - segment_params = { - library: 'Net::HTTP', - uri: 'http://remotehost.com/blogs/index', - procedure: 'GET' - } - segment, _http_response = with_external_segment(headers, cat_config, segment_params) - - refute_predicate segment, :cross_app_request? - assert_equal 200, segment.http_status_code - assert_nil segment.cross_process_id - assert_nil segment.cross_process_transaction_name - assert_nil segment.transaction_guid - end - def test_sets_http_status_code_ok headers = { 'X-NewRelic-App-Data' => 'this#is#not#valid#appdata', @@ -567,189 +452,6 @@ def test_uri_recorded_as_tt_attribute assert_equal uri, node.params[:uri] end - def test_guid_recorded_as_tt_attribute_for_cat_txn - segment = nil - - response = { - 'X-NewRelic-App-Data' => make_app_data_payload('1#1884', 'txn-name', 2, 8, 0, TRANSACTION_GUID) - } - - with_config(cat_config) do - in_transaction(:category => :controller) do - segment = Tracer.start_external_request_segment( - library: 'Net::HTTP', - uri: 'http://remotehost.com/blogs/index', - procedure: 'GET' - ) - segment.process_response_headers(response) - segment.finish - end - end - - sample = last_transaction_trace - node = find_node_with_name(sample, segment.name) - - assert_equal TRANSACTION_GUID, node.params[:transaction_guid] - end - - # --- get_request_metadata - - def test_get_request_metadata - with_config(cat_config.merge(:'cross_application_tracer.enabled' => true)) do - in_transaction do |txn| - rmd = external_request_segment { |s| s.get_request_metadata } - - assert_instance_of String, rmd - rmd = @obfuscator.deobfuscate(rmd) - rmd = JSON.parse(rmd) - - assert_instance_of Hash, rmd - - assert_equal '269975#22824', rmd['NewRelicID'] - - assert_instance_of Array, rmd['NewRelicTransaction'] - assert_equal txn.guid, rmd['NewRelicTransaction'][0] - refute rmd['NewRelicTransaction'][1] - - assert_equal txn.distributed_tracer.cat_trip_id, rmd['NewRelicTransaction'][2] - assert_equal txn.distributed_tracer.cat_path_hash, rmd['NewRelicTransaction'][3] - - refute rmd.key?('NewRelicSynthetics') - - assert_predicate txn.distributed_tracer, :is_cross_app_caller? - end - end - end - - def test_get_request_metadata_with_cross_app_tracing_disabled - with_config(cat_config.merge(:'cross_application_tracer.enabled' => false)) do - in_transaction do |txn| - rmd = external_request_segment { |s| s.get_request_metadata } - - refute rmd, '`get_request_metadata` should return nil with cross app tracing disabled' - end - end - end - - def test_get_request_metadata_with_synthetics_header - with_config(cat_config) do - in_transaction do |txn| - txn.raw_synthetics_header = 'raw_synth' - - rmd = external_request_segment { |s| s.get_request_metadata } - - rmd = @obfuscator.deobfuscate(rmd) - rmd = JSON.parse(rmd) - - assert_equal 'raw_synth', rmd['NewRelicSynthetics'] - end - end - end - - def test_get_request_metadata_not_in_transaction - with_config(cat_config) do - refute external_request_segment { |s| s.get_request_metadata } - end - end - - # --- process_response_metadata - - def test_process_response_metadata - with_config(cat_config) do - in_transaction do |txn| - rmd = @obfuscator.obfuscate(::JSON.dump({ - NewRelicAppData: [ - NewRelic::Agent.config[:cross_process_id], - 'Controller/root/index', - 0.001, - 0.5, - 60, - txn.guid - ] - })) - - segment = external_request_segment { |s| s.process_response_metadata(rmd); s } - - assert_equal 'ExternalTransaction/example.com/269975#22824/Controller/root/index', segment.name - end - end - end - - def test_process_response_metadata_not_in_transaction - with_config(cat_config) do - rmd = @obfuscator.obfuscate(::JSON.dump({ - NewRelicAppData: [ - NewRelic::Agent.config[:cross_process_id], - 'Controller/root/index', - 0.001, - 0.5, - 60, - 'abcdef' - ] - })) - - segment = external_request_segment { |s| s.process_response_metadata(rmd); s } - - assert_equal 'External/example.com/foo/get', segment.name - end - end - - def test_process_response_metadata_with_invalid_cross_app_id - with_config(cat_config) do - in_transaction do |txn| - rmd = @obfuscator.obfuscate(::JSON.dump({ - NewRelicAppData: [ - 'bugz', - 'Controller/root/index', - 0.001, - 0.5, - 60, - txn.guid - ] - })) - - segment = nil - l = with_array_logger do - segment = external_request_segment { |s| s.process_response_metadata(rmd); s } - end - - refute_empty l.array, 'process_response_metadata should log error on invalid ID' - assert_includes l.array.first, 'invalid/non-trusted ID' - - assert_equal 'External/example.com/foo/get', segment.name - end - end - end - - def test_process_response_metadata_with_untrusted_cross_app_id - with_config(cat_config) do - in_transaction do |txn| - rmd = @obfuscator.obfuscate(::JSON.dump({ - NewRelicAppData: [ - '190#666', - 'Controller/root/index', - 0.001, - 0.5, - 60, - txn.guid - ] - })) - - segment = nil - l = with_array_logger do - segment = external_request_segment { |s| s.process_response_metadata(rmd); s } - end - - refute_empty l.array, 'process_response_metadata should log error on invalid ID' - assert_includes l.array.first, 'invalid/non-trusted ID' - - assert_equal 'External/example.com/foo/get', segment.name - end - end - end - - # --- - def test_segment_adds_distributed_trace_header distributed_tracing_config = { :'distributed_tracing.enabled' => true, diff --git a/test/new_relic/agent/transaction/message_broker_segment_test.rb b/test/new_relic/agent/transaction/message_broker_segment_test.rb index 8c9b4eedaa..e439459374 100644 --- a/test/new_relic/agent/transaction/message_broker_segment_test.rb +++ b/test/new_relic/agent/transaction/message_broker_segment_test.rb @@ -77,43 +77,6 @@ def test_allows_symbol_exchange_names end end - def test_segment_adds_cat_headers_to_message_properties_for_produce - with_config(:"cross_application_tracer.enabled" => true, :"distributed_tracing.enabled" => false, :cross_process_id => '321#123', :encoding_key => 'abc') do - in_transaction('test_txn') do - segment = NewRelic::Agent::Tracer.start_message_broker_segment( - action: :produce, - library: 'RabbitMQ', - destination_type: :exchange, - destination_name: 'Default', - headers: {} - ) - - assert segment.headers.key?('NewRelicID'), 'Expected message_properties to contain: NewRelicId' - assert segment.headers.key?('NewRelicTransaction'), 'Expected message_properties to contain: NewRelicTransaction' - refute segment.headers.key?('NewRelicSynthetics') - end - end - end - - def test_segment_adds_synthetics_and_cat_headers_to_message_properties_for_produce - with_config(:"cross_application_tracer.enabled" => true, :"distributed_tracing.enabled" => false, :cross_process_id => '321#123', :encoding_key => 'abc') do - in_transaction('test_txn') do |txn| - txn.raw_synthetics_header = 'boo' - segment = NewRelic::Agent::Tracer.start_message_broker_segment( - action: :produce, - library: 'RabbitMQ', - destination_type: :exchange, - destination_name: 'Default', - headers: {} - ) - - assert segment.headers.key?('NewRelicID'), 'Expected message_properties to contain: NewRelicId' - assert segment.headers.key?('NewRelicTransaction'), 'Expected message_properties to contain: NewRelicTransaction' - assert segment.headers.key?('NewRelicSynthetics'), 'Expected message_properties to contain: NewRelicSynthetics' - end - end - end - def test_segment_adds_distributed_trace_headers_to_message_properties_for_produce NewRelic::Agent.instance.stubs(:connected?).returns(true) with_config(:"distributed_tracing.enabled" => true, diff --git a/test/new_relic/http_client_test_cases.rb b/test/new_relic/http_client_test_cases.rb index 8355f043a1..9ed7bb9933 100644 --- a/test/new_relic/http_client_test_cases.rb +++ b/test/new_relic/http_client_test_cases.rb @@ -263,54 +263,6 @@ def test_url_not_supported_by_stdlib_uri end end - # When an http call is made, the agent should add a request header named - # X-NewRelic-ID with a value equal to the encoded cross_app_id. - - def test_adds_a_request_header_to_outgoing_requests_if_xp_enabled - NewRelic::Agent::Agent.any_instance.stubs(:connected?).returns(true) - with_config(:"cross_application_tracer.enabled" => true, :'distributed_tracing.enabled' => false) do - in_transaction { get_response } - - assert_equal 'VURQV1BZRkZdXUFT', server.requests.last['HTTP_X_NEWRELIC_ID'] - end - NewRelic::Agent::Agent.any_instance.unstub(:connected?) - end - - def test_adds_a_request_header_to_outgoing_requests_if_old_xp_config_is_present - NewRelic::Agent::Agent.any_instance.stubs(:connected?).returns(true) - with_config(:'cross_application_tracer.enabled' => true, :'distributed_tracing.enabled' => false) do - in_transaction { get_response } - - assert_equal 'VURQV1BZRkZdXUFT', server.requests.last['HTTP_X_NEWRELIC_ID'] - end - NewRelic::Agent::Agent.any_instance.unstub(:connected?) - end - - def test_adds_newrelic_transaction_header - NewRelic::Agent::Agent.any_instance.stubs(:connected?).returns(true) - with_config(:'cross_application_tracer.enabled' => true, :'distributed_tracing.enabled' => false) do - guid = nil - path_hash = nil - in_transaction do |txn| - guid = txn.guid - path_hash = txn.distributed_tracer.cat_path_hash - get_response - end - - transaction_data = server.requests.last['HTTP_X_NEWRELIC_TRANSACTION'] - - refute_empty(transaction_data) - - decoded = decode_payload(transaction_data) - - assert_equal(guid, decoded[0]) - refute(decoded[1]) - assert_equal(guid, decoded[2]) - assert_equal(path_hash, decoded[3]) - end - NewRelic::Agent::Agent.any_instance.unstub(:connected?) - end - def test_agent_doesnt_add_a_request_header_to_outgoing_requests_if_xp_disabled in_transaction { get_response } @@ -356,46 +308,6 @@ def test_instrumentation_with_crossapp_disabled_records_normal_metrics_even_if_h assert_metrics_recorded([["External/localhost/#{client_name}/GET", 'test']]) end - def test_instrumentation_with_crossapp_enabled_records_crossapp_metrics_if_header_present - $fake_server.override_response_headers('X-NewRelic-App-Data' => - make_app_data_payload('18#1884', 'txn-name', 2, 8, 0, TRANSACTION_GUID)) - - with_config(:"cross_application_tracer.enabled" => true, :'distributed_tracing.enabled' => false) do - in_transaction('test') do - get_response - end - end - - perform_last_node_error_assertions([ - 'External/all', - 'External/allOther', - 'ExternalApp/localhost/18#1884/all', - 'ExternalTransaction/localhost/18#1884/txn-name', - 'External/localhost/all', - ['ExternalTransaction/localhost/18#1884/txn-name', 'test'] - ]) - end - - def test_crossapp_metrics_allow_valid_utf8_characters - $fake_server.override_response_headers('X-NewRelic-App-Data' => - make_app_data_payload('12#1114', '世界線航跡蔵', 18.0, 88.1, 4096, TRANSACTION_GUID)) - - with_config(:"cross_application_tracer.enabled" => true, :'distributed_tracing.enabled' => false) do - in_transaction('test') do - get_response - end - end - - perform_last_node_error_assertions([ - 'External/all', - 'External/allOther', - 'ExternalApp/localhost/12#1114/all', - 'External/localhost/all', - 'ExternalTransaction/localhost/12#1114/世界線航跡蔵', - ['ExternalTransaction/localhost/12#1114/世界線航跡蔵', 'test'] - ]) - end - def test_crossapp_metrics_ignores_crossapp_header_with_malformed_cross_process_id $fake_server.override_response_headers('X-NewRelic-App-Data' => make_app_data_payload('88#88#88', 'invalid', 1, 2, 4096, TRANSACTION_GUID)) @@ -536,51 +448,6 @@ def test_no_raw_synthetics_header_if_not_present end end - load_cross_agent_test('cat_map').each do |test_case| - # Test cases that don't involve outgoing calls are done elsewhere - if test_case['outboundRequests'] - define_method("test_#{test_case['name']}") do - NewRelic::Agent::Agent.any_instance.stubs(:connected?).returns(true) - config = { - :app_name => test_case['appName'], - :'cross_application_tracer.enabled' => true, - :'distributed_tracing.enabled' => false, - :'disable_all_tracing.enabled' => false - } - with_config(config) do - NewRelic::Agent.instance.events.notify(:initial_configuration_complete) - - in_transaction do |txn| - txn_info = test_case['inboundPayload'] - payload = NewRelic::Agent::CrossAppPayload.new('someId', txn, txn_info) - txn.distributed_tracer.cross_app_payload = payload - stub_transaction_guid(test_case['transactionGuid']) - test_case['outboundRequests'].each do |req| - set_explicit_transaction_name(req['outboundTxnName']) - get_response - - outbound_payload = server.requests.last['HTTP_X_NEWRELIC_TRANSACTION'] - decoded_outbound_payload = decode_payload(outbound_payload) - - assert_equal(req['expectedOutboundPayload'], decoded_outbound_payload) - end - set_explicit_transaction_name(test_case['transactionName']) - end - end - - event = get_last_analytics_event - - assert_event_attributes( - event, - test_case['name'], - test_case['expectedIntrinsicFields'], - test_case['nonExpectedIntrinsicFields'] - ) - NewRelic::Agent::Agent.any_instance.unstub(:connected?) - end - end - end - # These tests only cover receiving, validating, and passing on the synthetics # request header to any outgoing HTTP requests. They do *not* cover attaching # of appropriate data to analytics events or transaction traces.