newrelic_rpm 6.3.0.355 → 6.8.0.360

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +50 -10
  4. data/CHANGELOG.md +198 -0
  5. data/Guardfile +7 -1
  6. data/lib/new_relic/agent.rb +80 -0
  7. data/lib/new_relic/agent/agent.rb +87 -26
  8. data/lib/new_relic/agent/agent_logger.rb +4 -0
  9. data/lib/new_relic/agent/attribute_filter.rb +7 -7
  10. data/lib/new_relic/agent/attributes.rb +152 -0
  11. data/lib/new_relic/agent/autostart.rb +19 -14
  12. data/lib/new_relic/agent/commands/agent_command_router.rb +2 -21
  13. data/lib/new_relic/agent/configuration/default_source.rb +129 -39
  14. data/lib/new_relic/agent/configuration/environment_source.rb +4 -2
  15. data/lib/new_relic/agent/configuration/event_harvest_config.rb +45 -0
  16. data/lib/new_relic/agent/configuration/high_security_source.rb +1 -0
  17. data/lib/new_relic/agent/configuration/manager.rb +13 -9
  18. data/lib/new_relic/agent/configuration/server_source.rb +33 -9
  19. data/lib/new_relic/agent/configuration/yaml_source.rb +10 -5
  20. data/lib/new_relic/agent/connect/request_builder.rb +11 -13
  21. data/lib/new_relic/agent/connect/response_handler.rb +1 -1
  22. data/lib/new_relic/agent/cross_app_monitor.rb +1 -1
  23. data/lib/new_relic/agent/datastores/mongo/event_formatter.rb +2 -2
  24. data/lib/new_relic/agent/datastores/mongo/obfuscator.rb +8 -8
  25. data/lib/new_relic/agent/distributed_trace_intrinsics.rb +90 -0
  26. data/lib/new_relic/agent/distributed_trace_metrics.rb +74 -0
  27. data/lib/new_relic/agent/distributed_trace_monitor.rb +2 -12
  28. data/lib/new_relic/agent/distributed_trace_payload.rb +9 -76
  29. data/lib/new_relic/agent/distributed_trace_transport_type.rb +43 -0
  30. data/lib/new_relic/agent/error_collector.rb +2 -2
  31. data/lib/new_relic/agent/error_event_aggregator.rb +2 -1
  32. data/lib/new_relic/agent/error_trace_aggregator.rb +1 -0
  33. data/lib/new_relic/agent/event_aggregator.rb +26 -32
  34. data/lib/new_relic/agent/guid_generator.rb +28 -0
  35. data/lib/new_relic/agent/inbound_request_monitor.rb +2 -2
  36. data/lib/new_relic/agent/instrumentation/action_cable_subscriber.rb +24 -42
  37. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +45 -69
  38. data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +70 -53
  39. data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +25 -18
  40. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +33 -47
  41. data/lib/new_relic/agent/instrumentation/active_storage_subscriber.rb +4 -4
  42. data/lib/new_relic/agent/instrumentation/grape.rb +2 -3
  43. data/lib/new_relic/agent/instrumentation/{evented_subscriber.rb → notifications_subscriber.rb} +7 -66
  44. data/lib/new_relic/agent/instrumentation/rails_notifications/action_cable.rb +2 -3
  45. data/lib/new_relic/agent/javascript_instrumentor.rb +1 -1
  46. data/lib/new_relic/agent/logging.rb +129 -0
  47. data/lib/new_relic/agent/new_relic_service.rb +7 -9
  48. data/lib/new_relic/agent/priority_sampled_buffer.rb +2 -0
  49. data/lib/new_relic/agent/span_event_aggregator.rb +2 -4
  50. data/lib/new_relic/agent/span_event_primitive.rb +29 -7
  51. data/lib/new_relic/agent/sql_sampler.rb +1 -1
  52. data/lib/new_relic/agent/threading/backtrace_service.rb +3 -3
  53. data/lib/new_relic/agent/threading/thread_profile.rb +9 -23
  54. data/lib/new_relic/agent/trace_context.rb +244 -0
  55. data/lib/new_relic/agent/trace_context_payload.rb +134 -0
  56. data/lib/new_relic/agent/trace_context_request_monitor.rb +42 -0
  57. data/lib/new_relic/agent/tracer.rb +32 -0
  58. data/lib/new_relic/agent/transaction.rb +26 -20
  59. data/lib/new_relic/agent/transaction/abstract_segment.rb +2 -2
  60. data/lib/new_relic/agent/transaction/distributed_tracing.rb +20 -101
  61. data/lib/new_relic/agent/transaction/external_request_segment.rb +18 -5
  62. data/lib/new_relic/agent/transaction/segment.rb +7 -1
  63. data/lib/new_relic/agent/transaction/trace.rb +3 -8
  64. data/lib/new_relic/agent/transaction/trace_builder.rb +0 -1
  65. data/lib/new_relic/agent/transaction/trace_context.rb +159 -0
  66. data/lib/new_relic/agent/transaction/trace_node.rb +8 -3
  67. data/lib/new_relic/agent/transaction_error_primitive.rb +4 -11
  68. data/lib/new_relic/agent/transaction_event_primitive.rb +3 -11
  69. data/lib/new_relic/agent/transaction_event_recorder.rb +3 -3
  70. data/lib/new_relic/agent/transaction_sampler.rb +1 -5
  71. data/lib/new_relic/cli/commands/deployments.rb +1 -1
  72. data/lib/new_relic/coerce.rb +29 -6
  73. data/lib/new_relic/control/instance_methods.rb +10 -1
  74. data/lib/new_relic/dependency_detection.rb +4 -4
  75. data/lib/new_relic/noticed_error.rb +8 -4
  76. data/lib/new_relic/rack/browser_monitoring.rb +10 -8
  77. data/lib/new_relic/version.rb +1 -1
  78. data/lib/tasks/config.rake +1 -2
  79. data/newrelic_rpm.gemspec +13 -4
  80. data/test/agent_helper.rb +95 -9
  81. data/true +0 -0
  82. metadata +58 -24
  83. data/lib/new_relic/agent/commands/xray_session.rb +0 -55
  84. data/lib/new_relic/agent/commands/xray_session_collection.rb +0 -161
  85. data/lib/new_relic/agent/configuration/event_data.rb +0 -39
  86. data/lib/new_relic/agent/transaction/attributes.rb +0 -154
  87. data/lib/new_relic/agent/transaction/xray_sample_buffer.rb +0 -64
  88. data/lib/tasks/versions.html.erb +0 -28
  89. data/lib/tasks/versions.postface.html +0 -8
  90. data/lib/tasks/versions.preface.html +0 -9
  91. data/lib/tasks/versions.rake +0 -65
  92. data/lib/tasks/versions.txt.erb +0 -14
