newrelic_rpm 2.9.9 → 2.10.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of newrelic_rpm might be problematic. Click here for more details.
- data/CHANGELOG +117 -49
- data/bin/mongrel_rpm +2 -2
- data/install.rb +42 -33
- data/lib/new_relic/agent.rb +149 -39
- data/lib/new_relic/agent/agent.rb +139 -122
- data/lib/new_relic/agent/busy_calculator.rb +91 -0
- data/lib/new_relic/agent/collection_helper.rb +11 -2
- data/lib/new_relic/agent/error_collector.rb +33 -27
- data/lib/new_relic/agent/instrumentation/active_record_instrumentation.rb +30 -26
- data/lib/new_relic/agent/instrumentation/authlogic.rb +8 -0
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +316 -105
- data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +22 -0
- data/lib/new_relic/agent/instrumentation/memcache.rb +18 -12
- data/lib/new_relic/agent/instrumentation/merb/errors.rb +2 -1
- data/lib/new_relic/agent/instrumentation/metric_frame.rb +258 -0
- data/lib/new_relic/agent/instrumentation/net.rb +7 -11
- data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +1 -1
- data/lib/new_relic/agent/instrumentation/rack.rb +109 -0
- data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +6 -5
- data/lib/new_relic/agent/instrumentation/rails/errors.rb +7 -7
- data/lib/new_relic/agent/instrumentation/sinatra.rb +46 -0
- data/lib/new_relic/agent/method_tracer.rb +305 -150
- data/lib/new_relic/agent/sampler.rb +34 -0
- data/lib/new_relic/agent/samplers/cpu_sampler.rb +11 -1
- data/lib/new_relic/agent/samplers/delayed_job_lock_sampler.rb +37 -0
- data/lib/new_relic/agent/samplers/memory_sampler.rb +22 -10
- data/lib/new_relic/agent/samplers/object_sampler.rb +24 -0
- data/lib/new_relic/agent/shim_agent.rb +10 -0
- data/lib/new_relic/agent/stats_engine.rb +16 -278
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +118 -0
- data/lib/new_relic/agent/stats_engine/samplers.rb +81 -0
- data/lib/new_relic/agent/stats_engine/transactions.rb +149 -0
- data/lib/new_relic/agent/transaction_sampler.rb +73 -67
- data/lib/new_relic/agent/worker_loop.rb +69 -68
- data/lib/new_relic/commands/deployments.rb +4 -6
- data/lib/new_relic/control.rb +121 -60
- data/lib/new_relic/control/external.rb +13 -0
- data/lib/new_relic/control/merb.rb +2 -0
- data/lib/new_relic/control/rails.rb +16 -6
- data/lib/new_relic/control/ruby.rb +8 -5
- data/lib/new_relic/control/sinatra.rb +18 -0
- data/lib/new_relic/delayed_job_injection.rb +25 -0
- data/lib/new_relic/histogram.rb +89 -0
- data/lib/new_relic/local_environment.rb +64 -30
- data/lib/new_relic/metric_data.rb +15 -6
- data/lib/new_relic/metric_parser.rb +14 -1
- data/lib/new_relic/metric_parser/active_record.rb +14 -0
- data/lib/new_relic/metric_parser/controller.rb +5 -2
- data/lib/new_relic/metric_parser/external.rb +50 -0
- data/lib/new_relic/metric_parser/other_transaction.rb +15 -0
- data/lib/new_relic/metric_parser/web_frontend.rb +14 -0
- data/lib/new_relic/metric_spec.rb +39 -20
- data/lib/new_relic/metrics.rb +9 -7
- data/lib/new_relic/noticed_error.rb +6 -8
- data/lib/new_relic/rack/metric_app.rb +5 -4
- data/lib/new_relic/rack/{newrelic.ru → mongrel_rpm.ru} +4 -4
- data/lib/new_relic/rack/newrelic.yml +1 -0
- data/lib/new_relic/{rack.rb → rack_app.rb} +0 -0
- data/lib/new_relic/recipes.rb +1 -1
- data/lib/new_relic/stats.rb +40 -26
- data/lib/new_relic/transaction_analysis.rb +5 -2
- data/lib/new_relic/transaction_sample.rb +134 -55
- data/lib/new_relic/version.rb +27 -20
- data/lib/new_relic_api.rb +67 -47
- data/lib/newrelic_rpm.rb +5 -5
- data/lib/tasks/tests.rake +2 -0
- data/newrelic.yml +69 -29
- data/test/active_record_fixtures.rb +2 -2
- data/test/config/newrelic.yml +4 -7
- data/test/config/test_control.rb +1 -2
- data/test/new_relic/agent/active_record_instrumentation_test.rb +115 -31
- data/test/new_relic/agent/agent_controller_test.rb +274 -0
- data/test/new_relic/agent/agent_test_controller.rb +42 -6
- data/test/new_relic/agent/busy_calculator_test.rb +79 -0
- data/test/new_relic/agent/collection_helper_test.rb +10 -3
- data/test/new_relic/agent/error_collector_test.rb +35 -17
- data/test/new_relic/agent/method_tracer_test.rb +60 -20
- data/test/new_relic/agent/metric_data_test.rb +2 -2
- data/test/new_relic/agent/metric_frame_test.rb +51 -0
- data/test/new_relic/agent/net_instrumentation_test.rb +77 -0
- data/test/new_relic/agent/{agent_test.rb → rpm_agent_test.rb} +26 -5
- data/test/new_relic/agent/stats_engine/metric_stats_test.rb +79 -0
- data/test/new_relic/{samplers_test.rb → agent/stats_engine/samplers_test.rb} +23 -22
- data/test/new_relic/agent/{stats_engine_test.rb → stats_engine/stats_engine_test.rb} +19 -101
- data/test/new_relic/agent/task_instrumentation_test.rb +176 -0
- data/test/new_relic/agent/transaction_sample_builder_test.rb +2 -2
- data/test/new_relic/agent/transaction_sample_test.rb +53 -38
- data/test/new_relic/agent/transaction_sampler_test.rb +101 -33
- data/test/new_relic/agent/worker_loop_test.rb +16 -14
- data/test/new_relic/control_test.rb +26 -13
- data/test/new_relic/metric_parser_test.rb +31 -1
- data/test/new_relic/metric_spec_test.rb +2 -2
- data/test/new_relic/stats_test.rb +0 -8
- data/test/new_relic/version_number_test.rb +31 -1
- data/test/test_helper.rb +37 -1
- data/ui/controllers/newrelic_controller.rb +19 -11
- data/ui/helpers/google_pie_chart.rb +5 -11
- data/ui/helpers/newrelic_helper.rb +40 -35
- data/ui/views/layouts/newrelic_default.rhtml +7 -7
- data/ui/views/newrelic/_sample.rhtml +5 -1
- data/ui/views/newrelic/images/new-relic-rpm-desktop.gif +0 -0
- data/ui/views/newrelic/images/textmate.png +0 -0
- data/ui/views/newrelic/index.rhtml +13 -1
- data/ui/views/newrelic/show_sample.rhtml +5 -2
- data/ui/views/newrelic/stylesheets/style.css +54 -3
- metadata +65 -145
- data/Manifest +0 -143
- data/Rakefile +0 -22
- data/init.rb +0 -38
- data/lib/new_relic/agent/instrumentation/dispatcher_instrumentation.rb +0 -127
- data/lib/new_relic/agent/instrumentation/error_instrumentation.rb +0 -14
- data/lib/new_relic/agent/instrumentation/merb/dispatcher.rb +0 -13
- data/lib/new_relic/agent/instrumentation/rails/dispatcher.rb +0 -38
- data/lib/new_relic/agent/patch_const_missing.rb +0 -125
- data/lib/new_relic/agent/samplers/mongrel_sampler.rb +0 -22
- data/lib/new_relic/metric_parser/database.rb +0 -23
- data/newrelic_rpm.gemspec +0 -35
- data/test/new_relic/agent/classloader_patch_test.rb +0 -56
- data/test/new_relic/agent/controller_test.rb +0 -107
- data/test/new_relic/agent/dispatcher_instrumentation_test.rb +0 -70
@@ -1,4 +1,5 @@
|
|
1
|
-
module NewRelic
|
1
|
+
module NewRelic
|
2
|
+
module Agent
|
2
3
|
|
3
4
|
# A worker loop executes a set of registered tasks on a single thread.
|
4
5
|
# A task is a proc or block with a specified call period in seconds.
|
@@ -13,7 +14,7 @@ module NewRelic::Agent
|
|
13
14
|
@should_run = true
|
14
15
|
@pid = $$
|
15
16
|
end
|
16
|
-
|
17
|
+
|
17
18
|
# Run infinitely, calling the registered tasks at their specified
|
18
19
|
# call periods. The caller is responsible for creating the thread
|
19
20
|
# that runs this worker loop
|
@@ -30,89 +31,89 @@ module NewRelic::Agent
|
|
30
31
|
def stop
|
31
32
|
@should_run = false
|
32
33
|
end
|
33
|
-
|
34
|
+
|
34
35
|
MIN_CALL_PERIOD = 0.1
|
35
36
|
|
36
37
|
# add a task to the worker loop. The task will be called approximately once
|
37
38
|
# every call_period seconds. The task is passed as a block
|
38
|
-
def add_task(call_period, &task_proc)
|
39
|
+
def add_task(call_period, desc="", &task_proc)
|
39
40
|
if call_period < MIN_CALL_PERIOD
|
40
41
|
raise ArgumentError, "Invalid Call Period (must be > #{MIN_CALL_PERIOD}): #{call_period}"
|
41
42
|
end
|
42
|
-
@tasks << LoopTask.new(call_period, &task_proc)
|
43
|
+
@tasks << LoopTask.new(call_period, desc, &task_proc)
|
43
44
|
end
|
44
|
-
|
45
|
+
|
45
46
|
private
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
47
|
+
def next_task
|
48
|
+
@tasks.inject do |soonest, task|
|
49
|
+
(task.next_invocation_time < soonest.next_invocation_time) ? task : soonest
|
50
50
|
end
|
51
|
+
end
|
51
52
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
# get the next task to be executed, which is the task with the lowest (ie, soonest)
|
59
|
-
# next invocation time.
|
60
|
-
task = next_task
|
61
|
-
|
62
|
-
# sleep in chunks no longer than 1 second
|
63
|
-
while Time.now < task.next_invocation_time
|
64
|
-
|
65
|
-
# sleep until this next task's scheduled invocation time
|
66
|
-
sleep_time = [task.next_invocation_time - Time.now, 0.000001].max
|
67
|
-
sleep_time = (sleep_time > 1) ? 1 : sleep_time
|
68
|
-
|
69
|
-
sleep sleep_time
|
70
|
-
|
71
|
-
return if !keep_running
|
72
|
-
end
|
73
|
-
|
74
|
-
begin
|
75
|
-
# wrap task execution in a block that won't collect a TT
|
76
|
-
NewRelic::Agent.disable_transaction_tracing do
|
77
|
-
task.execute
|
78
|
-
end
|
79
|
-
rescue ServerError => e
|
80
|
-
log.debug "Server Error: #{e}"
|
81
|
-
rescue RuntimeError => e
|
82
|
-
# This is probably a server error which has been logged in the server along
|
83
|
-
# with your account name. Check and see if the agent listener is in the
|
84
|
-
# stack trace and log it quietly if it is.
|
85
|
-
message = "Error running task in worker loop, likely a server error (#{e})"
|
86
|
-
if e.backtrace.grep(/agent_listener/).empty?
|
87
|
-
log.error message
|
88
|
-
else
|
89
|
-
log.debug message
|
90
|
-
log.debug e.backtrace.join("\n")
|
91
|
-
end
|
92
|
-
rescue Timeout::Error, NewRelic::Agent::IgnoreSilentlyException
|
93
|
-
# Want to ignore these because they are handled already
|
94
|
-
rescue ScriptError, StandardError => e
|
95
|
-
log.error "Error running task in Agent Worker Loop (#{e.class}): #{e} "
|
96
|
-
log.debug e.backtrace.join("\n")
|
97
|
-
end
|
53
|
+
def run_next_task
|
54
|
+
if @tasks.empty?
|
55
|
+
sleep 5.0
|
56
|
+
return
|
98
57
|
end
|
99
58
|
|
100
|
-
|
59
|
+
# get the next task to be executed, which is the task with the lowest (ie, soonest)
|
60
|
+
# next invocation time.
|
61
|
+
task = next_task
|
101
62
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
63
|
+
while Time.now < task.next_invocation_time
|
64
|
+
|
65
|
+
# sleep until this next task's scheduled invocation time
|
66
|
+
sleep_time = task.next_invocation_time - Time.now
|
67
|
+
sleep sleep_time if sleep_time > 0
|
68
|
+
return if !keep_running
|
69
|
+
end
|
107
70
|
|
108
|
-
|
109
|
-
|
71
|
+
begin
|
72
|
+
task.execute if keep_running
|
73
|
+
rescue ServerError => e
|
74
|
+
log.debug "Server Error: #{e}"
|
75
|
+
rescue NewRelic::Agent::ForceRestartException => e
|
76
|
+
# blow out the loop
|
77
|
+
raise
|
78
|
+
rescue RuntimeError => e
|
79
|
+
# This is probably a server error which has been logged in the server along
|
80
|
+
# with your account name. Check and see if the agent listener is in the
|
81
|
+
# stack trace and log it quietly if it is.
|
82
|
+
message = "Error running task in worker loop, likely a server error (#{e})"
|
83
|
+
if e.backtrace.grep(/agent_listener/).empty?
|
84
|
+
log.error message
|
85
|
+
else
|
86
|
+
log.debug message
|
87
|
+
log.debug e.backtrace.join("\n")
|
110
88
|
end
|
89
|
+
rescue Timeout::Error, NewRelic::Agent::IgnoreSilentlyException
|
90
|
+
# Want to ignore these because they are handled already
|
91
|
+
rescue ScriptError, StandardError => e
|
92
|
+
log.error "Error running task in Agent Worker Loop '#{e}': #{e.backtrace.first}"
|
93
|
+
log.debug e.backtrace.join("\n")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class LoopTask
|
111
98
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
99
|
+
def initialize(call_period, desc="", &task_proc)
|
100
|
+
@call_period = call_period
|
101
|
+
@last_invocation_time = Time.now
|
102
|
+
@task = task_proc
|
103
|
+
@desc = desc
|
116
104
|
end
|
105
|
+
def to_s
|
106
|
+
"Task[#{@desc}]"
|
107
|
+
end
|
108
|
+
def next_invocation_time
|
109
|
+
@last_invocation_time + @call_period
|
110
|
+
end
|
111
|
+
|
112
|
+
def execute
|
113
|
+
@last_invocation_time = Time.now
|
114
|
+
@task.call
|
115
|
+
end
|
116
|
+
end
|
117
117
|
end
|
118
118
|
end
|
119
|
+
end
|
@@ -87,7 +87,7 @@ module NewRelic
|
|
87
87
|
response = http.request(request)
|
88
88
|
|
89
89
|
if response.is_a? Net::HTTPSuccess
|
90
|
-
info "Recorded deployment to
|
90
|
+
info "Recorded deployment to '#{@appname}' (#{@description || Time.now })"
|
91
91
|
else
|
92
92
|
err_string = [ "Unexpected response from server: #{response.code}: #{response.message}" ]
|
93
93
|
begin
|
@@ -107,7 +107,7 @@ module NewRelic
|
|
107
107
|
raise
|
108
108
|
rescue Exception => e
|
109
109
|
err "Unexpected error attempting to connect to #{config.api_server}"
|
110
|
-
info e.backtrace.join("\n")
|
110
|
+
info "#{e}: #{e.backtrace.join("\n ")}"
|
111
111
|
raise CommandFailure.new(e.to_s, -1)
|
112
112
|
end
|
113
113
|
end
|
@@ -115,9 +115,9 @@ module NewRelic
|
|
115
115
|
private
|
116
116
|
|
117
117
|
def options
|
118
|
-
OptionParser.new
|
118
|
+
OptionParser.new %Q{Usage: #{$0} [OPTIONS] ["description"] }, 40 do |o|
|
119
119
|
o.separator "OPTIONS:"
|
120
|
-
o.on("-a", "--appname=
|
120
|
+
o.on("-a", "--appname=NAME", String,
|
121
121
|
"Set the application name.",
|
122
122
|
"Default is app_name setting in newrelic.yml") { | e | @appname = e }
|
123
123
|
o.on("-e", "--environment=name", String,
|
@@ -131,8 +131,6 @@ module NewRelic
|
|
131
131
|
o.on("-c", "--changes",
|
132
132
|
"Read in a change log from the standard input") { @changelog = STDIN.read }
|
133
133
|
o.on("-h", "--help", "Print this help") { raise CommandFailure.new(o.help, 0) }
|
134
|
-
o.separator ""
|
135
|
-
o.separator 'description = "short text"'
|
136
134
|
end
|
137
135
|
end
|
138
136
|
|
data/lib/new_relic/control.rb
CHANGED
@@ -6,7 +6,6 @@ require 'socket'
|
|
6
6
|
require 'net/https'
|
7
7
|
require 'logger'
|
8
8
|
|
9
|
-
|
10
9
|
module NewRelic
|
11
10
|
|
12
11
|
# The Control is a singleton responsible for the startup and
|
@@ -18,20 +17,38 @@ module NewRelic
|
|
18
17
|
#
|
19
18
|
class Control
|
20
19
|
|
20
|
+
# A flag used in dev mode to indicate if profiling is available
|
21
|
+
def profiling?
|
22
|
+
@profiling
|
23
|
+
end
|
24
|
+
|
25
|
+
def profiling_available?
|
26
|
+
@profiling_available ||=
|
27
|
+
begin
|
28
|
+
require 'ruby-prof'
|
29
|
+
true
|
30
|
+
rescue LoadError; end
|
31
|
+
end
|
32
|
+
# Set the flag for capturing profiles in dev mode. If RubyProf is not
|
33
|
+
# loaded a true value is ignored.
|
34
|
+
def profiling=(val)
|
35
|
+
@profiling = profiling_available? && val && defined?(RubyProf)
|
36
|
+
end
|
37
|
+
|
21
38
|
attr_accessor :log_file
|
22
39
|
# The env is the setting used to identify which section of the newrelic.yml
|
23
40
|
# to load. This defaults to a framework specific value, such as ENV['RAILS_ENV']
|
24
41
|
# but can be overridden as long as you set it before calling #init_plugin
|
25
42
|
attr_writer :env
|
26
43
|
attr_reader :local_env
|
27
|
-
|
28
|
-
# Structs holding info for the remote server and proxy server
|
44
|
+
|
45
|
+
# Structs holding info for the remote server and proxy server
|
29
46
|
class Server < Struct.new :name, :port, :ip #:nodoc:
|
30
47
|
def to_s; "#{name}:#{port}"; end
|
31
48
|
end
|
32
49
|
|
33
50
|
ProxyServer = Struct.new :name, :port, :user, :password #:nodoc:
|
34
|
-
|
51
|
+
|
35
52
|
# Access the Control singleton, lazy initialized
|
36
53
|
def self.instance
|
37
54
|
@instance ||= new_instance
|
@@ -57,11 +74,15 @@ module NewRelic
|
|
57
74
|
# is called at most once.
|
58
75
|
#
|
59
76
|
def init_plugin(options={})
|
77
|
+
options['app_name'] = ENV['NEWRELIC_APP_NAME'] if ENV['NEWRELIC_APP_NAME']
|
78
|
+
|
60
79
|
require 'new_relic/agent'
|
61
80
|
# Merge the stringified options into the config as overrides:
|
62
81
|
logger_override = options.delete(:log)
|
63
|
-
environment_name = options.delete(:env)
|
64
|
-
|
82
|
+
environment_name = options.delete(:env) and self.env = environment_name
|
83
|
+
dispatcher = options.delete(:dispatcher) and @local_env.dispatcher = dispatcher
|
84
|
+
dispatcher_instance_id = options.delete(:dispatcher_instance_id) and @local_env.dispatcher_instance_id = dispatcher_instance_id
|
85
|
+
|
65
86
|
# Clear out the settings, if they've already been loaded. It may be that
|
66
87
|
# between calling init_plugin the first time and the second time, the env
|
67
88
|
# has been overridden
|
@@ -73,6 +94,10 @@ module NewRelic
|
|
73
94
|
# Try to grab the log filename
|
74
95
|
@log_file = @log.instance_eval { @logdev.filename rescue nil }
|
75
96
|
end
|
97
|
+
# An artifact of earlier implementation, we put both #add_method_tracer and #trace_execution
|
98
|
+
# methods in the module methods.
|
99
|
+
Module.send :include, NewRelic::Agent::MethodTracer::ClassMethods
|
100
|
+
Module.send :include, NewRelic::Agent::MethodTracer::InstanceMethods
|
76
101
|
init_config(options)
|
77
102
|
if agent_enabled? && !@started
|
78
103
|
setup_log unless logger_override
|
@@ -102,7 +127,14 @@ module NewRelic
|
|
102
127
|
@settings = (@yaml && merge_defaults(@yaml[env])) || {}
|
103
128
|
# At the time we bind the settings, we also need to run this little piece
|
104
129
|
# of magic which allows someone to augment the id with the app name, necessary
|
105
|
-
|
130
|
+
if self['multi_homed'] && app_names.size > 0
|
131
|
+
if @local_env.dispatcher_instance_id
|
132
|
+
@local_env.dispatcher_instance_id << ":#{app_names.first}"
|
133
|
+
else
|
134
|
+
@local_env.dispatcher_instance_id = app_names.first
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
106
138
|
end
|
107
139
|
@settings
|
108
140
|
end
|
@@ -124,6 +156,10 @@ module NewRelic
|
|
124
156
|
###################################
|
125
157
|
# Agent config conveniences
|
126
158
|
|
159
|
+
def apdex_t
|
160
|
+
# Always initialized with a default
|
161
|
+
fetch('apdex_t').to_f
|
162
|
+
end
|
127
163
|
def license_key
|
128
164
|
fetch('license_key')
|
129
165
|
end
|
@@ -132,11 +168,22 @@ module NewRelic
|
|
132
168
|
end
|
133
169
|
# True if we are sending data to the server, monitoring production
|
134
170
|
def monitor_mode?
|
135
|
-
fetch('
|
171
|
+
fetch('monitor_mode', fetch('enabled'))
|
136
172
|
end
|
137
173
|
# True if we are capturing data and displaying in /newrelic
|
138
174
|
def developer_mode?
|
139
|
-
fetch('
|
175
|
+
fetch('developer_mode', fetch('developer'))
|
176
|
+
end
|
177
|
+
# True if the app runs in multi-threaded mode
|
178
|
+
def multi_threaded?
|
179
|
+
fetch('multi_threaded')
|
180
|
+
end
|
181
|
+
# True if we should view files in textmate
|
182
|
+
def use_textmate?
|
183
|
+
fetch('textmate')
|
184
|
+
end
|
185
|
+
def post_size_limit
|
186
|
+
fetch('post_size_limit', 2 * 1024 * 1024)
|
140
187
|
end
|
141
188
|
# True if dev mode or monitor mode are enabled, and we are running
|
142
189
|
# inside a valid dispatcher like mongrel or passenger. Can be overridden
|
@@ -144,7 +191,7 @@ module NewRelic
|
|
144
191
|
# agent_enabled config option when true or false.
|
145
192
|
def agent_enabled?
|
146
193
|
return false if !developer_mode? && !monitor_mode?
|
147
|
-
return self['agent_enabled'].to_s =~ /true|on|yes/i if self['agent_enabled'] && self['agent_enabled'] != 'auto'
|
194
|
+
return self['agent_enabled'].to_s =~ /true|on|yes/i if !self['agent_enabled'].nil? && self['agent_enabled'] != 'auto'
|
148
195
|
return false if ENV['NEWRELIC_ENABLE'].to_s =~ /false|off|no/i
|
149
196
|
return true if self['monitor_daemons'].to_s =~ /true|on|yes/i
|
150
197
|
return true if ENV['NEWRELIC_ENABLE'].to_s =~ /true|on|yes/i
|
@@ -184,15 +231,15 @@ module NewRelic
|
|
184
231
|
def api_server
|
185
232
|
api_host = self['api_host'] || 'rpm.newrelic.com'
|
186
233
|
@api_server ||=
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
234
|
+
NewRelic::Control::Server.new \
|
235
|
+
api_host,
|
236
|
+
(self['api_port'] || self['port'] || (use_ssl? ? 443 : 80)).to_i,
|
237
|
+
nil
|
191
238
|
end
|
192
239
|
|
193
240
|
def proxy_server
|
194
241
|
@proxy_server ||=
|
195
|
-
|
242
|
+
NewRelic::Control::ProxyServer.new self['proxy_host'], self['proxy_port'], self['proxy_user'], self['proxy_pass']
|
196
243
|
end
|
197
244
|
|
198
245
|
def server_from_host(hostname=nil)
|
@@ -215,6 +262,7 @@ module NewRelic
|
|
215
262
|
http_class = Net::HTTP::Proxy(proxy_server.name, proxy_server.port,
|
216
263
|
proxy_server.user, proxy_server.password)
|
217
264
|
http = http_class.new(host.ip || host.name, host.port)
|
265
|
+
log.debug("Http Connection opened to #{host.ip||host.name}:#{host.port}")
|
218
266
|
if use_ssl?
|
219
267
|
http.use_ssl = true
|
220
268
|
if verify_certificate?
|
@@ -256,50 +304,57 @@ module NewRelic
|
|
256
304
|
# Once we install instrumentation, you can't undo that by installing the shim.
|
257
305
|
raise "Cannot install the Agent shim after instrumentation has already been installed!" if @instrumented
|
258
306
|
NewRelic::Agent.agent = NewRelic::Agent::ShimAgent.instance
|
259
|
-
Module.send :include, NewRelic::Agent::MethodTracerShim
|
260
307
|
end
|
261
308
|
|
309
|
+
# Add instrumentation. Don't call this directly. Use NewRelic::Agent#add_instrumentation.
|
310
|
+
# This will load the file synchronously if we've already loaded the default
|
311
|
+
# instrumentation.
|
312
|
+
#
|
313
|
+
def add_instrumentation pattern
|
314
|
+
if @instrumented
|
315
|
+
load_instrumentation_files pattern
|
316
|
+
else
|
317
|
+
@instrumentation_files << pattern
|
318
|
+
end
|
319
|
+
end
|
262
320
|
def install_instrumentation
|
263
321
|
return if @instrumented
|
264
322
|
|
265
323
|
@instrumented = true
|
266
324
|
|
267
|
-
Module.send :include, NewRelic::Agent::MethodTracer
|
268
|
-
|
269
325
|
# Instrumentation for the key code points inside rails for monitoring by NewRelic.
|
270
326
|
# note this file is loaded only if the newrelic agent is enabled (through config/newrelic.yml)
|
271
327
|
instrumentation_path = File.join(File.dirname(__FILE__), 'agent','instrumentation')
|
272
|
-
instrumentation_files
|
328
|
+
@instrumentation_files <<
|
273
329
|
File.join(instrumentation_path, '*.rb') <<
|
274
330
|
File.join(instrumentation_path, app.to_s, '*.rb')
|
275
|
-
instrumentation_files.each
|
276
|
-
Dir.glob(pattern) do |file|
|
277
|
-
begin
|
278
|
-
log.debug "Processing instrumentation file '#{file}'"
|
279
|
-
require file
|
280
|
-
rescue => e
|
281
|
-
log.error "Error loading instrumentation file '#{file}': #{e}"
|
282
|
-
log.debug e.backtrace.join("\n")
|
283
|
-
end
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
331
|
+
@instrumentation_files.each { | pattern | load_instrumentation_files pattern }
|
287
332
|
log.debug "Finished instrumentation"
|
288
333
|
end
|
289
|
-
|
334
|
+
|
290
335
|
def load_samplers
|
291
336
|
agent = NewRelic::Agent.instance
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
337
|
+
NewRelic::Agent::Sampler.sampler_classes.each do | subclass |
|
338
|
+
begin
|
339
|
+
log.debug "#{subclass.name} not supported on this platform." and next if not subclass.supported_on_this_platform?
|
340
|
+
sampler = subclass.new
|
341
|
+
if subclass.use_harvest_sampler?
|
342
|
+
agent.stats_engine.add_harvest_sampler sampler
|
343
|
+
log.debug "Registered #{subclass.name} for harvest time sampling"
|
344
|
+
else
|
345
|
+
agent.stats_engine.add_sampler sampler
|
346
|
+
log.debug "Registered #{subclass.name} for periodic sampling"
|
347
|
+
end
|
348
|
+
rescue NewRelic::Agent::Sampler::Unsupported => e
|
349
|
+
log.info "#{subclass} sampler not available: #{e}"
|
350
|
+
rescue => e
|
351
|
+
log.error "Error registering sampler: #{e}, #{e.backtrace.join("\n")}"
|
352
|
+
end
|
298
353
|
end
|
299
354
|
end
|
300
|
-
|
355
|
+
|
301
356
|
protected
|
302
|
-
|
357
|
+
|
303
358
|
# Append framework specific environment information for uploading to
|
304
359
|
# the server for change detection. Override in subclasses
|
305
360
|
def append_environment_info; end
|
@@ -325,7 +380,7 @@ module NewRelic
|
|
325
380
|
end
|
326
381
|
ip_address
|
327
382
|
end
|
328
|
-
|
383
|
+
|
329
384
|
def merge_defaults(settings_hash)
|
330
385
|
s = {
|
331
386
|
'host' => 'collector.newrelic.com',
|
@@ -338,6 +393,7 @@ module NewRelic
|
|
338
393
|
s['agent_enabled'] = s.delete('monitor_daemons') if s['agent_enabled'].nil? && s.include?('monitor_daemons')
|
339
394
|
s
|
340
395
|
end
|
396
|
+
|
341
397
|
# Control subclasses may override this, but it can be called multiple times.
|
342
398
|
def setup_log
|
343
399
|
@log_file = "#{log_path}/newrelic_agent.log"
|
@@ -348,14 +404,14 @@ module NewRelic
|
|
348
404
|
def @log.format_message(severity, timestamp, progname, msg)
|
349
405
|
"[#{timestamp.strftime("%m/%d/%y %H:%M:%S %z")} #{Socket.gethostname} (#{$$})] #{severity} : #{msg}\n"
|
350
406
|
end
|
351
|
-
|
407
|
+
|
352
408
|
# set the log level as specified in the config file
|
353
409
|
case fetch("log_level","info").downcase
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
410
|
+
when "debug" then @log.level = Logger::DEBUG
|
411
|
+
when "info" then @log.level = Logger::INFO
|
412
|
+
when "warn" then @log.level = Logger::WARN
|
413
|
+
when "error" then @log.level = Logger::ERROR
|
414
|
+
when "fatal" then @log.level = Logger::FATAL
|
359
415
|
else @log.level = Logger::INFO
|
360
416
|
end
|
361
417
|
@log
|
@@ -380,26 +436,18 @@ module NewRelic
|
|
380
436
|
# Create the concrete class for environment specific behavior:
|
381
437
|
def self.new_instance
|
382
438
|
@local_env = NewRelic::LocalEnvironment.new
|
383
|
-
|
384
|
-
when :test
|
439
|
+
if @local_env.framework == :test
|
385
440
|
require File.join(newrelic_root, "test", "config", "test_control.rb")
|
386
441
|
NewRelic::Control::Test.new @local_env
|
387
|
-
|
388
|
-
require
|
389
|
-
NewRelic::Control
|
390
|
-
when :rails
|
391
|
-
require 'new_relic/control/rails'
|
392
|
-
NewRelic::Control::Rails.new @local_env
|
393
|
-
when :ruby
|
394
|
-
require 'new_relic/control/ruby'
|
395
|
-
NewRelic::Control::Ruby.new @local_env
|
396
|
-
else
|
397
|
-
raise "Unknown framework: #{@local_env.framework}"
|
442
|
+
else
|
443
|
+
require "new_relic/control/#{@local_env.framework}.rb"
|
444
|
+
NewRelic::Control.const_get(@local_env.framework.to_s.capitalize).new @local_env
|
398
445
|
end
|
399
446
|
end
|
400
447
|
|
401
448
|
def initialize local_env
|
402
449
|
@local_env = local_env
|
450
|
+
@instrumentation_files = []
|
403
451
|
newrelic_file = config_file
|
404
452
|
# Next two are for populating the newrelic.yml via erb binding, necessary
|
405
453
|
# when using the default newrelic.yml file
|
@@ -424,5 +472,18 @@ module NewRelic
|
|
424
472
|
def newrelic_root
|
425
473
|
self.class.newrelic_root
|
426
474
|
end
|
475
|
+
|
476
|
+
def load_instrumentation_files pattern
|
477
|
+
Dir.glob(pattern) do |file|
|
478
|
+
begin
|
479
|
+
log.debug "Processing instrumentation file '#{file}'"
|
480
|
+
require file
|
481
|
+
rescue => e
|
482
|
+
log.error "Error loading instrumentation file '#{file}': #{e}"
|
483
|
+
log.debug e.backtrace.join("\n")
|
484
|
+
end
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
427
488
|
end
|
428
489
|
end
|