newrelic_rpm 3.5.4.35.beta → 3.5.5.38
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +42 -0
- data/GUIDELINES_FOR_CONTRIBUTING.md +3 -0
- data/Rakefile +8 -0
- data/bin/mongrel_rpm +1 -1
- data/init.rb +1 -8
- data/lib/new_relic/agent.rb +11 -13
- data/lib/new_relic/agent/agent.rb +89 -110
- data/lib/new_relic/agent/agent_logger.rb +165 -0
- data/lib/new_relic/agent/audit_logger.rb +72 -0
- data/lib/new_relic/agent/beacon_configuration.rb +4 -4
- data/lib/new_relic/agent/browser_monitoring.rb +13 -7
- data/lib/new_relic/agent/busy_calculator.rb +2 -2
- data/lib/new_relic/agent/configuration.rb +25 -0
- data/lib/new_relic/agent/configuration/defaults.rb +45 -8
- data/lib/new_relic/agent/configuration/environment_source.rb +8 -15
- data/lib/new_relic/agent/configuration/manager.rb +22 -2
- data/lib/new_relic/agent/configuration/mask_defaults.rb +10 -0
- data/lib/new_relic/agent/configuration/yaml_source.rb +4 -2
- data/lib/new_relic/agent/cross_process_monitoring.rb +43 -0
- data/lib/new_relic/agent/database.rb +2 -4
- data/lib/new_relic/agent/error_collector.rb +4 -9
- data/lib/new_relic/agent/instrumentation/active_merchant.rb +1 -1
- data/lib/new_relic/agent/instrumentation/active_record.rb +1 -1
- data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +1 -1
- data/lib/new_relic/agent/instrumentation/authlogic.rb +1 -1
- data/lib/new_relic/agent/instrumentation/browser_monitoring_timings.rb +41 -0
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +7 -7
- data/lib/new_relic/agent/instrumentation/data_mapper.rb +1 -1
- data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +1 -1
- data/lib/new_relic/agent/instrumentation/memcache.rb +4 -4
- data/lib/new_relic/agent/instrumentation/merb/controller.rb +1 -1
- data/lib/new_relic/agent/instrumentation/merb/errors.rb +1 -1
- data/lib/new_relic/agent/instrumentation/metric_frame/pop.rb +1 -1
- data/lib/new_relic/agent/instrumentation/net.rb +1 -1
- data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +2 -2
- data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +4 -4
- data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +1 -1
- data/lib/new_relic/agent/instrumentation/rails/errors.rb +1 -1
- data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +3 -3
- data/lib/new_relic/agent/instrumentation/rails3/errors.rb +1 -1
- data/lib/new_relic/agent/instrumentation/resque.rb +3 -2
- data/lib/new_relic/agent/instrumentation/sinatra.rb +1 -1
- data/lib/new_relic/agent/instrumentation/sunspot.rb +1 -1
- data/lib/new_relic/agent/instrumentation/unicorn_instrumentation.rb +2 -2
- data/lib/new_relic/agent/method_tracer.rb +6 -8
- data/lib/new_relic/agent/new_relic_service.rb +94 -106
- data/lib/new_relic/agent/pipe_channel_manager.rb +1 -1
- data/lib/new_relic/agent/samplers/memory_sampler.rb +4 -6
- data/lib/new_relic/agent/sql_sampler.rb +3 -18
- data/lib/new_relic/agent/stats_engine.rb +0 -5
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +3 -3
- data/lib/new_relic/agent/stats_engine/samplers.rb +2 -4
- data/lib/new_relic/agent/thread.rb +8 -3
- data/lib/new_relic/agent/thread_profiler.rb +38 -27
- data/lib/new_relic/agent/transaction_info.rb +1 -1
- data/lib/new_relic/agent/transaction_sample_builder.rb +2 -3
- data/lib/new_relic/agent/transaction_sampler.rb +3 -7
- data/lib/new_relic/agent/worker_loop.rb +3 -11
- data/lib/new_relic/control.rb +0 -2
- data/lib/new_relic/control/class_methods.rb +8 -2
- data/lib/new_relic/control/frameworks/merb.rb +0 -6
- data/lib/new_relic/control/frameworks/rails.rb +8 -29
- data/lib/new_relic/control/frameworks/rails3.rb +8 -20
- data/lib/new_relic/control/frameworks/rails4.rb +23 -0
- data/lib/new_relic/control/frameworks/ruby.rb +1 -22
- data/lib/new_relic/control/instance_methods.rb +12 -34
- data/lib/new_relic/control/instrumentation.rb +7 -12
- data/lib/new_relic/control/server_methods.rb +5 -8
- data/lib/new_relic/delayed_job_injection.rb +1 -1
- data/lib/new_relic/local_environment.rb +30 -64
- data/lib/new_relic/metric_data.rb +1 -1
- data/lib/new_relic/metric_spec.rb +1 -1
- data/lib/new_relic/noticed_error.rb +1 -1
- data/lib/new_relic/rack/browser_monitoring.rb +5 -5
- data/lib/new_relic/stats.rb +9 -7
- data/lib/new_relic/transaction_sample.rb +2 -7
- data/lib/new_relic/version.rb +1 -1
- data/lib/newrelic_rpm.rb +1 -1
- data/newrelic_rpm.gemspec.erb +15 -17
- data/test/config/newrelic.yml +1 -1
- data/test/config/test_control.rb +18 -18
- data/test/fixtures/gemspec_no_build.rb +0 -2
- data/test/fixtures/gemspec_with_build.rb +0 -2
- data/test/fixtures/gemspec_with_build_and_stage.rb +0 -2
- data/test/multiverse/README.md +3 -8
- data/test/multiverse/suites/agent_only/Envfile +1 -0
- data/test/multiverse/suites/agent_only/audit_log_test.rb +99 -0
- data/test/multiverse/suites/agent_only/marshaling_test.rb +1 -1
- data/test/multiverse/suites/config_file_loading/Envfile +7 -0
- data/test/multiverse/suites/config_file_loading/config_file_loading_test.rb +106 -0
- data/test/multiverse/suites/logging/Envfile +4 -0
- data/test/multiverse/suites/logging/config/newrelic.yml +22 -0
- data/test/multiverse/suites/logging/logging_test.rb +143 -0
- data/test/multiverse/suites/no_load/config/newrelic.yml +1 -2
- data/test/multiverse/suites/rum_auto_instrumentation/sanity_test.rb +0 -13
- data/test/new_relic/agent/agent/connect_test.rb +30 -92
- data/test/new_relic/agent/agent/start_test.rb +4 -84
- data/test/new_relic/agent/agent/start_worker_thread_test.rb +8 -43
- data/test/new_relic/agent/agent_logger_test.rb +153 -0
- data/test/new_relic/agent/agent_test.rb +10 -9
- data/test/new_relic/agent/audit_logger_test.rb +105 -0
- data/test/new_relic/agent/browser_monitoring_test.rb +2 -1
- data/test/new_relic/agent/busy_calculator_test.rb +7 -0
- data/test/new_relic/agent/configuration/environment_source_test.rb +25 -20
- data/test/new_relic/agent/configuration/manager_test.rb +59 -4
- data/test/new_relic/agent/configuration/yaml_source_test.rb +20 -1
- data/test/new_relic/agent/cross_process_monitoring_test.rb +77 -0
- data/test/new_relic/agent/database_test.rb +0 -11
- data/test/new_relic/agent/error_collector/notice_error_test.rb +1 -3
- data/test/new_relic/agent/error_collector_test.rb +11 -7
- data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +39 -19
- data/test/new_relic/agent/instrumentation/browser_monitoring_timings_test.rb +39 -0
- data/test/new_relic/agent/instrumentation/metric_frame/pop_test.rb +1 -1
- data/test/new_relic/agent/method_tracer/class_methods/add_method_tracer_test.rb +0 -6
- data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +3 -15
- data/test/new_relic/agent/new_relic_service_test.rb +48 -8
- data/test/new_relic/agent/pipe_channel_manager_test.rb +1 -1
- data/test/new_relic/agent/sql_sampler_test.rb +1 -1
- data/test/new_relic/agent/thread_profiler_test.rb +46 -45
- data/test/new_relic/agent/thread_test.rb +13 -0
- data/test/new_relic/agent/transaction_sample_builder_test.rb +1 -1
- data/test/new_relic/agent/worker_loop_test.rb +4 -9
- data/test/new_relic/agent_test.rb +6 -9
- data/test/new_relic/control/class_methods_test.rb +0 -18
- data/test/new_relic/control_test.rb +6 -9
- data/test/new_relic/dispatcher_test.rb +54 -0
- data/test/new_relic/fake_collector.rb +15 -14
- data/test/new_relic/fake_service.rb +4 -1
- data/test/new_relic/fakes_sending_data.rb +30 -0
- data/test/new_relic/framework_test.rb +53 -0
- data/test/new_relic/local_environment_test.rb +5 -2
- data/test/new_relic/rack/browser_monitoring_test.rb +2 -1
- data/test/new_relic/rack/developer_mode_test.rb +1 -1
- data/test/new_relic/stats_test.rb +10 -0
- data/test/new_relic/transaction_sample_test.rb +2 -2
- data/test/script/ci.sh +1 -1
- data/test/test_helper.rb +23 -0
- data/ui/views/newrelic/file/images/arrow-close.png +0 -0
- data/ui/views/newrelic/file/images/arrow-open.png +0 -0
- data/ui/views/newrelic/file/images/blue_bar.gif +0 -0
- data/ui/views/newrelic/file/images/file_icon.png +0 -0
- data/ui/views/newrelic/file/images/gray_bar.gif +0 -0
- metadata +47 -41
- data/InstallationNotes.md +0 -15
- data/lib/new_relic/control/logging_methods.rb +0 -125
- data/test/multiverse/Rakefile +0 -17
- data/test/multiverse/suites/rum_auto_instrumentation/problem_response.html +0 -422
- data/test/new_relic/control/logging_methods_test.rb +0 -211
data/CHANGELOG
CHANGED
@@ -1,6 +1,48 @@
|
|
1
1
|
|
2
2
|
# New Relic Ruby Agent Release Notes #
|
3
3
|
|
4
|
+
## v3.5.5 ##
|
5
|
+
|
6
|
+
* Add thread profiling support
|
7
|
+
|
8
|
+
Thread profiling performs statistical sampling of backtraces of all threads
|
9
|
+
within your Ruby processes. This feature requires MRI >= 1.9.2, and is
|
10
|
+
controlled via the New Relic web UI. JRuby support (in 1.9.x compat mode) is
|
11
|
+
considered experimental, due to issues with JRuby's Thread#backtrace.
|
12
|
+
|
13
|
+
* Add audit logging capability
|
14
|
+
|
15
|
+
The agent can now log all of the data it sends to the New Relic servers to
|
16
|
+
a special log file for human inspection. This feature is off by default, and
|
17
|
+
can be enabled by setting the audit_log.enabled configuration key to true.
|
18
|
+
You may also control the location of the audit log with the audit_log.path key.
|
19
|
+
|
20
|
+
* Use config system for dispatcher, framework, and config file detection
|
21
|
+
|
22
|
+
Several aspects of the agent's configuration were not being handled by the
|
23
|
+
configuration system. Detection/configuration of the dispatcher (e.g. passenger,
|
24
|
+
unicorn, resque), framework (e.g. rails3, sinatra), and newrelic.yml
|
25
|
+
location are now handled via the Agent environment, manual, and default
|
26
|
+
configuration sources.
|
27
|
+
|
28
|
+
* Updates to logging across the agent
|
29
|
+
|
30
|
+
We've carefully reviewed the logging messages that the agent outputs, adding
|
31
|
+
details in some cases, and removing unnecessary clutter. We've also altered
|
32
|
+
the startup sequence to ensure that we don't spam STDOUT with messages
|
33
|
+
during initialization.
|
34
|
+
|
35
|
+
* Fix passing environment to manual_start()
|
36
|
+
|
37
|
+
Thanks to Justin Hannus. The :env key, when passed to Agent.manual_start,
|
38
|
+
can again be used to specify which section of newrelic.yml is loaded.
|
39
|
+
|
40
|
+
* Rails 4 support
|
41
|
+
|
42
|
+
This release includes preliminary support for Rails 4 as of 4.0.0.beta.
|
43
|
+
Rails 4 is still in development, but the agent should work as expected for
|
44
|
+
people who are experimenting with the beta.
|
45
|
+
|
4
46
|
## v3.5.4 ##
|
5
47
|
|
6
48
|
* Add queue time support for sinatra apps
|
@@ -64,6 +64,9 @@ These tests can be run by invoking:
|
|
64
64
|
bundle
|
65
65
|
bundle exec rake test:multiverse
|
66
66
|
|
67
|
+
More details are available in
|
68
|
+
[test/multiverse/README.md](https://github.com/newrelic/rpm/blob/master/test/multiverse/README.md).
|
69
|
+
|
67
70
|
### And Finally...
|
68
71
|
|
69
72
|
You are welcome to send pull requests to us - however, by doing so you agree
|
data/Rakefile
CHANGED
@@ -23,6 +23,14 @@ namespace :test do
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
desc "Test the multiverse testing framework by executing tests in test/multiverse/test. Get meta with it."
|
27
|
+
task 'multiverse:self', [:suite, :mode] => [:gemspec] do |t, args|
|
28
|
+
args.with_defaults(:suite => "", :mode => "")
|
29
|
+
puts ("Testing the multiverse testing framework...")
|
30
|
+
test_files = FileList['test/multiverse/test/*_test.rb']
|
31
|
+
ruby test_files.join(" ")
|
32
|
+
end
|
33
|
+
|
26
34
|
Rake::TestTask.new(:intentional_fail) do |t|
|
27
35
|
t.libs << "#{agent_home}/test"
|
28
36
|
t.libs << "#{agent_home}/lib"
|
data/bin/mongrel_rpm
CHANGED
@@ -28,6 +28,6 @@ builder = Rack::Builder.new { eval rackup_code, binding, ru_file }
|
|
28
28
|
|
29
29
|
options = { :Host => '127.0.0.1', :Port => port }
|
30
30
|
Rack::Handler::Mongrel.run(builder.to_app, options) do | server |
|
31
|
-
NewRelic::
|
31
|
+
NewRelic::Agent.logger.info "Started Mongrel listening for '#{NewRelic::Control.instance.app_names.join(" and ")}' data at #{server.host}:#{server.port}"
|
32
32
|
end
|
33
33
|
|
data/init.rb
CHANGED
@@ -27,12 +27,5 @@ begin
|
|
27
27
|
NewRelic::Control.instance.init_plugin :config => current_config
|
28
28
|
|
29
29
|
rescue => e
|
30
|
-
NewRelic::
|
31
|
-
NewRelic::Control.instance.log! e.backtrace.join("\n"), :error
|
32
|
-
NewRelic::Control.instance.log! "Agent is disabled."
|
30
|
+
::NewRelic::Agent.logger.error "Error initializing New Relic plugin. Agent is disabled.", e
|
33
31
|
end
|
34
|
-
|
35
|
-
#ClassLoadingWatcher.flag_const_missing = nil
|
36
|
-
#
|
37
|
-
# ::RAILS_DEFAULT_LOGGER.warn "New Relic detected environment: #{NewRelic::Control.instance.local_env.to_s}, RAILS_ENV: #{RAILS_ENV}"
|
38
|
-
# ::RAILS_DEFAULT_LOGGER.warn "Enabled? #{NewRelic::Control.instance.agent_enabled?}"
|
data/lib/new_relic/agent.rb
CHANGED
@@ -77,6 +77,7 @@ module NewRelic
|
|
77
77
|
require 'new_relic/agent'
|
78
78
|
require 'new_relic/agent/chained_call'
|
79
79
|
require 'new_relic/agent/browser_monitoring'
|
80
|
+
require 'new_relic/agent/cross_process_monitoring'
|
80
81
|
require 'new_relic/agent/agent'
|
81
82
|
require 'new_relic/agent/shim_agent'
|
82
83
|
require 'new_relic/agent/method_tracer'
|
@@ -140,6 +141,16 @@ module NewRelic
|
|
140
141
|
|
141
142
|
alias instance agent #:nodoc:
|
142
143
|
|
144
|
+
# Primary interface to logging is fronted by this accessor
|
145
|
+
# Access via ::NewRelic::Agent.logger
|
146
|
+
def logger
|
147
|
+
@logger || StartupLogger.instance
|
148
|
+
end
|
149
|
+
|
150
|
+
def logger=(log)
|
151
|
+
@logger = log
|
152
|
+
end
|
153
|
+
|
143
154
|
# Get or create a statistics gatherer that will aggregate numerical data
|
144
155
|
# under a metric name.
|
145
156
|
#
|
@@ -154,19 +165,6 @@ module NewRelic
|
|
154
165
|
|
155
166
|
alias get_stats_no_scope get_stats
|
156
167
|
|
157
|
-
# Get the logger for the agent. Available after the agent has initialized.
|
158
|
-
# This sends output to the agent log file. If the agent has not initialized
|
159
|
-
# a standard output logger is returned.
|
160
|
-
def logger
|
161
|
-
control = NewRelic::Control.instance(false)
|
162
|
-
if control && control.log
|
163
|
-
control.log
|
164
|
-
else
|
165
|
-
require 'logger'
|
166
|
-
@stdoutlog ||= Logger.new $stdout
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
168
|
# Call this to manually start the Agent in situations where the Agent does
|
171
169
|
# not auto-start.
|
172
170
|
#
|
@@ -89,8 +89,13 @@ module NewRelic
|
|
89
89
|
# handles things like static setup of the header for inclusion
|
90
90
|
# into pages
|
91
91
|
attr_reader :beacon_configuration
|
92
|
+
# cross process id's and encoding
|
93
|
+
attr_reader :cross_process_id
|
94
|
+
attr_reader :cross_process_encoding_bytes
|
95
|
+
# service for communicating with collector
|
92
96
|
attr_accessor :service
|
93
97
|
|
98
|
+
|
94
99
|
# Returns the length of the unsent errors array, if it exists,
|
95
100
|
# otherwise nil
|
96
101
|
def unsent_errors_size
|
@@ -180,13 +185,12 @@ module NewRelic
|
|
180
185
|
@metric_ids = {}
|
181
186
|
end
|
182
187
|
|
183
|
-
# log.debug "Agent received after_fork notice in #$$: [#{control.agent_enabled?}; monitor=#{control.monitor_mode?}; connected: #{@connected.inspect}; thread=#{@worker_thread.inspect}]"
|
184
188
|
return if !Agent.config[:agent_enabled] ||
|
185
189
|
!Agent.config[:monitor_mode] ||
|
186
190
|
@connected == false ||
|
187
191
|
@worker_thread && @worker_thread.alive?
|
188
192
|
|
189
|
-
|
193
|
+
::NewRelic::Agent.logger.debug "Starting the worker thread in #{$$} after forking."
|
190
194
|
|
191
195
|
# Clear out stats that are left over from parent process
|
192
196
|
reset_stats
|
@@ -226,7 +230,7 @@ module NewRelic
|
|
226
230
|
@worker_loop.stop
|
227
231
|
end
|
228
232
|
|
229
|
-
|
233
|
+
::NewRelic::Agent.logger.info "Starting Agent shutdown"
|
230
234
|
|
231
235
|
# if litespeed, then ignore all future SIGUSR1 - it's
|
232
236
|
# litespeed trying to shut us down
|
@@ -241,14 +245,14 @@ module NewRelic
|
|
241
245
|
graceful_disconnect
|
242
246
|
end
|
243
247
|
rescue => e
|
244
|
-
|
245
|
-
log.error e.backtrace.join("\n")
|
248
|
+
::NewRelic::Agent.logger.error e
|
246
249
|
end
|
247
250
|
NewRelic::Agent.config.remove_config do |config|
|
248
251
|
config.class == NewRelic::Agent::Configuration::ManualSource ||
|
249
252
|
config.class == NewRelic::Agent::Configuration::ServerSource
|
250
253
|
end
|
251
254
|
@started = nil
|
255
|
+
Control.reset
|
252
256
|
end
|
253
257
|
|
254
258
|
# Tells the statistics engine we are starting a new transaction
|
@@ -298,18 +302,13 @@ module NewRelic
|
|
298
302
|
Thread.current[:newrelic_untraced].pop if Thread.current[:newrelic_untraced]
|
299
303
|
end
|
300
304
|
|
301
|
-
# Shorthand to the NewRelic::Agent.logger method
|
302
|
-
def log
|
303
|
-
NewRelic::Agent.logger
|
304
|
-
end
|
305
|
-
|
306
305
|
# Herein lies the corpse of the former 'start' method. May
|
307
306
|
# its unmatched flog score rest in pieces.
|
308
307
|
module Start
|
309
308
|
# Check whether we have already started, which is an error condition
|
310
309
|
def already_started?
|
311
310
|
if started?
|
312
|
-
|
311
|
+
::NewRelic::Agent.logger.error("Agent Started Already!")
|
313
312
|
true
|
314
313
|
end
|
315
314
|
end
|
@@ -321,22 +320,35 @@ module NewRelic
|
|
321
320
|
!Agent.config[:agent_enabled]
|
322
321
|
end
|
323
322
|
|
323
|
+
# Log startup information that we almost always want to know
|
324
|
+
def log_startup
|
325
|
+
log_environment
|
326
|
+
log_dispatcher
|
327
|
+
log_app_names
|
328
|
+
end
|
329
|
+
|
330
|
+
# Log the environment the app thinks it's running in.
|
331
|
+
# Useful in debugging, as this is the key for config YAML lookups.
|
332
|
+
def log_environment
|
333
|
+
::NewRelic::Agent.logger.info "Environment: #{NewRelic::Control.instance.env}"
|
334
|
+
end
|
335
|
+
|
324
336
|
# Logs the dispatcher to the log file to assist with
|
325
337
|
# debugging. When no debugger is present, logs this fact to
|
326
338
|
# assist with proper dispatcher detection
|
327
339
|
def log_dispatcher
|
328
340
|
dispatcher_name = Agent.config[:dispatcher].to_s
|
329
|
-
return if log_if(dispatcher_name.empty?, :
|
330
|
-
|
341
|
+
return if log_if(dispatcher_name.empty?, :warn, "No dispatcher detected.")
|
342
|
+
::NewRelic::Agent.logger.info "Dispatcher: #{dispatcher_name}"
|
331
343
|
end
|
332
344
|
|
333
345
|
# Logs the configured application names
|
334
346
|
def log_app_names
|
335
347
|
names = Agent.config.app_names
|
336
348
|
if names.respond_to?(:any?) && names.any?
|
337
|
-
|
349
|
+
::NewRelic::Agent.logger.info "Application: #{names.join(", ")}"
|
338
350
|
else
|
339
|
-
|
351
|
+
::NewRelic::Agent.logger.error 'Unable to determine application name. Please set the application name in your newrelic.yml or in a NEW_RELIC_APP_NAME environment variable.'
|
340
352
|
end
|
341
353
|
end
|
342
354
|
|
@@ -384,28 +396,18 @@ module NewRelic
|
|
384
396
|
end
|
385
397
|
end
|
386
398
|
|
387
|
-
# Tells us in the log file where the log file is
|
388
|
-
# located. This seems redundant, but can come in handy when
|
389
|
-
# we have some log file path set by the user which parses
|
390
|
-
# incorrectly, sending the log file to who-knows-where
|
391
|
-
def notify_log_file_location
|
392
|
-
log_file = NewRelic::Control.instance.log_file
|
393
|
-
log_if(File.exists?(log_file.to_s), :info,
|
394
|
-
"Agent Log at #{log_file}")
|
395
|
-
end
|
396
|
-
|
397
399
|
# Classy logging of the agent version and the current pid,
|
398
400
|
# so we can disambiguate processes in the log file and make
|
399
401
|
# sure they're running a reasonable version
|
400
402
|
def log_version_and_pid
|
401
|
-
|
403
|
+
::NewRelic::Agent.logger.debug "New Relic Ruby Agent #{NewRelic::VERSION::STRING} Initialized: pid = #{$$}"
|
402
404
|
end
|
403
405
|
|
404
406
|
# A helper method that logs a condition if that condition is
|
405
407
|
# true. Mentally cleaner than having every method set a
|
406
408
|
# local and log if it is true
|
407
409
|
def log_if(boolean, level, message)
|
408
|
-
|
410
|
+
::NewRelic::Agent.logger.send(level, message) if boolean
|
409
411
|
boolean
|
410
412
|
end
|
411
413
|
|
@@ -413,7 +415,7 @@ module NewRelic
|
|
413
415
|
# condition is true. Mentally cleaner than having every
|
414
416
|
# method set a local and log unless it is true
|
415
417
|
def log_unless(boolean, level, message)
|
416
|
-
|
418
|
+
::NewRelic::Agent.logger.send(level, message) unless boolean
|
417
419
|
boolean
|
418
420
|
end
|
419
421
|
|
@@ -428,7 +430,8 @@ module NewRelic
|
|
428
430
|
# fix it by adding it to the file
|
429
431
|
def has_license_key?
|
430
432
|
log_unless(Agent.config[:license_key], :warn,
|
431
|
-
"No license key found in newrelic.yml config."
|
433
|
+
"No license key found in newrelic.yml config. " +
|
434
|
+
"This often means your newrelic.yml is missing a section for the running environment '#{NewRelic::Control.instance.env}'")
|
432
435
|
end
|
433
436
|
|
434
437
|
# A correct license key exists and is of the proper length
|
@@ -470,11 +473,9 @@ module NewRelic
|
|
470
473
|
return if already_started? || disabled?
|
471
474
|
@started = true
|
472
475
|
@local_host = determine_host
|
473
|
-
|
474
|
-
log_app_names
|
476
|
+
log_startup
|
475
477
|
check_config_and_start_agent
|
476
478
|
log_version_and_pid
|
477
|
-
notify_log_file_location
|
478
479
|
end
|
479
480
|
|
480
481
|
# Clear out the metric data, errors, and transaction traces,
|
@@ -497,8 +498,8 @@ module NewRelic
|
|
497
498
|
# logs info about the worker loop so users can see when the
|
498
499
|
# agent actually begins running in the background
|
499
500
|
def log_worker_loop_start
|
500
|
-
|
501
|
-
|
501
|
+
::NewRelic::Agent.logger.debug "Reporting performance data every #{Agent.config[:data_report_period]} seconds."
|
502
|
+
::NewRelic::Agent.logger.debug "Running worker loop"
|
502
503
|
end
|
503
504
|
|
504
505
|
# Creates the worker loop and loads it with the instructions
|
@@ -514,7 +515,7 @@ module NewRelic
|
|
514
515
|
# this clears the data, clears connection attempts, and
|
515
516
|
# waits a while to reconnect.
|
516
517
|
def handle_force_restart(error)
|
517
|
-
|
518
|
+
::NewRelic::Agent.logger.debug error.message
|
518
519
|
reset_stats
|
519
520
|
@metric_ids = {}
|
520
521
|
@connected = nil
|
@@ -525,15 +526,14 @@ module NewRelic
|
|
525
526
|
# is the worker thread that gathers data and talks to the
|
526
527
|
# server.
|
527
528
|
def handle_force_disconnect(error)
|
528
|
-
|
529
|
+
::NewRelic::Agent.logger.warn "New Relic forced this agent to disconnect (#{error.message})"
|
529
530
|
disconnect
|
530
531
|
end
|
531
532
|
|
532
533
|
# there is a problem with connecting to the server, so we
|
533
534
|
# stop trying to connect and shut down the agent
|
534
535
|
def handle_server_connection_problem(error)
|
535
|
-
|
536
|
-
log.debug("#{error.class.name}: #{error.message}\n#{error.backtrace.first}")
|
536
|
+
::NewRelic::Agent.logger.error "Unable to establish connection with the server.", error
|
537
537
|
disconnect
|
538
538
|
end
|
539
539
|
|
@@ -541,7 +541,7 @@ module NewRelic
|
|
541
541
|
# it and disconnecting the agent, since we are now in an
|
542
542
|
# unknown state
|
543
543
|
def handle_other_error(error)
|
544
|
-
|
544
|
+
::NewRelic::Agent.logger.error "Terminating worker loop.", error
|
545
545
|
disconnect
|
546
546
|
end
|
547
547
|
|
@@ -583,7 +583,7 @@ module NewRelic
|
|
583
583
|
# never reaches here unless there is a problem or
|
584
584
|
# the agent is exiting
|
585
585
|
else
|
586
|
-
|
586
|
+
::NewRelic::Agent.logger.debug "No connection. Worker thread ending."
|
587
587
|
end
|
588
588
|
end
|
589
589
|
end
|
@@ -595,7 +595,7 @@ module NewRelic
|
|
595
595
|
#
|
596
596
|
# See #connect for a description of connection_options.
|
597
597
|
def start_worker_thread(connection_options = {})
|
598
|
-
|
598
|
+
::NewRelic::Agent.logger.debug "Creating Ruby Agent worker thread."
|
599
599
|
@worker_thread = NewRelic::Agent::AgentThread.new('Worker Loop') do
|
600
600
|
deferred_work!(connection_options)
|
601
601
|
end
|
@@ -658,7 +658,7 @@ module NewRelic
|
|
658
658
|
if @keep_retrying
|
659
659
|
self.connect_attempts=(connect_attempts + 1)
|
660
660
|
increment_retry_period!
|
661
|
-
|
661
|
+
::NewRelic::Agent.logger.warn "Will re-attempt in #{connect_retry_period} seconds"
|
662
662
|
true
|
663
663
|
else
|
664
664
|
disconnect
|
@@ -670,8 +670,7 @@ module NewRelic
|
|
670
670
|
# to tell the user what happened, since this is not an error
|
671
671
|
# we can handle gracefully.
|
672
672
|
def log_error(error)
|
673
|
-
|
674
|
-
log.debug error.backtrace.join("\n")
|
673
|
+
::NewRelic::Agent.logger.error "Error establishing connection with New Relic Service at #{control.server}:", error
|
675
674
|
end
|
676
675
|
|
677
676
|
# When the server sends us an error with the license key, we
|
@@ -682,37 +681,18 @@ module NewRelic
|
|
682
681
|
# no longer try to connect to the server, saving the
|
683
682
|
# application and the server load
|
684
683
|
def handle_license_error(error)
|
685
|
-
|
686
|
-
|
684
|
+
::NewRelic::Agent.logger.error( \
|
685
|
+
error.message, \
|
686
|
+
"Visit NewRelic.com to obtain a valid license key, or to upgrade your account.")
|
687
687
|
disconnect
|
688
688
|
end
|
689
689
|
|
690
|
-
# If we are using a seed and token to validate the agent, we
|
691
|
-
# should debug log that fact so that debug logs include a
|
692
|
-
# clue that token authentication is what will be used
|
693
|
-
def log_seed_token
|
694
|
-
if Agent.config[:validate_seed]
|
695
|
-
log.debug "Connecting with validation seed/token: #{Agent.config[:validate_seed]}/#{Agent.config[:validate_token]}"
|
696
|
-
end
|
697
|
-
end
|
698
|
-
|
699
690
|
# Checks whether we should send environment info, and if so,
|
700
691
|
# returns the snapshot from the local environment
|
701
692
|
def environment_for_connect
|
702
693
|
Agent.config[:send_environment_info] ? Control.instance.local_env.snapshot : []
|
703
694
|
end
|
704
695
|
|
705
|
-
# These validation settings are used for cases where a
|
706
|
-
# dynamic server is spun up for clients - partners can
|
707
|
-
# include a seed and token to indicate that the host is
|
708
|
-
# allowed to connect, rather than setting a unique hostname
|
709
|
-
def validate_settings
|
710
|
-
{
|
711
|
-
:seed => Agent.config[:validate_seed],
|
712
|
-
:token => Agent.config[:validate_token]
|
713
|
-
}
|
714
|
-
end
|
715
|
-
|
716
696
|
# Initializes the hash of settings that we send to the
|
717
697
|
# server. Returns a literal hash containing the options
|
718
698
|
def connect_settings
|
@@ -723,16 +703,12 @@ module NewRelic
|
|
723
703
|
:language => 'ruby',
|
724
704
|
:agent_version => NewRelic::VERSION::STRING,
|
725
705
|
:environment => environment_for_connect,
|
726
|
-
:settings => Agent.config.
|
727
|
-
:validate => validate_settings
|
706
|
+
:settings => Agent.config.to_collector_hash,
|
728
707
|
}
|
729
708
|
end
|
730
709
|
|
731
|
-
#
|
732
|
-
# token for verification are correct, then returns the
|
733
|
-
# connect data passed back from the server
|
710
|
+
# Returns connect data passed back from the server
|
734
711
|
def connect_to_server
|
735
|
-
log_seed_token
|
736
712
|
@service.connect(connect_settings)
|
737
713
|
end
|
738
714
|
|
@@ -760,23 +736,38 @@ module NewRelic
|
|
760
736
|
@service.agent_id = config_data['agent_run_id'] if @service
|
761
737
|
|
762
738
|
if config_data['agent_config']
|
763
|
-
|
739
|
+
::NewRelic::Agent.logger.debug "Using config from server"
|
764
740
|
end
|
765
741
|
|
766
|
-
|
742
|
+
::NewRelic::Agent.logger.debug "Server provided config: #{config_data.inspect}"
|
767
743
|
server_config = NewRelic::Agent::Configuration::ServerSource.new(config_data)
|
768
744
|
Agent.config.apply_config(server_config, 1)
|
769
745
|
log_connection!(config_data) if @service
|
770
746
|
|
747
|
+
@cross_process_id = Agent.config[:cross_process_id]
|
748
|
+
@cross_process_encoding_key = Agent.config[:encoding_key]
|
749
|
+
@cross_process_encoding_bytes = get_bytes(@cross_process_encoding_key) unless @cross_process_encoding_key.nil?
|
750
|
+
|
771
751
|
@beacon_configuration = BeaconConfiguration.new
|
772
752
|
end
|
773
753
|
|
754
|
+
# Ruby 1.8.6 doesn't support the bytes method on strings.
|
755
|
+
def get_bytes(value)
|
756
|
+
return [] if value.nil?
|
757
|
+
|
758
|
+
bytes = []
|
759
|
+
value.each_byte do |b|
|
760
|
+
bytes << b
|
761
|
+
end
|
762
|
+
bytes
|
763
|
+
end
|
764
|
+
|
774
765
|
# Logs when we connect to the server, for debugging purposes
|
775
766
|
# - makes sure we know if an agent has not connected
|
776
767
|
def log_connection!(config_data)
|
777
|
-
|
778
|
-
|
779
|
-
|
768
|
+
::NewRelic::Agent.logger.debug "Connected to NewRelic Service at #{@service.collector.name}"
|
769
|
+
::NewRelic::Agent.logger.debug "Agent Run = #{@service.agent_id}."
|
770
|
+
::NewRelic::Agent.logger.debug "Connection data = #{config_data.inspect}"
|
780
771
|
if config_data['messages'] && config_data['messages'].any?
|
781
772
|
log_collector_messages(config_data['messages'])
|
782
773
|
end
|
@@ -784,7 +775,7 @@ module NewRelic
|
|
784
775
|
|
785
776
|
def log_collector_messages(messages)
|
786
777
|
messages.each do |message|
|
787
|
-
|
778
|
+
::NewRelic::Agent.logger.send(message['level'].downcase, message['message'])
|
788
779
|
end
|
789
780
|
end
|
790
781
|
end
|
@@ -859,7 +850,7 @@ module NewRelic
|
|
859
850
|
@connect_retry_period = should_keep_retrying?(options) ? 10 : 0
|
860
851
|
|
861
852
|
sleep connect_retry_period
|
862
|
-
|
853
|
+
::NewRelic::Agent.logger.debug "Connecting Process to New Relic: #$0"
|
863
854
|
query_server_for_configuration
|
864
855
|
@connected_pid = $$
|
865
856
|
@connected = true
|
@@ -930,11 +921,11 @@ module NewRelic
|
|
930
921
|
now.to_f,
|
931
922
|
@unsent_timeslice_data.values)
|
932
923
|
rescue UnrecoverableServerException => e
|
933
|
-
|
924
|
+
::NewRelic::Agent.logger.debug e.message
|
934
925
|
end
|
935
926
|
fill_metric_id_cache(metric_specs_and_ids)
|
936
927
|
|
937
|
-
|
928
|
+
::NewRelic::Agent.logger.debug "#{now}: sent #{@unsent_timeslice_data.length} timeslices (#{@service.agent_id}) in #{Time.now - now} seconds"
|
938
929
|
|
939
930
|
# if we successfully invoked this web service, then clear the unsent message cache.
|
940
931
|
@unsent_timeslice_data = {}
|
@@ -953,13 +944,13 @@ module NewRelic
|
|
953
944
|
# FIXME add the code to try to resend if our connection is down
|
954
945
|
sql_traces = @sql_sampler.harvest
|
955
946
|
unless sql_traces.empty?
|
956
|
-
|
947
|
+
::NewRelic::Agent.logger.debug "Sending (#{sql_traces.size}) sql traces"
|
957
948
|
begin
|
958
949
|
@service.sql_trace_data(sql_traces)
|
959
950
|
rescue UnrecoverableServerException => e
|
960
|
-
|
951
|
+
::NewRelic::Agent.logger.debug e.message
|
961
952
|
rescue => e
|
962
|
-
|
953
|
+
::NewRelic::Agent.logger.debug "Remerging SQL traces after #{e.class.name}: #{e.message}"
|
963
954
|
@sql_sampler.merge sql_traces
|
964
955
|
end
|
965
956
|
end
|
@@ -975,7 +966,7 @@ module NewRelic
|
|
975
966
|
harvest_transaction_traces
|
976
967
|
unless @traces.empty?
|
977
968
|
now = Time.now
|
978
|
-
|
969
|
+
::NewRelic::Agent.logger.debug "Sending (#{@traces.length}) transaction traces"
|
979
970
|
|
980
971
|
begin
|
981
972
|
options = { :keep_backtraces => true }
|
@@ -987,9 +978,9 @@ module NewRelic
|
|
987
978
|
end
|
988
979
|
traces = @traces.map {|trace| trace.prepare_to_send(options) }
|
989
980
|
@service.transaction_sample_data(traces)
|
990
|
-
|
981
|
+
::NewRelic::Agent.logger.debug "Sent slowest sample (#{@service.agent_id}) in #{Time.now - now} seconds"
|
991
982
|
rescue UnrecoverableServerException => e
|
992
|
-
|
983
|
+
::NewRelic::Agent.logger.debug e.message
|
993
984
|
end
|
994
985
|
end
|
995
986
|
|
@@ -1005,7 +996,7 @@ module NewRelic
|
|
1005
996
|
if @thread_profiler.finished?
|
1006
997
|
profile = @thread_profiler.harvest
|
1007
998
|
|
1008
|
-
|
999
|
+
::NewRelic::Agent.logger.debug "Sending thread profile #{profile.profile_id}"
|
1009
1000
|
@service.profile_data(profile)
|
1010
1001
|
end
|
1011
1002
|
end
|
@@ -1025,11 +1016,11 @@ module NewRelic
|
|
1025
1016
|
def harvest_and_send_errors
|
1026
1017
|
harvest_errors
|
1027
1018
|
if @unsent_errors && @unsent_errors.length > 0
|
1028
|
-
|
1019
|
+
::NewRelic::Agent.logger.debug "Sending #{@unsent_errors.length} errors"
|
1029
1020
|
begin
|
1030
1021
|
@service.error_data(@unsent_errors)
|
1031
1022
|
rescue UnrecoverableServerException => e
|
1032
|
-
|
1023
|
+
::NewRelic::Agent.logger.debug e.message
|
1033
1024
|
end
|
1034
1025
|
# if the remote invocation fails, then we never clear
|
1035
1026
|
# @unsent_errors, and therefore we can re-attempt to send on
|
@@ -1039,21 +1030,9 @@ module NewRelic
|
|
1039
1030
|
end
|
1040
1031
|
end
|
1041
1032
|
|
1042
|
-
# Only JSON marshalling appears to work with collector on
|
1043
|
-
# get_agent_commands and agent_command_results. We only support
|
1044
|
-
# these features on Ruby versions that can hack JSON out of the box
|
1045
|
-
def agent_commands_supported?
|
1046
|
-
RUBY_VERSION >= "1.9.2"
|
1047
|
-
end
|
1048
|
-
|
1049
1033
|
def check_for_agent_commands
|
1050
|
-
if !agent_commands_supported?
|
1051
|
-
log.debug("Skipping agent commands, as they aren't supported on this environment")
|
1052
|
-
return
|
1053
|
-
end
|
1054
|
-
|
1055
1034
|
commands = @service.get_agent_commands
|
1056
|
-
|
1035
|
+
::NewRelic::Agent.logger.debug "Received get_agent_commands = #{commands.inspect}"
|
1057
1036
|
|
1058
1037
|
@thread_profiler.respond_to_commands(commands) do |command_id, error|
|
1059
1038
|
@service.agent_command_results(command_id, error)
|
@@ -1062,7 +1041,7 @@ module NewRelic
|
|
1062
1041
|
|
1063
1042
|
def transmit_data(disconnecting=false)
|
1064
1043
|
now = Time.now
|
1065
|
-
|
1044
|
+
::NewRelic::Agent.logger.debug "Sending data to New Relic Service"
|
1066
1045
|
harvest_and_send_errors
|
1067
1046
|
harvest_and_send_slowest_sample
|
1068
1047
|
harvest_and_send_slowest_sql
|
@@ -1074,7 +1053,7 @@ module NewRelic
|
|
1074
1053
|
retry_count ||= 0
|
1075
1054
|
retry_count += 1
|
1076
1055
|
if retry_count <= 1
|
1077
|
-
|
1056
|
+
::NewRelic::Agent.logger.debug "retrying transmit_data after #{e}"
|
1078
1057
|
retry
|
1079
1058
|
end
|
1080
1059
|
raise e
|
@@ -1098,17 +1077,17 @@ module NewRelic
|
|
1098
1077
|
transmit_data(true)
|
1099
1078
|
|
1100
1079
|
if @connected_pid == $$ && !@service.kind_of?(NewRelic::Agent::NewRelicService)
|
1101
|
-
|
1080
|
+
::NewRelic::Agent.logger.debug "Sending New Relic service agent run shutdown message"
|
1102
1081
|
@service.shutdown(Time.now.to_f)
|
1103
1082
|
else
|
1104
|
-
|
1083
|
+
::NewRelic::Agent.logger.debug "This agent connected from parent process #{@connected_pid}--not sending shutdown"
|
1105
1084
|
end
|
1106
|
-
|
1085
|
+
::NewRelic::Agent.logger.debug "Graceful disconnect complete"
|
1107
1086
|
rescue Timeout::Error, StandardError => e
|
1108
|
-
|
1087
|
+
::NewRelic::Agent.logger.debug "Error when disconnecting #{e.class.name}: #{e.message}"
|
1109
1088
|
end
|
1110
1089
|
else
|
1111
|
-
|
1090
|
+
::NewRelic::Agent.logger.debug "Bypassing graceful disconnect - agent not connected"
|
1112
1091
|
end
|
1113
1092
|
end
|
1114
1093
|
end
|