newrelic_rpm 3.15.2.317 → 3.16.0.318

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +23 -0
  3. data/lib/new_relic/agent.rb +0 -3
  4. data/lib/new_relic/agent/agent.rb +29 -34
  5. data/lib/new_relic/agent/attribute_filter.rb +2 -0
  6. data/lib/new_relic/agent/configuration/default_source.rb +50 -4
  7. data/lib/new_relic/agent/database/obfuscation_helpers.rb +3 -2
  8. data/lib/new_relic/agent/hash_extensions.rb +16 -1
  9. data/lib/new_relic/agent/instrumentation/action_cable_subscriber.rb +82 -0
  10. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +9 -8
  11. data/lib/new_relic/agent/instrumentation/rails5/action_cable.rb +29 -0
  12. data/lib/new_relic/agent/new_relic_service.rb +12 -4
  13. data/lib/new_relic/agent/new_relic_service/encoders.rb +19 -3
  14. data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +5 -1
  15. data/lib/new_relic/agent/supported_versions.rb +1 -1
  16. data/lib/new_relic/agent/transaction.rb +2 -1
  17. data/lib/new_relic/agent/transaction/request_attributes.rb +15 -0
  18. data/lib/new_relic/agent/utilization_data.rb +45 -1
  19. data/lib/new_relic/recipes/capistrano3.rb +44 -34
  20. data/lib/new_relic/version.rb +2 -2
  21. data/lib/tasks/versions.preface.html +7 -1
  22. data/lib/tasks/versions.rake +1 -1
  23. data/newrelic_rpm.gemspec +1 -0
  24. data/test/fixtures/cross_agent_tests/README.md +10 -32
  25. data/test/fixtures/cross_agent_tests/aws.json +2 -2
  26. data/test/fixtures/cross_agent_tests/rum_client_config.json +33 -4
  27. data/test/fixtures/cross_agent_tests/sql_obfuscation/README.md +1 -0
  28. data/test/fixtures/cross_agent_tests/utilization/README.md +13 -0
  29. data/test/fixtures/cross_agent_tests/utilization/utilization_json.json +132 -0
  30. data/test/multiverse/suites/agent_only/agent_attributes_test.rb +82 -0
  31. data/test/multiverse/suites/agent_only/utilization_data_collection_test.rb +2 -9
  32. data/test/multiverse/suites/rails/Envfile +1 -1
  33. data/test/multiverse/suites/rails/action_cable_test.rb +81 -0
  34. data/test/new_relic/agent/agent_test.rb +0 -1
  35. data/test/new_relic/agent/hash_extensions_test.rb +26 -1
  36. data/test/new_relic/agent/instrumentation/action_cable_subscriber_test.rb +124 -0
  37. data/test/new_relic/agent/method_tracer_test.rb +0 -1
  38. data/test/new_relic/agent/new_relic_service/json_marshaller_test.rb +27 -0
  39. data/test/new_relic/agent/utilization_data_test.rb +86 -0
  40. metadata +10 -4
  41. data/lib/new_relic/agent/transction_event_recorder.rb +0 -35
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3e8eefedf383e69a41a5dfb8f9c607a8c93f3390
4
- data.tar.gz: 4aa588cdb66a876439bc666ab40a5dd8bb829a50
3
+ metadata.gz: 65e448cfa30a9ec08c2cafdeef4b85d91a4ab36b
4
+ data.tar.gz: 6ce77fbb0850fdd68d403672df4544c81c1c1937
5
5
  SHA512:
