newrelic_rpm 9.11.0 → 9.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +112 -0
  3. data/README.md +16 -20
  4. data/lib/new_relic/agent/agent_logger.rb +1 -0
  5. data/lib/new_relic/agent/configuration/default_source.rb +136 -5
  6. data/lib/new_relic/agent/configuration/manager.rb +8 -0
  7. data/lib/new_relic/agent/database/obfuscator.rb +1 -0
  8. data/lib/new_relic/agent/instrumentation/active_merchant.rb +0 -13
  9. data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +14 -0
  10. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +0 -19
  11. data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +1 -1
  12. data/lib/new_relic/agent/instrumentation/excon.rb +0 -16
  13. data/lib/new_relic/agent/instrumentation/grape.rb +3 -1
  14. data/lib/new_relic/agent/instrumentation/logstasher/chain.rb +21 -0
  15. data/lib/new_relic/agent/instrumentation/logstasher/instrumentation.rb +24 -0
  16. data/lib/new_relic/agent/instrumentation/logstasher/prepend.rb +13 -0
  17. data/lib/new_relic/agent/instrumentation/logstasher.rb +27 -0
  18. data/lib/new_relic/agent/instrumentation/opensearch/chain.rb +21 -0
  19. data/lib/new_relic/agent/instrumentation/opensearch/instrumentation.rb +66 -0
  20. data/lib/new_relic/agent/instrumentation/opensearch/prepend.rb +13 -0
  21. data/lib/new_relic/agent/instrumentation/opensearch.rb +25 -0
  22. data/lib/new_relic/agent/instrumentation/rack/instrumentation.rb +3 -0
  23. data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +9 -5
  24. data/lib/new_relic/agent/instrumentation/redis/cluster_middleware.rb +26 -0
  25. data/lib/new_relic/agent/instrumentation/redis/instrumentation.rb +14 -11
  26. data/lib/new_relic/agent/instrumentation/redis/middleware.rb +3 -0
  27. data/lib/new_relic/agent/instrumentation/redis.rb +11 -4
  28. data/lib/new_relic/agent/instrumentation/sidekiq.rb +0 -14
  29. data/lib/new_relic/agent/instrumentation/sinatra.rb +0 -13
  30. data/lib/new_relic/agent/local_log_decorator.rb +8 -1
  31. data/lib/new_relic/agent/log_event_aggregator.rb +91 -26
  32. data/lib/new_relic/agent/serverless_handler.rb +241 -12
  33. data/lib/new_relic/agent/serverless_handler_event_sources.json +155 -0
  34. data/lib/new_relic/agent/serverless_handler_event_sources.rb +49 -0
  35. data/lib/new_relic/agent/system_info.rb +14 -0
  36. data/lib/new_relic/agent/transaction/trace_context.rb +1 -1
  37. data/lib/new_relic/control/frameworks/grape.rb +14 -0
  38. data/lib/new_relic/control/frameworks/padrino.rb +14 -0
  39. data/lib/new_relic/control/frameworks/rails4.rb +4 -2
  40. data/lib/new_relic/control/instance_methods.rb +1 -0
  41. data/lib/new_relic/control/private_instance_methods.rb +4 -0
  42. data/lib/new_relic/control/security_interface.rb +57 -0
  43. data/lib/new_relic/control.rb +1 -1
  44. data/lib/new_relic/environment_report.rb +6 -2
  45. data/lib/new_relic/language_support.rb +7 -1
  46. data/lib/new_relic/local_environment.rb +1 -4
  47. data/lib/new_relic/rack/browser_monitoring.rb +11 -7
  48. data/lib/new_relic/version.rb +1 -1
  49. data/lib/tasks/config.rake +5 -2
  50. data/lib/tasks/helpers/config.html.erb +1 -1
  51. data/lib/tasks/helpers/format.rb +1 -1
  52. data/lib/tasks/helpers/newrelicyml.rb +76 -13
  53. data/lib/tasks/instrumentation_generator/instrumentation.thor +1 -0
  54. data/lib/tasks/instrumentation_generator/templates/dependency_detection.tt +3 -3
  55. data/newrelic.yml +209 -137
  56. data/test/agent_helper.rb +9 -0
  57. metadata +16 -2
