wd_newrelic_rpm 3.5.6 → 3.5.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +43 -3
- data/Gemfile +6 -2
- data/LICENSE +23 -0
- data/lib/new_relic/agent.rb +50 -3
- data/lib/new_relic/agent/agent.rb +40 -60
- data/lib/new_relic/agent/configuration/defaults.rb +9 -3
- data/lib/new_relic/agent/configuration/server_source.rb +4 -0
- data/lib/new_relic/agent/cross_app_monitor.rb +239 -0
- data/lib/new_relic/agent/cross_app_tracing.rb +281 -0
- data/lib/new_relic/agent/database.rb +28 -10
- data/lib/new_relic/agent/error_collector.rb +5 -0
- data/lib/new_relic/agent/event_listener.rb +4 -0
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +58 -39
- data/lib/new_relic/agent/instrumentation/metric_frame.rb +16 -3
- data/lib/new_relic/agent/instrumentation/net.rb +13 -11
- data/lib/new_relic/agent/instrumentation/queue_time.rb +50 -192
- data/lib/new_relic/agent/instrumentation/rails4/action_controller.rb +145 -0
- data/lib/new_relic/agent/instrumentation/rails4/errors.rb +45 -0
- data/lib/new_relic/agent/instrumentation/resque.rb +10 -10
- data/lib/new_relic/agent/instrumentation/sinatra.rb +19 -9
- data/lib/new_relic/agent/new_relic_service.rb +63 -9
- data/lib/new_relic/agent/pipe_service.rb +8 -12
- data/lib/new_relic/agent/rules_engine.rb +72 -0
- data/lib/new_relic/agent/shim_agent.rb +0 -1
- data/lib/new_relic/agent/sql_sampler.rb +3 -2
- data/lib/new_relic/agent/stats.rb +149 -0
- data/lib/new_relic/agent/stats_engine.rb +9 -0
- data/lib/new_relic/agent/stats_engine/gc_profiler.rb +1 -24
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +84 -185
- data/lib/new_relic/agent/stats_engine/stats_hash.rb +58 -0
- data/lib/new_relic/agent/stats_engine/transactions.rb +10 -2
- data/lib/new_relic/agent/transaction_info.rb +31 -6
- data/lib/new_relic/agent/transaction_sample_builder.rb +19 -8
- data/lib/new_relic/agent/transaction_sampler.rb +17 -10
- data/lib/new_relic/helper.rb +32 -0
- data/lib/new_relic/local_environment.rb +24 -32
- data/lib/new_relic/okjson.rb +599 -0
- data/lib/new_relic/transaction_sample.rb +2 -1
- data/lib/new_relic/transaction_sample/segment.rb +2 -1
- data/lib/new_relic/version.rb +1 -1
- data/newrelic.yml +27 -41
- data/test/multiverse/suites/agent_only/Envfile +5 -1
- data/test/multiverse/suites/agent_only/audit_log_test.rb +2 -4
- data/test/multiverse/suites/agent_only/config/newrelic.yml +1 -2
- data/test/multiverse/suites/agent_only/{cross_process_test.rb → cross_application_tracing_test.rb} +3 -3
- data/test/multiverse/suites/agent_only/key_transactions_test.rb +66 -0
- data/test/multiverse/suites/agent_only/marshaling_test.rb +9 -22
- data/test/multiverse/suites/agent_only/rename_rule_test.rb +57 -0
- data/test/multiverse/suites/agent_only/start_up_test.rb +1 -1
- data/test/multiverse/suites/agent_only/thread_profiling_test.rb +17 -6
- data/test/multiverse/suites/rails/error_tracing_test.rb +20 -8
- data/test/multiverse/suites/rails/queue_time_test.rb +2 -2
- data/test/multiverse/suites/resque/instrumentation_test.rb +4 -3
- data/test/multiverse/suites/sinatra/Envfile +2 -0
- data/test/multiverse/suites/sinatra/config/newrelic.yml +1 -0
- data/test/multiverse/suites/sinatra/sinatra_metric_explosion_test.rb +5 -5
- data/test/multiverse/suites/sinatra/sinatra_test.rb +77 -10
- data/test/new_relic/agent/agent/connect_test.rb +45 -1
- data/test/new_relic/agent/agent/start_worker_thread_test.rb +0 -3
- data/test/new_relic/agent/agent_test.rb +20 -40
- data/test/new_relic/agent/agent_test_controller_test.rb +27 -60
- data/test/new_relic/agent/busy_calculator_test.rb +1 -1
- data/test/new_relic/agent/configuration/server_source_test.rb +8 -3
- data/test/new_relic/agent/cross_app_monitor_test.rb +237 -0
- data/test/new_relic/agent/database_test.rb +60 -16
- data/test/new_relic/agent/error_collector_test.rb +28 -4
- data/test/new_relic/agent/event_listener_test.rb +23 -2
- data/test/new_relic/agent/instrumentation/browser_monitoring_timings_test.rb +1 -1
- data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +85 -12
- data/test/new_relic/agent/instrumentation/metric_frame_test.rb +95 -0
- data/test/new_relic/agent/instrumentation/net_instrumentation_test.rb +436 -59
- data/test/new_relic/agent/instrumentation/queue_time_test.rb +58 -357
- data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +2 -5
- data/test/new_relic/agent/method_tracer_test.rb +4 -2
- data/test/new_relic/agent/new_relic_service_test.rb +108 -6
- data/test/new_relic/agent/pipe_channel_manager_test.rb +1 -1
- data/test/new_relic/agent/pipe_service_test.rb +9 -9
- data/test/new_relic/agent/rpm_agent_test.rb +0 -11
- data/test/new_relic/agent/rules_engine_test.rb +82 -0
- data/test/new_relic/agent/shim_agent_test.rb +0 -4
- data/test/new_relic/agent/sql_sampler_test.rb +7 -0
- data/test/new_relic/agent/stats_engine/gc_profiler_test.rb +85 -0
- data/test/new_relic/agent/stats_engine/metric_stats_test.rb +110 -23
- data/test/new_relic/agent/stats_engine_test.rb +1 -46
- data/test/new_relic/agent/stats_hash_test.rb +93 -0
- data/test/new_relic/agent/stats_test.rb +197 -0
- data/test/new_relic/agent/transaction_info_test.rb +63 -11
- data/test/new_relic/agent/transaction_sample_builder_test.rb +10 -3
- data/test/new_relic/agent/transaction_sampler_test.rb +92 -80
- data/test/new_relic/agent/worker_loop_test.rb +1 -1
- data/test/new_relic/agent_test.rb +35 -5
- data/test/new_relic/control_test.rb +1 -1
- data/test/new_relic/fake_collector.rb +87 -9
- data/test/new_relic/helper_test.rb +24 -0
- data/test/new_relic/metric_data_test.rb +11 -11
- data/test/new_relic/metric_spec_test.rb +1 -1
- data/test/script/ci.sh +1 -1
- data/test/test_contexts.rb +0 -1
- data/test/test_helper.rb +21 -3
- metadata +34 -41
- data/lib/new_relic/agent/cross_process_monitoring.rb +0 -187
- data/lib/new_relic/stats.rb +0 -337
- data/test/new_relic/agent/cross_process_monitoring_test.rb +0 -190
- data/test/new_relic/agent/stats_engine/metric_stats/harvest_test.rb +0 -133
- data/test/new_relic/fakes_sending_data.rb +0 -30
- data/test/new_relic/stats_test.rb +0 -421
@@ -300,17 +300,30 @@ module NewRelic
|
|
300
300
|
end
|
301
301
|
|
302
302
|
def self.record_apdex(current_metric, action_duration, total_duration, is_error)
|
303
|
-
summary_stat = agent.stats_engine.
|
304
|
-
|
303
|
+
summary_stat = agent.stats_engine.lookup_stats("Apdex") ||
|
304
|
+
initialize_apdex("Apdex")
|
305
305
|
update_apdex(summary_stat, total_duration, is_error)
|
306
|
+
|
307
|
+
controller_stat = agent.stats_engine.lookup_stats(current_metric.apdex_metric_path) ||
|
308
|
+
initialize_apdex(current_metric.apdex_metric_path)
|
306
309
|
update_apdex(controller_stat, action_duration, is_error)
|
307
310
|
end
|
308
311
|
|
312
|
+
# Apdex min and max values should be initialized to the
|
313
|
+
# current apdex_t
|
314
|
+
def self.initialize_apdex(metric_name)
|
315
|
+
stats = agent.stats_engine.get_stats_no_scope(metric_name)
|
316
|
+
apdex_t = TransactionInfo.get.apdex_t
|
317
|
+
stats.min_call_time = apdex_t
|
318
|
+
stats.max_call_time = apdex_t
|
319
|
+
return stats
|
320
|
+
end
|
321
|
+
|
309
322
|
# Record an apdex value for the given stat. when `failed`
|
310
323
|
# the apdex should be recorded as a failure regardless of duration.
|
311
324
|
def self.update_apdex(stat, duration, failed)
|
312
325
|
duration = duration.to_f
|
313
|
-
apdex_t =
|
326
|
+
apdex_t = TransactionInfo.get.apdex_t
|
314
327
|
case
|
315
328
|
when failed
|
316
329
|
stat.record_apdex_f
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
DependencyDetection.defer do
|
2
4
|
@name = :net
|
3
5
|
|
@@ -7,23 +9,23 @@ DependencyDetection.defer do
|
|
7
9
|
|
8
10
|
executes do
|
9
11
|
::NewRelic::Agent.logger.info 'Installing Net instrumentation'
|
12
|
+
require 'new_relic/agent/cross_app_tracing'
|
10
13
|
end
|
11
|
-
|
14
|
+
|
12
15
|
executes do
|
13
|
-
Net::HTTP
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
self.class.trace_execution_scoped metrics do
|
22
|
-
request_without_newrelic_trace(*args, &block)
|
16
|
+
class Net::HTTP
|
17
|
+
|
18
|
+
# Instrument outgoing HTTP requests and fire associated events back
|
19
|
+
# into the Agent.
|
20
|
+
def request_with_newrelic_trace(request, *args, &block)
|
21
|
+
NewRelic::Agent::CrossAppTracing.trace_http_request( self, request ) do
|
22
|
+
request_without_newrelic_trace( request, *args, &block )
|
23
23
|
end
|
24
24
|
end
|
25
|
+
|
25
26
|
alias request_without_newrelic_trace request
|
26
27
|
alias request request_with_newrelic_trace
|
28
|
+
|
27
29
|
end
|
28
30
|
end
|
29
31
|
end
|
@@ -1,210 +1,68 @@
|
|
1
1
|
module NewRelic
|
2
2
|
module Agent
|
3
3
|
module Instrumentation
|
4
|
+
# https://newrelic.com/docs/features/tracking-front-end-time
|
5
|
+
# Record queue time metrics based on any of three headers
|
6
|
+
# which can be set on the request.
|
4
7
|
module QueueTime
|
5
|
-
unless defined?(
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
server_start = parse_server_time_from(env)
|
31
|
-
# returned for the controller instrumentation
|
32
|
-
[middleware_start, queue_start, server_start].min
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
# main method to extract server time info from env hash,
|
38
|
-
# records individual server metrics and one roll-up for all servers
|
39
|
-
def parse_server_time_from(env)
|
40
|
-
end_time = parse_end_time(env)
|
41
|
-
matches = get_matches_from_header(MAIN_HEADER, env)
|
42
|
-
|
43
|
-
record_individual_server_stats(end_time, matches)
|
44
|
-
record_rollup_server_stat(end_time, matches)
|
45
|
-
end
|
46
|
-
|
47
|
-
def parse_middleware_time_from(env)
|
48
|
-
end_time = parse_end_time(env)
|
49
|
-
matches = get_matches_from_header(MIDDLEWARE_HEADER, env)
|
50
|
-
|
51
|
-
record_individual_middleware_stats(end_time, matches)
|
52
|
-
oldest_time = record_rollup_middleware_stat(end_time, matches)
|
53
|
-
# notice this bit: we reset the end time to the earliest
|
54
|
-
# middleware tag so that other frontend metrics don't
|
55
|
-
# include this time.
|
56
|
-
add_end_time_header(oldest_time, env)
|
57
|
-
oldest_time
|
58
|
-
end
|
59
|
-
|
60
|
-
def parse_queue_time_from(env)
|
61
|
-
oldest_time = nil
|
62
|
-
end_time = parse_end_time(env)
|
63
|
-
alternate_length = check_for_alternate_queue_length(env)
|
64
|
-
if alternate_length
|
65
|
-
# skip all that fancy-dan stuff
|
66
|
-
NewRelic::Agent.get_stats(ALL_QUEUE_METRIC).trace_call(alternate_length)
|
67
|
-
oldest_time = (end_time - alternate_length) # should be a time
|
68
|
-
else
|
69
|
-
matches = get_matches_from_header(QUEUE_HEADER, env)
|
70
|
-
oldest_time = record_rollup_queue_stat(end_time, matches)
|
8
|
+
unless defined?(REQUEST_START_HEADER)
|
9
|
+
REQUEST_START_HEADER = 'HTTP_X_REQUEST_START'
|
10
|
+
QUEUE_START_HEADER = 'HTTP_X_QUEUE_START'
|
11
|
+
QUEUE_DURATION_HEADER = 'HTTP_X_QUEUE_TIME'
|
12
|
+
MIDDLEWARE_START_HEADER = 'HTTP_X_MIDDLEWARE_START'
|
13
|
+
ALL_QUEUE_METRIC = 'WebFrontend/QueueTime'
|
14
|
+
# any timestamps before this are thrown out and the parser
|
15
|
+
# will try again with a larger unit (2000/1/1 UTC)
|
16
|
+
EARLIEST_ACCEPTABLE_TIMESTAMP = 946684800
|
17
|
+
end
|
18
|
+
|
19
|
+
module_function
|
20
|
+
|
21
|
+
def parse_frontend_timestamp(headers, now=Time.now)
|
22
|
+
candidate_headers = [ REQUEST_START_HEADER, QUEUE_START_HEADER,
|
23
|
+
MIDDLEWARE_START_HEADER ]
|
24
|
+
earliest = candidate_headers.map do |header|
|
25
|
+
if headers[header]
|
26
|
+
parse_timestamp(timestamp_string_from_header_value(headers[header]))
|
27
|
+
end
|
28
|
+
end.compact.min
|
29
|
+
|
30
|
+
if earliest && earliest > now
|
31
|
+
NewRelic::Agent.logger.debug("Negative queue time detected, treating as zero: start=#{earliest.to_f} > now=#{now.to_f}")
|
32
|
+
earliest = now
|
71
33
|
end
|
72
|
-
# notice this bit: we reset the end time to the earliest
|
73
|
-
# queue tag or the start time minus the queue time so that
|
74
|
-
# other frontend metrics don't include this time.
|
75
|
-
add_end_time_header(oldest_time, env)
|
76
|
-
oldest_time
|
77
|
-
end
|
78
34
|
|
79
|
-
|
80
|
-
heroku_length = check_for_heroku_queue_length(env)
|
81
|
-
return heroku_length if heroku_length
|
82
|
-
header = env[ALT_QUEUE_HEADER]
|
83
|
-
return nil unless header
|
84
|
-
(header.gsub('t=', '').to_i / 1_000_000.0)
|
35
|
+
earliest
|
85
36
|
end
|
86
37
|
|
87
|
-
def
|
88
|
-
|
89
|
-
|
90
|
-
(header.gsub(/[^0-9]/, '').to_i / 1_000.0)
|
38
|
+
def record_frontend_metrics(start_time, now=Time.now)
|
39
|
+
NewRelic::Agent.instance.stats_engine.get_stats(ALL_QUEUE_METRIC) \
|
40
|
+
.record_data_point((now - start_time).to_f)
|
91
41
|
end
|
92
42
|
|
93
|
-
def
|
94
|
-
|
95
|
-
|
96
|
-
|
43
|
+
def timestamp_string_from_header_value(value)
|
44
|
+
case value
|
45
|
+
when /^\s*([\d+\.]+)\s*$/ then $1
|
46
|
+
# following regexp intentionally unanchored to handle
|
47
|
+
# (ie ignore) leading server names
|
48
|
+
when /t=([\d+\.]+)/ then $1
|
97
49
|
end
|
98
50
|
end
|
99
51
|
|
100
|
-
def
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
name, time = pair
|
113
|
-
self.send(type, name, time, end_time) if name
|
114
|
-
time
|
115
|
-
}
|
116
|
-
end
|
117
|
-
|
118
|
-
# goes through the list of servers and records each one in
|
119
|
-
# reverse order, subtracting the time for each successive
|
120
|
-
# server from the earlier ones in the list.
|
121
|
-
# an example because it's complicated:
|
122
|
-
# start data:
|
123
|
-
# [['a', Time.at(1000)], ['b', Time.at(1001)]], start time: Time.at(1002)
|
124
|
-
# initial run: Time.at(1002), ['b', Time.at(1001)]
|
125
|
-
# next: Time.at(1001), ['a', Time.at(1000)]
|
126
|
-
# see tests for more
|
127
|
-
def record_individual_server_stats(end_time, matches) # (Time, [[String, Time]]) -> nil
|
128
|
-
record_individual_stat_of_type(:record_server_time_for, end_time, matches)
|
129
|
-
end
|
130
|
-
|
131
|
-
def record_individual_middleware_stats(end_time, matches)
|
132
|
-
record_individual_stat_of_type(:record_middleware_time_for, end_time, matches)
|
133
|
-
end
|
134
|
-
|
135
|
-
# records the total time for all servers in a rollup metric
|
136
|
-
def record_rollup_server_stat(end_time, matches) # (Time, [String, Time]) -> nil
|
137
|
-
record_rollup_stat_of_type(ALL_SERVER_METRIC, end_time, matches)
|
138
|
-
end
|
139
|
-
|
140
|
-
def record_rollup_middleware_stat(end_time, matches)
|
141
|
-
record_rollup_stat_of_type(ALL_MIDDLEWARE_METRIC, end_time, matches)
|
142
|
-
end
|
143
|
-
|
144
|
-
def record_rollup_queue_stat(end_time, matches)
|
145
|
-
record_rollup_stat_of_type(ALL_QUEUE_METRIC, end_time, matches)
|
146
|
-
end
|
147
|
-
|
148
|
-
def record_rollup_stat_of_type(metric, end_time, matches)
|
149
|
-
oldest_time = find_oldest_time(matches) || end_time
|
150
|
-
record_time_stat(metric, oldest_time, end_time)
|
151
|
-
oldest_time
|
152
|
-
end
|
153
|
-
|
154
|
-
# searches for the first server to touch a request
|
155
|
-
def find_oldest_time(matches) # [[String, Time]] -> Time
|
156
|
-
matches.map do |name, time|
|
157
|
-
time
|
158
|
-
end.min
|
159
|
-
end
|
160
|
-
|
161
|
-
# basically just assembles the metric name
|
162
|
-
def record_server_time_for(name, start_time, end_time) # (Maybe String, Time, Time) -> nil
|
163
|
-
record_time_stat(SERVER_METRIC + name, start_time, end_time) if name
|
164
|
-
end
|
165
|
-
|
166
|
-
def record_middleware_time_for(name, start_time, end_time)
|
167
|
-
record_time_stat(MIDDLEWARE_METRIC + name, start_time, end_time)
|
168
|
-
end
|
169
|
-
|
170
|
-
# Checks that the time is not negative, and does the actual
|
171
|
-
# data recording
|
172
|
-
def record_time_stat(name, start_time, end_time) # (String, Time, Time) -> nil
|
173
|
-
total_time = end_time - start_time
|
174
|
-
if total_time < 0
|
175
|
-
raise "should not provide an end time less than start time: #{end_time.strftime('%s.%N')} is less than #{start_time.strftime('%s.%N')}. total time is #{total_time}."
|
176
|
-
else
|
177
|
-
NewRelic::Agent.get_stats(name).trace_call(total_time)
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
def add_end_time_header(end_time, env) # (Time, Env) -> nil
|
182
|
-
return unless end_time
|
183
|
-
env[APP_HEADER] = "t=#{convert_to_microseconds(end_time)}"
|
184
|
-
end
|
185
|
-
|
186
|
-
def parse_end_time(env)
|
187
|
-
header = env[APP_HEADER]
|
188
|
-
return Time.now unless header
|
189
|
-
convert_from_microseconds(header.gsub('t=', '').to_i)
|
190
|
-
end
|
191
|
-
|
192
|
-
# convert a time to the value provided by the header, for convenience
|
193
|
-
def convert_to_microseconds(time) # Time -> Int
|
194
|
-
raise TypeError.new('Cannot convert a non-time into microseconds') unless time.is_a?(Time) || time.is_a?(Numeric)
|
195
|
-
return time if time.is_a?(Numeric)
|
196
|
-
(time.to_f * 1_000_000).to_i
|
197
|
-
end
|
198
|
-
|
199
|
-
# convert a time from the header value (time in microseconds)
|
200
|
-
# into a ruby time object
|
201
|
-
def convert_from_microseconds(int) # Int -> Time
|
202
|
-
raise TypeError.new('Cannot convert a non-number into a time') unless int.is_a?(Time) || int.is_a?(Numeric)
|
203
|
-
return int if int.is_a?(Time)
|
204
|
-
Time.at((int / 1_000_000.0))
|
52
|
+
def parse_timestamp(string)
|
53
|
+
cut_off = Time.at(EARLIEST_ACCEPTABLE_TIMESTAMP)
|
54
|
+
[1_000_000, 1_000, 1].map do |divisor|
|
55
|
+
begin
|
56
|
+
Time.at(string.to_f / divisor)
|
57
|
+
rescue RangeError
|
58
|
+
# On Ruby versions built with a 32-bit time_t, attempting to
|
59
|
+
# instantiate a Time object in the far future raises a RangeError,
|
60
|
+
# in which case we know we've chosen the wrong divisor.
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
end.compact.find { |candidate| candidate > cut_off }
|
205
64
|
end
|
206
65
|
end
|
207
66
|
end
|
208
67
|
end
|
209
68
|
end
|
210
|
-
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# This file is distributed under New Relic's license terms.
|
3
|
+
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
|
+
|
5
|
+
module NewRelic
|
6
|
+
module Agent
|
7
|
+
module Instrumentation
|
8
|
+
module Rails4
|
9
|
+
module ActionController
|
10
|
+
def self.newrelic_write_attr(attr_name, value) # :nodoc:
|
11
|
+
write_inheritable_attribute(attr_name, value)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.newrelic_read_attr(attr_name) # :nodoc:
|
15
|
+
read_inheritable_attribute(attr_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
# determine the path that is used in the metric name for
|
19
|
+
# the called controller action
|
20
|
+
def newrelic_metric_path(action_name_override = nil)
|
21
|
+
action_part = action_name_override || action_name
|
22
|
+
if action_name_override || self.class.action_methods.include?(action_part)
|
23
|
+
"#{self.class.controller_path}/#{action_part}"
|
24
|
+
else
|
25
|
+
"#{self.class.controller_path}/(other)"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def process_action(*args)
|
30
|
+
# skip instrumentation if we are in an ignored action
|
31
|
+
if _is_filtered?('do_not_trace')
|
32
|
+
NewRelic::Agent.disable_all_tracing do
|
33
|
+
return super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
perform_action_with_newrelic_trace(:category => :controller, :name => self.action_name, :path => newrelic_metric_path, :params => request.filtered_parameters, :class_name => self.class.name) do
|
38
|
+
super
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
module ActionView
|
45
|
+
module NewRelic
|
46
|
+
extend self
|
47
|
+
def template_metric(identifier, options = {})
|
48
|
+
if options[:file]
|
49
|
+
"file"
|
50
|
+
elsif identifier.nil?
|
51
|
+
"(unknown)"
|
52
|
+
elsif identifier.include? '/' # this is a filepath
|
53
|
+
identifier.split('/')[-2..-1].join('/')
|
54
|
+
else
|
55
|
+
identifier
|
56
|
+
end
|
57
|
+
end
|
58
|
+
def render_type(file_path)
|
59
|
+
file = File.basename(file_path)
|
60
|
+
if file.starts_with?('_')
|
61
|
+
return 'Partial'
|
62
|
+
else
|
63
|
+
return 'Rendering'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
DependencyDetection.defer do
|
74
|
+
@name = :rails4_controller
|
75
|
+
|
76
|
+
depends_on do
|
77
|
+
defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i == 4
|
78
|
+
end
|
79
|
+
|
80
|
+
depends_on do
|
81
|
+
defined?(ActionController) && defined?(ActionController::Base)
|
82
|
+
end
|
83
|
+
|
84
|
+
executes do
|
85
|
+
::NewRelic::Agent.logger.info 'Installing Rails 4 Controller instrumentation'
|
86
|
+
end
|
87
|
+
|
88
|
+
executes do
|
89
|
+
class ActionController::Base
|
90
|
+
include NewRelic::Agent::Instrumentation::ControllerInstrumentation
|
91
|
+
include NewRelic::Agent::Instrumentation::Rails4::ActionController
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
DependencyDetection.defer do
|
97
|
+
@name = :rails40_view
|
98
|
+
|
99
|
+
depends_on do
|
100
|
+
defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i == 4
|
101
|
+
end
|
102
|
+
|
103
|
+
depends_on do
|
104
|
+
!NewRelic::Agent.config[:disable_view_instrumentation]
|
105
|
+
end
|
106
|
+
|
107
|
+
executes do
|
108
|
+
::NewRelic::Agent.logger.info 'Installing Rails 4 view instrumentation'
|
109
|
+
end
|
110
|
+
|
111
|
+
executes do
|
112
|
+
ActionView::TemplateRenderer.class_eval do
|
113
|
+
include NewRelic::Agent::MethodTracer
|
114
|
+
# namespaced helper methods
|
115
|
+
|
116
|
+
def render_with_newrelic(context, options)
|
117
|
+
@details = extract_details(options) if respond_to? :extract_details, true
|
118
|
+
identifier = determine_template(options) ? determine_template(options).identifier : nil
|
119
|
+
str = "View/#{NewRelic::Agent::Instrumentation::Rails4::ActionView::NewRelic.template_metric(identifier, options)}/Rendering"
|
120
|
+
trace_execution_scoped str do
|
121
|
+
render_without_newrelic(context, options)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
alias_method :render_without_newrelic, :render
|
126
|
+
alias_method :render, :render_with_newrelic
|
127
|
+
end
|
128
|
+
|
129
|
+
ActionView::PartialRenderer.class_eval do
|
130
|
+
include NewRelic::Agent::MethodTracer
|
131
|
+
|
132
|
+
def render_with_newrelic(*args, &block)
|
133
|
+
setup(*args, &block)
|
134
|
+
identifier = find_partial ? find_partial.identifier : nil
|
135
|
+
str = "View/#{NewRelic::Agent::Instrumentation::Rails4::ActionView::NewRelic.template_metric(identifier)}/Partial"
|
136
|
+
trace_execution_scoped str do
|
137
|
+
render_without_newrelic(*args, &block)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
alias_method :render_without_newrelic, :render
|
142
|
+
alias_method :render, :render_with_newrelic
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|