6
- metadata.gz: aa28051c2fe6daef0a6adbbb71cb884da9ecb83ec26835ad6e5de7ddbbfd43180bdd220669ca226dbba226668b7f9e1c56274ecc01e0fe3dd9af7a0db901f9da
7
- data.tar.gz: 6e9e0e4b9183378f59fab486acf5ca1eeae547f0850f6657ba50cf3df7122a9a665bfb5ce4207439c345775286516ac7c48baf3958a9182715cbe68c6ff490a4
6
+ metadata.gz: e5b765cb31305ef2f4e1faffe2f715a8a89c39320d21baa7d375f8c4c88d7fabd8d104b8933727ca4750fd51080d92d9c0ee361486fe40ba5e3900602137efc4
7
+ data.tar.gz: 6722c3012daab68738f96f5237bdbb72a18f972ba799b5e8046179d9a42f9dfbfed8e67c8382cf22e4a923748cc547de15134bef2f1c93984ad7c2569fef081c
data/CHANGELOG CHANGED
@@ -1,5 +1,28 @@
1
1
  # New Relic Ruby Agent Release Notes #
2
2
 
3
+ ## v3.16.0
4
+
5
+ * Experimental Action Cable instrumentation
6
+
7
+ The Ruby agent instruments Action Cable channel actions and calls to
8
+ ActionCable::Channel#Transmit in Rails 5 RC1. Feedback is welcome!
9
+
10
+ * Obfuscate queries from `oracle_enhanced` adapter correctly
11
+
12
+ This change allows the `oracle_enhanced` adapter to use the same
13
+ obfuscation as `oracle` adapters. Thanks Dan Drinkard for the contribution!
14
+
15
+ * Make it possible to define a newrelic_role for deployment with Capistrano 3
16
+
17
+ Thanks NielsKSchjoedt for the contribution!
18
+
19
+ * Retry initial connection to New Relic in Resque master if needed
20
+
21
+ Previously, if the initial connection to New Relic in a monitored Resque
22
+ master process failed, the agent would not retry, and monitoring for the
23
+ process would be lost. This has been fixed, and the agent will continue
24
+ retrying in its background harvest thread until it successfully connects.
25
+
3
26
  ## v3.15.2 ##
4
27
 
5
28
  * Run explain plans on parameterized slow queries in AR4
@@ -286,9 +286,6 @@ module NewRelic
286
286
  #
287
287
  def manual_start(options={})
288
288
  raise "Options must be a hash" unless Hash === options
289
- if options[:start_channel_listener]
290
- NewRelic::Agent::PipeChannelManager.listener.start
291
- end
292
289
  NewRelic::Control.instance.init_plugin({ :agent_enabled => true, :sync_startup => true }.merge(options))
293
290
  end
294
291
 
@@ -730,8 +730,8 @@ module NewRelic
730
730
  # number of attempts we've made to contact the server
731
731
  attr_accessor :connect_attempts
732
732
 
733
- # Disconnect just sets connected to false, which prevents
734
- # the agent from trying to connect again
733
+ # Disconnect just sets the connect state to disconnected, preventing
734
+ # further retries.
735
735
  def disconnect
736
736
  @connect_state = :disconnected
737
737
  true
@@ -818,24 +818,19 @@ module NewRelic
818
818
  def connect_settings
819
819
  sanitize_environment_report
820
820
 