@@ -0,0 +1,49 @@
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 'json'
6
+
7
+ module NewRelic
8
+ module Agent
9
+ # ServerlessHandlerEventSources - New Relic's language agent devs maintain
10
+ # a cross-agent JSON map of all AWS resources with the potential to invoke
11
+ # an AWS Lambda function by issuing it an event. This map is used to glean
12
+ # source specific attributes while instrumenting the function's invocation.
13
+ #
14
+ # Given that the event arrives as a Ruby hash argument to the AWS Lambda
15
+ # function, the JSON map's values need to be converted into arrays that can
16
+ # be passed to `Hash#dig`. So a value such as `'records[0].name'` needs to
17
+ # be converted to `['records', 0, 'name']`. This class's `.to_hash` method
18
+ # yields the converted data.
19
+ #
20
+ # Furthermore, `.length` calls are converted to Ruby `#size` notation to
21
+ # denote that a method call must be performed on the dug value.
22
+ class ServerlessHandlerEventSources
23
+ JSON_SOURCE = File.join(File.dirname(__FILE__), 'serverless_handler_event_sources.json').freeze
24
+ JSON_RAW = JSON.parse(File.read(JSON_SOURCE)).freeze
25
+
26
+ def self.to_hash
27
+ JSON_RAW.each_with_object({}) do |(type, info), hash|
28
+ hash[type] = {'attributes' => {},
29
+ 'name' => info['name'],
30
+ 'required_keys' => []}
31
+ info['attributes'].each { |attr, value| hash[type]['attributes'][attr] = transform(value) }
32
+ info['required_keys'].each { |key| hash[type]['required_keys'].push(transform(key)) }
33
+ end.freeze
34
+ end
35
+
36
+ def self.transform(value)
37
+ value.gsub(/\[(\d+)\]/, '.\1').split('.').map do |e|
38
+ if e.match?(/^\d+$/)
39
+ e.to_i
40
+ elsif e == 'length'
41
+ '#size'
42
+ else
43
+ e
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -19,6 +19,20 @@ module NewRelic
19
19
  RbConfig::CONFIG['target_os']
20
20
  end
21
21
 
22
+ def self.os_distribution
23
+ case
24
+ when darwin? then :darwin
25
+ when linux? then :linux
26
+ when bsd? then :bsd
27
+ when windows? then :windows
28
+ else ruby_os_identifier
29
+ end
30
+ end
31
+
32
+ def self.windows?
33
+ !!(ruby_os_identifier[/mingw|mswin/i])
34
+ end
35
+
22
36
  def self.darwin?
23
37
  !!(ruby_os_identifier =~ /darwin/i)
24
38
  end
@@ -95,7 +95,7 @@ module NewRelic
95
95
 
96
96
  def create_trace_state_payload
97
97
  unless Agent.config[:'distributed_tracing.enabled']
98
- NewRelic::Agent.logger.warn('Not configured to create WC3 trace context payload')
98
+ NewRelic::Agent.logger.warn('Not configured to create W3C trace context payload')
99
99
  return
100
100
  end
101
101
 
@@ -0,0 +1,14 @@
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 Grape
10
+ class Grape < NewRelic::Control::Frameworks::Ruby
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
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/sinatra'
6
+ module NewRelic
7
+ class Control
8
+ module Frameworks
9
+ # Contains basic control logic for Padrino
10
+ class Padrino < NewRelic::Control::Frameworks::Sinatra
11
+ end
12
+ end
13
+ end
14
+ end
@@ -9,8 +9,10 @@ module NewRelic
9
9
  module Frameworks
10
10
  class Rails4 < NewRelic::Control::Frameworks::Rails3
11
11
  def rails_gem_list
12
- Bundler.rubygems.all_specs.map do |gem|
13
- "#{gem.name} (#{gem.version})"
12
+ if Gem::Version.new(Bundler::VERSION) >= Gem::Version.new('2.0.0')
13
+ Bundler.rubygems.installed_specs.map { |gem| "#{gem.name} (#{gem.version})" }
14
+ else
15
+ Bundler.rubygems.all_specs.map { |gem| "#{gem.name} (#{gem.version})" }
14
16
  end
15
17
  end
16
18
 
@@ -73,6 +73,7 @@ module NewRelic
73
73
  init_config(options)
74
74
  NewRelic::Agent.agent = NewRelic::Agent::Agent.instance
75
75
  init_instrumentation
76
+ init_security_agent
76
77
  end
77
78
 
78
79
  def determine_env(options)
@@ -43,6 +43,10 @@ module NewRelic
43
43
  DependencyDetection.detect!
