newrelic_rpm 9.3.0 → 9.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/.build_ignore +6 -1
  3. data/CHANGELOG.md +193 -6
  4. data/README.md +4 -0
  5. data/Rakefile +1 -1
  6. data/lib/new_relic/agent/attribute_pre_filtering.rb +109 -0
  7. data/lib/new_relic/agent/configuration/default_source.rb +177 -34
  8. data/lib/new_relic/agent/configuration/environment_source.rb +1 -1
  9. data/lib/new_relic/agent/distributed_tracing.rb +1 -1
  10. data/lib/new_relic/agent/http_clients/async_http_wrappers.rb +83 -0
  11. data/lib/new_relic/agent/http_clients/ethon_wrappers.rb +111 -0
  12. data/lib/new_relic/agent/http_clients/httpx_wrappers.rb +93 -0
  13. data/lib/new_relic/agent/instrumentation/action_controller_other_subscriber.rb +1 -1
  14. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +1 -2
  15. data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger/chain.rb +69 -0
  16. data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger/instrumentation.rb +13 -0
  17. data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger/prepend.rb +37 -0
  18. data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger.rb +23 -0
  19. data/lib/new_relic/agent/instrumentation/active_support_logger/instrumentation.rb +4 -0
  20. data/lib/new_relic/agent/instrumentation/active_support_logger.rb +3 -1
  21. data/lib/new_relic/agent/instrumentation/async_http/chain.rb +23 -0
  22. data/lib/new_relic/agent/instrumentation/async_http/instrumentation.rb +37 -0
  23. data/lib/new_relic/agent/instrumentation/async_http/prepend.rb +15 -0
  24. data/lib/new_relic/agent/instrumentation/async_http.rb +26 -0
  25. data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +9 -0
  26. data/lib/new_relic/agent/instrumentation/concurrent_ruby/instrumentation.rb +2 -2
  27. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +1 -2
  28. data/lib/new_relic/agent/instrumentation/curb/instrumentation.rb +4 -0
  29. data/lib/new_relic/agent/instrumentation/delayed_job/instrumentation.rb +3 -0
  30. data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +4 -1
  31. data/lib/new_relic/agent/instrumentation/ethon/chain.rb +39 -0
  32. data/lib/new_relic/agent/instrumentation/ethon/instrumentation.rb +105 -0
  33. data/lib/new_relic/agent/instrumentation/ethon/prepend.rb +35 -0
  34. data/lib/new_relic/agent/instrumentation/ethon.rb +39 -0
  35. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +3 -0
  36. data/lib/new_relic/agent/instrumentation/grape/instrumentation.rb +4 -0
  37. data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +4 -0
  38. data/lib/new_relic/agent/instrumentation/grpc/server/instrumentation.rb +4 -0
  39. data/lib/new_relic/agent/instrumentation/grpc_client.rb +1 -1
  40. data/lib/new_relic/agent/instrumentation/grpc_server.rb +1 -1
  41. data/lib/new_relic/agent/instrumentation/httpclient/instrumentation.rb +4 -0
  42. data/lib/new_relic/agent/instrumentation/httprb/instrumentation.rb +4 -0
  43. data/lib/new_relic/agent/instrumentation/httpx/chain.rb +20 -0
  44. data/lib/new_relic/agent/instrumentation/httpx/instrumentation.rb +51 -0
  45. data/lib/new_relic/agent/instrumentation/httpx/prepend.rb +15 -0
  46. data/lib/new_relic/agent/instrumentation/httpx.rb +27 -0
  47. data/lib/new_relic/agent/instrumentation/logger/instrumentation.rb +3 -0
  48. data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +9 -0
  49. data/lib/new_relic/agent/instrumentation/memcache.rb +2 -2
  50. data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +1 -3
  51. data/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb +5 -1
  52. data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +4 -0
  53. data/lib/new_relic/agent/instrumentation/padrino/instrumentation.rb +4 -0
  54. data/lib/new_relic/agent/instrumentation/queue_time.rb +1 -1
  55. data/lib/new_relic/agent/instrumentation/rack/instrumentation.rb +6 -0
  56. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +4 -0
  57. data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +1 -0
  58. data/lib/new_relic/agent/instrumentation/rake/instrumentation.rb +4 -0
  59. data/lib/new_relic/agent/instrumentation/redis/instrumentation.rb +4 -0
  60. data/lib/new_relic/agent/instrumentation/resque/instrumentation.rb +4 -0
  61. data/lib/new_relic/agent/instrumentation/roda/chain.rb +43 -0
  62. data/lib/new_relic/agent/instrumentation/roda/ignorer.rb +45 -0
  63. data/lib/new_relic/agent/instrumentation/roda/instrumentation.rb +68 -0
  64. data/lib/new_relic/agent/instrumentation/roda/prepend.rb +24 -0
  65. data/lib/new_relic/agent/instrumentation/roda/roda_transaction_namer.rb +29 -0
  66. data/lib/new_relic/agent/instrumentation/roda.rb +36 -0
  67. data/lib/new_relic/agent/instrumentation/sequel.rb +1 -1
  68. data/lib/new_relic/agent/instrumentation/sidekiq/client.rb +4 -0
  69. data/lib/new_relic/agent/instrumentation/sidekiq/server.rb +26 -3
  70. data/lib/new_relic/agent/instrumentation/sidekiq.rb +5 -3
  71. data/lib/new_relic/agent/instrumentation/sinatra/instrumentation.rb +4 -0
  72. data/lib/new_relic/agent/instrumentation/sinatra/transaction_namer.rb +1 -3
  73. data/lib/new_relic/agent/instrumentation/stripe.rb +28 -0
  74. data/lib/new_relic/agent/instrumentation/stripe_subscriber.rb +77 -0
  75. data/lib/new_relic/agent/instrumentation/tilt/instrumentation.rb +4 -0
  76. data/lib/new_relic/agent/instrumentation/typhoeus/instrumentation.rb +5 -1
  77. data/lib/new_relic/agent/log_event_attributes.rb +1 -1
  78. data/lib/new_relic/agent/messaging.rb +2 -2
  79. data/lib/new_relic/agent/monitors/synthetics_monitor.rb +12 -1
  80. data/lib/new_relic/agent/new_relic_service.rb +33 -17
  81. data/lib/new_relic/agent/pipe_service.rb +1 -1
  82. data/lib/new_relic/agent/rules_engine.rb +1 -1
  83. data/lib/new_relic/agent/span_event_primitive.rb +16 -4
  84. data/lib/new_relic/agent/system_info.rb +26 -0
  85. data/lib/new_relic/agent/tracer.rb +5 -6
  86. data/lib/new_relic/agent/transaction/abstract_segment.rb +55 -0
  87. data/lib/new_relic/agent/transaction/external_request_segment.rb +5 -2
  88. data/lib/new_relic/agent/transaction/message_broker_segment.rb +1 -2
  89. data/lib/new_relic/agent/transaction/request_attributes.rb +46 -10
  90. data/lib/new_relic/agent/transaction.rb +30 -6
  91. data/lib/new_relic/agent/transaction_error_primitive.rb +16 -0
  92. data/lib/new_relic/agent/transaction_event_primitive.rb +19 -0
  93. data/lib/new_relic/agent/utilization/gcp.rb +1 -3
  94. data/lib/new_relic/agent/utilization/vendor.rb +5 -7
  95. data/lib/new_relic/agent.rb +19 -3
  96. data/lib/new_relic/cli/command.rb +1 -0
  97. data/lib/new_relic/constants.rb +3 -0
  98. data/lib/new_relic/control/class_methods.rb +1 -7
  99. data/lib/new_relic/control/frameworks/rails.rb +14 -2
  100. data/lib/new_relic/control/frameworks/roda.rb +20 -0
  101. data/lib/new_relic/language_support.rb +9 -0
  102. data/lib/new_relic/noticed_error.rb +5 -2
  103. data/lib/new_relic/rack/agent_hooks.rb +1 -1
  104. data/lib/new_relic/rack/agent_middleware.rb +0 -16
  105. data/lib/new_relic/rack/browser_monitoring.rb +1 -1
  106. data/lib/new_relic/supportability_helper.rb +1 -0
  107. data/lib/new_relic/version.rb +1 -1
  108. data/lib/tasks/bump_version.rake +1 -1
  109. data/lib/tasks/config.rake +3 -2
  110. data/lib/tasks/helpers/config.html.erb +93 -0
  111. data/lib/tasks/helpers/format.rb +11 -7
  112. data/lib/tasks/helpers/version_bump.rb +2 -2
  113. data/lib/tasks/instrumentation_generator/instrumentation.thor +3 -3
  114. data/lib/tasks/newrelicyml.rake +1 -1
  115. data/lib/tasks/tests.rake +71 -0
  116. data/newrelic.yml +103 -31
  117. data/newrelic_rpm.gemspec +12 -6
  118. data/test/agent_helper.rb +1027 -0
  119. metadata +63 -8
  120. data/lib/tasks/helpers/removers.rb +0 -33
  121. data/lib/tasks/multiverse.rake +0 -6
  122. data/lib/tasks/multiverse.rb +0 -76
