newrelic_rpm 9.3.1 → 9.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -1
  3. data/README.md +4 -0
  4. data/lib/new_relic/agent/configuration/default_source.rb +25 -2
  5. data/lib/new_relic/agent/configuration/environment_source.rb +1 -1
  6. data/lib/new_relic/agent/instrumentation/action_controller_other_subscriber.rb +1 -1
  7. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +1 -2
  8. data/lib/new_relic/agent/instrumentation/memcache.rb +2 -2
  9. data/lib/new_relic/agent/instrumentation/queue_time.rb +1 -1
  10. data/lib/new_relic/agent/instrumentation/roda/chain.rb +43 -0
  11. data/lib/new_relic/agent/instrumentation/roda/instrumentation.rb +52 -0
  12. data/lib/new_relic/agent/instrumentation/roda/prepend.rb +24 -0
  13. data/lib/new_relic/agent/instrumentation/roda/roda_transaction_namer.rb +30 -0
  14. data/lib/new_relic/agent/instrumentation/roda.rb +33 -0
  15. data/lib/new_relic/agent/instrumentation/sequel.rb +1 -1
  16. data/lib/new_relic/agent/log_event_attributes.rb +1 -1
  17. data/lib/new_relic/agent/new_relic_service.rb +33 -17
  18. data/lib/new_relic/agent/pipe_service.rb +1 -1
  19. data/lib/new_relic/agent/tracer.rb +4 -3
  20. data/lib/new_relic/agent/transaction/request_attributes.rb +45 -7
  21. data/lib/new_relic/agent/transaction.rb +5 -4
  22. data/lib/new_relic/agent/utilization/vendor.rb +5 -7
  23. data/lib/new_relic/control/class_methods.rb +1 -7
  24. data/lib/new_relic/control/frameworks/roda.rb +20 -0
  25. data/lib/new_relic/language_support.rb +5 -0
  26. data/lib/new_relic/noticed_error.rb +5 -2
  27. data/lib/new_relic/version.rb +2 -2
  28. data/lib/tasks/bump_version.rake +1 -1
  29. data/lib/tasks/config.rake +3 -2
  30. data/lib/tasks/helpers/config.html.erb +93 -0
  31. data/lib/tasks/helpers/format.rb +11 -7
  32. data/lib/tasks/helpers/version_bump.rb +2 -2
  33. data/lib/tasks/newrelicyml.rake +1 -1
  34. data/newrelic.yml +11 -0
  35. data/newrelic_rpm.gemspec +3 -2
  36. metadata +24 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a1208297462f0c1fa6193688659b805394587801a45b08dd7405f6189bc8c195
4
- data.tar.gz: b0dbfa4168393aa4a86572f693f591a7bd356b59b6ba2c4852c991f7ca6cfd97
3
+ metadata.gz: c8e0198f3fe3562d84248d3be65acdc8e7ae92e0ca27ecaa1023ca2303152464
4
+ data.tar.gz: 6d721589df2371d8d63b96eba38adddff1e534678e19b9adfdf028807233d109
5
5
  SHA512:
6
- metadata.gz: 900feb5ed5bb4b15c526e3149bb4324c50c0a3aeff51cdb4820ba985459fb87e6f4f1e4dad0c35715a445a0a533e58655ecb0be6bf51e5051eb290ff39c5d5aa
7
- data.tar.gz: 748f6043761bfa4e86555fe24b82db22498426959e99dacf56ae7a9d27a1bb8afc759ce9f0720b226054369b9a45a01318f14326ece5bb5ddb0176c18c6c9c6b
6
+ metadata.gz: 5e72bfc0219779d6912631c687d64d896b5becf69be013b35f0a88729ebc444f592d72261b2620d7fdc419b7f3fe0557af56e7e3577a6a482c1cdd4fd19aea7a
7
+ data.tar.gz: 99a8dee22642c178cf8800e1eec28544262c9b09abcfeb9f856495121de33d5fe1e33483e233d41d746d37cb2e0a2377db00a446d80653816dc252967b64b3e1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # New Relic Ruby Agent Release Notes
2
2
 
