newrelic_rpm 7.0.0 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -84,8 +84,6 @@ module NewRelic
84
84
  end
85
85
 
86
86
  def active_record_config(payload)
87
- return unless payload[:connection_id]
88
-
89
87
  # handle if the notification payload provides the AR connection
90
88
  # available in Rails 6+ & our ActiveRecordNotifications#log extension
91
89
  if payload[:connection]
@@ -93,8 +91,8 @@ module NewRelic
93
91
  return connection_config if connection_config
94
92
  end
95
93
 
94
+ return unless connection_id = payload[:connection_id]
96
95
  connection = nil
97
- connection_id = payload[:connection_id]
98
96
 
99
97
  ::ActiveRecord::Base.connection_handler.connection_pool_list.each do |handler|
100
98
  connection = handler.connections.detect do |conn|
@@ -179,6 +179,7 @@ module NewRelic
179
179
  #{without_method_name}(*args, &block)
180
180
  end
181
181
  end
182
+ ruby2_keywords(:#{with_method_name}) if respond_to?(:ruby2_keywords, true)
182
183
  EOC
183
184
 
184
185
  visibility = NewRelic::Helper.instance_method_visibility self, method
@@ -17,8 +17,13 @@ DependencyDetection.defer do
17
17
  require 'new_relic/agent/http_clients/net_http_wrappers'
18
18
  end
19
19
 
20
+ # Airbrake uses method chaining on Net::HTTP in versions < 10.0.2 (10.0.2 updated to prepend for Net:HTTP)
20
21
  conflicts_with_prepend do
21
- defined?(::Airbrake)
22
+ defined?(::Airbrake) && defined?(::Airbrake::AIRBRAKE_VERSION) && ::Gem::Version.create(::Airbrake::AIRBRAKE_VERSION) < ::Gem::Version.create('10.0.2')
23
+ end
24
+
25
+ conflicts_with_prepend do
26
+ defined?(::ScoutApm)
22
27
  end
23
28
 
24
29
  conflicts_with_prepend do
@@ -18,6 +18,10 @@ DependencyDetection.defer do
18
18
  defined?(::Redis) && defined?(::Redis::VERSION)
19
19
  end
20
20
 
21
+ conflicts_with_prepend do
22
+ defined?(::PrometheusExporter)
23
+ end
24
+
21
25
  depends_on do
22
26
  NewRelic::Agent::Datastores::Redis.is_supported_version? &&
23
27
  NewRelic::Agent::Datastores::Redis.safe_from_third_party_gem?
@@ -13,6 +13,11 @@ DependencyDetection.defer do
13
13
  defined?(::Resque::Job) && !NewRelic::Agent.config[:disable_resque]
14
14
  end
15
15
 
16
+ # Airbrake uses method chaining on Resque::Job
17
+ conflicts_with_prepend do
18
+ defined?(::Airbrake)
19
+ end
20
+
16
21
  executes do
17
22
  ::NewRelic::Agent.logger.info 'Installing Resque instrumentation'
18
23
  end
@@ -32,7 +37,7 @@ DependencyDetection.defer do
32
37
  chain_instrument NewRelic::Agent::Instrumentation::Resque::Chain
33
38
  end
34
39
 
35
- if NewRelic::LanguageSupport.can_fork?
40
+ if NewRelic::Agent::Instrumentation::Resque::Helper.resque_fork_per_job?
36
41
  ::Resque.before_first_fork do
37
42
  NewRelic::Agent.manual_start(:dispatcher => :resque,
38
43
  :sync_startup => true,
@@ -40,9 +45,7 @@ DependencyDetection.defer do
40
45
  end
41
46
 
42
47
  ::Resque.before_fork do |job|
43
- if ENV['FORK_PER_JOB'] != 'false'
44
- NewRelic::Agent.register_report_channel(job.object_id)
45
- end
48
+ NewRelic::Agent.register_report_channel(job.object_id)
46
49
  end
47
50
 
48
51
  ::Resque.after_fork do |job|
@@ -51,6 +54,12 @@ DependencyDetection.defer do
51
54
  NewRelic::Agent.after_fork(:report_to_channel => job.object_id,
52
55
  :report_instance_busy => false)
53
56
  end
57
+ else
58
+ ::Resque.before_first_fork do
59
+ NewRelic::Agent.manual_start(:dispatcher => :resque,
60
+ :sync_startup => true,
61
+ :start_channel_listener => false)
62
+ end
54
63
  end
55
64
  end
56
65
  end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module Instrumentation
8
+ module Resque
9
+ module Helper
10
+ extend self
11
+
12
+ def resque_fork_per_job?
13
+ ENV["FORK_PER_JOB"] != 'false' && NewRelic::LanguageSupport.can_fork?
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -6,7 +6,7 @@
6
6
  module NewRelic::Agent::Instrumentation
7
7
  module Resque
8
8
  include NewRelic::Agent::Instrumentation::ControllerInstrumentation
9
-
9
+
10
10
  def with_tracing
11
11
  begin
12
12
  perform_action_with_newrelic_trace(
@@ -24,8 +24,10 @@ module NewRelic::Agent::Instrumentation
24
24
  ensure
25
25
  # Stopping the event loop before flushing the pipe.
26
26
  # The goal is to avoid conflict during write.
27
- NewRelic::Agent.agent.stop_event_loop
28
- NewRelic::Agent.agent.flush_pipe_data
27
+ if NewRelic::Agent::Instrumentation::Resque::Helper.resque_fork_per_job?
28
+ NewRelic::Agent.agent.stop_event_loop
29
+ NewRelic::Agent.agent.flush_pipe_data
30
+ end
29
31
  end
30
32
  end
31
33
 
@@ -39,9 +39,15 @@ module NewRelic::Agent::Instrumentation
39
39
  yield
40
40
  end
41
41
 
42
+ def install_lock
43
+ @install_lock ||= Mutex.new
44
+ end
45
+
42
46
  def try_to_use(app, clazz)
43
- has_middleware = app.middleware.any? { |info| info[0] == clazz }
44
- app.use(clazz) unless has_middleware
47
+ install_lock.synchronize do
48
+ has_middleware = app.middleware && app.middleware.any? { |info| info && info[0] == clazz }
49
+ app.use(clazz) unless has_middleware
50
+ end
45
51
  end
46
52
 
47
53
  # Capture last route we've seen. Will set for transaction on route_eval
@@ -83,39 +83,44 @@ module NewRelic
83
83
  value.nil? || value.empty?
84
84
  end
85
85
 
86
- def browser_timing_header #THREAD_LOCAL_ACCESS
86
+ def browser_timing_header(nonce=nil) #THREAD_LOCAL_ACCESS
87
87
  return '' unless js_enabled_and_ready? # fast exit
88
88
 
89
89
  state = NewRelic::Agent::Tracer.state
90
90
 
91
91
  return '' unless insert_js?(state) # slower exit
92
92
 
93
- bt_config = browser_timing_config(state)
93
+ bt_config = browser_timing_config(state, nonce)
94
94
  return '' if bt_config.empty?
95
95
 
96
- bt_config + browser_timing_loader
96
+ bt_config + browser_timing_loader(nonce)
97
97
  rescue => e
98
98
  ::NewRelic::Agent.logger.debug "Failure during RUM browser_timing_header construction", e
99
99
  ''
100
100
  end
101
101
 
102
- def browser_timing_loader
103
- html_safe_if_needed("\n<script>#{Agent.config[:js_agent_loader]}</script>")
102
+ def browser_timing_loader(nonce=nil)
103
+ html_safe_if_needed("\n<script type=\"text/javascript\"#{create_nonce(nonce)}>#{Agent.config[:js_agent_loader]}</script>")
104
104
  end
105
105
 
106
- def browser_timing_config(state)
106
+ def browser_timing_config(state, nonce=nil)
107
107
  txn = state.current_transaction
108
108
  return '' if txn.nil?
109
109
 
110
110
  txn.freeze_name_and_execute_if_not_ignored do
111
111
  data = data_for_js_agent(txn)
112
112
  json = ::JSON.dump(data)
113
- return html_safe_if_needed("\n<script>window.NREUM||(NREUM={});NREUM.info=#{json}</script>")
113
+ return html_safe_if_needed("\n<script type=\"text/javascript\"#{create_nonce(nonce)}>window.NREUM||(NREUM={});NREUM.info=#{json}</script>")
114
114
  end
115
115
 
116
116
  ''
117
117
  end
118
118
 
119
+ def create_nonce(nonce=nil)
120
+ return '' unless nonce
121
+ " nonce=\"#{nonce.to_s}\""
122
+ end
123
+
119
124
  BEACON_KEY = "beacon".freeze
120
125
  ERROR_BEACON_KEY = "errorBeacon".freeze
121
126
  LICENSE_KEY_KEY = "licenseKey".freeze
@@ -426,7 +426,18 @@ module NewRelic
426
426
  size = data.size
427
427
 
428
428
  # Preconnect needs to always use the configured collector host, not the redirect host
429
- endpoint_specific_collector = (method == :preconnect) ? @configured_collector : @collector
429
+ # endpoint_specific_collector = (method == :preconnect) ? @configured_collector : @collector
430
+
431
+ # This is a temporary workaround due to errors occurring on the staging collector. The prod collector does not have the same issue.
432
+ # The staging collector does not respond correctly when using the configured collector host for preconnect, so must use the redirect host
433
+ # Once this issue is resolved on the staging collector, use the original line that is commented out above.
434
+ endpoint_specific_collector = if method == :preconnect && (@configured_collector && @configured_collector.name != 'staging-collector.newrelic.com')
435
+ ::NewRelic::Agent.logger.debug "Using configured collector for preconnect: #{@configured_collector}"
436
+ @configured_collector
437
+ else
438
+ ::NewRelic::Agent.logger.debug "Using redirect host for collector: #{@collector}"
439
+ @collector
440
+ end
430
441
 
431
442
  uri = remote_method_uri(method)
432
443
  full_uri = "#{endpoint_specific_collector}#{uri}"
@@ -359,10 +359,10 @@ module NewRelic
359
359
  # need to hash the same way in every process, to be able to aggregate slow SQL traces
360
360
  def consistent_hash(string)
361
361
  if NewRelic::Agent.config[:'slow_sql.use_longer_sql_id']
362
- Digest::MD5.hexdigest(string).hex.modulo(2**63-1)
362
+ Digest::SHA1.hexdigest(string).hex.modulo(2**63-1)
363
363
  else
364
364
  # from when sql_id needed to fit in an INT(11)
365
- Digest::MD5.hexdigest(string).hex.modulo(2**31-1)
365
+ Digest::SHA1.hexdigest(string).hex.modulo(2**31-1)
366
366
  end
367
367
  end
368
368
  end
@@ -11,7 +11,7 @@ module NewRelic
11
11
  end
12
12
 
13
13
  MAJOR = 7
14
- MINOR = 0
14
+ MINOR = 1
15
15
  TINY = 0
16
16
 
17
17
  begin
@@ -1,32 +1,21 @@
1
1
  <% sections.each do |(section_key, section_name, section_description, configs)| %>
2
- <h2 id="<%=section_key%>"><%=section_name%></h2>
2
+ ## <%=section_name%>
3
3
 
4
- <%= "<p>#{section_description}</p>" unless section_description.nil? %>
4
+ <%= "#{section_description}" unless section_description.nil? %>
5
5
 
6
- <dl class="clamshell-list">
6
+ <CollapserGroup>
7
7
  <% configs.each do |config|%>
8
- <!-- ********** <%= config[:key] %> ********** -->
9
- <dt id="<%= config[:key].gsub('.', '-') %>"><%=config[:key]%></dt>
10
- <dd>
11
- <table class="specs">
12
- <tbody>
13
- <tr>
14
- <th>Type</th>
15
- <td><%=config[:type]%></td>
16
- </tr>
17
- <tr>
18
- <th>Default</th>
19
- <td><%=config[:default]%></td>
20
- </tr>
21
- <tr>
22
- <th>Environ variable</th>
23
- <td><code><%=config[:env_var]%></code></td>
24
- </tr>
25
- </tbody>
26
- </table>
8
+ <Collapser id="<%= config[:key].gsub('.', '-') %>" title="<%=config[:key]%>">
9
+ <table>
10
+ <tbody>
11
+ <tr><th>Type</th><td><%=config[:type]%></td></tr>
12
+ <tr><th>Default</th><td>`<%=config[:default]%>`</td></tr>
13
+ <tr><th>Environ variable</th><td>`<%=config[:env_var]%>`</td></tr>
14
+ </tbody>
15
+ </table>
27
16
 
28
- <p><%=config[:description]%></p>
29
- </dd>
17
+ <%=config[:description]%>
18
+ </Collapser>
30
19
  <% end %>
31
- </dl>
20
+ </CollapserGroup>
32
21
  <% end %>
@@ -9,11 +9,11 @@ namespace :newrelic do
9
9
  SECTION_DESCRIPTIONS = {
10
10
  GENERAL => 'These settings are available for agent configuration. Some settings depend on your New Relic subscription level.',
11
11
  DISABLING => 'Use these settings to toggle instrumentation types during agent startup.',
12
- ATTRIBUTES => '<a href="https://docs.newrelic.com/docs/features/agent-attributes">Attributes</a> are key-value pairs containing information that determines the properties of an event or transaction. These key-value pairs can be viewed within transaction traces in New Relic APM, traced errors in New Relic APM, transaction events in Insights, and page views in Insights. You can customize exactly which attributes will be sent to each of these destinations.',
13
- "transaction_tracer" => 'The <a href="/docs/apm/traces/transaction-traces/transaction-traces">transaction traces</a> feature collects detailed information from a selection of transactions, including a summary of the calling sequence, a breakdown of time spent, and a list of SQL queries and their query plans (on mysql and postgresql). Available features depend on your New Relic subscription level.',
12
+ ATTRIBUTES => '[Attributes](/docs/features/agent-attributes) are key-value pairs containing information that determines the properties of an event or transaction. These key-value pairs can be viewed within transaction traces in APM, traced errors in APM, transaction events in dashboards, and page views in dashboards. You can customize exactly which attributes will be sent to each of these destinations',
13
+ "transaction_tracer" => 'The [transaction traces](/docs/apm/traces/transaction-traces/transaction-traces) feature collects detailed information from a selection of transactions, including a summary of the calling sequence, a breakdown of time spent, and a list of SQL queries and their query plans (on mysql and postgresql). Available features depend on your New Relic subscription level.',
14
14
  "error_collector" => 'The agent collects and reports all uncaught exceptions by default. These configuration options allow you to customize the error collection.',
15
- "browser_monitoring" => 'New Relic Browser\'s <a href="/docs/browser/new-relic-browser/page-load-timing/page-load-timing-process">page load timing</a> feature (sometimes referred to as real user monitoring or RUM) gives you insight into the performance real users are experiencing with your website. This is accomplished by measuring the time it takes for your users\' browsers to download and render your web pages by injecting a small amount of JavaScript code into the header and footer of each page.',
16
- "analytics_events" => '<a href="/docs/insights/new-relic-insights/understanding-insights/new-relic-insights">New Relic Insights</a> is a software analytics resource to gather and visualize data about your software and what it says about your business. With it you can quickly and easily create real-time dashboards to get immediate answers about end-user experiences, clickstreams, mobile activities, and server transactions.'
15
+ "browser_monitoring" => 'The Browser monitoring [page load timing](/docs/browser/new-relic-browser/page-load-timing/page-load-timing-process) feature (sometimes referred to as real user monitoring or RUM) gives you insight into the performance real users are experiencing with your website. This is accomplished by measuring the time it takes for your users\' browsers to download and render your web pages by injecting a small amount of JavaScript code into the header and footer of each page.',
16
+ "analytics_events" => '[New Relic dashboards](/docs/query-your-data/explore-query-data/dashboards/introduction-new-relic-one-dashboards) is a resource to gather and visualize data about your software and what it says about your business. With it you can quickly and easily create real-time dashboards to get immediate answers about end-user experiences, clickstreams, mobile activities, and server transactions.'
17
17
  }
18
18
 
19
19
  NAME_OVERRIDES = {
@@ -96,8 +96,9 @@ namespace :newrelic do
96
96
  end
97
97
 
98
98
  def format_description(value)
99
- description = value[:description]
100
- description = "<b>DEPRECATED</b> #{description}" if value[:deprecated]
99
+ description = ''
100
+ description += "<b>DEPRECATED</b> " if value[:deprecated]
101
+ description += value[:description]
101
102
  description
102
103
  end
103
104
 
@@ -105,7 +106,7 @@ namespace :newrelic do
105
106
  if spec[:default].is_a?(Proc)
106
107
  '(Dynamic)'
107
108
  else
108
- "<code>#{spec[:default].inspect}</code>"
109
+ "#{spec[:default].inspect}"
109
110
  end
110
111
  end
111
112
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: newrelic_rpm
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.0
4
+ version: 7.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Huntsman
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-04-23 00:00:00.000000000 Z
13
+ date: 2021-06-03 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
@@ -385,6 +385,7 @@ files:
385
385
  - lib/new_relic/agent/instrumentation/redis/prepend.rb
386
386
  - lib/new_relic/agent/instrumentation/resque.rb
387
387
  - lib/new_relic/agent/instrumentation/resque/chain.rb
388
+ - lib/new_relic/agent/instrumentation/resque/helper.rb
388
389
  - lib/new_relic/agent/instrumentation/resque/instrumentation.rb
389
390
  - lib/new_relic/agent/instrumentation/resque/prepend.rb
390
391
  - lib/new_relic/agent/instrumentation/sequel.rb