newrelic_rpm 8.13.1 → 8.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.rubocop.yml +1 -0
  4. data/CHANGELOG.md +3257 -3152
  5. data/CONTRIBUTING.md +1 -2
  6. data/init.rb +1 -1
  7. data/lib/new_relic/agent/agent.rb +14 -466
  8. data/lib/new_relic/agent/agent_helpers/connect.rb +227 -0
  9. data/lib/new_relic/agent/agent_helpers/harvest.rb +153 -0
  10. data/lib/new_relic/agent/agent_helpers/shutdown.rb +72 -0
  11. data/lib/new_relic/agent/agent_helpers/special_startup.rb +75 -0
  12. data/lib/new_relic/agent/agent_helpers/start_worker_thread.rb +167 -0
  13. data/lib/new_relic/agent/agent_helpers/startup.rb +202 -0
  14. data/lib/new_relic/agent/agent_helpers/transmit.rb +76 -0
  15. data/lib/new_relic/agent/configuration/default_source.rb +22 -0
  16. data/lib/new_relic/agent/datastores.rb +2 -2
  17. data/lib/new_relic/agent/guid_generator.rb +11 -2
  18. data/lib/new_relic/agent/instrumentation/active_job.rb +7 -7
  19. data/lib/new_relic/agent/instrumentation/active_merchant.rb +2 -2
  20. data/lib/new_relic/agent/instrumentation/active_record.rb +9 -9
  21. data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +24 -24
  22. data/lib/new_relic/agent/instrumentation/active_storage.rb +2 -2
  23. data/lib/new_relic/agent/instrumentation/active_support.rb +12 -0
  24. data/lib/new_relic/agent/instrumentation/active_support_logger.rb +3 -3
  25. data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +2 -2
  26. data/lib/new_relic/agent/instrumentation/authlogic.rb +2 -2
  27. data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +3 -3
  28. data/lib/new_relic/agent/instrumentation/bunny.rb +4 -4
  29. data/lib/new_relic/agent/instrumentation/curb/instrumentation.rb +1 -1
  30. data/lib/new_relic/agent/instrumentation/curb.rb +6 -6
  31. data/lib/new_relic/agent/instrumentation/custom_events_subscriber.rb +37 -0
  32. data/lib/new_relic/agent/instrumentation/data_mapper.rb +50 -50
  33. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +5 -5
  34. data/lib/new_relic/agent/instrumentation/elasticsearch.rb +5 -5
  35. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +1 -1
  36. data/lib/new_relic/agent/instrumentation/excon.rb +9 -9
  37. data/lib/new_relic/agent/instrumentation/grape.rb +8 -8
  38. data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +1 -1
  39. data/lib/new_relic/agent/instrumentation/grpc_client.rb +3 -3
  40. data/lib/new_relic/agent/instrumentation/grpc_server.rb +4 -4
  41. data/lib/new_relic/agent/instrumentation/httpclient/instrumentation.rb +1 -1
  42. data/lib/new_relic/agent/instrumentation/httpclient.rb +2 -2
  43. data/lib/new_relic/agent/instrumentation/httprb/instrumentation.rb +1 -1
  44. data/lib/new_relic/agent/instrumentation/httprb.rb +3 -3
  45. data/lib/new_relic/agent/instrumentation/logger.rb +3 -3
  46. data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +3 -3
  47. data/lib/new_relic/agent/instrumentation/memcache.rb +16 -16
  48. data/lib/new_relic/agent/instrumentation/mongo.rb +1 -1
  49. data/lib/new_relic/agent/instrumentation/net_http.rb +6 -6
  50. data/lib/new_relic/agent/instrumentation/padrino.rb +3 -3
  51. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +5 -5
  52. data/lib/new_relic/agent/instrumentation/rack.rb +14 -14
  53. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +5 -5
  54. data/lib/new_relic/agent/instrumentation/rails_middleware.rb +3 -3
  55. data/lib/new_relic/agent/instrumentation/rails_notifications/action_cable.rb +6 -6
  56. data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +2 -2
  57. data/lib/new_relic/agent/instrumentation/rails_notifications/action_view.rb +5 -3
  58. data/lib/new_relic/agent/instrumentation/rails_notifications/custom_events.rb +30 -0
  59. data/lib/new_relic/agent/instrumentation/rainbows_instrumentation.rb +4 -4
  60. data/lib/new_relic/agent/instrumentation/rake.rb +7 -7
  61. data/lib/new_relic/agent/instrumentation/redis/instrumentation.rb +29 -8
  62. data/lib/new_relic/agent/instrumentation/redis.rb +4 -4
  63. data/lib/new_relic/agent/instrumentation/resque.rb +9 -9
  64. data/lib/new_relic/agent/instrumentation/sequel.rb +2 -2
  65. data/lib/new_relic/agent/instrumentation/sidekiq.rb +3 -3
  66. data/lib/new_relic/agent/instrumentation/sinatra.rb +7 -7
  67. data/lib/new_relic/agent/instrumentation/sunspot.rb +4 -4
  68. data/lib/new_relic/agent/instrumentation/thread.rb +3 -3
  69. data/lib/new_relic/agent/instrumentation/tilt.rb +3 -3
  70. data/lib/new_relic/agent/instrumentation/typhoeus/instrumentation.rb +2 -2
  71. data/lib/new_relic/agent/instrumentation/typhoeus.rb +1 -1
  72. data/lib/new_relic/agent/method_tracer_helpers.rb +6 -11
  73. data/lib/new_relic/agent/tracer.rb +1 -1
  74. data/lib/new_relic/agent/transaction/segment.rb +6 -0
  75. data/lib/new_relic/control/instance_methods.rb +6 -2
  76. data/lib/new_relic/recipes/helpers/send_deployment.rb +2 -1
  77. data/lib/new_relic/version.rb +2 -2
  78. data/lib/newrelic_rpm.rb +13 -2
  79. data/lib/sequel/extensions/newrelic_instrumentation.rb +1 -1
  80. data/lib/sequel/plugins/newrelic_instrumentation.rb +1 -1
  81. data/newrelic.yml +10 -0
  82. data/test/agent_helper.rb +5 -5
  83. metadata +12 -6
  84. data/lib/new_relic/agent/agent/shutdown.rb +0 -35
  85. data/lib/new_relic/agent/agent/special_startup.rb +0 -72
  86. data/lib/new_relic/agent/agent/start_worker_thread.rb +0 -163
  87. data/lib/new_relic/agent/agent/startup.rb +0 -197