821
- settings = {
822
- :pid => $$,
823
- :host => local_host,
824
- :display_host => Agent.config[:'process_host.display_name'],
825
- :app_name => Agent.config.app_names,
826
- :language => 'ruby',
827
- :labels => Agent.config.parsed_labels,
821
+ {
822
+ :pid => $$,
823
+ :host => local_host,
824
+ :display_host => Agent.config[:'process_host.display_name'],
825
+ :app_name => Agent.config.app_names,
826
+ :language => 'ruby',
827
+ :labels => Agent.config.parsed_labels,
828
828
  :agent_version => NewRelic::VERSION::STRING,
829
- :environment => @environment_report,
830
- :settings => Agent.config.to_collector_hash,
831
- :high_security => Agent.config[:high_security]
829
+ :environment => @environment_report,
830
+ :settings => Agent.config.to_collector_hash,
831
+ :high_security => Agent.config[:high_security],
832
+ :utilization => UtilizationData.new.to_collector_hash
832
833
  }
833
-
834
- unless Agent.config[:disable_utilization]
835
- settings[:utilization] = UtilizationData.new.to_collector_hash
836
- end
837
-
838
- settings
839
834
  end
840
835
 
841
836
  # Returns connect data passed back from the server
@@ -952,22 +947,24 @@ module NewRelic
952
947
 
953
948
  public :merge_data_for_endpoint
954
949
 
955
- # Connect to the server and validate the license. If successful,
956
- # connected? returns true when finished. If not successful, you can
957
- # keep calling this. Return false if we could not establish a
958
- # connection with the server and we should not retry, such as if
959
- # there's a bad license key.
950
+ # Establish a connection to New Relic servers.
951
+ #
952
+ # By default, if a connection has already been established, this method
953
+ # will be a no-op.
960
954
  #
961
- # Set keep_retrying=false to disable retrying and return asap, such as when
962
- # invoked in the foreground. Otherwise this runs until a successful
963
- # connection is made, or the server rejects us.
955
+ # @param [Hash] options
956
+ # @option options [Boolean] :keep_retrying (true)
957
+ # If true, this method will block until a connection is successfully
958
+ # established, continuing to retry upon failure. If false, this method
959
+ # will return after either successfully connecting, or after failing
960
+ # once.
961
+ #
962
+ # @option options [Boolean] :force_reconnect (false)
963
+ # If true, this method will force establishment of a new connection
964
+ # with New Relic, even if there is already an existing connection.
965
+ # This is useful primarily when re-establishing a new connection after
966
+ # forking off from a parent process.
964
967
  #
965
- # * <tt>:keep_retrying => false</tt> to only try to connect once, and
966
- # return with the connection set to nil. This ensures we may try again
967
- # later (default true).
968
- # * <tt>force_reconnect => true</tt> if you want to establish a new connection
969
- # to the server before running the worker loop. This means you get a separate
970
- # agent run and New Relic sees it as a separate instance (default is false).
971
968
  def connect(options={})
972
969
  defaults = {
973
970
  :keep_retrying => Agent.config[:keep_retrying],
@@ -995,8 +992,6 @@ module NewRelic
995
992
  ::NewRelic::Agent.logger.info "Will re-attempt in #{connect_retry_period} seconds"
996
993
  sleep connect_retry_period
997
994
  retry
998
- else
999
- disconnect
1000
995
  end
1001
996
  rescue Exception => e
1002
997
  ::NewRelic::Agent.logger.error "Exception of unexpected type during Agent#connect():", e
@@ -101,6 +101,8 @@ module NewRelic
101
101
  build_rule(config[:'transaction_events.attributes.include'], DST_TRANSACTION_EVENTS, true)
102
102
  build_rule(config[:'error_collector.attributes.include'], DST_ERROR_COLLECTOR, true)
103
103
  build_rule(config[:'browser_monitoring.attributes.include'], DST_BROWSER_MONITORING, true)
104
+ # This agent attribute has unexpected behaviors and we need to ensure it only goes where directed in configuration
105
+ build_rule(['request_uri'], DST_TRANSACTION_TRACER | DST_ERROR_COLLECTOR, false)
104
106
 
105
107
  @rules.sort!
106
108
 
@@ -515,6 +515,27 @@ module NewRelic
515
515
  :allowed_from_server => true,
516
516
  :description => 'Maximum number of bytes to send to the New Relic data collection service.'
517
517
  },
518
+ :put_for_data_send => {
519
+ :default => false,
520
+ :public => false,
521
+ :type => Boolean,
522
+ :allowed_from_server => false,
523
+ :description => 'Use HTTP PUT requests instead of POST.'
524
+ },
525
+ :compressed_content_encoding => {
526
+ :default => 'deflate',
527
+ :public => false,
528
+ :type => String,
529
+ :allowed_from_server => false,
530
+ :description => 'Encoding to use if data needs to be compressed. The options are deflate and gzip.'
531
+ },
532
+ :simple_compression => {
533
+ :default => false,
534
+ :public => false,
535
+ :type => Boolean,
536
+ :allowed_from_server => false,
537
+ :description => 'When enabled the agent will compress payloads destined for the collector, but will not pre-compress parts of the payload.'
538
+ },
518
539
  :timeout => {
519
540
  :default => 2 * 60, # 2 minutes
520
541
  :public => true,
@@ -694,6 +715,14 @@ module NewRelic
694
715
  :allowed_from_server => false,
695
716
  :description => 'If <code>true</code>, disables ActiveJob instrumentation.'
696
717
  },
718
+ :disable_action_cable_instrumentation => {
719
+ :default => false,
720
+ :public => true,
721
+ :type => Boolean,
722
+ :dynamic_name => true,
723
+ :allowed_from_server => false,
724
+ :description => 'If <code>true</code>, disables Action Cable instrumentation.'
725
+ },
697
726
  :disable_memcached => {
698
727
  :default => value_of(:disable_memcache_instrumentation),
699
728
  :public => true,
@@ -1542,12 +1571,29 @@ module NewRelic
1542
1571
  :allowed_from_server => false,
1543
1572
  :description => 'If <code>true</code>, the agent automatically detects that it is running in Docker.'
1544
1573
  },
1545
- :'disable_utilization' => {
1546
- :default => false,
1574
+ :'utilization.billing_hostname' => {
1575
+ :default => nil,
1576
+ :allow_nil => true,
1547
1577
  :public => false,
1548
- :type => Boolean,
1578
+ :type => String,
1579
+ :allowed_from_server => false,
1580
+ :description => 'The configured server name by a customer.'
1581
+ },
1582
+ :'utilization.logical_processors' => {
1583
+ :default => nil,
1584
+ :allow_nil => true,
1585
+ :public => false,
1586
+ :type => Fixnum,
1587
+ :allowed_from_server => false,
1588
+ :description => 'The total number of hyper-threaded execution contexts available.'
1589
+ },
1590
+ :'utilization.total_ram_mib' => {
1591
+ :default => nil,
1592
+ :allow_nil => true,
1593
+ :public => false,
1594
+ :type => Fixnum,
1549
1595
  :allowed_from_server => false,
1550
- :description => 'Disable sending utilization data as part of connect settings hash.'
1596
+ :description => 'This value represents the total amount of memory available to the host (not the process), in mebibytes (1024 squared or 1,048,576 bytes).'
1551
1597
  }
1552
1598
  }.freeze
1553
1599
  end
@@ -44,7 +44,8 @@ module NewRelic
44
44
  :postgres => /'|\/\*|\*\/|\$(?!\?)/,
45
45
  :sqlite => /'|\/\*|\*\//,
46
46
  :cassandra => /'|\/\*|\*\//,
47
- :oracle => /'|\/\*|\*\//
47
+ :oracle => /'|\/\*|\*\//,
48
+ :oracle_enhanced => /'|\/\*|\*\//
48
49
  }