44
44
  end
45
45
  end
46
+
47
+ def init_security_agent
48
+ SecurityInterface.instance.init_agent
49
+ end
46
50
  end
47
51
  end
48
52
  end
@@ -0,0 +1,57 @@
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 'singleton'
6
+
7
+ module NewRelic
8
+ class Control
9
+ class SecurityInterface
10
+ include Singleton
11
+
12
+ attr_accessor :wait
13
+
14
+ SUPPORTABILITY_PREFIX_SECURITY = 'Supportability/Ruby/SecurityAgent/Enabled/'
15
+ SUPPORTABILITY_PREFIX_SECURITY_AGENT = 'Supportability/Ruby/SecurityAgent/Agent/Enabled/'
16
+ ENABLED = 'enabled'
17
+ DISABLED = 'disabled'
18
+
19
+ def agent_started?
20
+ (@agent_started ||= false) == true
21
+ end
22
+
23
+ def waiting?
24
+ (@wait ||= false) == true
25
+ end
26
+
27
+ def init_agent
28
+ return if agent_started? || waiting?
29
+
30
+ record_supportability_metrics
31
+
32
+ if Agent.config[:'security.agent.enabled'] && !Agent.config[:high_security]
33
+ Agent.logger.info('Invoking New Relic security module')
34
+ require 'newrelic_security'
35
+
36
+ @agent_started = true
37
+ else
38
+ Agent.logger.info('New Relic Security is completely disabled by one of the user-provided configurations: `security.agent.enabled` or `high_security`. Not loading security capabilities.')
39
+ Agent.logger.info("high_security = #{Agent.config[:high_security]}")
40
+ Agent.logger.info("security.agent.enabled = #{Agent.config[:'security.agent.enabled']}")
41
+ end
42
+ rescue LoadError
43
+ Agent.logger.info('New Relic security agent not found - skipping')
44
+ rescue StandardError => exception
45
+ Agent.logger.error("Exception in New Relic security module loading: #{exception} #{exception.backtrace}")
46
+ end
47
+
48
+ def record_supportability_metrics
49
+ Agent.config[:'security.agent.enabled'] ? security_agent_metric(ENABLED) : security_agent_metric(DISABLED)
50
+ end
51
+
52
+ def security_agent_metric(setting)
53
+ NewRelic::Agent.record_metric_once(SUPPORTABILITY_PREFIX_SECURITY_AGENT + setting)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -8,7 +8,6 @@ require 'new_relic/local_environment'
8
8
  require 'new_relic/language_support'
9
9
  require 'new_relic/helper'
10
10
 
11
- require 'singleton'
12
11
  require 'erb'
13
12
  require 'socket'
14
13
  require 'net/https'
@@ -18,6 +17,7 @@ require 'new_relic/control/server_methods'
18
17
  require 'new_relic/control/instrumentation'
19
18
  require 'new_relic/control/class_methods'
20
19
  require 'new_relic/control/instance_methods'
20
+ require 'new_relic/control/security_interface'
21
21
 
22
22
  require 'new_relic/agent'
23
23
  require 'new_relic/delayed_job_injection'
@@ -44,7 +44,11 @@ module NewRelic
44
44
  ####################################
45
45
  report_on('Gems') do
46
46
  begin
47
- Bundler.rubygems.all_specs.map { |gem| "#{gem.name}(#{gem.version})" }
47
+ if Gem::Version.new(Bundler::VERSION) >= Gem::Version.new('2.0.0')
48
+ Bundler.rubygems.installed_specs.map { |gem| "#{gem.name}(#{gem.version})" }
49
+ else
50
+ Bundler.rubygems.all_specs.map { |gem| "#{gem.name}(#{gem.version})" }
51
+ end
48
52
  rescue
49
53
  # There are certain rubygem, bundler, rails combinations (e.g. gem
50
54
  # 1.6.2, rails 2.3, bundler 1.2.3) where the code above throws an error
@@ -67,7 +71,7 @@ module NewRelic
67
71
  report_on('Physical Cores') { ::NewRelic::Agent::SystemInfo.num_physical_cores }
68
72
  report_on('Arch') { ::NewRelic::Agent::SystemInfo.processor_arch }
69
73
  report_on('OS version') { ::NewRelic::Agent::SystemInfo.os_version }
