newrelic_rpm 9.2.0 → 9.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/.build_ignore +26 -0
  3. data/CHANGELOG.md +197 -2
  4. data/README.md +8 -4
  5. data/lib/new_relic/agent/attribute_pre_filtering.rb +109 -0
  6. data/lib/new_relic/agent/configuration/default_source.rb +218 -63
  7. data/lib/new_relic/agent/configuration/environment_source.rb +1 -1
  8. data/lib/new_relic/agent/configuration/manager.rb +14 -0
  9. data/lib/new_relic/agent/configuration/yaml_source.rb +13 -0
  10. data/lib/new_relic/agent/distributed_tracing.rb +1 -1
  11. data/lib/new_relic/agent/error_collector.rb +1 -1
  12. data/lib/new_relic/agent/instrumentation/action_controller_other_subscriber.rb +1 -1
  13. data/lib/new_relic/agent/instrumentation/active_record.rb +1 -1
  14. data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +2 -1
  15. data/lib/new_relic/agent/instrumentation/active_support_logger/instrumentation.rb +4 -0
  16. data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +9 -0
  17. data/lib/new_relic/agent/instrumentation/concurrent_ruby/chain.rb +1 -1
  18. data/lib/new_relic/agent/instrumentation/concurrent_ruby/instrumentation.rb +3 -4
  19. data/lib/new_relic/agent/instrumentation/concurrent_ruby/prepend.rb +1 -1
  20. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +1 -2
  21. data/lib/new_relic/agent/instrumentation/curb/instrumentation.rb +4 -0
  22. data/lib/new_relic/agent/instrumentation/delayed_job/instrumentation.rb +3 -0
  23. data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +4 -1
  24. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +3 -0
  25. data/lib/new_relic/agent/instrumentation/fiber/chain.rb +10 -3
  26. data/lib/new_relic/agent/instrumentation/fiber/instrumentation.rb +1 -2
  27. data/lib/new_relic/agent/instrumentation/fiber/prepend.rb +10 -3
  28. data/lib/new_relic/agent/instrumentation/grape/instrumentation.rb +4 -0
  29. data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +4 -0
  30. data/lib/new_relic/agent/instrumentation/grpc/server/instrumentation.rb +4 -0
  31. data/lib/new_relic/agent/instrumentation/grpc_client.rb +1 -1
  32. data/lib/new_relic/agent/instrumentation/grpc_server.rb +1 -1
  33. data/lib/new_relic/agent/instrumentation/httpclient/instrumentation.rb +4 -0
  34. data/lib/new_relic/agent/instrumentation/httprb/instrumentation.rb +4 -0
  35. data/lib/new_relic/agent/instrumentation/logger/instrumentation.rb +3 -0
  36. data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +12 -3
  37. data/lib/new_relic/agent/instrumentation/memcache.rb +2 -2
  38. data/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb +4 -0
  39. data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +4 -0
  40. data/lib/new_relic/agent/instrumentation/padrino/instrumentation.rb +4 -0
  41. data/lib/new_relic/agent/instrumentation/queue_time.rb +1 -1
  42. data/lib/new_relic/agent/instrumentation/rack/instrumentation.rb +6 -0
  43. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +4 -0
  44. data/lib/new_relic/agent/instrumentation/rails_notifications/action_cable.rb +1 -1
  45. data/lib/new_relic/agent/instrumentation/rake/instrumentation.rb +4 -0
  46. data/lib/new_relic/agent/instrumentation/redis/instrumentation.rb +4 -0
  47. data/lib/new_relic/agent/instrumentation/resque/instrumentation.rb +4 -0
  48. data/lib/new_relic/agent/instrumentation/roda/chain.rb +43 -0
  49. data/lib/new_relic/agent/instrumentation/roda/instrumentation.rb +56 -0
  50. data/lib/new_relic/agent/instrumentation/roda/prepend.rb +24 -0
  51. data/lib/new_relic/agent/instrumentation/roda/roda_transaction_namer.rb +30 -0
  52. data/lib/new_relic/agent/instrumentation/roda.rb +34 -0
  53. data/lib/new_relic/agent/instrumentation/sequel.rb +1 -1
  54. data/lib/new_relic/agent/instrumentation/sidekiq/client.rb +4 -0
  55. data/lib/new_relic/agent/instrumentation/sidekiq/server.rb +26 -3
  56. data/lib/new_relic/agent/instrumentation/sidekiq.rb +2 -2
  57. data/lib/new_relic/agent/instrumentation/sinatra/instrumentation.rb +4 -0
  58. data/lib/new_relic/agent/instrumentation/stripe.rb +28 -0
  59. data/lib/new_relic/agent/instrumentation/stripe_subscriber.rb +77 -0
  60. data/lib/new_relic/agent/instrumentation/thread/chain.rb +1 -1
  61. data/lib/new_relic/agent/instrumentation/thread/instrumentation.rb +0 -1
  62. data/lib/new_relic/agent/instrumentation/thread/prepend.rb +1 -1
  63. data/lib/new_relic/agent/instrumentation/tilt/instrumentation.rb +4 -0
  64. data/lib/new_relic/agent/instrumentation/typhoeus/instrumentation.rb +5 -1
  65. data/lib/new_relic/agent/log_event_aggregator.rb +49 -2
  66. data/lib/new_relic/agent/log_event_attributes.rb +115 -0
  67. data/lib/new_relic/agent/logging.rb +4 -4
  68. data/lib/new_relic/agent/method_tracer_helpers.rb +26 -5
  69. data/lib/new_relic/agent/new_relic_service.rb +33 -17
  70. data/lib/new_relic/agent/pipe_service.rb +1 -1
  71. data/lib/new_relic/agent/tracer.rb +7 -6
  72. data/lib/new_relic/agent/transaction/abstract_segment.rb +52 -0
  73. data/lib/new_relic/agent/transaction/request_attributes.rb +45 -7
  74. data/lib/new_relic/agent/transaction/tracing.rb +6 -0
  75. data/lib/new_relic/agent/transaction.rb +9 -4
  76. data/lib/new_relic/agent/utilization/vendor.rb +5 -7
  77. data/lib/new_relic/agent.rb +50 -1
  78. data/lib/new_relic/cli/command.rb +1 -0
  79. data/lib/new_relic/control/class_methods.rb +1 -7
  80. data/lib/new_relic/control/frameworks/roda.rb +20 -0
  81. data/lib/new_relic/control/instrumentation.rb +0 -14
  82. data/lib/new_relic/dependency_detection.rb +16 -1
  83. data/lib/new_relic/language_support.rb +5 -0
  84. data/lib/new_relic/latest_changes.rb +1 -1
  85. data/lib/new_relic/noticed_error.rb +5 -2
  86. data/lib/new_relic/rack/agent_hooks.rb +1 -1
  87. data/lib/new_relic/rack/agent_middleware.rb +0 -16
  88. data/lib/new_relic/rack/browser_monitoring.rb +1 -1
  89. data/lib/new_relic/supportability_helper.rb +2 -0
  90. data/lib/new_relic/traced_thread.rb +2 -3
  91. data/lib/new_relic/version.rb +1 -1
  92. data/lib/sequel/extensions/new_relic_instrumentation.rb +1 -1
  93. data/lib/tasks/bump_version.rake +21 -0
  94. data/lib/tasks/config.rake +3 -2
  95. data/lib/tasks/helpers/config.html.erb +93 -0
  96. data/lib/tasks/helpers/format.rb +11 -7
  97. data/lib/tasks/helpers/newrelicyml.rb +144 -0
  98. data/lib/tasks/helpers/version_bump.rb +62 -0
  99. data/lib/tasks/newrelicyml.rake +13 -0
  100. data/newrelic.yml +364 -267
  101. data/newrelic_rpm.gemspec +11 -7
  102. metadata +36 -25
  103. data/.gitignore +0 -43
  104. data/.project +0 -23
  105. data/.rubocop.yml +0 -1845
  106. data/.rubocop_todo.yml +0 -61
  107. data/.simplecov +0 -16
  108. data/.snyk +0 -11
  109. data/.yardopts +0 -27
  110. data/Brewfile +0 -13
  111. data/DOCKER.md +0 -167
  112. data/Dockerfile +0 -10
  113. data/Guardfile +0 -27
  114. data/config/database.yml +0 -5
  115. data/config.dot +0 -278
  116. data/docker-compose.yml +0 -107
  117. data/lefthook.yml +0 -9
  118. data/lib/tasks/helpers/removers.rb +0 -33
  119. data/lib/tasks/multiverse.rake +0 -6
  120. data/lib/tasks/multiverse.rb +0 -84