49
50
 
50
51
  PLACEHOLDER = '?'.freeze
@@ -75,7 +76,7 @@ module NewRelic
75
76
  regex = POSTGRES_COMPONENTS_REGEX
76
77
  when :sqlite
77
78
  regex = SQLITE_COMPONENTS_REGEX
78
- when :oracle
79
+ when :oracle, :oracle_enhanced
79
80
  regex = ORACLE_COMPONENTS_REGEX
80
81
  when :cassandra
81
82
  regex = CASSANDRA_COMPONENTS_REGEX
@@ -21,6 +21,21 @@ module NewRelic
21
21
  object
22
22
  end
23
23
  end
24
+
25
+ # recurses through hashes and arrays and symbolizes keys
26
+ def symbolize_keys_in_object(object)
27
+ case object
28
+ when Hash
29
+ object.inject({}) do |memo, (k, v)|
30
+ memo[k.to_sym] = symbolize_keys_in_object(v)
31
+ memo
32
+ end
33
+ when Array
34
+ object.map {|o| symbolize_keys_in_object(o)}
35
+ else
36
+ object
37
+ end
38
+ end
24
39
  end
25
40
  end
26
- end
41
+ end
@@ -0,0 +1,82 @@
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
+ require 'new_relic/agent/instrumentation/evented_subscriber'
5
+
6
+ module NewRelic
7
+ module Agent
8
+ module Instrumentation
9
+ class ActionCableSubscriber < EventedSubscriber
10
+
11
+ PERFORM_ACTION = 'perform_action.action_cable'.freeze
12
+
13
+ def start name, id, payload #THREAD_LOCAL_ACCESS
14
+ state = NewRelic::Agent::TransactionState.tl_get
15
+ return unless state.is_execution_traced?
16
+ event = super
17
+ if event.name == PERFORM_ACTION
18
+ start_transaction state, event
19
+ else
20
+ start_recording_metrics state, event
21
+ end
22
+ rescue => e
23
+ log_notification_error e, name, 'start'
24
+ end
25
+
26
+ def finish name, id, payload #THREAD_LOCAL_ACCESS
27
+ state = NewRelic::Agent::TransactionState.tl_get
28
+ return unless state.is_execution_traced?
29
+ event = super
30
+ notice_error payload if payload.key? :exception
31
+ if event.name == PERFORM_ACTION
32
+ finish_transaction state
33
+ else
34
+ stop_recording_metrics state, event
35
+ end
36
+ rescue => e
37
+ log_notification_error e, name, 'finish'
38
+ end
39
+
40
+ private
41
+
42
+ def start_transaction state, event
43
+ Transaction.start(state, :action_cable, :transaction_name => transaction_name_from_event(event))
44
+ end
45
+
46
+ def finish_transaction state
47
+ Transaction.stop(state)
48
+ end
49
+
50
+ def start_recording_metrics state, event
51
+ expected_scope = MethodTracerHelpers::trace_execution_scoped_header(state, event.time.to_f)
52
+ event.payload[:expected_scope] = expected_scope
53
+ end
54
+
55
+ def stop_recording_metrics state, event
56
+ expected_scope = event.payload.delete :expected_scope
57
+ metric_name = metric_name_from_event event
58
+ MethodTracerHelpers::trace_execution_scoped_footer(state, event.time.to_f, metric_name, [], expected_scope, {:metric => true}, event.end.to_f)
59
+ end
60
+
61
+ def transaction_name_from_event event
62
+ "Controller/ActionCable/#{event.payload[:channel_class]}/#{event.payload[:action]}"
63
+ end
64
+
65
+ def metric_name_from_event event
66
+ "Ruby/ActionCable/#{event.payload[:channel_class]}/#{action_name_from_event(event)}"
67
+ end
68
+
69
+ DOT_ACTION_CABLE = ".action_cable".freeze
70
+ EMPTY_STRING = "".freeze
71
+
72
+ def action_name_from_event event
73
+ event.name.gsub DOT_ACTION_CABLE, EMPTY_STRING
74
+ end
75
+
76
+ def notice_error payload
77
+ NewRelic::Agent.notice_error payload[:exception_object]
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -228,14 +228,15 @@ module NewRelic
228
228
  def self.prefix_for_category(txn, category = nil)