@@ -19,6 +19,7 @@ require 'new_relic/agent/commands/agent_command_router'
19
19
  require 'new_relic/agent/event_listener'
20
20
  require 'new_relic/agent/cross_app_monitor'
21
21
  require 'new_relic/agent/distributed_trace_monitor'
22
+ require 'new_relic/agent/trace_context_request_monitor'
22
23
  require 'new_relic/agent/synthetics_monitor'
23
24
  require 'new_relic/agent/transaction_event_recorder'
24
25
  require 'new_relic/agent/custom_event_aggregator'
@@ -58,8 +59,9 @@ module NewRelic
58
59
  @agent_command_router = NewRelic::Agent::Commands::AgentCommandRouter.new(@events)
59
60
  @cross_app_monitor = NewRelic::Agent::CrossAppMonitor.new(@events)
60
61
  @distributed_trace_monitor = NewRelic::Agent::DistributedTraceMonitor.new(@events)
62
+ @trace_context_monitor = NewRelic::Agent::TraceContextRequestMonitor.new(@events)
61
63
  @synthetics_monitor = NewRelic::Agent::SyntheticsMonitor.new(@events)
62
- @error_collector = NewRelic::Agent::ErrorCollector.new
64
+ @error_collector = NewRelic::Agent::ErrorCollector.new @events
63
65
  @transaction_rules = NewRelic::Agent::RulesEngine.new
64
66
  @harvest_samplers = NewRelic::Agent::SamplerCollection.new(@events)
65
67
  @monotonic_gc_profiler = NewRelic::Agent::VM::MonotonicGCProfiler.new
@@ -70,9 +72,9 @@ module NewRelic
70
72
  @harvester = NewRelic::Agent::Harvester.new(@events)
71
73
  @after_fork_lock = Mutex.new
72
74
 