70
- report_on('OS') { ::NewRelic::Agent::SystemInfo.ruby_os_identifier }
74
+ report_on('OS') { ::NewRelic::Agent::SystemInfo.os_distribution }
71
75
  report_on('Database adapter') { ::NewRelic::Agent::DatabaseAdapter.value }
72
76
  report_on('Framework') { Agent.config[:framework].to_s }
73
77
  report_on('Dispatcher') { Agent.config[:dispatcher].to_s }
@@ -88,7 +88,13 @@ module NewRelic
88
88
  end
89
89
 
90
90
  def bundled_gem?(gem_name)
91
- defined?(Bundler) && Bundler.rubygems.all_specs.map(&:name).include?(gem_name)
91
+ return false unless defined?(Bundler)
92
+
93
+ if Gem::Version.new(Bundler::VERSION) >= Gem::Version.new('2.0.0')
94
+ Bundler.rubygems.installed_specs.map(&:name).include?(gem_name)
95
+ else
96
+ Bundler.rubygems.all_specs.map(&:name).include?(gem_name)
97
+ end
92
98
  rescue => e
93
99
  ::NewRelic::Agent.logger.info("Could not determine if third party #{gem_name} gem is installed", e)
94
100
  false
@@ -142,10 +142,7 @@ module NewRelic
142
142
  end
143
143
 
144
144
  def check_for_falcon
145
- return unless defined?(::Falcon::Server) &&
146
- NewRelic::LanguageSupport.object_space_usable?
147
-
148
- @discovered_dispatcher = :falcon if find_class_in_object_space(::Falcon::Server)
145
+ @discovered_dispatcher = :falcon if defined?(::Falcon::Server) && File.basename($PROGRAM_NAME) == 'falcon'
149
146
  end
150
147
 
151
148
  def check_for_delayed_job
@@ -20,15 +20,15 @@ module NewRelic
20
20
  # examine in order to look for a RUM insertion point.
21
21
  SCAN_LIMIT = 50_000
22
22
 
23
- CONTENT_TYPE = 'Content-Type'.freeze
24
- CONTENT_DISPOSITION = 'Content-Disposition'.freeze
25
- CONTENT_LENGTH = 'Content-Length'.freeze
23
+ CONTENT_TYPE = 'Content-Type'
24
+ CONTENT_DISPOSITION = 'Content-Disposition'
25
+ CONTENT_LENGTH = 'Content-Length'
26
26
  ATTACHMENT = /attachment/.freeze
27
27
  TEXT_HTML = %r{text/html}.freeze
28
28
 
29
- BODY_START = '<body'.freeze
30
- HEAD_START = '<head'.freeze
31
- GT = '>'.freeze
29
+ BODY_START = '<body'
30
+ HEAD_START = '<head'
31
+ GT = '>'
32
32
 
33
33
  ALREADY_INSTRUMENTED_KEY = 'newrelic.browser_monitoring_already_instrumented'
34
34
  CHARSET_RE = /<\s*meta[^>]+charset\s*=[^>]*>/im.freeze
@@ -120,7 +120,11 @@ module NewRelic
120
120
  end
121
121
 
122
122
  def streaming?(env, headers)
123
- # Chunked transfer encoding is a streaming data transfer mechanism available only in HTTP/1.1
123
+ # Up until version 8.0, Rails would set 'Transfer-Encoding' to 'chunked'
124
+ # to trigger the desired HTTP/1.1 based streaming functionality in Rack.
125
+ # With version v8.0+, Rails assumes that the web server will be using
126
+ # Rack v3+ or an equally modern alternative and simply leaves the
127
+ # streaming behavior up to them.
124
128
  return true if headers && headers['Transfer-Encoding'] == 'chunked'
125
129
 
126
130
  defined?(ActionController::Live) &&
@@ -6,7 +6,7 @@
6
6
  module NewRelic
7
7
  module VERSION # :nodoc:
8
8
  MAJOR = 9
9
- MINOR = 11
9
+ MINOR = 13
10
10
  TINY = 0
11
11
 
12
12
  STRING = "#{MAJOR}.#{MINOR}.#{TINY}"