@@ -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
@@ -58,6 +58,7 @@ module NewRelic
58
58
  require 'new_relic/agent/deprecator'
59
59
  require 'new_relic/agent/logging'
60
60
  require 'new_relic/agent/distributed_tracing'
61
+ require 'new_relic/agent/attribute_pre_filtering'
61
62
  require 'new_relic/agent/attribute_processing'
62
63
  require 'new_relic/agent/linking_metadata'
63
64
  require 'new_relic/agent/local_log_decorator'
@@ -213,6 +214,17 @@ module NewRelic
213
214
  record_metric(metric_name, value)
214
215
  end
215
216
 
217
+ def record_instrumentation_invocation(library)
218
+ record_metric_once("Supportability/#{library}/Invoked")
219
+ end
220
+
221
+ # see ActiveSupport::Inflector.demodulize
222
+ def base_name(klass_name)
223
+ return klass_name unless ridx = klass_name.rindex('::')
224
+
225
+ klass_name[(ridx + 2), klass_name.length]
226
+ end
227
+
216
228
  SUPPORTABILITY_INCREMENT_METRIC = 'Supportability/API/increment_metric'.freeze
217
229
 
218
230
  # Increment a simple counter metric.
@@ -298,7 +310,7 @@ module NewRelic
298
310
 