@@ -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
@@ -62,7 +62,6 @@ module NewRelic
62
62
  File.join(instrumentation_path, app.to_s, '*.rb')
63
63
  @instrumentation_files.each { |pattern| load_instrumentation_files(pattern) }
64
64
  DependencyDetection.detect!
65
- ruby_deprecation
66
65
  rails_32_deprecation
67
66
  ::NewRelic::Agent.logger.info('Finished instrumentation')
68
67
  end
@@ -81,19 +80,6 @@ module NewRelic
81
80
  )
82
81
  end
83
82
 
84
- def ruby_deprecation
85
- return unless RUBY_VERSION < '2.4.0'
86
-
87
- deprecation_msg = 'The Ruby Agent is dropping support for Rubies below 2.4 ' \
88
- 'in version 9.0.0. Please upgrade your Ruby version to continue receiving support. ' \
89
-
90
- ::NewRelic::Agent.logger.log_once(
91
- :warn,
92
- :deprecated_ruby_version,
93
- deprecation_msg
94
- )
95
- end
96
-
97
83
  include Instrumentation
98
84
  end
99
85
  end
@@ -27,6 +27,8 @@ module DependencyDetection
27
27
  @items.each do |item|
28
28
  if item.dependencies_satisfied?
29
29
  item.execute