73
- @transaction_event_recorder = NewRelic::Agent::TransactionEventRecorder.new
74
- @custom_event_aggregator = NewRelic::Agent::CustomEventAggregator.new
75
- @span_event_aggregator = NewRelic::Agent::SpanEventAggregator.new
75
+ @transaction_event_recorder = NewRelic::Agent::TransactionEventRecorder.new @events
76
+ @custom_event_aggregator = NewRelic::Agent::CustomEventAggregator.new @events
77
+ @span_event_aggregator = NewRelic::Agent::SpanEventAggregator.new @events
76
78
 
77
79
  @connect_state = :pending
78
80
  @connect_attempts = 0
@@ -88,7 +90,7 @@ module NewRelic
88
90
  def setup_attribute_filter
89
91
  refresh_attribute_filter
90
92
 
91
- @events.subscribe(:finished_configuring) do
93
+ @events.subscribe(:initial_configuration_complete) do
92
94
  refresh_attribute_filter
93
95
  end
94
96
  end
@@ -147,6 +149,7 @@ module NewRelic
147
149
  attr_reader :transaction_event_recorder
148
150
  attr_reader :attribute_filter
149
151
  attr_reader :adaptive_sampler
152
+ attr_reader :environment_report
150
153
 
151
154
  def transaction_event_aggregator
152
155
  @transaction_event_recorder.transaction_event_aggregator
@@ -332,7 +335,7 @@ module NewRelic
332
335
  end
333
336
 
334
337
  def log_app_name
335
- ::NewRelic::Agent.logger.info "Application: #{Agent.config.app_names.join(", ")}"
338
+ ::NewRelic::Agent.logger.info "Application: #{Agent.config[:app_name].join(", ")}"
336
339
  end
337
340
 
338
341
  def log_ignore_url_regexes
@@ -345,7 +348,7 @@ module NewRelic
345
348
 
346
349
  # Logs the configured application names
347
350
  def app_name_configured?
348
- names = Agent.config.app_names
351
+ names = Agent.config[:app_name]
349
352
  return names.respond_to?(:any?) && names.any?
350
353
  end
351
354
 
@@ -482,6 +485,7 @@ module NewRelic
482
485
 
483
486
  unless in_resque_child_process?
484
487
  install_exit_handler
488
+ environment_for_connect
485
489
  @harvest_samplers.load_samplers unless Agent.config[:disable_samplers]
486
490
  end
487
491
 
@@ -531,7 +535,7 @@ module NewRelic
531
535
  check_config_and_start_agent
532
536
  log_version_and_pid
533
537
 
534
- events.subscribe(:finished_configuring) do
538
+ events.subscribe(:initial_configuration_complete) do
535
539
  log_ignore_url_regexes
536
540
  end
537
541
  end
@@ -561,7 +565,10 @@ module NewRelic
561
565
  def flush_pipe_data
562
566
  if connected? && @service.is_a?(::NewRelic::Agent::PipeService)
563
567
  transmit_data
564
- transmit_event_data
568
+ transmit_analytic_event_data
569
+ transmit_custom_event_data
570
+ transmit_error_event_data
571
+ transmit_span_event_data
565
572
  end
566
573
  end
567
574
 
@@ -577,20 +584,46 @@ module NewRelic
577
584
 
578
585
  LOG_ONCE_KEYS_RESET_PERIOD = 60.0
579
586
 
587
+ # Certain event types may sometimes need to be on the same interval as metrics,
588
+ # so we will check config assigned in EventHarvestConfig to determine the interval
589
+ # on which to report them
590
+ def interval_for event_type
591
+ interval = Agent.config[:"event_report_period.#{event_type}"]
592
+ :"#{interval}_second_harvest"
593
+ end
594
+
595
+ ANALYTIC_EVENT_DATA = "analytic_event_data".freeze
596
+ CUSTOM_EVENT_DATA = "custom_event_data".freeze
597
+ ERROR_EVENT_DATA = "error_event_data".freeze
598
+ SPAN_EVENT_DATA = "span_event_data".freeze
599
+
580
600
  def create_and_run_event_loop
601
+ data_harvest = :"#{Agent.config[:data_report_period]}_second_harvest"
602
+ event_harvest = :"#{Agent.config[:event_report_period]}_second_harvest"
603
+
581
604
  @event_loop = create_event_loop
582
- @event_loop.on(:report_data) do
605
+ @event_loop.on(data_harvest) do
583
606
  transmit_data
584
607
  end