299
311
  # Set a callback proc for determining an error's error group name
300
312
  #
301
- # @param [Proc] the callback proc
313
+ # @param callback_proc [Proc] the callback proc
302
314
  #
303
315
  # Typically this method should be called only once to set a callback for
304
316
  # use with all noticed errors. If it is called multiple times, each new
@@ -621,7 +633,9 @@ module NewRelic
621
633
  def add_new_segment_attributes(params, segment)
622
634
  # Make sure not to override existing segment-level custom attributes
623
635
  segment_custom_keys = segment.attributes.custom_attributes.keys.map(&:to_sym)
624
- segment.add_custom_attributes(params.reject { |k, _v| segment_custom_keys.include?(k.to_sym) })
636
+ segment.add_custom_attributes(params.reject do |k, _v|
637
+ segment_custom_keys.include?(k.to_sym) if k.respond_to?(:to_sym) # param keys can be integers
638
+ end)
625
639
  end
626
640
 
627
641
  # Add custom attributes to the span event for the current span. Attributes will be visible on spans in the
@@ -649,7 +663,9 @@ module NewRelic
649
663
  end
650
664
  end
651
665
 
652
- # Add custom attributes to log events for the current agent instance.
666
+ # Add global custom attributes to log events for the current agent instance. As these attributes are global to the
667
+ # agent instance, they will be attached to all log events generated by the agent, and this methods usage isn't
668
+ # suitable for setting dynamic values.
653
669
  #