@@ -23,13 +23,16 @@ namespace :newrelic do
23
23
  'browser_monitoring' => "The <InlinePopover type='browser' /> [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
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:",
25
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.',
26
- 'ai_monitoring' => "This section includes Ruby agent configurations for setting up AI monitoring.\n\n<Callout variant='important'>You need to enable distributed tracing to capture trace and feedback data. It is turned on by default in Ruby agents 8.0.0 and higher.</Callout>"
26
+ 'ai_monitoring' => "This section includes Ruby agent configurations for setting up AI monitoring.\n\n<Callout variant='important'>You need to enable distributed tracing to capture trace and feedback data. It is turned on by default in Ruby agents 8.0.0 and higher.</Callout>",
27
+ 'security_agent' => "[New Relic Interactive Application Security Testing](https://docs.newrelic.com/docs/iast/introduction/) (IAST) tests your applications for any exploitable vulnerability by replaying the generated HTTP request with vulnerable payloads.\n\n<Callout variant='important'>Run IAST with non-production deployments only to avoid exposing vulnerabilities on your production software. \
28
+ IAST mode requires Ruby agent version 9.12.0 or higher and the [newrelic_security](https://rubygems.org/gems/newrelic_security) gem. Security agent configurations are disabled by default.</Callout>"
27
29
  }
28
30
 
29
31
  NAME_OVERRIDES = {
30
32
  'slow_sql' => 'Slow SQL [#slow-sql]',
31
33
  'custom_insights_events' => 'Custom Events [#custom-events]',
32
- 'ai_monitoring' => 'AI Monitoring [#ai-monitoring]'
34
+ 'ai_monitoring' => 'AI Monitoring [#ai-monitoring]',
35
+ 'security_agent' => 'Security Agent [#security-agent]'
33
36
  }
34
37
 
35
38
  desc 'Describe available New Relic configuration settings'