585
- @event_loop.on(:report_event_data) do
586
- transmit_event_data
608
+
609
+ @event_loop.on(interval_for ANALYTIC_EVENT_DATA) do
610
+ transmit_analytic_event_data
611
+ end
612
+ @event_loop.on(interval_for CUSTOM_EVENT_DATA) do
613
+ transmit_custom_event_data
614
+ end
615
+ @event_loop.on(interval_for ERROR_EVENT_DATA) do
616
+ transmit_error_event_data
617
+ end
618
+ @event_loop.on(interval_for SPAN_EVENT_DATA) do
619
+ transmit_span_event_data
587
620
  end
588
621
  @event_loop.on(:reset_log_once_keys) do
589
622
  ::NewRelic::Agent.logger.clear_already_logged
590
623
  end
591
- @event_loop.fire_every(Agent.config[:data_report_period], :report_data)
592
- @event_loop.fire_every(Agent.config[:event_report_period], :report_event_data)
593
- @event_loop.fire_every(LOG_ONCE_KEYS_RESET_PERIOD, :reset_log_once_keys)
624
+ @event_loop.fire_every(Agent.config[:data_report_period], data_harvest)
625
+ @event_loop.fire_every(Agent.config[:event_report_period], event_harvest)
626
+ @event_loop.fire_every(LOG_ONCE_KEYS_RESET_PERIOD, :reset_log_once_keys)
594
627
 
595
628
  @event_loop.run
596
629
  end
@@ -760,14 +793,24 @@ module NewRelic
760
793
  # require calls in Rails environments, so this method should only
761
794
  # be called synchronously from on the main thread.
762
795
  def environment_for_connect
763
- Agent.config[:send_environment_info] ? Array(EnvironmentReport.new) : []
796
+ @environment_report ||= Agent.config[:send_environment_info] ? Array(EnvironmentReport.new) : []
797
+ end
798
+
799
+ # Constructs and memoizes an event_harvest_config hash to be used in
800
+ # the payload sent during connect (and reconnect)
801
+ def event_harvest_config
802
+ @event_harvest_config ||= Configuration::EventHarvestConfig.from_config(Agent.config)
764
803
  end
765
804
 
766
805
  # Builds the payload to send to the connect service,
767
- # connects, then configures the agent using the response from
806
+ # connects, then configures the agent using the response from
768
807
  # the connect service
769
808
  def connect_to_server
770
- request_builder = ::NewRelic::Agent::Connect::RequestBuilder.new(@service, Agent.config)
809
+ request_builder = ::NewRelic::Agent::Connect::RequestBuilder.new \
810
+ @service,
811
+ Agent.config,
812
+ event_harvest_config,
813
+ environment_for_connect
771
814
  connect_response = @service.connect request_builder.connect_payload
772
815
 
773
816
  response_handler = ::NewRelic::Agent::Connect::ResponseHandler.new(self, Agent.config)
@@ -1010,17 +1053,20 @@ module NewRelic
1010
1053
  def harvest_and_send_analytic_event_data
1011
1054
  harvest_and_send_from_container(transaction_event_aggregator, :analytic_event_data)
1012
1055
  harvest_and_send_from_container(synthetics_event_aggregator, :analytic_event_data)
1013
- harvest_and_send_from_container(@custom_event_aggregator, :custom_event_data)
1014
1056
  end
1015
1057
 
1016
- def harvest_and_send_span_event_data
1017
- harvest_and_send_from_container(span_event_aggregator, :span_event_data)
1058
+ def harvest_and_send_custom_event_data
1059
+ harvest_and_send_from_container(@custom_event_aggregator, :custom_event_data)
1018
1060
  end
1019
1061
 
1020
1062
  def harvest_and_send_error_event_data
1021
1063
  harvest_and_send_from_container @error_collector.error_event_aggregator, :error_event_data
1022
1064
  end
1023
1065
 
1066
+ def harvest_and_send_span_event_data
1067
+ harvest_and_send_from_container(span_event_aggregator, :span_event_data)
1068
+ end
1069
+
1024
1070
  def check_for_and_handle_agent_commands
1025
1071
  begin
1026
1072
  @agent_command_router.check_for_and_handle_agent_commands
@@ -1041,18 +1087,30 @@ module NewRelic
1041
1087
  NewRelic::Agent.record_metric("Supportability/remote_unavailable/#{endpoint.to_s}", 0.0)
1042
1088
  end
1043
1089
 