654
670
  # @param [Hash] params A Hash of attributes to attach to log
655
671
  # events. The agent accepts up to 240 custom
@@ -60,6 +60,7 @@ module NewRelic
60
60
  extra = []
61
61
  options = ARGV.options do |opts|
62
62
  script_name = File.basename($0)
63
+ # TODO: MAJOR VERSION - remove newrelic_cmd, deprecated since version 2.13
63
64
  if /newrelic_cmd$/.match?(script_name)
64
65
  $stdout.puts "warning: the 'newrelic_cmd' script has been renamed 'newrelic'"
65
66
  script_name = 'newrelic'
@@ -35,4 +35,7 @@ module NewRelic
35
35
 
36
36
  CONNECT_RETRY_PERIODS = [15, 15, 30, 60, 120, 300]
37
37
  MAX_RETRY_PERIOD = 300
38
+
39
+ SLASH = '/'
40
+ ROOT = SLASH
38
41
  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
@@ -10,6 +10,9 @@ module NewRelic
10
10
  # Rails specific configuration, instrumentation, environment values,
11
11
  # etc.
12
12
  class Rails < NewRelic::Control::Frameworks::Ruby
13
+ BROWSER_MONITORING_INSTALLED_SINGLETON = NewRelic::Agent.config
14
+ BROWSER_MONITORING_INSTALLED_VARIABLE = :@browser_monitoring_installed
15
+
13
16
  def env
14
17
  @env ||= (ENV['NEW_RELIC_ENV'] || RAILS_ENV.dup)
15
18
  end
@@ -97,9 +100,9 @@ module NewRelic
97
100
 
98
101
  def install_browser_monitoring(config)
99
102
  @install_lock.synchronize do
100
- return if defined?(@browser_monitoring_installed) && @browser_monitoring_installed
103
+ return if browser_agent_already_installed?
101
104
 
102
- @browser_monitoring_installed = true
105
+ mark_browser_agent_as_installed
103
106
  return if config.nil? || !config.respond_to?(:middleware) || !Agent.config[:'browser_monitoring.auto_instrument']
104
107
 
105
108
  begin
@@ -112,6 +115,15 @@ module NewRelic
112
115
  end
113
116
  end
114
117
 
118
+ def browser_agent_already_installed?
119
+ BROWSER_MONITORING_INSTALLED_SINGLETON.instance_variable_defined?(BROWSER_MONITORING_INSTALLED_VARIABLE) &&
120
+ BROWSER_MONITORING_INSTALLED_SINGLETON.instance_variable_get(BROWSER_MONITORING_INSTALLED_VARIABLE)
121
+ end
122
+
123
+ def mark_browser_agent_as_installed
124
+ BROWSER_MONITORING_INSTALLED_SINGLETON.instance_variable_set(BROWSER_MONITORING_INSTALLED_VARIABLE, true)
125
+ end
126
+
115
127
  def rails_version
116
128
  @rails_version ||= Gem::Version.new(::Rails::VERSION::STRING)
117
129
  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,15 @@ 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
+
86
+ def snakeize(string)
87
+ string.gsub(/(.)([A-Z])/, '\1_\2').downcase
88
+ end
89
+
81
90
  def bundled_gem?(gem_name)
82
91
  defined?(Bundler) && Bundler.rubygems.all_specs.map(&:name).include?(gem_name)
83
92
  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
@@ -23,7 +23,7 @@ module NewRelic::Rack
23
23
  #
24
24
  class AgentHooks < AgentMiddleware
25
25
  def self.needed?