@@ -1,163 +0,0 @@
1
- # This file is distributed under New Relic's license terms.
2
- # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
- # frozen_string_literal: true
4
-
5
- module NewRelic
6
- module Agent
7
- module StartWorkerThread
8
- LOG_ONCE_KEYS_RESET_PERIOD = 60.0
9
-
10
- TRANSACTION_EVENT_DATA = "transaction_event_data".freeze
11
- CUSTOM_EVENT_DATA = "custom_event_data".freeze
12
- ERROR_EVENT_DATA = "error_event_data".freeze
13
- SPAN_EVENT_DATA = "span_event_data".freeze
14
- LOG_EVENT_DATA = "log_event_data".freeze
15
-
16
- # Try to launch the worker thread and connect to the server.
17
- #
18
- # See #connect for a description of connection_options.
19
- def start_worker_thread(connection_options = {})
20
- if disable = NewRelic::Agent.config[:disable_harvest_thread]
21
- NewRelic::Agent.logger.info("Not starting Ruby Agent worker thread because :disable_harvest_thread is #{disable}")
22
- return
23
- end
24
-
25
- ::NewRelic::Agent.logger.debug("Creating Ruby Agent worker thread.")
26
- @worker_thread = Threading::AgentThread.create('Worker Loop') do
27
- deferred_work!(connection_options)
28
- end
29
- end
30
-
31
- def create_event_loop
32
- EventLoop.new
33
- end
34
-
35
- # If the @worker_thread encounters an error during the attempt to connect to the collector
36
- # then the connect attempts enter an exponential backoff retry loop. To avoid potential
37
- # race conditions with shutting down while also attempting to reconnect, we join the
38
- # @worker_thread with a timeout threshold. This allows potentially connecting and flushing
39
- # pending data to the server, but without waiting indefinitely for a reconnect to succeed.
40
- # The use-case where this typically arises is in cronjob scheduled rake tasks where there's
41
- # also some network stability/latency issues happening.
42
- def stop_event_loop
43
- @event_loop.stop if @event_loop
44
- # Wait the end of the event loop thread.
45
- if @worker_thread
46
- unless @worker_thread.join(3)
47
- ::NewRelic::Agent.logger.debug("Event loop thread did not stop within 3 seconds")
48
- end
49
- end
50
- end
51
-
52
- # Certain event types may sometimes need to be on the same interval as metrics,
53
- # so we will check config assigned in EventHarvestConfig to determine the interval
54
- # on which to report them
55
- def interval_for(event_type)
56
- interval = Agent.config[:"event_report_period.#{event_type}"]
57
- :"#{interval}_second_harvest"
58
- end
59
-
60
- def create_and_run_event_loop
61
- data_harvest = :"#{Agent.config[:data_report_period]}_second_harvest"
62
- event_harvest = :"#{Agent.config[:event_report_period]}_second_harvest"
63
-
64
- @event_loop = create_event_loop
65
- @event_loop.on(data_harvest) do
66
- transmit_data
67
- end
68
-
69
- @event_loop.on(interval_for(TRANSACTION_EVENT_DATA)) do
70
- transmit_analytic_event_data
71
- end
72
- @event_loop.on(interval_for(CUSTOM_EVENT_DATA)) do
73
- transmit_custom_event_data
74
- end
75
- @event_loop.on(interval_for(ERROR_EVENT_DATA)) do
76
- transmit_error_event_data
77
- end
78
- @event_loop.on(interval_for(SPAN_EVENT_DATA)) do
79
- transmit_span_event_data
80
- end
81
- @event_loop.on(interval_for(LOG_EVENT_DATA)) do
82
- transmit_log_event_data
83
- end
84
-
85
- @event_loop.on(:reset_log_once_keys) do
86
- ::NewRelic::Agent.logger.clear_already_logged
87
- end
88
- @event_loop.fire_every(Agent.config[:data_report_period], data_harvest)
89
- @event_loop.fire_every(Agent.config[:event_report_period], event_harvest)
90
- @event_loop.fire_every(LOG_ONCE_KEYS_RESET_PERIOD, :reset_log_once_keys)
91
-
92
- @event_loop.run
93
- end
94
-
95
- # Handles the case where the server tells us to restart -
96
- # this clears the data, clears connection attempts, and
97
- # waits a while to reconnect.
98
- def handle_force_restart(error)
99
- ::NewRelic::Agent.logger.debug(error.message)
100
- drop_buffered_data
101
- @service.force_restart if @service
102
- @connect_state = :pending
103
- sleep(30)
104
- end
105
-
106
- # when a disconnect is requested, stop the current thread, which
107
- # is the worker thread that gathers data and talks to the
108
- # server.
109
- def handle_force_disconnect(error)
110
- ::NewRelic::Agent.logger.warn("Agent received a ForceDisconnectException from the server, disconnecting. (#{error.message})")
111
- disconnect
112
- end
113
-
114
- # Handles an unknown error in the worker thread by logging
115
- # it and disconnecting the agent, since we are now in an
116
- # unknown state.
117
- def handle_other_error(error)
118
- ::NewRelic::Agent.logger.error("Unhandled error in worker thread, disconnecting.")
119
- # These errors are fatal (that is, they will prevent the agent from
120
- # reporting entirely), so we really want backtraces when they happen
121
- ::NewRelic::Agent.logger.log_exception(:error, error)
122
- disconnect
123
- end
124
-
125
- # a wrapper method to handle all the errors that can happen
126
- # in the connection and worker thread system. This
127
- # guarantees a no-throw from the background thread.
128
- def catch_errors
129
- yield
130
- rescue NewRelic::Agent::ForceRestartException => e
131
- handle_force_restart(e)
132
- retry
133
- rescue NewRelic::Agent::ForceDisconnectException => e
134
- handle_force_disconnect(e)
135
- rescue => e
136
- handle_other_error(e)
137
- end
138
-
139
- # This is the method that is run in a new thread in order to
140
- # background the harvesting and sending of data during the
141
- # normal operation of the agent.
142
- #
143
- # Takes connection options that determine how we should
144
- # connect to the server, and loops endlessly - typically we
145
- # never return from this method unless we're shutting down
146
- # the agent
147
- def deferred_work!(connection_options)
148
- catch_errors do
149
- NewRelic::Agent.disable_all_tracing do
150
- connect(connection_options)
151
- if connected?
152
- create_and_run_event_loop
153
- # never reaches here unless there is a problem or
154
- # the agent is exiting
155
- else
156
- ::NewRelic::Agent.logger.debug("No connection. Worker thread ending.")
157
- end
158
- end
159
- end
160
- end
161
- end
162
- end
163
- end
@@ -1,197 +0,0 @@
1
- # This file is distributed under New Relic's license terms.
2
- # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
- # frozen_string_literal: true
4
-
5
- module NewRelic
6
- module Agent
7
- module Startup
8
- # True if we have initialized and completed 'start'
9
- def started?
10
- @started
11
- end
12
-
13
- # Check whether we have already started, which is an error condition
14
- def already_started?
15
- if started?
16
- ::NewRelic::Agent.logger.error("Agent Started Already!")
17
- true
18
- end
19
- end
20
-
21
- # Logs a bunch of data and starts the agent, if needed
22
- def start
23
- return unless agent_should_start?
24
-
25
- log_startup
26
- check_config_and_start_agent
27
- log_version_and_pid
28
-
29
- events.subscribe(:initial_configuration_complete) do
30
- log_ignore_url_regexes
31
- end
32
- end
33
-
34
- # Sanity-check the agent configuration and start the agent,
35
- # setting up the worker thread and the exit handler to shut
36
- # down the agent
37
- def check_config_and_start_agent
38
- return unless monitoring? && has_correct_license_key?
39
- return if using_forking_dispatcher?
40
-
41
- setup_and_start_agent
42
- end
43
-
44
- # This is the shared method between the main agent startup and the
45
- # after_fork call restarting the thread in deferred dispatchers.
46
- #
47
- # Treatment of @started and env report is important to get right.
48
- def setup_and_start_agent(options = {})
49
- @started = true
50
- @harvester.mark_started
51
-
52
- unless in_resque_child_process?
53
- install_exit_handler
54
- environment_for_connect
55
- @harvest_samplers.load_samplers unless Agent.config[:disable_samplers]
56
- end
57
-
58
- connect_in_foreground if Agent.config[:sync_startup]
59
- start_worker_thread(options)
60
- end
61
-
62
- # Log startup information that we almost always want to know
63
- def log_startup
64
- log_environment
65
- log_dispatcher
66
- log_app_name
67
- end
68
-
69
- # Log the environment the app thinks it's running in.
70
- # Useful in debugging, as this is the key for config YAML lookups.
71
- def log_environment
72
- ::NewRelic::Agent.logger.info("Environment: #{NewRelic::Control.instance.env}")
73
- end
74
-
75
- # Logs the dispatcher to the log file to assist with
76
- # debugging. When no debugger is present, logs this fact to
77
- # assist with proper dispatcher detection
78
- def log_dispatcher
79
- dispatcher_name = Agent.config[:dispatcher].to_s
80
-
81
- if dispatcher_name.empty?
82
- ::NewRelic::Agent.logger.info('No known dispatcher detected.')
83
- else
84
- ::NewRelic::Agent.logger.info("Dispatcher: #{dispatcher_name}")
85
- end
86
- end
87
-
88
- def log_app_name
89
- ::NewRelic::Agent.logger.info("Application: #{Agent.config[:app_name].join(", ")}")
90
- end
91
-
92
- def log_ignore_url_regexes
93
- regexes = NewRelic::Agent.config[:'rules.ignore_url_regexes']
94
-
95
- unless regexes.empty?
96
- ::NewRelic::Agent.logger.info("Ignoring URLs that match the following regexes: #{regexes.map(&:inspect).join(", ")}.")
97
- end
98
- end
99
-
100
- # Classy logging of the agent version and the current pid,
101
- # so we can disambiguate processes in the log file and make
102
- # sure they're running a reasonable version
103
- def log_version_and_pid
104
- ::NewRelic::Agent.logger.debug("New Relic Ruby Agent #{NewRelic::VERSION::STRING} Initialized: pid = #{$$}")
105
- end
106
-
107
- # Logs the configured application names
108
- def app_name_configured?
109
- names = Agent.config[:app_name]
110
- return names.respond_to?(:any?) && names.any?
111
- end
112
-
113
- # Connecting in the foreground blocks further startup of the
114
- # agent until we have a connection - useful in cases where
115
- # you're trying to log a very-short-running process and want
116
- # to get statistics from before a server connection
117
- # (typically 20 seconds) exists
118
- def connect_in_foreground
119
- NewRelic::Agent.disable_all_tracing { connect(:keep_retrying => false) }
120
- end
121
-
122
- # Warn the user if they have configured their agent not to
123
- # send data, that way we can see this clearly in the log file
124
- def monitoring?
125
- if Agent.config[:monitor_mode]
126
- true
127
- else
128
- ::NewRelic::Agent.logger.warn('Agent configured not to send data in this environment.')
129
- false
130
- end
131
- end
132
-
133
- # Tell the user when the license key is missing so they can
134
- # fix it by adding it to the file
135
- def has_license_key?
136
- if Agent.config[:license_key] && Agent.config[:license_key].length > 0
137
- true
138
- else
139
- ::NewRelic::Agent.logger.warn("No license key found. " +
140
- "This often means your newrelic.yml file was not found, or it lacks a section for the running environment, '#{NewRelic::Control.instance.env}'. You may also want to try linting your newrelic.yml to ensure it is valid YML.")
141
- false
142
- end
143
- end
144
-
145
- # A correct license key exists and is of the proper length
146
- def has_correct_license_key?
147
- has_license_key? && correct_license_length
148
- end
149
-
150
- # A license key is an arbitrary 40 character string,
151
- # usually looks something like a SHA1 hash
152
- def correct_license_length
153
- key = Agent.config[:license_key]
154
-
155
- if key.length == 40
156
- true
157
- else
158
- ::NewRelic::Agent.logger.error("Invalid license key: #{key}")
159
- false
160
- end
161
- end
162
-
163
- # Check to see if the agent should start, returning +true+ if it should.
164
- def agent_should_start?
165
- return false if already_started? || disabled?
166
-
167
- if defer_for_delayed_job?
168
- ::NewRelic::Agent.logger.debug("Deferring startup for DelayedJob")
169
- return false
170
- end
171
-
172
- if defer_for_resque?
173
- ::NewRelic::Agent.logger.debug("Deferring startup for Resque in case it daemonizes")
174
- return false
175
- end
176
-
177
- unless app_name_configured?
178
- NewRelic::Agent.logger.error("No application name configured.",
179
- "The Agent cannot start without at least one. Please check your ",
180
- "newrelic.yml and ensure that it is valid and has at least one ",
181
- "value set for app_name in the #{NewRelic::Control.instance.env} ",
182
- "environment.")
183
- return false
184
- end
185
-
186
- return true
187
- end
188
-
189
- # The agent is disabled when it is not force enabled by the
190
- # 'agent_enabled' option (e.g. in a manual start), or
191
- # enabled normally through the configuration file
192
- def disabled?
193
- !Agent.config[:agent_enabled]
194
- end
195
- end
196
- end
197
- end