newrelic_rpm 2.13.0.beta5 → 2.13.1
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 +4 -0
- data/lib/new_relic/agent.rb +50 -50
- data/lib/new_relic/agent/agent.rb +24 -19
- data/lib/new_relic/agent/busy_calculator.rb +22 -22
- data/lib/new_relic/agent/chained_call.rb +3 -3
- data/lib/new_relic/agent/error_collector.rb +19 -19
- data/lib/new_relic/agent/instrumentation/active_record_instrumentation.rb +11 -11
- data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +2 -2
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +43 -43
- data/lib/new_relic/agent/instrumentation/data_mapper.rb +6 -6
- data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +2 -2
- data/lib/new_relic/agent/instrumentation/memcache.rb +8 -8
- data/lib/new_relic/agent/instrumentation/merb/controller.rb +4 -4
- data/lib/new_relic/agent/instrumentation/metric_frame.rb +307 -303
- data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +8 -8
- data/lib/new_relic/agent/instrumentation/rack.rb +2 -2
- data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +10 -10
- data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +3 -3
- data/lib/new_relic/agent/instrumentation/rails/errors.rb +5 -5
- data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +5 -5
- data/lib/new_relic/agent/instrumentation/sinatra.rb +5 -5
- data/lib/new_relic/agent/instrumentation/sunspot.rb +1 -1
- data/lib/new_relic/agent/method_tracer.rb +55 -55
- data/lib/new_relic/agent/sampler.rb +42 -38
- data/lib/new_relic/agent/samplers/cpu_sampler.rb +4 -4
- data/lib/new_relic/agent/samplers/delayed_job_lock_sampler.rb +7 -7
- data/lib/new_relic/agent/samplers/memory_sampler.rb +11 -11
- data/lib/new_relic/agent/samplers/object_sampler.rb +1 -1
- data/lib/new_relic/agent/shim_agent.rb +20 -16
- data/lib/new_relic/agent/stats_engine.rb +3 -3
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +28 -28
- data/lib/new_relic/agent/stats_engine/samplers.rb +16 -16
- data/lib/new_relic/agent/stats_engine/transactions.rb +25 -25
- data/lib/new_relic/agent/transaction_sampler.rb +68 -69
- data/lib/new_relic/agent/worker_loop.rb +13 -13
- data/lib/new_relic/collection_helper.rb +6 -6
- data/lib/new_relic/command.rb +14 -14
- data/lib/new_relic/commands/deployments.rb +19 -19
- data/lib/new_relic/commands/install.rb +25 -15
- data/lib/new_relic/control.rb +25 -25
- data/lib/new_relic/control/configuration.rb +17 -17
- data/lib/new_relic/control/frameworks/external.rb +3 -3
- data/lib/new_relic/control/frameworks/merb.rb +6 -6
- data/lib/new_relic/control/frameworks/rails.rb +17 -17
- data/lib/new_relic/control/frameworks/rails3.rb +11 -27
- data/lib/new_relic/control/frameworks/ruby.rb +6 -6
- data/lib/new_relic/control/frameworks/sinatra.rb +4 -4
- data/lib/new_relic/control/instrumentation.rb +8 -8
- data/lib/new_relic/control/logging_methods.rb +13 -13
- data/lib/new_relic/control/profiling.rb +2 -2
- data/lib/new_relic/control/server_methods.rb +17 -17
- data/lib/new_relic/delayed_job_injection.rb +1 -1
- data/lib/new_relic/histogram.rb +73 -71
- data/lib/new_relic/local_environment.rb +45 -45
- data/lib/new_relic/merbtasks.rb +1 -1
- data/lib/new_relic/metric_data.rb +5 -5
- data/lib/new_relic/metric_parser.rb +22 -22
- data/lib/new_relic/metric_parser/action_mailer.rb +4 -4
- data/lib/new_relic/metric_parser/active_merchant.rb +8 -8
- data/lib/new_relic/metric_parser/active_record.rb +2 -2
- data/lib/new_relic/metric_parser/apdex.rb +86 -51
- data/lib/new_relic/metric_parser/controller.rb +10 -10
- data/lib/new_relic/metric_parser/controller_cpu.rb +5 -5
- data/lib/new_relic/metric_parser/errors.rb +1 -1
- data/lib/new_relic/metric_parser/external.rb +3 -3
- data/lib/new_relic/metric_parser/mem_cache.rb +2 -2
- data/lib/new_relic/metric_parser/other_transaction.rb +7 -7
- data/lib/new_relic/metric_parser/view.rb +5 -5
- data/lib/new_relic/metric_parser/web_frontend.rb +1 -1
- data/lib/new_relic/metric_parser/web_service.rb +1 -1
- data/lib/new_relic/metric_spec.rb +13 -13
- data/lib/new_relic/noticed_error.rb +4 -4
- data/lib/new_relic/rack/developer_mode.rb +33 -33
- data/lib/new_relic/rack/metric_app.rb +2 -2
- data/lib/new_relic/recipes.rb +9 -9
- data/lib/new_relic/stats.rb +57 -57
- data/lib/new_relic/timer_lib.rb +2 -2
- data/lib/new_relic/transaction_analysis.rb +19 -19
- data/lib/new_relic/transaction_sample.rb +101 -101
- data/lib/new_relic/url_rule.rb +3 -3
- data/lib/new_relic/version.rb +10 -10
- data/lib/newrelic_rpm.rb +6 -4
- data/lib/tasks/all.rb +1 -1
- data/newrelic_rpm.gemspec +3 -3
- data/test/new_relic/rack/episodes_test.rb +1 -0
- metadata +24 -42
@@ -4,43 +4,43 @@ module NewRelic
|
|
4
4
|
# one harvest period. It's similar to what you would get if you just added up all the
|
5
5
|
# execution times of controller calls, however that will be inaccurate when requests
|
6
6
|
# span the minute boundaries. This module manages accounting of requests not yet
|
7
|
-
# completed.
|
7
|
+
# completed.
|
8
8
|
#
|
9
9
|
# Calls are re-entrant. All start calls must be paired with finish
|
10
10
|
# calls, or a reset call.
|
11
11
|
module BusyCalculator
|
12
|
-
|
12
|
+
|
13
13
|
extend self
|
14
|
-
|
14
|
+
|
15
15
|
# For testability, add accessors:
|
16
16
|
attr_reader :harvest_start, :accumulator
|
17
|
-
|
17
|
+
|
18
18
|
def dispatcher_start(time)
|
19
|
-
Thread.current[:busy_entries] ||= 0
|
19
|
+
Thread.current[:busy_entries] ||= 0
|
20
20
|
callers = Thread.current[:busy_entries] += 1
|
21
21
|
return if callers > 1
|
22
22
|
@lock.synchronize do
|
23
|
-
@entrypoint_stack.push time
|
23
|
+
@entrypoint_stack.push time
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def dispatcher_finish(end_time = Time.now)
|
28
28
|
callers = Thread.current[:busy_entries] -= 1
|
29
29
|
# Ignore nested calls
|
30
30
|
return if callers > 0
|
31
31
|
@lock.synchronize do
|
32
32
|
if @entrypoint_stack.empty?
|
33
|
-
NewRelic::Agent.logger.error("Stack underflow tracking dispatcher entry and exit!\n #{caller.join(" \n")}")
|
33
|
+
NewRelic::Agent.logger.error("Stack underflow tracking dispatcher entry and exit!\n #{caller.join(" \n")}")
|
34
34
|
else
|
35
35
|
@accumulator += (end_time - @entrypoint_stack.pop).to_f
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
def busy_count
|
41
41
|
@entrypoint_stack.size
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
# Reset the state of the information accumulated by all threads,
|
45
45
|
# but only reset the recursion counter for this thread.
|
46
46
|
def reset
|
@@ -50,9 +50,9 @@ module NewRelic
|
|
50
50
|
@accumulator = 0
|
51
51
|
@harvest_start = Time.now
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
self.reset
|
55
|
-
|
55
|
+
|
56
56
|
# Called before uploading to to the server to collect current busy stats.
|
57
57
|
def harvest_busy
|
58
58
|
busy = 0
|
@@ -60,32 +60,32 @@ module NewRelic
|
|
60
60
|
@lock.synchronize do
|
61
61
|
busy = accumulator
|
62
62
|
@accumulator = 0
|
63
|
-
|
64
|
-
# Walk through the stack and capture all times up to
|
63
|
+
|
64
|
+
# Walk through the stack and capture all times up to
|
65
65
|
# now for entrypoints
|
66
|
-
@entrypoint_stack.size.times do |frame|
|
66
|
+
@entrypoint_stack.size.times do |frame|
|
67
67
|
busy += (t0 - @entrypoint_stack[frame]).to_f
|
68
68
|
@entrypoint_stack[frame] = t0
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
busy = 0.0 if busy < 0.0 # don't go below 0%
|
74
|
-
|
74
|
+
|
75
75
|
time_window = (t0 - harvest_start).to_f
|
76
76
|
time_window = 1.0 if time_window == 0.0 # protect against divide by zero
|
77
|
-
|
77
|
+
|
78
78
|
busy = busy / time_window
|
79
|
-
|
79
|
+
|
80
80
|
instance_busy_stats.record_data_point busy
|
81
81
|
@harvest_start = t0
|
82
82
|
end
|
83
83
|
private
|
84
84
|
def instance_busy_stats
|
85
85
|
# Late binding on the Instance/busy stats
|
86
|
-
NewRelic::Agent.agent.stats_engine.get_stats_no_scope 'Instance/Busy'
|
86
|
+
NewRelic::Agent.agent.stats_engine.get_stats_no_scope 'Instance/Busy'
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
@@ -1,13 +1,13 @@
|
|
1
|
-
# This is used to allow obfuscators to be chained.
|
1
|
+
# This is used to allow obfuscators to be chained.
|
2
2
|
|
3
3
|
class NewRelic::ChainedCall
|
4
4
|
def initialize(block1, block2)
|
5
5
|
@block1 = block1
|
6
6
|
@block2 = block2
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
def call(sql)
|
10
10
|
sql = @block1.call(sql)
|
11
11
|
@block2.call(sql)
|
12
12
|
end
|
13
|
-
end
|
13
|
+
end
|
@@ -3,15 +3,15 @@ module NewRelic
|
|
3
3
|
module Agent
|
4
4
|
class ErrorCollector
|
5
5
|
include NewRelic::CollectionHelper
|
6
|
-
|
6
|
+
|
7
7
|
# Defined the methods that need to be stubbed out when the
|
8
8
|
# agent is disabled
|
9
9
|
module Shim #:nodoc:
|
10
10
|
def notice_error(*args); end
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
MAX_ERROR_QUEUE_LENGTH = 20 unless defined? MAX_ERROR_QUEUE_LENGTH
|
14
|
-
|
14
|
+
|
15
15
|
attr_accessor :enabled
|
16
16
|
attr_reader :config_enabled
|
17
17
|
|
@@ -22,17 +22,17 @@ module NewRelic
|
|
22
22
|
@ignore_filter = nil
|
23
23
|
|
24
24
|
config = NewRelic::Control.instance.fetch('error_collector', {})
|
25
|
-
|
25
|
+
|
26
26
|
@enabled = @config_enabled = config.fetch('enabled', true)
|
27
27
|
@capture_source = config.fetch('capture_source', true)
|
28
|
-
|
28
|
+
|
29
29
|
ignore_errors = config.fetch('ignore_errors', "")
|
30
30
|
ignore_errors = ignore_errors.split(",") if ignore_errors.is_a? String
|
31
|
-
ignore_errors.each { |error| error.strip! }
|
31
|
+
ignore_errors.each { |error| error.strip! }
|
32
32
|
ignore(ignore_errors)
|
33
33
|
@lock = Mutex.new
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
def ignore_error_filter(&block)
|
37
37
|
if block
|
38
38
|
@ignore_filter = block
|
@@ -40,13 +40,13 @@ module NewRelic
|
|
40
40
|
@ignore_filter
|
41
41
|
end
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
# errors is an array of Exception Class Names
|
45
45
|
#
|
46
46
|
def ignore(errors)
|
47
47
|
errors.each { |error| @ignore[error] = true; log.debug("Ignoring errors of type '#{error}'") }
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
# Notice the error with the given available options:
|
51
51
|
#
|
52
52
|
# * <tt>:uri</tt> => The request path, minus any request params or query string.
|
@@ -59,7 +59,7 @@ module NewRelic
|
|
59
59
|
# If exception is nil, the error count is bumped and no traced error is recorded
|
60
60
|
def notice_error(exception, options={})
|
61
61
|
return unless @enabled
|
62
|
-
return if exception && @ignore[exception.class.name]
|
62
|
+
return if exception && @ignore[exception.class.name]
|
63
63
|
if @ignore_filter && exception
|
64
64
|
exception = @ignore_filter.call(exception)
|
65
65
|
return if exception.nil?
|
@@ -76,17 +76,17 @@ module NewRelic
|
|
76
76
|
custom_params = options.delete(:custom_params) || {}
|
77
77
|
# If anything else is left over, treat it like a custom param:
|
78
78
|
custom_params.merge! options
|
79
|
-
|
79
|
+
|
80
80
|
data[:request_params] = normalize_params(request_params) if NewRelic::Control.instance.capture_params && request_params
|
81
81
|
data[:custom_params] = normalize_params(custom_params) unless custom_params.empty?
|
82
82
|
data[:rails_root] = NewRelic::Control.instance.root
|
83
83
|
data[:file_name] = exception.file_name if exception.respond_to?('file_name')
|
84
84
|
data[:line_number] = exception.line_number if exception.respond_to?('line_number')
|
85
|
-
|
85
|
+
|
86
86
|
if @capture_source && exception.respond_to?('source_extract')
|
87
87
|
data[:source] = exception.source_extract
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
90
|
if exception.respond_to? 'original_exception'
|
91
91
|
inside_exception = exception.original_exception
|
92
92
|
else
|
@@ -94,20 +94,20 @@ module NewRelic
|
|
94
94
|
end
|
95
95
|
|
96
96
|
data[:stack_trace] = (inside_exception && inside_exception.respond_to?('backtrace')) ? inside_exception.backtrace : '<no stack trace>'
|
97
|
-
|
97
|
+
|
98
98
|
noticed_error = NewRelic::NoticedError.new(action_path, data, exception)
|
99
|
-
|
99
|
+
|
100
100
|
@lock.synchronize do
|
101
101
|
if @errors.length == MAX_ERROR_QUEUE_LENGTH
|
102
|
-
log.warn("The error reporting queue has reached #{MAX_ERROR_QUEUE_LENGTH}. The error detail for this and subsequent errors will not be transmitted to RPM until the queued errors have been sent: #{exception
|
102
|
+
log.warn("The error reporting queue has reached #{MAX_ERROR_QUEUE_LENGTH}. The error detail for this and subsequent errors will not be transmitted to RPM until the queued errors have been sent: #{exception}")
|
103
103
|
else
|
104
104
|
@errors << noticed_error
|
105
105
|
end
|
106
106
|
end
|
107
107
|
exception
|
108
108
|
end
|
109
|
-
|
110
|
-
# Get the errors currently queued up. Unsent errors are left
|
109
|
+
|
110
|
+
# Get the errors currently queued up. Unsent errors are left
|
111
111
|
# over from a previous unsuccessful attempt to send them to the server.
|
112
112
|
# We first clear out all unsent errors before sending the newly queued errors.
|
113
113
|
def harvest_errors(unsent_errors)
|
@@ -121,7 +121,7 @@ module NewRelic
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
end
|
124
|
-
|
124
|
+
|
125
125
|
private
|
126
126
|
def log
|
127
127
|
NewRelic::Agent.logger
|
@@ -6,7 +6,7 @@ if defined?(ActiveRecord) && defined?(ActiveRecord::Base) && !NewRelic::Control.
|
|
6
6
|
module Agent
|
7
7
|
module Instrumentation
|
8
8
|
module ActiveRecordInstrumentation
|
9
|
-
|
9
|
+
|
10
10
|
def self.included(instrumented_class)
|
11
11
|
instrumented_class.class_eval do
|
12
12
|
alias_method :log_without_newrelic_instrumentation, :log
|
@@ -14,11 +14,11 @@ if defined?(ActiveRecord) && defined?(ActiveRecord::Base) && !NewRelic::Control.
|
|
14
14
|
protected :log
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def log_with_newrelic_instrumentation(sql, name, &block)
|
19
|
-
|
19
|
+
|
20
20
|
return log_without_newrelic_instrumentation(sql, name, &block) unless NewRelic::Agent.is_execution_traced?
|
21
|
-
|
21
|
+
|
22
22
|
# Capture db config if we are going to try to get the explain plans
|
23
23
|
if (defined?(ActiveRecord::ConnectionAdapters::MysqlAdapter) && self.is_a?(ActiveRecord::ConnectionAdapters::MysqlAdapter)) ||
|
24
24
|
(defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) && self.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter))
|
@@ -39,7 +39,7 @@ if defined?(ActiveRecord) && defined?(ActiveRecord::Base) && !NewRelic::Control.
|
|
39
39
|
end
|
40
40
|
metric = "ActiveRecord/#{model}/#{metric_name}" if metric_name
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
if metric.nil?
|
44
44
|
metric = NewRelic::Agent::Instrumentation::MetricFrame.database_metric_name
|
45
45
|
if metric.nil?
|
@@ -53,7 +53,7 @@ if defined?(ActiveRecord) && defined?(ActiveRecord::Base) && !NewRelic::Control.
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
if !metric
|
58
58
|
log_without_newrelic_instrumentation(sql, name, &block)
|
59
59
|
else
|
@@ -62,21 +62,21 @@ if defined?(ActiveRecord) && defined?(ActiveRecord::Base) && !NewRelic::Control.
|
|
62
62
|
self.class.trace_execution_scoped(metrics) do
|
63
63
|
t0 = Time.now
|
64
64
|
begin
|
65
|
-
log_without_newrelic_instrumentation(sql, name, &block)
|
65
|
+
log_without_newrelic_instrumentation(sql, name, &block)
|
66
66
|
ensure
|
67
|
-
NewRelic::Agent.instance.transaction_sampler.notice_sql(sql, supported_config, (Time.now - t0).to_f)
|
67
|
+
NewRelic::Agent.instance.transaction_sampler.notice_sql(sql, supported_config, (Time.now - t0).to_f)
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
# instrumentation to catch logged SQL statements in sampled transactions
|
76
76
|
ActiveRecord::ConnectionAdapters::AbstractAdapter.module_eval do
|
77
77
|
include ::NewRelic::Agent::Instrumentation::ActiveRecordInstrumentation
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
# This instrumentation will add an extra scope to the transaction traces
|
81
81
|
# which will show the code surrounding the query, inside the model find_by_sql
|
82
82
|
# method.
|
@@ -1,5 +1,5 @@
|
|
1
1
|
if defined?(::ActsAsSolr)
|
2
|
-
|
2
|
+
|
3
3
|
module NewRelic
|
4
4
|
module Instrumentation
|
5
5
|
module ActsAsSolrInstrumentation
|
@@ -13,7 +13,7 @@ if defined?(::ActsAsSolr)
|
|
13
13
|
NewRelic::Agent.instance.transaction_sampler.notice_nosql(args.first.inspect, (Time.now - t0).to_f) rescue nil
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -7,7 +7,7 @@ module NewRelic
|
|
7
7
|
# This instrumentation is applied to the action controller to collect
|
8
8
|
# metrics for every web request.
|
9
9
|
#
|
10
|
-
# It can also be used to capture performance information for
|
10
|
+
# It can also be used to capture performance information for
|
11
11
|
# background tasks and other non-web transactions, including
|
12
12
|
# detailed transaction traces and traced errors.
|
13
13
|
#
|
@@ -16,17 +16,17 @@ module NewRelic
|
|
16
16
|
# #perform_action_with_newrelic_trace
|
17
17
|
#
|
18
18
|
module ControllerInstrumentation
|
19
|
-
|
19
|
+
|
20
20
|
def self.included(clazz) # :nodoc:
|
21
21
|
clazz.extend(ClassMethods)
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
# This module is for importing stubs when the agent is disabled
|
25
25
|
module ClassMethodsShim # :nodoc:
|
26
26
|
def newrelic_ignore(*args); end
|
27
27
|
def newrelic_ignore_apdex(*args); end
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
module Shim # :nodoc:
|
31
31
|
def self.included(clazz)
|
32
32
|
clazz.extend(ClassMethodsShim)
|
@@ -36,20 +36,20 @@ module NewRelic
|
|
36
36
|
def newrelic_metric_path; end
|
37
37
|
def perform_action_with_newrelic_trace(*args); yield; end
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
module ClassMethods
|
41
41
|
# Have NewRelic ignore actions in this controller. Specify the actions as hash options
|
42
42
|
# using :except and :only. If no actions are specified, all actions are ignored.
|
43
43
|
def newrelic_ignore(specifiers={})
|
44
44
|
newrelic_ignore_aspect('do_not_trace', specifiers)
|
45
45
|
end
|
46
|
-
# Have NewRelic omit apdex measurements on the given actions. Typically used for
|
46
|
+
# Have NewRelic omit apdex measurements on the given actions. Typically used for
|
47
47
|
# actions that are not user facing or that skew your overall apdex measurement.
|
48
48
|
# Accepts :except and :only options, as with #newrelic_ignore.
|
49
49
|
def newrelic_ignore_apdex(specifiers={})
|
50
50
|
newrelic_ignore_aspect('ignore_apdex', specifiers)
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
def newrelic_ignore_aspect(property, specifiers={}) # :nodoc:
|
54
54
|
if specifiers.empty?
|
55
55
|
self.newrelic_write_attr property, true
|
@@ -59,7 +59,7 @@ module NewRelic
|
|
59
59
|
self.newrelic_write_attr property, specifiers
|
60
60
|
end
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
# Should be monkey patched into the controller class implemented
|
64
64
|
# with the inheritable attribute mechanism.
|
65
65
|
def newrelic_write_attr(attr_name, value) # :nodoc:
|
@@ -68,11 +68,11 @@ module NewRelic
|
|
68
68
|
def newrelic_read_attr(attr_name) # :nodoc:
|
69
69
|
instance_variable_get "@#{attr_name}"
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
# Add transaction tracing to the given method. This will treat
|
73
73
|
# the given method as a main entrypoint for instrumentation, just
|
74
74
|
# like controller actions are treated by default. Useful especially
|
75
|
-
# for background tasks.
|
75
|
+
# for background tasks.
|
76
76
|
#
|
77
77
|
# Example for background job:
|
78
78
|
# class Job
|
@@ -89,7 +89,7 @@ module NewRelic
|
|
89
89
|
# action to invoke operations which you want treated as top
|
90
90
|
# level actions, so they aren't all lumped into the invoker
|
91
91
|
# action.
|
92
|
-
#
|
92
|
+
#
|
93
93
|
# MyController < ActionController::Base
|
94
94
|
# include NewRelic::Agent::Instrumentation::ControllerInstrumentation
|
95
95
|
# # dispatch the given op to the method given by the service parameter.
|
@@ -149,22 +149,22 @@ module NewRelic
|
|
149
149
|
NewRelic::Control.instance.log.debug("Traced transaction: class = #{self.name}, method = #{method.to_s}, options = #{options.inspect}")
|
150
150
|
end
|
151
151
|
end
|
152
|
-
|
152
|
+
|
153
153
|
# Must be implemented in the controller class:
|
154
154
|
# Determine the path that is used in the metric name for
|
155
155
|
# the called controller action. Of the form controller_path/action_name
|
156
|
-
#
|
156
|
+
#
|
157
157
|
def newrelic_metric_path(action_name_override = nil) # :nodoc:
|
158
158
|
raise "Not implemented!"
|
159
159
|
end
|
160
|
-
|
161
|
-
# Yield to the given block with NewRelic tracing. Used by
|
160
|
+
|
161
|
+
# Yield to the given block with NewRelic tracing. Used by
|
162
162
|
# default instrumentation on controller actions in Rails and Merb.
|
163
163
|
# But it can also be used in custom instrumentation of controller
|
164
164
|
# methods and background tasks.
|
165
165
|
#
|
166
166
|
# This is the method invoked by instrumentation added by the
|
167
|
-
# <tt>ClassMethods#add_transaction_tracer</tt>.
|
167
|
+
# <tt>ClassMethods#add_transaction_tracer</tt>.
|
168
168
|
#
|
169
169
|
# Here's a more verbose version of the example shown in
|
170
170
|
# <tt>ClassMethods#add_transaction_tracer</tt> using this method instead of
|
@@ -176,7 +176,7 @@ module NewRelic
|
|
176
176
|
# the +invoke_operation+ action is ignored but the operation
|
177
177
|
# methods show up in RPM as if they were first class controller
|
178
178
|
# actions
|
179
|
-
#
|
179
|
+
#
|
180
180
|
# MyController < ActionController::Base
|
181
181
|
# include NewRelic::Agent::Instrumentation::ControllerInstrumentation
|
182
182
|
# # dispatch the given op to the method given by the service parameter.
|
@@ -191,7 +191,7 @@ module NewRelic
|
|
191
191
|
# end
|
192
192
|
#
|
193
193
|
#
|
194
|
-
# When invoking this method explicitly as in the example above, pass in a
|
194
|
+
# When invoking this method explicitly as in the example above, pass in a
|
195
195
|
# block to measure with some combination of options:
|
196
196
|
#
|
197
197
|
# * <tt>:category => :controller</tt> indicates that this is a
|
@@ -201,7 +201,7 @@ module NewRelic
|
|
201
201
|
# background task and will show up in RPM with other background
|
202
202
|
# tasks instead of in the controllers list
|
203
203
|
# * <tt>:category => :rack</tt> if you are instrumenting a rack
|
204
|
-
# middleware call. The <tt>:name</tt> is optional, useful if you
|
204
|
+
# middleware call. The <tt>:name</tt> is optional, useful if you
|
205
205
|
# have more than one potential transaction in the #call.
|
206
206
|
# * <tt>:category => :uri</tt> indicates that this is a
|
207
207
|
# web transaction whose name is a normalized URI, where 'normalized'
|
@@ -224,14 +224,14 @@ module NewRelic
|
|
224
224
|
# * <tt>:path => metric_path</tt> is *deprecated* in the public API. It
|
225
225
|
# allows you to set the entire metric after the category part. Overrides
|
226
226
|
# all the other options.
|
227
|
-
# * <tt>:request => Rack::Request#new(env)</tt> is used to pass in a
|
227
|
+
# * <tt>:request => Rack::Request#new(env)</tt> is used to pass in a
|
228
228
|
# request object that may respond to uri and referer.
|
229
229
|
#
|
230
230
|
# If a single argument is passed in, it is treated as a metric
|
231
231
|
# path. This form is deprecated.
|
232
232
|
def perform_action_with_newrelic_trace(*args, &block)
|
233
|
-
|
234
|
-
# Skip instrumentation based on the value of 'do_not_trace' and if
|
233
|
+
|
234
|
+
# Skip instrumentation based on the value of 'do_not_trace' and if
|
235
235
|
# we aren't calling directly with a block.
|
236
236
|
if !block_given? && _is_filtered?('do_not_trace')
|
237
237
|
# Also ignore all instrumentation in the call sequence
|
@@ -239,11 +239,11 @@ module NewRelic
|
|
239
239
|
return perform_action_without_newrelic_trace(*args)
|
240
240
|
end
|
241
241
|
end
|
242
|
-
|
242
|
+
|
243
243
|
return perform_action_with_newrelic_profile(args, &block) if NewRelic::Control.instance.profiling?
|
244
|
-
|
244
|
+
|
245
245
|
frame_data = _push_metric_frame(block_given? ? args : [])
|
246
|
-
begin
|
246
|
+
begin
|
247
247
|
NewRelic::Agent.trace_execution_scoped frame_data.recorded_metrics, :force => frame_data.force_flag do
|
248
248
|
frame_data.start_transaction
|
249
249
|
begin
|
@@ -270,14 +270,14 @@ module NewRelic
|
|
270
270
|
protected
|
271
271
|
# Should be implemented in the dispatcher class
|
272
272
|
def newrelic_response_code; end
|
273
|
-
|
273
|
+
|
274
274
|
def newrelic_request_headers
|
275
275
|
self.respond_to?(:request) && self.request.respond_to?(:headers) && self.request.headers
|
276
276
|
end
|
277
|
-
|
277
|
+
|
278
278
|
private
|
279
|
-
|
280
|
-
# Profile the instrumented call. Dev mode only. Experimental.
|
279
|
+
|
280
|
+
# Profile the instrumented call. Dev mode only. Experimental.
|
281
281
|
def perform_action_with_newrelic_profile(args)
|
282
282
|
frame_data = _push_metric_frame(block_given? ? args : [])
|
283
283
|
val = nil
|
@@ -299,20 +299,20 @@ module NewRelic
|
|
299
299
|
ensure
|
300
300
|
frame_data.pop
|
301
301
|
end
|
302
|
-
|
302
|
+
|
303
303
|
# Write a metric frame onto a thread local if there isn't already one there.
|
304
304
|
# If there is one, just update it.
|
305
305
|
def _push_metric_frame(args) # :nodoc:
|
306
306
|
frame_data = NewRelic::Agent::Instrumentation::MetricFrame.current(true)
|
307
|
-
|
307
|
+
|
308
308
|
frame_data.apdex_start ||= _detect_upstream_wait(frame_data.start)
|
309
|
-
_record_queue_length
|
309
|
+
_record_queue_length
|
310
310
|
# If a block was passed in, then the arguments represent options for the instrumentation,
|
311
311
|
# not app method arguments.
|
312
312
|
if args.any?
|
313
313
|
if args.last.is_a?(Hash)
|
314
314
|
options = args.last
|
315
|
-
frame_data.force_flag = options[:force]
|
315
|
+
frame_data.force_flag = options[:force]
|
316
316
|
frame_data.request = options[:request] if options[:request]
|
317
317
|
end
|
318
318
|
category, path, available_params = _convert_args_to_path(args)
|
@@ -326,7 +326,7 @@ module NewRelic
|
|
326
326
|
frame_data.filtered_params = (respond_to? :filter_parameters) ? filter_parameters(available_params) : available_params
|
327
327
|
frame_data
|
328
328
|
end
|
329
|
-
|
329
|
+
|
330
330
|
def _convert_args_to_path(args)
|
331
331
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
332
332
|
params = options[:params] || {}
|
@@ -340,7 +340,7 @@ module NewRelic
|
|
340
340
|
else options[:category].to_s
|
341
341
|
end
|
342
342
|
unless path = options[:path]
|
343
|
-
action = options[:name] || args.first
|
343
|
+
action = options[:name] || args.first
|
344
344
|
metric_class = options[:class_name] || (self.is_a?(Class) ? self.name : self.class.name)
|
345
345
|
path = metric_class
|
346
346
|
path += ('/' + action) if action
|
@@ -348,7 +348,7 @@ module NewRelic
|
|
348
348
|
[category, path, params]
|
349
349
|
end
|
350
350
|
|
351
|
-
# Filter out
|
351
|
+
# Filter out
|
352
352
|
def _is_filtered?(key)
|
353
353
|
ignore_actions = self.class.newrelic_read_attr(key) if self.class.respond_to? :newrelic_read_attr
|
354
354
|
case ignore_actions
|
@@ -374,7 +374,7 @@ module NewRelic
|
|
374
374
|
NewRelic::Agent.agent.stats_engine.get_stats_no_scope('Mongrel/Queue Length').trace_call(queue_depth) if queue_depth
|
375
375
|
end
|
376
376
|
end
|
377
|
-
|
377
|
+
|
378
378
|
# Return a Time instance representing the upstream start time.
|
379
379
|
# now is a Time instance to fall back on if no other candidate
|
380
380
|
# for the start time is found.
|
@@ -396,14 +396,14 @@ module NewRelic
|
|
396
396
|
total_time = (now - http_entry_time)
|
397
397
|
queue_stat.trace_call(total_time.to_f) unless total_time.to_f <= 0.0 # using remote timestamps could lead to negative queue time
|
398
398
|
end
|
399
|
-
return http_entry_time ? Time.at(http_entry_time) : now
|
399
|
+
return http_entry_time ? Time.at(http_entry_time) : now
|
400
400
|
end
|
401
|
-
|
401
|
+
|
402
402
|
def _dispatch_stat
|
403
|
-
NewRelic::Agent.agent.stats_engine.get_stats_no_scope 'HttpDispatcher'
|
403
|
+
NewRelic::Agent.agent.stats_engine.get_stats_no_scope 'HttpDispatcher'
|
404
404
|
end
|
405
|
-
|
406
|
-
end
|
407
|
-
end
|
405
|
+
|
406
|
+
end
|
407
|
+
end
|
408
408
|
end
|
409
409
|
end
|