26
- !NewRelic::Agent.config[:disable_middleware_instrumentation]
26
+ NewRelic::Agent.config[:disable_middleware_instrumentation]
27
27
  end
28
28
 
29
29
  def traced_call(env)
@@ -26,22 +26,6 @@ module NewRelic
26
26
  prefix = ::NewRelic::Agent::Instrumentation::ControllerInstrumentation::TransactionNamer.prefix_for_category(nil, @category)
27
27
  "#{prefix}#{self.class.name}/call"
28
28
  end
29
-
30
- # If middleware tracing is disabled, we'll still inject our agent-specific
31
- # middlewares, and still trace those, but we don't want to capture HTTP
32
- # response codes, since middleware that's outside of ours might change the
33
- # response code before it goes back to the client.
34
- def capture_http_response_code(state, result)
35
- return if NewRelic::Agent.config[:disable_middleware_instrumentation]
36
-
37
- super
38
- end
39
-
40
- def capture_response_content_type(state, result)
41
- return if NewRelic::Agent.config[:disable_middleware_instrumentation]
42
-
43
- super
44
- end
45
29
  end
46
30
  end
47
31
  end
@@ -143,7 +143,7 @@ module NewRelic
143
143
  end
144
144
 
145
145
  # Per "The Response > The Body" section of Rack spec, we should close
146
- # if our response is able. http://rack.rubyforge.org/doc/SPEC.html
146
+ # if our response is able. https://github.com/rack/rack/blob/main/SPEC.rdoc
147
147
  def close_old_response(response)
148
148
  response.close if response.respond_to?(:close)
149
149
  end
@@ -46,6 +46,7 @@ module NewRelic
46
46
  :recording_web_transaction?,
47
47
  :require_test_helper,
48
48
  :set_error_group_callback,
49
+ :set_segment_callback,
49
50
  :set_sql_obfuscator,
50
51
  :set_transaction_name,
51
52
  :set_user_id,
@@ -6,7 +6,7 @@
6
6
  module NewRelic
7
7
  module VERSION # :nodoc:
8
8
  MAJOR = 9
9
- MINOR = 3
9
+ MINOR = 6
10
10
  TINY = 0
11
11
 
12
12
  STRING = "#{MAJOR}.#{MINOR}.#{TINY}"
@@ -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
@@ -82,7 +82,7 @@ class Instrumentation < Thor
82
82
  insert_into_file(
83
83
  DEFAULT_SOURCE_LOCATION,
84
84
  config_block(name.downcase),
85
- after: ":description => 'Controls auto-instrumentation of bunny at start up. May be one of [auto|prepend|chain|disabled].'
85
+ after: ":description => 'Controls auto-instrumentation of bunny at start-up. May be one of [auto|prepend|chain|disabled].'
86
86
  },\n"
87
87
  )
88
88
  end
@@ -103,7 +103,7 @@ class Instrumentation < Thor
103
103
  :type => String,
104
104
  :dynamic_name => true,
105
105
  :allowed_from_server => false,
106
- :description => 'Controls auto-instrumentation of the #{name} library at start up. May be one of [auto|prepend|chain|disabled].'
106
+ :description => 'Controls auto-instrumentation of the #{name} library at start-up. May be one of [auto|prepend|chain|disabled].'
107
107
  },
108
108
  CONFIG
109
109
  end
@@ -111,7 +111,7 @@ class Instrumentation < Thor
111
111
  def yaml_block(name)
112
112
  <<~HEREDOC
113
113
 
114
- # Controls auto-instrumentation of #{name} at start up.
114
+ # Controls auto-instrumentation of #{name} at start-up.
115
115
  # May be one of [auto|prepend|chain|disabled]
116
116
  # instrumentation.#{name.downcase}: auto
117
117
  HEREDOC
@@ -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/lib/tasks/tests.rake CHANGED
@@ -11,6 +11,75 @@ rescue LoadError
11
11
  end