1044
- def transmit_event_data
1045
- transmit_single_data_type(:harvest_and_send_analytic_event_data, "TransactionEvent")
1090
+ TRANSACTION_EVENT = "TransactionEvent".freeze
1091
+ def transmit_analytic_event_data
1092
+ transmit_single_data_type(:harvest_and_send_analytic_event_data, TRANSACTION_EVENT)
1093
+ end
1094
+
1095
+ CUSTOM_EVENT = "CustomEvent".freeze
1096
+ def transmit_custom_event_data
1097
+ transmit_single_data_type(:harvest_and_send_custom_event_data, CUSTOM_EVENT)
1098
+ end
1099
+
1100
+ ERROR_EVENT = "ErrorEvent".freeze
1101
+ def transmit_error_event_data
1102
+ transmit_single_data_type(:harvest_and_send_error_event_data, ERROR_EVENT)
1046
1103
  end
1047
1104
 
1105
+ SPAN_EVENT = "SpanEvent".freeze
1048
1106
  def transmit_span_event_data
1049
- transmit_single_data_type(:harvest_and_send_span_event_data, "SpanEvent")
1107
+ transmit_single_data_type(:harvest_and_send_span_event_data, SPAN_EVENT)
1050
1108
  end
1051
1109
 
1052
1110
  def transmit_single_data_type(harvest_method, supportability_name)
1053
1111
  now = Time.now
1054
1112
 
1055
- msg = "Sending #{harvest_method.to_s.gsub("harvest_and_send_", "")} to New Relic Service"
1113
+ msg = "Sending #{supportability_name} data to New Relic Service"
1056
1114
  ::NewRelic::Agent.logger.debug msg
1057
1115
 
1058
1116
  @service.session do # use http keep-alive
@@ -1099,7 +1157,10 @@ module NewRelic
1099
1157
 
1100
1158
  @events.notify(:before_shutdown)
1101
1159
  transmit_data
1102
- transmit_event_data
1160
+ transmit_analytic_event_data
1161
+ transmit_custom_event_data
1162
+ transmit_error_event_data
1163
+ transmit_span_event_data
1103
1164
 
1104
1165
  if @connected_pid == $$ && !@service.kind_of?(NewRelic::Agent::NewRelicService)
1105
1166
  ::NewRelic::Agent.logger.debug "Sending New Relic service agent run shutdown message"
@@ -173,6 +173,10 @@ module NewRelic
173
173
  StartupLogger.instance.dump(self)
174
174
  end
175
175
 
176
+ def self.format_fatal_error message
177
+ "** [NewRelic] FATAL : #{message}\n"
178
+ end
179
+
176
180
  end
177
181
 
178
182
  # In an effort to not lose messages during startup, we trap them in memory
@@ -121,7 +121,7 @@ module NewRelic
121
121
  @high_security = config[:high_security]
122
122
 
123
123
  setup_key_cache
124
- cache_prefix_blacklist
124
+ cache_prefix_denylist
125
125
  end
126
126
 
127
127
  # Note the key_cache is a global cache, accessible by multiple threads,
@@ -222,16 +222,16 @@ module NewRelic
222
222
  # arguments for Sidekiq and Resque in the common case, since none of
223
223
  # these attributes are captured by default.
224
224
  #
225
- def cache_prefix_blacklist
226
- @prefix_blacklist = {}
227
- @prefix_blacklist[:'request.parameters'] = true unless might_allow_prefix_uncached?(:'request.parameters')
228
- @prefix_blacklist[:'job.sidekiq.args'] = true unless might_allow_prefix_uncached?(:'job.sidekiq.args')
229
- @prefix_blacklist[:'job.resque.args'] = true unless might_allow_prefix_uncached?(:'job.resque.args')
225
+ def cache_prefix_denylist
226
+ @prefix_denylist = {}
227
+ @prefix_denylist[:'request.parameters'] = true unless might_allow_prefix_uncached?(:'request.parameters')
228
+ @prefix_denylist[:'job.sidekiq.args'] = true unless might_allow_prefix_uncached?(:'job.sidekiq.args')
229
+ @prefix_denylist[:'job.resque.args'] = true unless might_allow_prefix_uncached?(:'job.resque.args')
230
230
  end
231
231
 
232
232
  # Note that the given prefix *must* be a Symbol
233
233
  def might_allow_prefix?(prefix)
234
- !@prefix_blacklist.include?(prefix)
234
+ !@prefix_denylist.include?(prefix)
235
235
  end