30
+ else
31
+ item.configure_as_unsatisfied unless item.disabled_configured?
30
32
  end
31
33
  end
32
34
  end
@@ -62,6 +64,10 @@ module DependencyDetection
62
64
  !executed and check_dependencies
63
65
  end
64
66
 
67
+ def configure_as_unsatisfied
68
+ NewRelic::Agent.config.instance_variable_get(:@cache)[config_key] = :unsatisfied
69
+ end
70
+
65
71
  def source_location_for(klass, method_name)
66
72
  Object.instance_method(:method).bind(klass.allocate).call(method_name).source_location.to_s
67
73
  end
@@ -179,6 +185,15 @@ module DependencyDetection
179
185
  return valid_value
180
186
  end
181
187
 
188
+ # update any :auto config value to be either :prepend or :chain after auto
189
+ # determination has selected one of those to use
190
+ def update_config_value(use_prepend)
191
+ if config_key && auto_configured?
192
+ NewRelic::Agent.config.instance_variable_get(:@cache)[config_key] = use_prepend ? :prepend : :chain
193
+ end
194
+ use_prepend
195
+ end
196
+
182
197
  def config_value
183
198
  return AUTO_CONFIG_VALUE unless config_key
184
199
 
@@ -202,7 +217,7 @@ module DependencyDetection
202
217
  end
203
218
 
204
219
  def use_prepend?
205
- prepend_configured? || (auto_configured? && !prepend_conflicts?)
220
+ update_config_value(prepend_configured? || (auto_configured? && !prepend_conflicts?))
206
221
  end
207
222
 
208
223
  def prepend_conflicts?
@@ -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
@@ -8,7 +8,7 @@ module NewRelic
8
8
  File.join(File.dirname(__FILE__), '..', '..', 'CHANGELOG.md')
9
9
  end
10
10
 
11
- FOOTER = <<'EOS'
11
+ FOOTER = <<EOS
12
12
  See https://github.com/newrelic/newrelic-ruby-agent/blob/main/CHANGELOG.md for a full list of
13
13
  changes.
14
14
  EOS
@@ -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
@@ -13,6 +13,7 @@ module NewRelic
13
13
  :insert_distributed_trace_headers,
14
14
  :accept_distributed_trace_headers,
15
15
  :add_custom_attributes,
16
+ :add_custom_log_attributes,
16
17
  :add_custom_span_attributes,
17
18
  :add_instrumentation,
18
19
  :add_method_tracer,
@@ -45,6 +46,7 @@ module NewRelic
45
46
  :recording_web_transaction?,
46
47
  :require_test_helper,
47
48
  :set_error_group_callback,
49
+ :set_segment_callback,
48
50
  :set_sql_obfuscator,
49
51
  :set_transaction_name,
50
52
  :set_user_id,
@@ -22,15 +22,14 @@ module NewRelic
22
22
  # @api public
23
23
  def initialize(*args, &block)
24
24
  NewRelic::Agent.record_api_supportability_metric(:traced_thread)
25
- traced_block = create_traced_block(*args, &block)
25
+ traced_block = create_traced_block(&block)
26
26
  super(*args, &traced_block)
27
27
  end
28
28
 
29
- def create_traced_block(*args, &block)
29
+ def create_traced_block(&block)
30
30
  return block if NewRelic::Agent.config[:'instrumentation.thread.tracing'] # if this is on, don't double trace
31
31
 
32
32
  NewRelic::Agent::Tracer.thread_block_with_current_transaction(
33
- *args,
34
33
  segment_name: 'Ruby/TracedThread',
35
34
  &block
36
35
  )
@@ -6,7 +6,7 @@
6
6
  module NewRelic
7
7
  module VERSION # :nodoc:
8
8
  MAJOR = 9
9
- MINOR = 2
9
+ MINOR = 5
10
10
  TINY = 0
11
11
 
12
12
  STRING = "#{MAJOR}.#{MINOR}.#{TINY}"
@@ -27,7 +27,7 @@ module Sequel
27
27
  # If you don't want your models or database connections to be instrumented,
28
28
  # you can disable them by setting `disable_database_instrumentation` in
29
29
  # your `newrelic.yml` to `true`. It will also honor the
30
- # `disable_activerecord_instrumentation` setting.
30
+ # `disable_active_record_instrumentation` setting.
31
31
  #
32
32
  module NewRelicInstrumentation
33
33
  module Naming
@@ -0,0 +1,21 @@
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 'helpers/version_bump'
6
+
7
+ namespace :newrelic do
8
+ namespace :version do
9
+ desc 'Returns the current version'
10
+ task :current do
11
+ puts "#{NewRelic::VERSION::STRING}"
12
+ end
13
+
14
+ desc 'Update version file and changelog to next version'
15
+ task :bump, [:format] => [] do |t, args|
16
+ new_version = VersionBump.update_version
17
+ VersionBump.update_changelog(new_version)
18
+ puts "New version: #{new_version}"
19
+ end
20
+ end
21
+ end
@@ -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)
@@ -0,0 +1,144 @@
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 '../../new_relic/agent/configuration/default_source'
6
+
7
+ module NewRelicYML
8
+ CRITICAL = [:'agent_enabled', :'app_name', :'license_key', :'log_level']
9
+ DEFAULTS = NewRelic::Agent::Configuration::DEFAULTS
10
+ # Skip because not configurable via yml
11
+ SKIP = [:'defer_rails_initialization']
12
+ # Don't evaluate Procs, instead use set values
13
+ PROCS = {:'config_path' => 'newrelic.yml',
14
+ :'process_host.display_name' => 'default hostname',
15
+ :'transaction_tracer.transaction_threshold' => 1.0}
16
+
17
+ HEADER = <<~HEADER
18
+ #
19
+ # This file configures the New Relic Agent. New Relic monitors Ruby, Java,
20
+ # .NET, PHP, Python, Node, and Go applications with deep visibility and low
21
+ # overhead. For more information, visit www.newrelic.com.
22
+
23
+ # Generated <%= Time.now.strftime('%B %d, %Y') %><%= ", for version \#{@agent_version}" if @agent_version %>
24
+ #<%= "\\n# \#{generated_for_user}\\n#" if generated_for_user %>
25
+ # For full documentation of agent configuration options, please refer to
26
+ # https://docs.newrelic.com/docs/agents/ruby-agent/installation-configuration/ruby-agent-configuration
27
+
28
+ common: &default_settings
29
+ # Required license key associated with your New Relic account.
30
+ license_key: <%= license_key %>
31
+
32
+ # Your application name. Renaming here affects where data displays in New
33
+ # Relic. For more details, see https://docs.newrelic.com/docs/apm/new-relic-apm/maintenance/renaming-applications
34
+ app_name: <%= app_name %>
35
+
36
+ # To disable the agent regardless of other settings, uncomment the following:
37
+ # agent_enabled: false
38
+
39
+ # Logging level for log/newrelic_agent.log; options are error, warn, info, or
40
+ # debug.
41
+ log_level: info
42
+
43
+ # All of the following configuration options are optional. Review them, and
44
+ # uncomment or edit them if they appear relevant to your application needs.
45
+
46
+ HEADER
47
+
48
+ FOOTER = <<~FOOTER
49
+ # Environment-specific settings are in this section.
50
+ # RAILS_ENV or RACK_ENV (as appropriate) is used to determine the environment.
51
+ # If your application has other named environments, configure them here.
52
+ development:
53
+ <<: *default_settings
54
+ app_name: <%= app_name %> (Development)
55
+
56
+ test:
57
+ <<: *default_settings
58
+ # It doesn't make sense to report to New Relic from automated test runs.
59
+ monitor_mode: false
60
+
61
+ staging:
62
+ <<: *default_settings
63
+ app_name: <%= app_name %> (Staging)
64
+
65
+ production:
66
+ <<: *default_settings
67
+ FOOTER
68
+
69
+ def self.get_configs(defaults)
70
+ defaults.sort.each_with_object({}) do |(key, value), final_configs|
71
+ next if CRITICAL.include?(key) || SKIP.include?(key)
72
+
73
+ next unless public_config?(value) && !deprecated?(value)
74
+
75
+ sanitized_description = sanitize_description(value[:description])
76
+ description = format_description(sanitized_description)
77
+ default = default_value(key, value)
78
+ final_configs[key] = {description: description, default: default}
79
+ end
80
+ end
81
+
82
+ def self.public_config?(value)
83
+ value[:public] == true
84
+ end
85
+
86
+ def self.deprecated?(value)
87
+ value[:deprecated] == true
88
+ end
89
+
90
+ def self.sanitize_description(description)
91
+ # remove callouts
92
+ description = description.split("\n").reject { |line| line.match?('</?Callout') }.join("\n")
93
+ # remove InlinePopover, keep the text inside type
94
+ description.gsub!(/<InlinePopover type="(.*)" \/>/, '\1')
95
+ # remove hyperlinks
96
+ description.gsub!(/\[([^\]]+)\]\([^\)]+\)/, '\1')
97
+ # remove single pairs of backticks
98
+ description.gsub!(/`([^`]+)`/, '\1')
99
+ # removed href links
100
+ description.gsub!(/<a href="(.*)">(.*)<\/a>/, '\2')
101
+
102
+ description
103
+ end
104
+
105
+ def self.format_description(description)
106
+ # remove leading and trailing whitespace
107
+ description.strip!
108
+ # wrap text after 80 characters
109
+ description.gsub!(/(.{1,80})(\s+|\Z)/, "\\1\n")
110
+ # add hashtags to lines
111
+ description = description.split("\n").map { |line| " # #{line}" }.join("\n")
112
+
113
+ description
114
+ end
115
+
116
+ def self.default_value(key, config_hash)
117
+ if PROCS.include?(key)
118
+ PROCS[key]
119
+ else
120
+ default = config_hash[:documentation_default].nil? ? config_hash[:default] : config_hash[:documentation_default]
121
+ default = 'nil' if default.nil?
122
+ default = '""' if default == ''
123
+
124
+ default
125
+ end
126
+ end
127
+
128
+ def self.build_string(defaults)
129
+ configs = get_configs(defaults)
130
+ yml_string = ''
131
+
132
+ configs.each do |key, value|
133
+ yml_string += "#{value[:description]}\n # #{key}: #{value[:default]}\n\n"
134
+ end
135
+
136
+ yml_string
137
+ end
138
+
139
+ # :nocov:
140
+ def self.write_file(defaults = DEFAULTS)
141
+ File.write('newrelic.yml', HEADER + build_string(defaults) + FOOTER)
142
+ end
143
+ # :nocov:
144
+ end
@@ -0,0 +1,62 @@
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 VersionBump
6
+ MAJOR = 0
7
+ MINOR = 1
8
+ TINY = 2
9
+ VERSION = {major: MAJOR, minor: MINOR, tiny: TINY}
10
+
11
+ # Updates version.rb with new version number
12
+ def self.update_version
13
+ bump_type = determine_bump_type
14
+ file = read_file('lib/new_relic/version.rb')
15
+ new_version = {}
16
+
17
+ VERSION.each do |key, current|
18
+ file.gsub!(/(#{key.to_s.upcase} = )(\d+)/) do
19
+ match = Regexp.last_match
20
+
21
+ new_version[key] = if bump_type == current # bump type, increase by 1
22
+ match[2].to_i + 1
23
+ elsif bump_type < current # right of bump type, goes to 0
24
+ 0
25
+ else # left of bump type, stays the same
26
+ match[2].to_i
27
+ end
28
+
29
+ match[1] + new_version[key].to_s
30
+ end
31
+ end
32
+
33
+ write_file('lib/new_relic/version.rb', file)
34
+ new_version.values.join('.')
35
+ end
36
+
37
+ def self.read_file(path)
38
+ File.read(File.expand_path(path))
39
+ end
40
+
41
+ def self.write_file(path, file)
42
+ File.write(File.expand_path(path), file)
43
+ end
44
+
45
+ # Determined version based on if changelog has a feature or not for version
46
+ def self.determine_bump_type
47
+ file = read_file('CHANGELOG.md')
48
+ lines = file.split('## ')[1].split('- **')
49
+ return MAJOR if lines.first.include?('Major version')
50
+ return MINOR if lines.any? { |line| line.include?('Feature:') }
51
+
52
+ TINY
53
+ end
54
+
55
+ # Replace dev with version number in changelog
56
+ def self.update_changelog(version)
57
+ file = read_file('CHANGELOG.md')
58
+ file.gsub!('## dev', "## v#{version}")
59
+ file.gsub!('Version <dev>', "Version #{version}")
60
+ write_file('CHANGELOG.md', file)
61
+ end
62
+ end