229
229
  category ||= (txn && txn.category)
230
230
  case category
231
- when :controller then ::NewRelic::Agent::Transaction::CONTROLLER_PREFIX
232
- when :task then ::NewRelic::Agent::Transaction::TASK_PREFIX
233
- when :rack then ::NewRelic::Agent::Transaction::RACK_PREFIX
234
- when :uri then ::NewRelic::Agent::Transaction::CONTROLLER_PREFIX
235
- when :sinatra then ::NewRelic::Agent::Transaction::SINATRA_PREFIX
236
- when :middleware then ::NewRelic::Agent::Transaction::MIDDLEWARE_PREFIX
237
- when :grape then ::NewRelic::Agent::Transaction::GRAPE_PREFIX
238
- when :rake then ::NewRelic::Agent::Transaction::RAKE_PREFIX
231
+ when :controller then ::NewRelic::Agent::Transaction::CONTROLLER_PREFIX
232
+ when :task then ::NewRelic::Agent::Transaction::TASK_PREFIX
233
+ when :rack then ::NewRelic::Agent::Transaction::RACK_PREFIX
234
+ when :uri then ::NewRelic::Agent::Transaction::CONTROLLER_PREFIX
235
+ when :sinatra then ::NewRelic::Agent::Transaction::SINATRA_PREFIX
236
+ when :middleware then ::NewRelic::Agent::Transaction::MIDDLEWARE_PREFIX
237
+ when :grape then ::NewRelic::Agent::Transaction::GRAPE_PREFIX
238
+ when :rake then ::NewRelic::Agent::Transaction::RAKE_PREFIX
239
+ when :action_cable then ::NewRelic::Agent::Transaction::ACTION_CABLE_PREFIX
239
240
  else "#{category.to_s}/" # for internal use only