12
12
 
13
13
  if defined? Rake::TestTask
14
+ def name_for_number(content, number)
15
+ (number - 1).downto(0).each do |i|
16
+ return Regexp.last_match(1) if content[i] =~ /^\s*def (test_.+)\s*$/
17
+ end
18
+ end
19
+
20
+ def info_from_test_var
21
+ return {} unless ENV['TEST'].to_s =~ /^(.+)((?::\d+)+)/
22
+
23
+ file = Regexp.last_match(1)
24
+ numbers = Regexp.last_match(2).split(':').reject(&:empty?).uniq.map(&:to_i)
25
+ abs = File.expand_path(File.join('../../..', file), __FILE__)
26
+ raise "File >>#{abs}<< does not exist!" unless File.exist?(abs)
27
+
28
+ content = File.read(abs).split("\n")
29
+ {file: file, numbers: numbers, content: content}
30
+ end
31
+
32
+ def test_names_from_test_file(info)
33
+ info[:numbers].each_with_object([]) do |number, names|
34
+ name = name_for_number(info[:content], number)
35
+ unless name
36
+ warn "Unable to determine a test name given line >>#{number}<< for file >>#{info[:file]}<<"
37
+ next
38
+ end
39
+ names << name
40
+ end
41
+ end
42
+
43
+ # Allow ENV['TEST'] to be set to a test file path with one or more
44
+ # `:<line number>` patterns on the end of it.
45
+ #
46
+ # For example:
47
+ # TEST=test/new_relic/agent/autostart_test.rb:57 bundle exec rake test
48
+ #
49
+ # The `autostart_test.rb` file will be read, and starting from line 57 and
50
+ # working upwards in the file (downwards by line number), a test definition
51
+ # will be searched for that matches `def test_<rest of the test name>`.
52
+ #
53
+ # Multiple line numbers can be specified like so:
54
+ # TEST=test/new_relic/agent/autostart_test.rb:57:26 bundle exec rake test
55
+ #
56
+ # For this multiple line number based example, both lines 57 and 26 will
57
+ # serve as separate starting points for the search for a test name.
58
+ #
59
+ # All test names that are discovered will be "ORed" into a regex pattern with
60
+ # pipes ('|') that is passed to Minitest via
61
+ # `TESTOPTS="--name='test_name1|test_name2'"`
62
+ #
63
+ # Once a line with one or more `:<line number>` values on the end of it has
64
+ # been found, replace the value of ENV['TEST'] with the path leading up to
65
+ # the first colon before invoking Minitest.
66
+ #
67
+ # Why refer to a test by line number instead of just supplying the name
68
+ # directly? The primary use case is text editor integration. A text editor
69
+ # can be taught to "run the single unit test containing the line the cursor is
70
+ # on" by building a string containing the path to the file, a colon, (':'),
71
+ # and the line number.
72
+ def process_line_numbers
73
+ info = info_from_test_var
74
+ return unless info.key?(:file)
75
+
76
+ test_names = test_names_from_test_file(info)
77
+ raise "Could not determine any test names for file >>#{abs}<< given numbers >>#{numbers}" if test_names.empty?
78
+
79
+ ENV['TESTOPTS'] = "#{ENV['TESTOPTS']} --name='#{test_names.map { |n| Regexp.escape(n) }.join('|')}'"
80
+ ENV['TEST'] = info[:file]
81
+ end
82
+
14
83
  namespace :test do
15
84
  tasks = Rake.application.top_level_tasks
16
85
  ENV['TESTOPTS'] ||= ''
@@ -21,6 +90,8 @@ if defined? Rake::TestTask
21
90
  ENV['TESTOPTS'] += ' --' + seed
22
91
  end
23
92
 
93
+ process_line_numbers
94
+
24
95
  agent_home = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
25
96
 
26
97
  Rake::TestTask.new(:newrelic) do |t|