3
+ ## v9.4.0
4
+
5
+ Version 9.4.0 of the agent adds [Roda](https://roda.jeremyevans.net/) instrumentation, adds a new `allow_all_headers` configuration option to permit capturing all HTTP headers, introduces improved error tracking functionality by associating a transaction id with each error, and uses more reliable network timeout logic.
6
+
7
+ - **Feature: Add Roda instrumentation**
8
+
9
+ [Roda](https://roda.jeremyevans.net/) is a now an instrumented framework. The agent currently supports Roda versions 3.19.0+. [PR#2144](https://github.com/newrelic/newrelic-ruby-agent/pull/2144)
10
+
11
+ - **Feature: New allow_all_headers configuration option**
12
+
13
+ A new `allow_all_headers` configuration option brings parity with the [Node.js agent](https://docs.newrelic.com/docs/release-notes/agent-release-notes/nodejs-release-notes/node-agent-270/) to capture all HTTP request headers.
14
+
15
+ This configuration option:
16
+ * Defaults to `false`
17
+ * Is not compatible with high security mode
18
+ * Requires Rack version 2 or higher (as does Ruby on Rails version 5 and above)
19
+ * Respects all existing behavior for the `attributes.include` and `attributes.exclude` [configuration options](https://docs.newrelic.com/docs/apm/agents/ruby-agent/configuration/ruby-agent-configuration/#attributes)
20
+ * Captures the additional headers as attributes prefixed with `request.headers.`
21
+
22
+ This work was done in response to a feature request submitted by community member [@jamesarosen](https://github.com/jamesarosen). Thank you very much, @jamesarosen! [Issue#1029](https://github.com/newrelic/newrelic-ruby-agent/issues/1029)
23
+
24
+ - **Feature: Improved error tracking transaction linking**
25
+
26
+ Errors tracked and sent to the New Relic errors inbox will now be associated with a transaction id to enable improved UI/UX associations between transactions and errors. [PR#2035](https://github.com/newrelic/newrelic-ruby-agent/pull/2035)
27
+
28
+ - **Feature: Use Net::HTTP native timeout logic**
29
+
30
+ In line with current Ruby best practices, make use of Net::HTTP's own timeout logic and avoid the use of `Timeout.timeout()` when possible. The agent's data transmissions and cloud provider detection routines have been updated accordingly. [PR#2147](https://github.com/newrelic/newrelic-ruby-agent/pull/2147)
31
+
3
32
  ## v9.3.1
4
33
 
5
34
  Version 9.3.1 of the agent fixes `NewRelic::Agent.require_test_helper`.
@@ -14,7 +43,6 @@ Version 9.3.1 of the agent fixes `NewRelic::Agent.require_test_helper`.
14
43
 
15
44
  Community member [@olleolleolle](https://github.com/olleolleolle) noticed that our source code was referencing a now defunct URL for the Rack specification and submitted [PR#2121](https://github.com/newrelic/newrelic-ruby-agent/pull/2121) to update it. He also provided a terrific recommendation that we automate the checking of links to proactively catch defunct ones in future. Thanks, @olleolleolle!
16
45
 
17
-
18
46
  ## v9.3.0
19
47
 
20
48
  Version 9.3.0 of the agent adds log-level filtering, adds custom attributes for log events, and updates instrumentation for Action Cable. It also provides fixes for how `Fiber` args are treated, Code-Level Metrics, unnecessary files being included in the gem, and `NewRelic::Agent::Logging::DecoratingFormatter#clear_tags!` being incorrectly private.
data/README.md CHANGED
@@ -134,6 +134,10 @@ The New Relic Ruby agent may use source code from third-party libraries. When us
134
134
 
135
135
  ## Thank You
136
136
 
137
+ We always look forward to connecting with the community. We welcome [contributions](https://github.com/newrelic/newrelic-ruby-agent#contributing) to our source code and suggestions for improvements, and would love to hear about what you like and want to see in the future.
138
+
139
+ Visit our [project board](https://github.com/orgs/newrelic/projects/84/) to see what's upcoming in a future release, what we're currently working on, and what we're planning next.
140
+
137
141
  Thank you,
138
142
 
139
143
  New Relic Ruby agent team
@@ -24,7 +24,7 @@ module NewRelic
24
24
  # Does not appear in logs.
25
25
  def self.deprecated_description(new_setting, description)
26
26
  link_ref = new_setting.to_s.tr('.', '-')
27
- %{Please see: [#{new_setting}](docs/agents/ruby-agent/configuration/ruby-agent-configuration##{link_ref}). \n\n#{description}}
27
+ %{Please see: [#{new_setting}](##{link_ref}). \n\n#{description}}
28
28
  end
29
29
 
30
30
  class Boolean
@@ -115,6 +115,7 @@ module NewRelic
115
115
  :rails_notifications
116
116
  end
117
117
  when defined?(::Sinatra) && defined?(::Sinatra::Base) then :sinatra
118
+ when defined?(::Roda) then :roda
118
119
  when defined?(::NewRelic::IA) then :external
119
120
  else :ruby
120
121
  end
@@ -818,6 +819,13 @@ module NewRelic
818
819
  :description => 'If `true`, the agent captures metrics related to logging for your application.'
819
820
  },
820
821
  # Attributes
822
+ :'allow_all_headers' => {
823
+ :default => false,
824
+ :public => true,
825
+ :type => Boolean,
826
+ :allowed_from_server => false,
827
+ :description => 'If `true`, enables capture of all HTTP request headers for all destinations.'
828
+ },
821
829
  :'attributes.enabled' => {
822
830
  :default => true,
823
831
  :public => true,
@@ -1042,7 +1050,7 @@ module NewRelic
1042
1050
  :allowed_from_server => true,
1043
1051
  :deprecated => true,
1044
1052
  :description => deprecated_description(
1045
- :'distributed_tracing-enabled',
1053
+ :'distributed_tracing.enabled',
1046
1054
  'If `true`, enables [cross-application tracing](/docs/agents/ruby-agent/features/cross-application-tracing-ruby/) when `distributed_tracing.enabled` is set to `false`.'
1047
1055
  )
1048
1056
  },
@@ -1227,6 +1235,13 @@ module NewRelic
1227
1235
  :allowed_from_server => false,
1228
1236
  :description => 'If `true`, disables [Sidekiq instrumentation](/docs/agents/ruby-agent/background-jobs/sidekiq-instrumentation).'
1229
1237
  },
1238
+ :disable_roda_auto_middleware => {
1239
+ :default => false,
1240
+ :public => true,
1241
+ :type => Boolean,
1242
+ :allowed_from_server => false,
1243
+ :description => 'If `true`, disables agent middleware for Roda. This middleware is responsible for advanced feature support such as [page load timing](/docs/browser/new-relic-browser/getting-started/new-relic-browser) and [error collection](/docs/apm/applications-menu/events/view-apm-error-analytics).'
1244
+ },
1230
1245
  :disable_sinatra_auto_middleware => {
1231
1246
  :default => false,
1232
1247
  :public => true,
@@ -1564,6 +1579,14 @@ module NewRelic
1564
1579
  :allowed_from_server => false,
1565
1580
  :description => 'Controls auto-instrumentation of resque at start up. May be one of: `auto`, `prepend`, `chain`, `disabled`.'
1566
1581
  },
1582
+ :'instrumentation.roda' => {
1583
+ :default => 'auto',
1584
+ :public => true,
1585
+ :type => String,
1586
+ :dynamic_name => true,
1587
+ :allowed_from_server => false,
1588
+ :description => 'Controls auto-instrumentation of Roda at start up. May be one of: `auto`, `prepend`, `chain`, `disabled`.'
1589
+ },
1567
1590
  :'instrumentation.sinatra' => {
1568
1591
  :default => 'auto',
1569
1592
  :public => true,
@@ -101,7 +101,7 @@ module NewRelic
101
101
  end
102
102
  else
103
103
  ::NewRelic::Agent.logger.info("#{environment_key} does not have a corresponding configuration setting (#{config_key} does not exist).")
104
- ::NewRelic::Agent.logger.info('Run `rake newrelic:config:docs` or visit https://newrelic.com/docs/ruby/ruby-agent-configuration to see a list of available configuration settings.')
104
+ ::NewRelic::Agent.logger.info('Run `rake newrelic:config:docs` or visit https://docs.newrelic.com/docs/apm/agents/ruby-agent/configuration/ruby-agent-configuration to see a list of available configuration settings.')
105
105
  self[config_key] = value
106
106
  end
107
107
  end
@@ -23,7 +23,7 @@ module NewRelic
23
23
 
24
24
  def metric_name(name, payload)
25
25
  controller_name = controller_name_for_metric(payload)
26
- "Ruby/ActionController#{"/#{controller_name}" if controller_name}/#{name.gsub(/\.action_controller/, '')}"
26
+ "Ruby/ActionController#{"/#{controller_name}" if controller_name}/#{name.gsub('.action_controller', '')}"
27
27
  end
28
28
 
29
29
  def controller_name_for_metric(payload)
@@ -41,8 +41,6 @@ module NewRelic
41
41
  clazz.extend(ClassMethodsShim)
42
42
  end
43
43
 
44
- def new_relic_trace_controller_action(*args); yield; end
45
-
46
44
  def perform_action_with_newrelic_trace(*args); yield; end
47
45
  end
48
46
 
@@ -245,6 +243,7 @@ module NewRelic
245
243
  when :background then ::NewRelic::Agent::Transaction::TASK_PREFIX
246
244
  when :rack then ::NewRelic::Agent::Transaction::RACK_PREFIX
247
245
  when :uri then ::NewRelic::Agent::Transaction::CONTROLLER_PREFIX
246
+ when :roda then ::NewRelic::Agent::Transaction::RODA_PREFIX
248
247
  when :sinatra then ::NewRelic::Agent::Transaction::SINATRA_PREFIX
249
248
  when :middleware then ::NewRelic::Agent::Transaction::MIDDLEWARE_PREFIX
250
249
  when :grape then ::NewRelic::Agent::Transaction::GRAPE_PREFIX
@@ -5,8 +5,8 @@
5
5
  # NOTE: there are multiple implementations of the Memcached client in Ruby,
6
6
  # each with slightly different APIs and semantics.
7
7
  # See:
8
- # http://www.deveiate.org/code/Ruby-MemCache/ (Gem: Ruby-MemCache)
9
- # http://seattlerb.rubyforge.org/memcache-client/ (Gem: memcache-client)
8
+ # https://rubygems.org/gems/Ruby-MemCache (Gem: Ruby-MemCache)
9
+ # https://github.com/mperham/memcache-client (Gem: memcache-client)
10
10
  # https://github.com/mperham/dalli (Gem: dalli)
11
11
 
12
12
  require_relative 'memcache/helper'
@@ -5,7 +5,7 @@
5
5
  module NewRelic
6
6
  module Agent
7
7
  module Instrumentation
8
- # https://newrelic.com/docs/features/tracking-front-end-time
8
+ # https://docs.newrelic.com/docs/features/tracking-front-end-time
9
9
  # Record queue time metrics based on any of three headers
10
10
  # which can be set on the request.
11
11
  module QueueTime
@@ -0,0 +1,43 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic::Agent::Instrumentation
6
+ module Roda
7
+ module Chain
8
+ def self.instrument!
9
+ ::Roda.class_eval do
10
+ include ::NewRelic::Agent::Instrumentation::Roda::Tracer
11
+
12
+ alias_method(:_roda_handle_main_route_without_tracing, :_roda_handle_main_route)
13
+
14
+ def _roda_handle_main_route(*args)
15
+ _roda_handle_main_route_with_tracing(*args) do
16
+ _roda_handle_main_route_without_tracing(*args)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ module Build
24
+ module Chain
25
+ def self.instrument!
26
+ ::Roda.class_eval do
27
+ include ::NewRelic::Agent::Instrumentation::Roda::Tracer
28
+
29
+ class << self
30
+ alias_method(:build_rack_app_without_tracing, :build_rack_app)
31
+
32
+ def build_rack_app
33
+ build_rack_app_with_tracing do
34
+ build_rack_app_without_tracing
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,52 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic::Agent::Instrumentation
6
+ module Roda
7
+ module Tracer
8
+ include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
9
+
10
+ def self.included(clazz)
11
+ clazz.extend(self)
12
+ end
13
+
14
+ def newrelic_middlewares
15
+ middlewares = [NewRelic::Rack::BrowserMonitoring]
16
+ if NewRelic::Rack::AgentHooks.needed?
17
+ middlewares << NewRelic::Rack::AgentHooks
18
+ end
19
+ middlewares
20
+ end
21
+
22
+ def build_rack_app_with_tracing
23
+ unless NewRelic::Agent.config[:disable_roda_auto_middleware]
24
+ newrelic_middlewares.each do |middleware_class|
25
+ self.use middleware_class
26
+ end
27
+ end
28
+ yield
29
+ end
30
+
31
+ # Roda makes use of Rack, so we can get params from the request object
32
+ def rack_request_params
33
+ begin
34
+ @_request.params
35
+ rescue => e
36
+ NewRelic::Agent.logger.debug('Failed to get params from Rack request.', e)
37
+ NewRelic::EMPTY_HASH
38
+ end
39
+ end
40
+
41
+ def _roda_handle_main_route_with_tracing(*args)
42
+ perform_action_with_newrelic_trace(
43
+ category: :roda,
44
+ name: TransactionNamer.transaction_name(request),
45
+ params: ::NewRelic::Agent::ParameterFiltering::apply_filters(request.env, rack_request_params)
46
+ ) do
47
+ yield
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,24 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic::Agent::Instrumentation
6
+ module Roda
7
+ module Prepend
8
+ include ::NewRelic::Agent::Instrumentation::Roda::Tracer
9
+
10
+ def _roda_handle_main_route(*args)
11
+ _roda_handle_main_route_with_tracing(*args) { super }
12
+ end
13
+ end
14
+
15
+ module Build
16
+ module Prepend
17
+ include ::NewRelic::Agent::Instrumentation::Roda::Tracer
18
+ def build_rack_app
19
+ build_rack_app_with_tracing { super }
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module Instrumentation
8
+ module Roda
9
+ module TransactionNamer
10
+ extend self
11
+
12
+ ROOT = '/'.freeze
13
+ REGEX_MULTIPLE_SLASHES = %r{^[/^\A]*(.*?)[/$?\z]*$}.freeze
14
+
15
+ def transaction_name(request)
16
+ path = request.path || ::NewRelic::Agent::UNKNOWN_METRIC
17
+ name = path.gsub(REGEX_MULTIPLE_SLASHES, '\1') # remove any rogue slashes
18
+ name = ROOT if name.empty?
19
+ name = "#{request.request_method} #{name}" if request.respond_to?(:request_method)
20
+
21
+ name
22
+ rescue => e
23
+ ::NewRelic::Agent.logger.debug("#{e.class} : #{e.message} - Error encountered trying to identify Roda transaction name")
24
+ ::NewRelic::Agent::UNKNOWN_METRIC
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,33 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require_relative 'roda/instrumentation'
6
+
7
+ DependencyDetection.defer do
8
+ named :roda
9
+
10
+ depends_on do
11
+ defined?(Roda) &&
12
+ Gem::Version.new(Roda::RodaVersion) >= Gem::Version.new('3.19.0') &&
13
+ Roda::RodaPlugins::Base::ClassMethods.private_method_defined?(:build_rack_app) &&
14
+ Roda::RodaPlugins::Base::InstanceMethods.method_defined?(:_roda_handle_main_route)
15
+ end
16
+
17
+ executes do
18
+ require_relative '../../rack/agent_hooks'
19
+ require_relative '../../rack/browser_monitoring'
20
+
21
+ NewRelic::Agent.logger.info('Installing Roda instrumentation')
22
+
23
+ if use_prepend?
24
+ require_relative 'roda/prepend'
25
+ prepend_instrument Roda.singleton_class, NewRelic::Agent::Instrumentation::Roda::Build::Prepend
26
+ prepend_instrument Roda, NewRelic::Agent::Instrumentation::Roda::Prepend
27
+ else
28
+ require_relative 'roda/chain'
29
+ chain_instrument NewRelic::Agent::Instrumentation::Roda::Build::Chain
30
+ chain_instrument NewRelic::Agent::Instrumentation::Roda::Chain
31
+ end
32
+ end
33
+ end
@@ -30,7 +30,7 @@ DependencyDetection.defer do
30
30
  else
31
31
  NewRelic::Agent.logger.info('Detected Sequel version %s.' % [Sequel::VERSION])
32
32
  NewRelic::Agent.logger.info('Please see additional documentation: ' +
33
- 'https://newrelic.com/docs/ruby/sequel-instrumentation')
33
+ 'https://docs.newrelic.com/docs/apm/agents/ruby-agent/frameworks/sequel-instrumentation/')
34
34
  end
35
35
 
36
36
  Sequel.synchronize { Sequel::DATABASES.dup }.each do |db|
@@ -10,7 +10,7 @@ module NewRelic
10
10
  ATTRIBUTE_VALUE_CHARACTER_LIMIT = 4094
11
11
 
12
12
  def add_custom_attributes(attributes)
13
- return if @custom_attribute_limit_reached
13
+ return if defined?(@custom_attribute_limit_reached) && @custom_attribute_limit_reached
14
14
 
15
15
  attributes.each do |key, value|
16
16
  next if absent?(key) || absent?(value)
@@ -3,7 +3,6 @@
3
3
  # frozen_string_literal: true
4
4
 
5
5
  require 'zlib'
6
- require 'timeout'
7
6
  require 'new_relic/agent/audit_logger'
8
7
  require 'new_relic/agent/new_relic_service/encoders'
9
8
  require 'new_relic/agent/new_relic_service/marshaller'
@@ -19,7 +18,13 @@ module NewRelic
19
18
 
20
19
  # These include Errno connection errors, and all indicate that the
21
20
  # underlying TCP connection may be in a bad state.
22
- CONNECTION_ERRORS = [Timeout::Error, EOFError, SystemCallError, SocketError].freeze
21
+ CONNECTION_ERRORS = [Net::OpenTimeout, Net::ReadTimeout, EOFError, SystemCallError, SocketError]
22
+ # TODO: MAJOR VERSION - Net::WriteTimeout wasn't defined until Ruby 2.6.
23
+ # Once support for Ruby 2.5 is dropped, we should simply include
24
+ # Net::WriteTimeout in the connection errors array directly instead
25
+ # of with a conditional
26
+ CONNECTION_ERRORS << Net::WriteTimeout if defined?(Net::WriteTimeout)
27
+ CONNECTION_ERRORS.freeze
23
28
 
24
29
  # The maximum number of times to attempt an HTTP request
25
30
  MAX_ATTEMPTS = 2
@@ -319,13 +324,15 @@ module NewRelic
319
324
 
320
325
  def start_connection(conn)
321
326
  NewRelic::Agent.logger.debug("Opening TCP connection to #{conn.address}:#{conn.port}")
322
- Timeout.timeout(@request_timeout) { conn.start }
323
- conn
327
+ conn.start
324
328
  end
325
329
 
326
330
  def setup_connection_timeouts(conn)
327
- # We use Timeout explicitly instead of this
328
- conn.read_timeout = nil
331
+ conn.open_timeout = @request_timeout
332
+ conn.read_timeout = @request_timeout
333
+ # TODO: MAJOR VERSION - #write_timeout= requires Ruby 2.6+, so remove
334
+ # the conditional check once support for Ruby 2.5 is dropped
335
+ conn.write_timeout = @request_timeout if conn.respond_to?(:write_timeout=)
329
336
 
330
337
  if conn.respond_to?(:keep_alive_timeout) && NewRelic::Agent.config[:aggressive_keepalive]
331
338
  conn.keep_alive_timeout = NewRelic::Agent.config[:keep_alive_timeout]
@@ -362,8 +369,8 @@ module NewRelic
362
369
  conn = create_http_connection
363
370
  start_connection(conn)
364
371
  conn
365
- rescue Timeout::Error
366
- ::NewRelic::Agent.logger.info('Timeout while attempting to connect. You may need to install system-level CA Certificates, as the ruby agent no longer includes these.')
372
+ rescue Net::OpenTimeout
373
+ ::NewRelic::Agent.logger.info('Timed out while attempting to connect. For SSL issues, you may need to install system-level CA Certificates to be used by Net::HTTP.')
367
374
  raise
368
375
  end
369
376
 
@@ -436,13 +443,9 @@ module NewRelic
436
443
  end
437
444
 
438
445
  def attempt_request(request, opts)
439
- response = nil
440
446
  conn = http_connection
441
447
  ::NewRelic::Agent.logger.debug("Sending request to #{opts[:collector]}#{opts[:uri]} with #{request.method}")
442
- Timeout.timeout(@request_timeout) do
443
- response = conn.request(request)
444
- end
445
- response
448
+ conn.request(request)
446
449
  end
447
450
 
448
451
  def handle_error_response(response, endpoint)
@@ -450,7 +453,9 @@ module NewRelic
450
453
  when Net::HTTPRequestTimeOut,
451
454
  Net::HTTPTooManyRequests,
452
455
  Net::HTTPInternalServerError,
453
- Net::HTTPServiceUnavailable
456
+ Net::HTTPServiceUnavailable,
457
+ Net::OpenTimeout,
458
+ Net::ReadTimeout
454
459
  handle_server_connection_exception(response, endpoint)
455
460
  when Net::HTTPBadRequest,
456
461
  Net::HTTPForbidden,
@@ -471,9 +476,20 @@ module NewRelic
471
476
  when Net::HTTPGone
472
477
  handle_gone_response(response, endpoint)
473
478
  else
474
- record_endpoint_attempts_supportability_metrics(endpoint)
475
- record_error_response_supportability_metrics(response.code)
476
- raise UnrecoverableServerException, "#{response.code}: #{response.message}"
479
+ # TODO: MAJOR VERSION - Net::WriteTimeout wasn't defined until
480
+ # Ruby 2.6, so it can't be included in the case statement
481
+ # as a constant and instead needs to be found here. Once
482
+ # support for Ruby 2.5 is dropped, we should have
483
+ # Net::WriteTimeout sit in the 'when' clause above alongside
484
+ # Net::OpenTimeout and Net::ReadTimeout and this entire if/else
485
+ # conditional can be removed.
486
+ if response.respond_to?(:name) && response.name == 'Net::WriteTimeout'
487
+ handle_server_connection_exception(response, endpoint)
488
+ else
489
+ record_endpoint_attempts_supportability_metrics(endpoint)
490
+ record_error_response_supportability_metrics(response.code)
491
+ raise UnrecoverableServerException, "#{response.code}: #{response.message}"
492
+ end
477
493
  end
478
494
  response
479
495
  end
@@ -15,7 +15,7 @@ module NewRelic
15
15
  if @pipe && @pipe.parent_pid != $$
16
16
  @pipe.after_fork_in_child
17
17
  else
18
- NewRelic::Agent.logger.error('No communication channel to parent process, please see https://newrelic.com/docs/ruby/resque-instrumentation for more information.')
18
+ NewRelic::Agent.logger.error('No communication channel to parent process, please see https://docs.newrelic.com/docs/apm/agents/ruby-agent/background-jobs/resque-instrumentation/ for more information.')
19
19
  end
20
20
  end
21
21
 
@@ -66,9 +66,10 @@ module NewRelic
66
66
  #
67
67
  # @api public
68
68
  def transaction_sampled?
69
- if txn = current_transaction
70
- txn.sampled?
71
- end
69
+ txn = current_transaction
70
+ return false unless txn
71
+
72
+ txn.sampled?
72
73
  end
73
74
  alias_method :sampled?, :transaction_sampled?
74
75
 
@@ -8,11 +8,17 @@ module NewRelic
8
8
  module Agent
9
9
  class Transaction
10
10
  class RequestAttributes
11
- attr_reader :request_path, :referer, :accept, :content_length, :content_type,
12
- :host, :port, :user_agent, :request_method
11
+ # the HTTP standard has "referrer" mispelled as "referer"
12
+ attr_reader :accept, :content_length, :content_type, :host, :other_headers, :port, :referer, :request_method,
13
+ :request_path, :user_agent
13
14
 
14
15
  HTTP_ACCEPT_HEADER_KEY = 'HTTP_ACCEPT'.freeze
15
16
 
17
+ BASE_HEADERS = %w[CONTENT_LENGTH CONTENT_TYPE HTTP_ACCEPT HTTP_REFERER HTTP_USER_AGENT PATH_INFO REMOTE_HOST
18
+ REQUEST_METHOD REQUEST_URI SERVER_PORT].freeze
19
+
20
+ ATTRIBUTE_PREFIX = 'request.headers.'
21
+
16
22
  def initialize(request)
17
23
  @request_path = path_from_request(request)
18
24
  @referer = referer_from_request(request)
@@ -23,6 +29,7 @@ module NewRelic
23
29
  @port = port_from_request(request)
24
30
  @user_agent = attribute_from_request(request, :user_agent)
25
31
  @request_method = attribute_from_request(request, :request_method)
32
+ @other_headers = other_headers_from_request(request)
26
33
  end
27
34
 
28
35
  def assign_agent_attributes(txn)
@@ -31,14 +38,17 @@ module NewRelic
31
38
  AttributeFilter::DST_ERROR_COLLECTOR
32
39
 
33
40
  if referer
34
- txn.add_agent_attribute(:'request.headers.referer', referer, AttributeFilter::DST_ERROR_COLLECTOR)
41
+ destinations = allow_other_headers? ? default_destinations : AttributeFilter::DST_ERROR_COLLECTOR
42
+ txn.add_agent_attribute(:'request.headers.referer', referer, destinations)
35
43
  end
36
44
 
37
45
  if request_path
38
- txn.add_agent_attribute(:'request.uri',
39
- request_path,
40
- AttributeFilter::DST_TRANSACTION_TRACER |
41
- AttributeFilter::DST_ERROR_COLLECTOR)
46
+ destinations = if allow_other_headers?
47
+ default_destinations
48
+ else
49
+ AttributeFilter::DST_TRANSACTION_TRACER | AttributeFilter::DST_ERROR_COLLECTOR
50
+ end
51
+ txn.add_agent_attribute(:'request.uri', request_path, destinations)
42
52
  end
43
53
 
44
54
  if accept
@@ -64,6 +74,14 @@ module NewRelic
64
74
  if request_method
65
75
  txn.add_agent_attribute(:'request.method', request_method, default_destinations)
66
76
  end
77
+
78
+ if port && allow_other_headers?
79
+ txn.add_agent_attribute(:'request.headers.port', port, default_destinations)
80
+ end
81
+
82
+ other_headers.each do |header, value|
83
+ txn.add_agent_attribute(header, value, default_destinations)
84
+ end
67
85
  end
68
86
 
69
87
  private
@@ -116,6 +134,26 @@ module NewRelic
116
134
  env[key]
117
135
  end
118
136
  end
137
+
138
+ def allow_other_headers?
139
+ NewRelic::Agent.config[:allow_all_headers] && !NewRelic::Agent.config[:high_security]
140
+ end
141
+
142
+ def other_headers_from_request(request)
143
+ # confirm that `request` is an instance of `Rack::Request` by checking
144
+ # for #each_header
145
+ return NewRelic::EMPTY_HASH unless allow_other_headers? && request.respond_to?(:each_header)
146
+
147
+ request.each_header.with_object({}) do |(header, value), hash|
148
+ next if BASE_HEADERS.include?(header)
149
+
150
+ hash[formatted_header(header)] = value
151
+ end
152
+ end
153
+
154
+ def formatted_header(raw_name)
155
+ "#{ATTRIBUTE_PREFIX}#{NewRelic::LanguageSupport.camelize_with_first_letter_downcased(raw_name)}".to_sym
156
+ end
119
157
  end
120
158
  end
121
159
  end
@@ -31,11 +31,12 @@ module NewRelic
31
31
  RAKE_PREFIX = "#{OTHER_TRANSACTION_PREFIX}Rake/"
32
32
  MESSAGE_PREFIX = "#{OTHER_TRANSACTION_PREFIX}Message/"
33
33
  RACK_PREFIX = "#{CONTROLLER_PREFIX}Rack/"
34
+ RODA_PREFIX = "#{CONTROLLER_PREFIX}Roda/"
34
35
  SINATRA_PREFIX = "#{CONTROLLER_PREFIX}Sinatra/"
35
36
  GRAPE_PREFIX = "#{CONTROLLER_PREFIX}Grape/"
36
37
  ACTION_CABLE_PREFIX = "#{CONTROLLER_PREFIX}ActionCable/"
37
38
 
38
- WEB_TRANSACTION_CATEGORIES = [:web, :controller, :uri, :rack, :sinatra, :grape, :middleware, :action_cable].freeze
39
+ WEB_TRANSACTION_CATEGORIES = %i[action_cable controller grape middleware rack roda sinatra web uri].freeze
39
40
 
40
41
  MIDDLEWARE_SUMMARY_METRICS = ['Middleware/all'].freeze
41
42
  WEB_SUMMARY_METRIC = 'HttpDispatcher'
@@ -289,7 +290,7 @@ module NewRelic
289
290
  end
290
291
 
291
292
  def sampled?
292
- return unless Agent.config[:'distributed_tracing.enabled']
293
+ return false unless Agent.config[:'distributed_tracing.enabled']
293
294
 
294
295
  if @sampled.nil?
295
296
  @sampled = NewRelic::Agent.instance.adaptive_sampler.sampled?
@@ -545,8 +546,8 @@ module NewRelic
545
546
  end
546
547
 
547
548
  def user_defined_rules_ignore?
548
- return unless request_path
549
- return if (rules = NewRelic::Agent.config[:"rules.ignore_url_regexes"]).empty?
549
+ return false unless request_path
550
+ return false if (rules = NewRelic::Agent.config[:"rules.ignore_url_regexes"]).empty?
550
551
 
551
552
  rules.any? do |rule|
552
553
  request_path.match(rule)
@@ -75,14 +75,12 @@ module NewRelic
75
75
  processed_headers = headers
76
76
  raise if processed_headers.value?(:error)
77
77
 
78
- Timeout.timeout(1) do
79
- response = nil
80
- Net::HTTP.start(endpoint.host, endpoint.port) do |http|
81
- req = Net::HTTP::Get.new(endpoint, processed_headers)
82
- response = http.request(req)
83
- end
84
- response
78
+ response = nil
79
+ Net::HTTP.start(endpoint.host, endpoint.port, open_timeout: 1, read_timeout: 1) do |http|
80
+ req = Net::HTTP::Get.new(endpoint, processed_headers)
81
+ response = http.request(req)
85
82
  end
83
+ response
86
84
  rescue
87
85
  NewRelic::Agent.logger.debug("#{vendor_name} environment not detected")
88
86
  end
@@ -49,19 +49,13 @@ module NewRelic
49
49
  # maybe it is already loaded by some external system
50
50
  # i.e. rpm_contrib or user extensions?
51
51
  end
52
- NewRelic::Control::Frameworks.const_get(camelize(framework.to_s))
52
+ NewRelic::Control::Frameworks.const_get(NewRelic::LanguageSupport.camelize(framework.to_s))
53
53
  end
54
54
 
55
55
  # The root directory for the plugin or gem
56
56
  def newrelic_root
57
57
  File.expand_path(File.join('..', '..', '..', '..'), __FILE__)
58
58
  end
59
-
60
- def camelize(snake_case_name)
61
- snake_case_name.gsub(/(\_|^)[a-z]/) do |substring|
62
- substring[-1].capitalize!
63
- end
64
- end
65
59
  end
66
60
  extend ClassMethods
67
61
  end
@@ -0,0 +1,20 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require 'new_relic/control/frameworks/ruby'
6
+ module NewRelic
7
+ class Control
8
+ module Frameworks
9
+ # Contains basic control logic for Roda
10
+ class Roda < NewRelic::Control::Frameworks::Ruby
11
+ protected
12
+
13
+ def install_shim
14
+ super
15
+ ::Roda.class_eval { include NewRelic::Agent::Instrumentation::ControllerInstrumentation::Shim }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -78,6 +78,11 @@ module NewRelic
78
78
  camelized.split(/\-|\_/).map(&:capitalize).join
79
79
  end
80
80
 
81
+ def camelize_with_first_letter_downcased(string)
82
+ camelized = camelize(string)
83
+ camelized[0].downcase.concat(camelized[1..-1])
84
+ end
85
+
81
86
  def bundled_gem?(gem_name)
82
87
  defined?(Bundler) && Bundler.rubygems.all_specs.map(&:name).include?(gem_name)
83
88
  rescue => e
@@ -13,7 +13,7 @@ class NewRelic::NoticedError
13
13
  attr_accessor :path, :timestamp, :message, :exception_class_name,
14
14
  :request_uri, :request_port, :file_name, :line_number,
15
15
  :stack_trace, :attributes_from_notice_error, :attributes,
16
- :expected
16
+ :expected, :transaction_id
17
17
 
18
18
  attr_reader :error_group, :exception_id, :is_internal
19
19
 
@@ -45,6 +45,7 @@ class NewRelic::NoticedError
45
45
  @is_internal = (exception.class < NewRelic::Agent::InternalAgentError)
46
46
 
47
47
  extract_class_name_and_message_from(exception)
48
+ @transaction_id = NewRelic::Agent::Tracer&.current_transaction&.guid
48
49
 
49
50
  # clamp long messages to 4k so that we don't send a lot of
50
51
  # overhead across the wire
@@ -79,11 +80,13 @@ class NewRelic::NoticedError
79
80
  include NewRelic::Coerce
80
81
 
81
82
  def to_collector_array(encoder = nil)
82
- [NewRelic::Helper.time_to_millis(timestamp),
83
+ arr = [NewRelic::Helper.time_to_millis(timestamp),
83
84
  string(path),
84
85
  string(message),
85
86
  string(exception_class_name),
86
87
  processed_attributes]
88
+ arr << @transaction_id if @transaction_id
89
+ arr
87
90
  end
88
91
 
89
92
  # Note that we process attributes lazily and store the result. This is because
@@ -6,8 +6,8 @@
6
6
  module NewRelic
7
7
  module VERSION # :nodoc:
8
8
  MAJOR = 9
9
- MINOR = 3
10
- TINY = 1
9
+ MINOR = 4
10
+ TINY = 0
11
11
 
12
12
  STRING = "#{MAJOR}.#{MINOR}.#{TINY}"
13
13
  end
@@ -2,7 +2,7 @@
2
2
  # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
3
  # frozen_string_literal: true
4
4
 
5
- require_relative './helpers/version_bump'
5
+ require_relative 'helpers/version_bump'
6
6
 
7
7
  namespace :newrelic do
8
8
  namespace :version do
@@ -21,12 +21,13 @@ namespace :newrelic do
21
21
  '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.',
22
22
  'error_collector' => "The agent collects and reports all uncaught exceptions by default. These configuration options allow you to customize the error collection.\n\nFor information on ignored and expected errors, [see this page on Error Analytics in APM](/docs/agents/manage-apm-agents/agent-data/manage-errors-apm-collect-ignore-or-mark-expected/). To set expected errors via the `NewRelic::Agent.notice_error` Ruby method, [consult the Ruby Agent API](/docs/agents/ruby-agent/api-guides/sending-handled-errors-new-relic/).",
23
23
  '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.",
24
+ 'application_logging' => "The Ruby agent supports [APM logs in context](/docs/apm/new-relic-apm/getting-started/get-started-logs-context). For some tips on configuring logs for the Ruby agent, see [Configure Ruby logs in context](/docs/logs/logs-context/configure-logs-context-ruby).\n\nAvailable logging-related config options include:",
24
25
  '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.'
25
26
  }
26
27
 
27
28
  NAME_OVERRIDES = {
28
- 'slow_sql' => 'Slow SQL',
29
- 'custom_insights_events' => 'Custom Events'
29
+ 'slow_sql' => 'Slow SQL [#slow-sql]',
30
+ 'custom_insights_events' => 'Custom Events [#custom-events]'
30
31
  }
31
32
 
32
33
  desc 'Describe available New Relic configuration settings'
@@ -1,3 +1,96 @@
1
+ ---
2
+ title: Ruby agent configuration
3
+ tags:
4
+ - Agents
5
+ - Ruby agent
6
+ - Configuration
7
+ metaDescription: 'APM for Ruby: how to configure the Ruby agent, including editing the config file and setting environment variables.'
8
+ redirects:
9
+ - /docs/agents/ruby-agent/configuration/ruby-agent-configuration
10
+ - /docs/ruby/ruby-agent-configuration
11
+ - /docs/agents/ruby-agent/installation-and-configuration/ruby-agent-configuration
12
+ - /docs/agents/ruby-agent/installation-configuration/ruby-agent-configuration
13
+ ---
14
+
15
+ <CONTRIBUTOR_NOTE>
16
+ This file is automatically generated from values defined in `lib/new_relic/agent/configuration/default_source.rb`.
17
+ All changes should be made directly to `default_source.rb.`
18
+ Submit PRs or raise issues at: https://github.com/newrelic/newrelic-ruby-agent
19
+ </CONTRIBUTOR_NOTE>
20
+
21
+ You can configure the New Relic Ruby agent with settings in a configuration file, environment variables, or programmatically with server-side configuration. This document summarizes the configuration options available for the Ruby agent.
22
+
23
+ If the default value for a configuration option is `(Dynamic)`, this means the Ruby agent calculates the default at runtime. The value for the config setting defaults to the value of another setting as appropriate.
24
+
25
+ ## Configuration methods and precedence [#Options]
26
+
27
+ The primary (default) method to configure the Ruby agent is via the configuration file (`newrelic.yml`) in the `config` subdirectory. To set configuration values using environment variables:
28
+
29
+ 1. Add the prefix `NEW_RELIC_` to the setting's name.
30
+ 2. Replace any periods `.` with underscores `_`.
31
+
32
+ You can also configure a few values in the UI via [server-side configuration](/docs/agents/manage-apm-agents/configuration/server-side-agent-configuration).
33
+
34
+ The Ruby agent follows this order of precedence for configuration:
35
+
36
+ 1. Environment variables
37
+ 2. Server-side configuration
38
+ 3. Configuration file (`newrelic.yml`)
39
+ 4. Default configuration settings
40
+
41
+ In other words, environment variables override all other configuration settings and info, server-side configuration overrides the configuration file and default config settings, and so on.
42
+
43
+ ## View and edit config file options [#Edit]
44
+
45
+ The Ruby agent's `newrelic.yml` is a standard YAML configuration file. It typically includes a `Defaults` section at the top, plus sections below for each application environment; for example, `Development`, `Testing`, and `Production`.
46
+
47
+ The Ruby agent determines which section of the `newrelic.yml` config file to read from by looking at certain environment variables to derive the application's environment. This can be useful, for example, when you want to use `info` for the `log_level` config setting in your production environment, and you want more verbose `log_level` config settings (such as `debug` in your development environment.
48
+
49
+ Here is an example `newrelic.yml` config file:
50
+
51
+ ```yaml
52
+ common: &default_settings
53
+ license_key: 'YOUR_LICENSE_KEY'
54
+ app_name: 'My Application Name'
55
+ production:
56
+ <<: *default_settings
57
+ log_level: info
58
+ development:
59
+ <<: *default_settings
60
+ log_level: debug
61
+ ```
62
+
63
+ For non-Rails apps, the Ruby agent looks for the following environment variables, in this order, to determine the application environment:
64
+
65
+ 1. `NEW_RELIC_ENV`
66
+ 2. `RUBY_ENV`
67
+ 3. `RAILS_ENV`
68
+ 4. `APP_ENV`
69
+ 5. `RACK_ENV`
70
+
71
+ If the Ruby agent does not detect values for any of those environment variables, it will default the application environment to `development` and read from the `development` section of the `newrelic.yml` config file.
72
+
73
+ When running the Ruby agent in a Rails app, the agent first looks for the `NEW_RELIC_ENV` environment variable to determine the application environment and which section of the `newrelic.yml` to use. If `NEW_RELIC_ENV` is not present, the agent uses the Rails environment (`RAILS_ENV` or `RAILS.env`, depending on the version of Rails) .
74
+
75
+ When you edit the config file, be sure to:
76
+
77
+ * Indent only with two spaces.
78
+ * Indent only where relevant, in stanzas such as **`error_collector`**.
79
+
80
+ If you do not indent correctly, the agent may throw an `Unable to parse configuration file` error on startup.
81
+
82
+ To view the most current list of available Ruby agent configuration options, use the `rake newrelic:config:docs` command. This document describes the most common options.
83
+
84
+ ## Update the config file [#Updates]
85
+
86
+ This documentation applies to the Ruby agent's latest release. For details on earlier versions, refer to the comments in `newrelic.yml` itself.
87
+
88
+ To update `newrelic.yml` file after a new release, use the template in the base directory of the agent gem. When you update to new gem versions, examine or diff `config/newrelic.yml` and `newrelic.yml` in the [installation directory](/docs/agents/manage-apm-agents/troubleshooting/find-agent-root-directory#ruby-agent) to take advantage of new configuration options.
89
+
90
+ <Callout variant="important">
91
+ Updating the gem does not automatically update `config/newrelic.yml`.
92
+ </Callout>
93
+
1
94
  <% sections.each do |(section_key, section_name, section_description, configs)| %>
2
95
  ## <%=section_name%>
3
96
 
@@ -3,16 +3,19 @@
3
3
  # frozen_string_literal: true
4
4
 
5
5
  module Format
6
- def output(format)
7
- config_hash = build_config_hash
8
- sections = flatten_config_hash(config_hash)
6
+ DEFAULT_CONFIG_PATH = 'ruby-agent-configuration.mdx'
9
7
 
10
- puts build_erb(format).result(binding).split("\n").map(&:rstrip).join("\n").gsub('. ', '. ')
11
- sections # silences unused warning to return this
8
+ def output(format)
9
+ result = build_erb(format).result(binding).split("\n").map(&:rstrip).join("\n").gsub('. ', '. ')
10
+ File.write(DEFAULT_CONFIG_PATH, result)
12
11
  end
13
12
 
14
13
  private
15
14
 
15
+ def sections
16
+ @sections ||= flatten_config_hash(build_config_hash)
17
+ end
18
+
16
19
  def add_data_to_sections(sections)
17
20
  sections.each do |section|
18
21
  section_key = section[0]
@@ -66,7 +69,7 @@ module Format
66
69
 
67
70
  def format_description(value)
68
71
  description = ''
69
- description += '<b>DEPRECATED</b> ' if value[:deprecated]
72
+ description += '**DEPRECATED** ' if value[:deprecated]
70
73
  description += value[:description]
71
74
  description
72
75
  end
@@ -81,9 +84,10 @@ module Format
81
84
  name = NAME_OVERRIDES[key]
82
85
  return name if name
83
86
 
84
- key.split('_')
87
+ title = key.split('_')
85
88
  .each { |fragment| fragment[0] = fragment[0].upcase }
86
89
  .join(' ')
90
+ "#{title} [##{key.tr('_', '-')}]"
87
91
  end
88
92
 
89
93
  def format_sections(key, value)
@@ -55,8 +55,8 @@ module VersionBump
55
55
  # Replace dev with version number in changelog
56
56
  def self.update_changelog(version)
57
57
  file = read_file('CHANGELOG.md')
58
- file.gsub!(/## dev/, "## v#{version}")
59
- file.gsub!(/Version <dev>/, "Version #{version}")
58
+ file.gsub!('## dev', "## v#{version}")
59
+ file.gsub!('Version <dev>', "Version #{version}")
60
60
  write_file('CHANGELOG.md', file)
61
61
  end
62
62
  end
@@ -2,7 +2,7 @@
2
2
  # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
3
  # frozen_string_literal: true
4
4
 
5
- require_relative './helpers/newrelicyml'
5
+ require_relative 'helpers/newrelicyml'
6
6
 
7
7
  namespace :newrelic do
8
8
  desc 'Update newrelic.yml with latest config options from default_source.rb'
data/newrelic.yml CHANGED
@@ -33,6 +33,9 @@ common: &default_settings
33
33
  # - a.third.event
34
34
  # active_support_custom_events_names: []
35
35
 
36
+ # If true, enables capture of all HTTP request headers for all destinations.
37
+ # allow_all_headers: false
38
+
36
39
  # Your New Relic userKey. Required when using the New Relic REST API v2 to record
37
40
  # deployments using the newrelic deployments command.
38
41
  # api_key: ""
@@ -222,6 +225,10 @@ common: &default_settings
222
225
  # (regardless of whether they are installed via Rack::Builder or Rails).
223
226
  # disable_middleware_instrumentation: false
224
227
 
228
+ # If true, disables agent middleware for Roda. This middleware is responsible for
229
+ # advanced feature support such as page load timing and error collection.
230
+ # disable_roda_auto_middleware: false
231
+
225
232
  # If true, disables the collection of sampler metrics. Sampler metrics are metrics
226
233
  # that are not event-based (such as CPU time or memory usage).
227
234
  # disable_samplers: false
@@ -479,6 +486,10 @@ common: &default_settings
479
486
  # prepend, chain, disabled.
480
487
  # instrumentation.resque: auto
481
488
 
489
+ # Controls auto-instrumentation of Roda at start up. May be one of: auto, prepend,
490
+ # chain, disabled.
491
+ # instrumentation.roda: auto
492
+
482
493
  # Controls auto-instrumentation of Sinatra at start up. May be one of: auto,
483
494
  # prepend, chain, disabled.
484
495
  # instrumentation.sinatra: auto
data/newrelic_rpm.gemspec CHANGED
@@ -39,7 +39,7 @@ Gem::Specification.new do |s|
39
39
  'homepage_uri' => 'https://newrelic.com/ruby'
40
40
  }
41
41
 
42
- reject_list = File.read('./.build_ignore').split("\n")
42
+ reject_list = File.read(File.expand_path('../.build_ignore', __FILE__)).split("\n")
43
43
  file_list = `git ls-files -z`.split("\x0").reject { |f| reject_list.any? { |rf| f.start_with?(rf) } }
44
44
  # test/agent_helper.rb is a requirement for the NewRelic::Agent.require_test_helper public API
45
45
  test_helper_path = 'test/agent_helper.rb'
@@ -56,9 +56,10 @@ Gem::Specification.new do |s|
56
56
  s.add_development_dependency 'minitest-stub-const', '0.6'
57
57
  s.add_development_dependency 'mocha', '~> 1.16'
58
58
  s.add_development_dependency 'pry' unless ENV['CI']
59
+ s.add_development_dependency 'rack'
59
60
  s.add_development_dependency 'rake', '12.3.3'
60
61
 
61
- s.add_development_dependency 'rubocop', '1.51' unless ENV['CI'] && RUBY_VERSION < '3.0.0'
62
+ s.add_development_dependency 'rubocop', '1.54' unless ENV['CI'] && RUBY_VERSION < '3.0.0'
62
63
  s.add_development_dependency 'rubocop-ast', '1.28.1' unless ENV['CI'] && RUBY_VERSION < '3.0.0'
63
64
  s.add_development_dependency 'rubocop-minitest', '0.27.0' unless ENV['CI'] && RUBY_VERSION < '3.0.0'
64
65
  s.add_development_dependency 'rubocop-performance', '1.16.0' unless ENV['CI'] && RUBY_VERSION < '3.0.0'
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: 9.3.1
4
+ version: 9.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tanna McClure
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2023-07-11 00:00:00.000000000 Z
14
+ date: 2023-08-15 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -69,6 +69,20 @@ dependencies:
69
69
  - - "~>"
70
70
  - !ruby/object:Gem::Version
71
71
  version: '1.16'
72
+ - !ruby/object:Gem::Dependency
73
+ name: rack
74
+ requirement: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
72
86
  - !ruby/object:Gem::Dependency
73
87
  name: rake
74
88
  requirement: !ruby/object:Gem::Requirement
@@ -89,14 +103,14 @@ dependencies:
89
103
  requirements:
90
104
  - - '='
91
105
  - !ruby/object:Gem::Version
92
- version: '1.51'
106
+ version: '1.54'
93
107
  type: :development
94
108
  prerelease: false
95
109
  version_requirements: !ruby/object:Gem::Requirement
96
110
  requirements:
97
111
  - - '='
98
112
  - !ruby/object:Gem::Version
99
- version: '1.51'
113
+ version: '1.54'
100
114
  - !ruby/object:Gem::Dependency
101
115
  name: rubocop-ast
102
116
  requirement: !ruby/object:Gem::Requirement
@@ -440,6 +454,11 @@ files:
440
454
  - lib/new_relic/agent/instrumentation/resque/helper.rb
441
455
  - lib/new_relic/agent/instrumentation/resque/instrumentation.rb
442
456
  - lib/new_relic/agent/instrumentation/resque/prepend.rb
457
+ - lib/new_relic/agent/instrumentation/roda.rb
458
+ - lib/new_relic/agent/instrumentation/roda/chain.rb
459
+ - lib/new_relic/agent/instrumentation/roda/instrumentation.rb
460
+ - lib/new_relic/agent/instrumentation/roda/prepend.rb
461
+ - lib/new_relic/agent/instrumentation/roda/roda_transaction_namer.rb
443
462
  - lib/new_relic/agent/instrumentation/sequel.rb
444
463
  - lib/new_relic/agent/instrumentation/sequel_helper.rb
445
464
  - lib/new_relic/agent/instrumentation/sidekiq.rb
@@ -571,6 +590,7 @@ files:
571
590
  - lib/new_relic/control/frameworks/rails3.rb
572
591
  - lib/new_relic/control/frameworks/rails4.rb
573
592
  - lib/new_relic/control/frameworks/rails_notifications.rb
593
+ - lib/new_relic/control/frameworks/roda.rb
574
594
  - lib/new_relic/control/frameworks/ruby.rb
575
595
  - lib/new_relic/control/frameworks/sinatra.rb
576
596
  - lib/new_relic/control/instance_methods.rb