@@ -76,7 +76,7 @@ When running the Ruby agent in a Rails app, the agent first looks for the `NEW_R
76
76
  When you edit the config file, be sure to:
77
77
 
78
78
  * Indent only with two spaces.
79
- * Indent only where relevant, in sections such as <DoNotTranslate>**`error_collector`**</DoNotTranslate>.
79
+ * Indent only where relevant, in sections such as **`error_collector`**.
80
80
 
81
81
  If you do not indent correctly, the agent may throw an `Unable to parse configuration file` error on startup.
82
82
 
@@ -69,7 +69,7 @@ module Format
69
69
 
70
70
  def format_description(value)
71
71
  description = ''
72
- description += '<DoNotTranslate>**DEPRECATED**</DoNotTranslate>' if value[:deprecated]
72
+ description += '<DNT>**DEPRECATED**</DNT> ' if value[:deprecated]
73
73
  description += value[:description]
74
74
  description
75
75
  end
@@ -45,6 +45,34 @@ module NewRelicYML
45
45
 
46
46
  HEADER
47
47
 
48
+ SECURITY_BEGIN = <<-SECURITY
49
+ # BEGIN security agent
50
+ #
51
+ # NOTE: At this time, the security agent is intended for use only within
52
+ # a dedicated security testing environment with data that can tolerate
53
+ # modification or deletion. The security agent is available as a
54
+ # separate Ruby gem, newrelic_security. It is recommended that this
55
+ # separate gem only be introduced to a security testing environment
56
+ # by leveraging Bundler grouping like so:
57
+ #
58
+ # # Gemfile
59
+ # gem 'newrelic_rpm' # New Relic APM observability agent
60
+ # gem 'newrelic-infinite_tracing' # New Relic Infinite Tracing
61
+ #
62
+ # group :security do
63
+ # gem 'newrelic_security', require: false # New Relic security agent
64
+ # end
65
+ #
66
+ # NOTE: All "security.*" configuration parameters are related only to the
67
+ # security agent, and all other configuration parameters that may
68
+ # have "security" in the name somewhere are related to the APM agent.
69
+
70
+ SECURITY
71
+
72
+ SECURITY_END = <<-SECURITY
73
+ # END security agent
74
+ SECURITY
75
+
48
76
  FOOTER = <<~FOOTER
49
77
  # Environment-specific settings are in this section.
50
78
  # RAILS_ENV or RACK_ENV (as appropriate) is used to determine the environment.
@@ -67,16 +95,35 @@ module NewRelicYML
67
95
  FOOTER
68
96
 
69
97
  def self.get_configs(defaults)
70
- defaults.sort.each_with_object({}) do |(key, value), final_configs|
98
+ agent_configs = {}
99
+ security_configs = {}
100
+
101
+ defaults.sort.each do |key, value|
71
102
  next if CRITICAL.include?(key) || SKIP.include?(key)
72
103
 
73
104
  next unless public_config?(value) && !deprecated?(value)
74
105
 
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}
106
+ # TODO: OLD RUBIES < 2.6
107
+ # Remove `to_s`. `start_with?` doesn't accept symbols in Ruby <2.6
108
+ if key.to_s.start_with?('security.')
109
+ description, default = build_config(key, value)
110
+ security_configs[key] = {description: description, default: default}
111
+ next
112
+ end
113
+
114
+ description, default = build_config(key, value)
115
+ agent_configs[key] = {description: description, default: default}
79
116
  end
117
+
118
+ [agent_configs, security_configs]
119
+ end
120
+
121
+ def self.build_config(key, value)
122
+ sanitized_description = sanitize_description(value[:description])
123
+ description = format_description(sanitized_description)
124
+ default = default_value(key, value)
125
+
126
+ [description, default]
80
127
  end
81
128
 
82
129
  def self.public_config?(value)
@@ -105,8 +152,9 @@ module NewRelicYML
105
152
  def self.format_description(description)
106
153
  # remove leading and trailing whitespace
107
154
  description.strip!
108
- # wrap text after 80 characters
109
- description.gsub!(/(.{1,80})(\s+|\Z)/, "\\1\n")
155
+ # wrap text after 80 characters, assuming we're at one tabstop's (two
156
+ # spaces') level of indentation already
157
+ description.gsub!(/(.{1,78})(\s+|\Z)/, "\\1\n")
110
158
  # add hashtags to lines
111
159
  description = description.split("\n").map { |line| " # #{line}" }.join("\n")
112
160
 
@@ -125,15 +173,30 @@ module NewRelicYML
125
173
  end
126
174
  end
127
175
 
128
- def self.build_string(defaults)
129
- configs = get_configs(defaults)
130
- yml_string = ''
176
+ def self.agent_configs_yml(agent_configs)
177
+ agent_yml = ''
178
+ agent_configs.each do |key, value|
179
+ agent_yml += "#{value[:description]}\n # #{key}: #{value[:default]}\n\n"
180
+ end
181
+
182
+ agent_yml
183
+ end
131
184
 
132
- configs.each do |key, value|
133
- yml_string += "#{value[:description]}\n # #{key}: #{value[:default]}\n\n"
185
+ def self.security_configs_yml(security_configs)
186
+ security_yml = ''
187
+ security_configs.each do |key, value|
188
+ security_yml += "#{value[:description]}\n # #{key}: #{value[:default]}\n\n"
134
189
  end
135
190
 
136
- yml_string
191
+ security_yml
192
+ end
193
+
194
+ def self.build_string(defaults)
195
+ agent_configs, security_configs = get_configs(defaults)
196
+ agent_string = agent_configs_yml(agent_configs)
197
+ security_string = security_configs_yml(security_configs)
198
+
199
+ agent_string + SECURITY_BEGIN + security_string + SECURITY_END + "\n"
137
200
  end
138
201
 
139
202
  # :nocov:
@@ -103,6 +103,7 @@ class Instrumentation < Thor
103
103
  <<-CONFIG
104
104
  :'instrumentation.#{snake_name}' => {
105
105
  :default => 'auto',
106
+ :documentation_default => 'auto',
106
107
  :public => true,
107
108
  :type => String,
108
109
  :dynamic_name => true,
@@ -12,16 +12,16 @@ DependencyDetection.defer do
12
12
  depends_on do
13
13
  # The class that needs to be defined to prepend/chain onto. This can be used
14
14
  # to determine whether the library is installed.
15
- defined?(::<%= @class_name %>)
15
+ defined?(<%= @class_name %>)
16
16
  # Add any additional requirements to verify whether this instrumentation
17
17
  # should be installed
18
18
  end
19
19
 
20
20
  executes do
21
- ::NewRelic::Agent.logger.info('Installing <%= @name.downcase %> instrumentation')
21
+ NewRelic::Agent.logger.info('Installing <%= @name.downcase %> instrumentation')
22
22
 
23
23
  if use_prepend?
24
- prepend_instrument ::<%= @class_name %>, NewRelic::Agent::Instrumentation::<%= @class_name %>::Prepend
24
+ prepend_instrument <%= @class_name %>, NewRelic::Agent::Instrumentation::<%= @class_name %>::Prepend
25
25
  else
26
26
  chain_instrument NewRelic::Agent::Instrumentation::<%= @class_name %>::Chain
27
27
  end