240
241
  end
241
242
  end
@@ -0,0 +1,29 @@
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
+ require 'new_relic/agent/instrumentation/action_cable_subscriber'
5
+
6
+ DependencyDetection.defer do
7
+ @name = :rails5_action_cable
8
+
9
+ depends_on do
10
+ defined?(::Rails) &&
11
+ ::Rails::VERSION::MAJOR.to_i == 5 &&
12
+ defined?(::ActionCable)
13
+ end
14
+
15
+ depends_on do
16
+ !NewRelic::Agent.config[:disable_action_cable_instrumentation] &&
17
+ !NewRelic::Agent::Instrumentation::ActionCableSubscriber.subscribed?
18
+ end
19
+
20
+ executes do
21
+ ::NewRelic::Agent.logger.info 'Installing Rails 5 Action Cable instrumentation'
22
+ end
23
+
24
+ executes do
25
+ # enumerate the specific events we want so that we do not get unexpected additions in the future
26
+ ActiveSupport::Notifications.subscribe(/(perform_action|transmit)\.action_cable/,
27
+ NewRelic::Agent::Instrumentation::ActionCableSubscriber.new)
28
+ end
29
+ end
@@ -164,8 +164,12 @@ module NewRelic
164
164
  def compress_request_if_needed(data)
165
165
  encoding = 'identity'
166
166
  if data.size > 64 * 1024
167
- data = Encoders::Compressed.encode(data)
168
- encoding = 'deflate'
167
+ encoding = Agent.config[:compressed_content_encoding]
168
+ data = if encoding == 'gzip'
169
+ Encoders::Compressed::Gzip.encode(data)
170
+ else
171
+ Encoders::Compressed::Deflate.encode(data)
172
+ end
169
173
  end
170
174
  check_post_size(data)
171
175
  [data, encoding]
@@ -432,7 +436,11 @@ module NewRelic
432
436
  # contact
433
437
  # - :data => the data to send as the body of the request
434
438
  def send_request(opts)
435
- request = Net::HTTP::Post.new(opts[:uri], 'CONTENT-ENCODING' => opts[:encoding], 'HOST' => opts[:collector].name)
439
+ if Agent.config[:put_for_data_send]
440
+ request = Net::HTTP::Put.new(opts[:uri], 'CONTENT-ENCODING' => opts[:encoding], 'HOST' => opts[:collector].name)
441
+ else
442
+ request = Net::HTTP::Post.new(opts[:uri], 'CONTENT-ENCODING' => opts[:encoding], 'HOST' => opts[:collector].name)
443
+ end
436
444
  request['user-agent'] = user_agent
437
445
  request.content_type = "application/octet-stream"
438
446
  request.body = opts[:data]
@@ -444,7 +452,7 @@ module NewRelic
444
452
  begin
445
453
  attempts += 1
446
454
  conn = http_connection
447
- ::NewRelic::Agent.logger.debug "Sending request to #{opts[:collector]}#{opts[:uri]}"
455
+ ::NewRelic::Agent.logger.debug "Sending request to #{opts[:collector]}#{opts[:uri]} with #{request.method}"
448
456
  NewRelic::TimerLib.timeout(@request_timeout) do
449
457
  response = conn.request(request)
450
458
  end