236
236
 
237
237
  def might_allow_prefix_uncached?(prefix)
@@ -0,0 +1,152 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ require 'new_relic/agent/attribute_processing'
6
+
7
+ module NewRelic
8
+ module Agent
9
+ class Attributes
10
+ KEY_LIMIT = 255
11
+ VALUE_LIMIT = 255
12
+ COUNT_LIMIT = 64
13
+
14
+ EMPTY_HASH = {}.freeze
15
+
16
+ def initialize(filter)
17
+ @filter = filter
18
+
19
+ @custom_attributes = {}
20
+ @agent_attributes = {}
21
+ @intrinsic_attributes = {}
22
+
23
+ @custom_destinations = {}
24
+ @agent_destinations = {}
25
+ @already_warned_count_limit = nil
26
+ end
27
+
28
+ def add_agent_attribute(key, value, default_destinations)
29
+ destinations = @filter.apply(key, default_destinations)
30
+ return if destinations == AttributeFilter::DST_NONE
31
+
32
+ @agent_destinations[key] = destinations
33
+ add(@agent_attributes, key, value)
34
+ end
35
+
36
+ def add_agent_attribute_with_key_check(key, value, default_destinations)
37
+ if exceeds_bytesize_limit? key, KEY_LIMIT
38
+ NewRelic::Agent.logger.debug("Agent attribute #{key} was dropped for exceeding key length limit #{KEY_LIMIT}")
39
+ return
40
+ end
41
+
42
+ add_agent_attribute(key, value, default_destinations)
43
+ end
44
+
45
+ def add_intrinsic_attribute(key, value)
46
+ add(@intrinsic_attributes, key, value)
47
+ end
48
+
49
+ def merge_untrusted_agent_attributes(attributes, prefix, default_destinations)
50
+ return if @filter.high_security?
51
+ return if !@filter.might_allow_prefix?(prefix)
52
+
53
+ AttributeProcessing.flatten_and_coerce(attributes, prefix) do |k, v|
54
+ add_agent_attribute_with_key_check(k, v, AttributeFilter::DST_NONE)
55
+ end
56
+ end
57
+
58
+ def merge_custom_attributes(other)
59
+ return unless Agent.config[:'custom_attributes.enabled']
60
+ return if other.empty?
61
+ AttributeProcessing.flatten_and_coerce(other) do |k, v|
62
+ add_custom_attribute(k, v)
63
+ end
64
+ end
65
+
66
+ def custom_attributes_for(destination)
67
+ for_destination(@custom_attributes, @custom_destinations, destination)
68
+ end
69
+
70
+ def agent_attributes_for(destination)
71
+ for_destination(@agent_attributes, @agent_destinations, destination)
72
+ end
73
+
74
+ def intrinsic_attributes_for(destination)
75
+ if destination == NewRelic::Agent::AttributeFilter::DST_TRANSACTION_TRACER ||
76
+ destination == NewRelic::Agent::AttributeFilter::DST_ERROR_COLLECTOR
77
+ @intrinsic_attributes
78
+ else
79
+ EMPTY_HASH
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def add_custom_attribute(key, value)
86
+ if @custom_attributes.size >= COUNT_LIMIT
87
+ unless @already_warned_count_limit
88
+ NewRelic::Agent.logger.warn("Custom attributes count exceeded limit of #{COUNT_LIMIT}. Any additional custom attributes during this transaction will be dropped.")
89
+ @already_warned_count_limit = true
90
+ end
91
+ return
92
+ end
93
+
94
+ if @filter.high_security?
95
+ NewRelic::Agent.logger.debug("Unable to add custom attribute #{key} while in high security mode.")
96
+ return
97
+ end
98
+
99
+ if exceeds_bytesize_limit?(key, KEY_LIMIT)
100
+ NewRelic::Agent.logger.warn("Custom attribute key '#{key}' was longer than limit of #{KEY_LIMIT} bytes. This attribute will be dropped.")
101
+ return
102
+ end
103
+
104
+ destinations = @filter.apply(key, AttributeFilter::DST_ALL)
105
+ return if destinations == AttributeFilter::DST_NONE
106
+
107
+ @custom_destinations[key] = destinations
108
+ add(@custom_attributes, key, value)
109
+ end
110
+
111
+ def add(attributes, key, value)
112
+ return if value.nil?
113
+
114
+ if exceeds_bytesize_limit?(value, VALUE_LIMIT)
115
+ value = slice(value)
116
+ end
117
+
118
+ attributes[key] = value
119
+ end
120
+
121
+ def for_destination(attributes, calculated_destinations, destination)
122
+ # Avoid allocating anything if there are no attrs at all
123
+ return EMPTY_HASH if attributes.empty?
124
+
125
+ attributes.inject({}) do |memo, (key, value)|
126
+ if @filter.allows?(calculated_destinations[key], destination)
127
+ memo[key] = value
128
+ end
129
+ memo
130
+ end
131
+ end
132
+
133
+ def exceeds_bytesize_limit?(value, limit)
134
+ if value.respond_to?(:bytesize)
135
+ value.bytesize > limit
136
+ elsif value.is_a?(Symbol)
137
+ value.to_s.bytesize > limit
138
+ else
139
+ false
140
+ end
141
+ end
142
+
143
+ # Take one byte past our limit. Why? This lets us unconditionally chop!
144
+ # the end. It'll either remove the one-character-too-many we have, or
145
+ # peel off the partial, mangled character left by the byteslice.
146
+ def slice(incoming)
147
+ result = incoming.to_s.byteslice(0, VALUE_LIMIT + 1)
148
+ result.chop!
149
+ end
150
+ end
151
+ end
152
+ end
@@ -20,23 +20,28 @@ module NewRelic
20
20
 
21
21
 
22
22
  # The constants, executables (i.e. $0) and rake tasks used can be
23
- # configured with the config keys 'autostart.blacklisted_constants',
24
- # 'autostart.blacklisted_executables' and
25
- # 'autostart.blacklisted_rake_tasks'
23
+ # configured with the config keys 'autostart.denylisted_constants',
24
+ # 'autostart.denylisted_executables' and
25
+ # 'autostart.denylisted_rake_tasks'
26
26
  def agent_should_start?
27
- !blacklisted_constants? &&
28
- !blacklisted_executables? &&
29
- !in_blacklisted_rake_task?
27
+ !denylisted_constants? &&
28
+ !denylisted_executables? &&
29
+ !in_denylisted_rake_task?
30
30
  end
31
31
 
32
- def blacklisted_constants?
33
- blacklisted?(NewRelic::Agent.config[:'autostart.blacklisted_constants']) do |name|
32
+ COMMA = ",".freeze
33
+
34
+ def denylisted_constants?
35
+ # For backwards compatibility until :'autostart_blacklisted_constants' config option is removed
36
+ constants = NewRelic::Agent.config[:'autostart.denylisted_constants'] << COMMA << NewRelic::Agent.config[:'autostart.blacklisted_constants']
37
+
38
+ denylisted?(constants) do |name|
34
39
  constant_is_defined?(name)
35
40
  end
36
41
  end
37
42
 
38
- def blacklisted_executables?
39
- blacklisted?(NewRelic::Agent.config[:'autostart.blacklisted_executables']) do |bin|
43
+ def denylisted_executables?
44
+ denylisted?(NewRelic::Agent.config[:'autostart.denylisted_executables']) do |bin|
40
45
  File.basename($0) == bin
41
46
  end
42
47
  end
@@ -47,18 +52,18 @@ module NewRelic
47
52
  !!::NewRelic::LanguageSupport.constantize(const_name)
48
53
  end
49
54
 
50
- def blacklisted?(value, &block)
55
+ def denylisted?(value, &block)
51
56
  value.split(/\s*,\s*/).any?(&block)
52
57
  end
53
58
 
54
- def in_blacklisted_rake_task?
59
+ def in_denylisted_rake_task?
55
60
  tasks = begin
56
61
  ::Rake.application.top_level_tasks
57
62
  rescue => e
58
- ::NewRelic::Agent.logger.debug("Not in Rake environment so skipping blacklisted_rake_tasks check: #{e}")
63
+ ::NewRelic::Agent.logger.debug("Not in Rake environment so skipping denylisted_rake_tasks check: #{e}")
59
64
  []
60
65
  end
61
- !(tasks & ::NewRelic::Agent.config[:'autostart.blacklisted_rake_tasks'].split(/\s*,\s*/)).empty?
66
+ !(tasks & ::NewRelic::Agent.config[:'autostart.denylisted_rake_tasks'].split(/\s*,\s*/)).empty?
62
67
  end
63
68
  end
64
69
  end