newrelic_rpm 3.9.4.245 → 3.9.5.251
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +57 -0
- data/Guardfile +1 -0
- data/lib/new_relic/agent/agent.rb +3 -3
- data/lib/new_relic/agent/audit_logger.rb +5 -2
- data/lib/new_relic/agent/configuration/default_source.rb +11 -5
- data/lib/new_relic/agent/error_collector.rb +14 -1
- data/lib/new_relic/agent/hostname.rb +22 -1
- data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +8 -2
- data/lib/new_relic/agent/instrumentation/queue_time.rb +9 -6
- data/lib/new_relic/agent/method_tracer.rb +51 -172
- data/lib/new_relic/agent/method_tracer_helpers.rb +90 -0
- data/lib/new_relic/agent/new_relic_service.rb +33 -11
- data/lib/new_relic/agent/new_relic_service/encoders.rb +9 -5
- data/lib/new_relic/agent/request_sampler.rb +20 -12
- data/lib/new_relic/agent/rules_engine.rb +31 -78
- data/lib/new_relic/agent/rules_engine/replacement_rule.rb +76 -0
- data/lib/new_relic/agent/rules_engine/segment_terms_rule.rb +48 -0
- data/lib/new_relic/agent/samplers/cpu_sampler.rb +1 -1
- data/lib/new_relic/agent/sql_sampler.rb +39 -10
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +1 -0
- data/lib/new_relic/agent/stats_engine/stats_hash.rb +7 -13
- data/lib/new_relic/agent/system_info.rb +96 -10
- data/lib/new_relic/agent/threading/agent_thread.rb +4 -1
- data/lib/new_relic/agent/threading/backtrace_node.rb +67 -57
- data/lib/new_relic/agent/threading/thread_profile.rb +30 -15
- data/lib/new_relic/agent/transaction.rb +11 -4
- data/lib/new_relic/environment_report.rb +21 -20
- data/lib/new_relic/version.rb +1 -1
- data/test/agent_helper.rb +12 -0
- data/test/fixtures/cross_agent_tests/README.md +1 -0
- data/test/fixtures/cross_agent_tests/proc_cpuinfo/1pack_1core_1logical.txt +3 -0
- data/test/fixtures/cross_agent_tests/proc_cpuinfo/1pack_1core_2logical.txt +14 -0
- data/test/fixtures/cross_agent_tests/proc_cpuinfo/1pack_2core_2logical.txt +14 -0
- data/test/fixtures/cross_agent_tests/proc_cpuinfo/1pack_4core_4logical.txt +28 -0
- data/test/fixtures/{proc_cpuinfo.txt → cross_agent_tests/proc_cpuinfo/2pack_12core_24logical.txt} +0 -0
- data/test/fixtures/cross_agent_tests/proc_cpuinfo/2pack_20core_40logical.txt +999 -0
- data/test/fixtures/cross_agent_tests/proc_cpuinfo/2pack_2core_2logical.txt +51 -0
- data/test/fixtures/cross_agent_tests/proc_cpuinfo/2pack_2core_4logical.txt +28 -0
- data/test/fixtures/cross_agent_tests/proc_cpuinfo/2pack_4core_4logical.txt +28 -0
- data/test/fixtures/cross_agent_tests/proc_cpuinfo/4pack_4core_4logical.txt +103 -0
- data/test/fixtures/cross_agent_tests/proc_cpuinfo/8pack_8core_8logical.txt +199 -0
- data/test/fixtures/cross_agent_tests/proc_cpuinfo/README.md +24 -0
- data/test/fixtures/cross_agent_tests/proc_cpuinfo/Xpack_Xcore_2logical.txt +43 -0
- data/test/fixtures/cross_agent_tests/transaction_segment_terms.json +101 -0
- data/test/multiverse/lib/multiverse/suite.rb +1 -1
- data/test/multiverse/suites/agent_only/agent_run_id_handling_test.rb +40 -0
- data/test/multiverse/suites/agent_only/labels_test.rb +9 -14
- data/test/multiverse/suites/agent_only/marshaling_test.rb +4 -6
- data/test/multiverse/suites/agent_only/rename_rule_test.rb +41 -4
- data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +11 -3
- data/test/multiverse/suites/config_file_loading/config_file_loading_test.rb +8 -8
- data/test/multiverse/suites/rack/example_app.rb +20 -0
- data/test/multiverse/suites/rack/http_response_code_test.rb +51 -0
- data/test/multiverse/suites/sidekiq/Envfile +13 -6
- data/test/multiverse/suites/sidekiq/sidekiq_server.rb +4 -3
- data/test/new_relic/agent/audit_logger_test.rb +27 -0
- data/test/new_relic/agent/error_collector_test.rb +26 -5
- data/test/new_relic/agent/hostname_test.rb +66 -14
- data/test/new_relic/agent/instrumentation/action_controller_subscriber_test.rb +8 -12
- data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +7 -45
- data/test/new_relic/agent/method_tracer_test.rb +52 -1
- data/test/new_relic/agent/new_relic_service_test.rb +76 -0
- data/test/new_relic/agent/request_sampler_test.rb +7 -0
- data/test/new_relic/agent/rules_engine_test.rb +87 -56
- data/test/new_relic/agent/sql_sampler_test.rb +50 -14
- data/test/new_relic/agent/stats_engine/metric_stats_test.rb +2 -2
- data/test/new_relic/agent/stats_engine/samplers_test.rb +1 -1
- data/test/new_relic/agent/{stats_hash_test.rb → stats_engine/stats_hash_test.rb} +1 -38
- data/test/new_relic/agent/system_info_test.rb +45 -0
- data/test/new_relic/agent/threading/agent_thread_test.rb +30 -0
- data/test/new_relic/agent/threading/backtrace_node_test.rb +27 -44
- data/test/new_relic/agent/threading/thread_profile_test.rb +35 -14
- data/test/new_relic/agent/transaction_test.rb +13 -10
- data/test/new_relic/environment_report_test.rb +7 -6
- data/test/new_relic/fake_collector.rb +10 -6
- data/test/new_relic/multiverse_helpers.rb +4 -11
- data/test/new_relic/rack/agent_hooks_test.rb +1 -1
- data/test/performance/lib/performance/baseline_compare_reporter.rb +24 -7
- data/test/performance/lib/performance/result.rb +3 -1
- data/test/performance/lib/performance/runner.rb +10 -0
- data/test/performance/lib/performance/timer.rb +6 -10
- data/test/performance/script/runner +18 -1
- data/test/performance/suites/queue_time.rb +21 -0
- data/test/performance/suites/stats_hash.rb +34 -0
- data/test/performance/suites/thread_profiling.rb +26 -0
- metadata +25 -4
- metadata.gz.sig +0 -0
@@ -2,12 +2,19 @@ suite_condition("SideKiq requires MRI 1.9.3 or JRuby 1.6 in 1.9 mode") do
|
|
2
2
|
RUBY_VERSION >= '1.9.3' || (RUBY_PLATFORM == 'java' && RUBY_VERSION >= '1.9')
|
3
3
|
end
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
# Sidekiq 3.x does not support MRI 1.9.x
|
6
|
+
if RUBY_VERSION >= '2.0.0' || (RUBY_PLATFORM == 'java')
|
7
|
+
gemfile <<-RB
|
8
|
+
gem 'json'
|
9
|
+
gem 'sidekiq', '~> 3.0.0'
|
10
|
+
gem 'rack'
|
11
|
+
|
12
|
+
# Work around for https://github.com/celluloid/celluloid/issues/457
|
13
|
+
gem 'celluloid', '0.15.2'
|
14
|
+
|
15
|
+
gem 'newrelic_rpm', :require => false, :path => File.expand_path('../../../../')
|
16
|
+
RB
|
17
|
+
end
|
11
18
|
|
12
19
|
gemfile <<-RB
|
13
20
|
gem 'json'
|
@@ -18,13 +18,14 @@ class SidekiqServer
|
|
18
18
|
def run(file="test_worker.rb")
|
19
19
|
@sidekiq.parse(["--require", File.join(File.dirname(__FILE__), file),
|
20
20
|
"--queue", "#{queue_name},1"])
|
21
|
-
Thread.new { @sidekiq.run }
|
21
|
+
@cli_thread = Thread.new { @sidekiq.run }
|
22
22
|
end
|
23
23
|
|
24
24
|
# If we just let the process go away, occasional timing issues cause the
|
25
25
|
# Launcher actor in Sidekiq to throw a fuss and exit with a failed code.
|
26
26
|
def stop
|
27
|
-
puts "Trying to stop Sidekiq gracefully"
|
28
|
-
|
27
|
+
puts "Trying to stop Sidekiq gracefully from #{$$}"
|
28
|
+
Process.kill("INT", $$)
|
29
|
+
@cli_thread.join
|
29
30
|
end
|
30
31
|
end
|
@@ -31,6 +31,11 @@ class AuditLoggerTest < Minitest::Test
|
|
31
31
|
@logger.stubs(:ensure_log_path).returns(@fakelog)
|
32
32
|
end
|
33
33
|
|
34
|
+
def setup_fake_logger_with_failure(error)
|
35
|
+
setup_fake_logger
|
36
|
+
@logger.stubs(:enabled?).raises(error)
|
37
|
+
end
|
38
|
+
|
34
39
|
def assert_log_contains_string(str)
|
35
40
|
log_body = read_log_body
|
36
41
|
assert(log_body.include?(str), "Expected log to contain string '#{str}'\nLog body was: #{log_body}")
|
@@ -133,4 +138,26 @@ class AuditLoggerTest < Minitest::Test
|
|
133
138
|
end
|
134
139
|
assert_log_contains_string('cachey-mccaherson')
|
135
140
|
end
|
141
|
+
|
142
|
+
TRAPPABLE_ERRORS = [
|
143
|
+
StandardError.new,
|
144
|
+
SystemStackError.new,
|
145
|
+
SystemCallError.new("Syscalls FTW")
|
146
|
+
]
|
147
|
+
|
148
|
+
TRAPPABLE_ERRORS.each do |error|
|
149
|
+
define_method("test_traps_#{error.class}") do
|
150
|
+
setup_fake_logger_with_failure(error)
|
151
|
+
@logger.log_request(@uri, @dummy_data, @marshaller)
|
152
|
+
assert_empty read_log_body
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_allows_other_exceptions_through
|
157
|
+
setup_fake_logger_with_failure(Exception.new)
|
158
|
+
assert_raises(Exception) do
|
159
|
+
@logger.log_request(@uri, @dummy_data, @marshaller)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
136
163
|
end
|
@@ -237,10 +237,30 @@ class NewRelic::Agent::ErrorCollectorTest < Minitest::Test
|
|
237
237
|
end
|
238
238
|
|
239
239
|
def test_increment_error_count_record_summary_and_txn_metric
|
240
|
-
|
241
|
-
|
240
|
+
in_web_transaction('Controller/class/method') do
|
241
|
+
@error_collector.increment_error_count!(StandardError.new('Boo'))
|
242
|
+
end
|
243
|
+
|
244
|
+
assert_metrics_recorded(['Errors/all',
|
245
|
+
'Errors/allWeb',
|
246
|
+
'Errors/Controller/class/method'])
|
247
|
+
end
|
248
|
+
|
249
|
+
def test_increment_error_count_record_summary_and_txn_metric
|
250
|
+
in_background_transaction('OtherTransaction/AnotherFramework/Job/perform') do
|
251
|
+
@error_collector.increment_error_count!(StandardError.new('Boo'))
|
252
|
+
end
|
253
|
+
|
254
|
+
assert_metrics_recorded(['Errors/all',
|
255
|
+
'Errors/allOther',
|
256
|
+
'Errors/OtherTransaction/AnotherFramework/Job/perform'])
|
257
|
+
end
|
258
|
+
|
259
|
+
def test_icrement_error_count_summary_outside_transaction
|
260
|
+
@error_collector.increment_error_count!(StandardError.new('Boo'))
|
242
261
|
|
243
|
-
assert_metrics_recorded(['Errors/all'
|
262
|
+
assert_metrics_recorded(['Errors/all'])
|
263
|
+
assert_metrics_not_recorded(['Errors/allWeb', 'Errors/allOther'])
|
244
264
|
end
|
245
265
|
|
246
266
|
def test_doesnt_increment_error_count_on_transaction_if_nameless
|
@@ -353,8 +373,9 @@ class NewRelic::Agent::ErrorCollectorTest < Minitest::Test
|
|
353
373
|
end
|
354
374
|
assert_metrics_recorded_exclusive(
|
355
375
|
{
|
356
|
-
'Errors/all'
|
357
|
-
'Errors/boo'
|
376
|
+
'Errors/all' => { :call_count => 1 },
|
377
|
+
'Errors/boo' => { :call_count => 1 },
|
378
|
+
'Errors/allOther' => { :call_count => 1 }
|
358
379
|
},
|
359
380
|
:filter => /^Errors\//
|
360
381
|
)
|
@@ -8,30 +8,82 @@ require 'new_relic/agent/hostname'
|
|
8
8
|
module NewRelic
|
9
9
|
module Agent
|
10
10
|
class HostnameTest < Minitest::Test
|
11
|
-
def
|
11
|
+
def setup
|
12
12
|
Socket.stubs(:gethostname).returns('Rivendell')
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_get_returns_socket_hostname
|
13
16
|
assert_equal 'Rivendell', NewRelic::Agent::Hostname.get
|
14
17
|
end
|
15
18
|
|
16
19
|
def test_get_uses_dyno_name_if_dyno_env_set_and_dyno_names_enabled
|
17
|
-
|
18
|
-
|
19
|
-
ENV['DYNO'] = 'Imladris'
|
20
|
-
|
21
|
-
expected = 'Imladris'
|
22
|
-
assert_equal expected, NewRelic::Agent::Hostname.get
|
20
|
+
with_dyno_name('Imladris', :'heroku.use_dyno_names' => true) do
|
21
|
+
assert_equal 'Imladris', NewRelic::Agent::Hostname.get
|
23
22
|
end
|
24
|
-
ensure
|
25
|
-
ENV.delete('DYNO')
|
26
23
|
end
|
27
24
|
|
28
25
|
def test_get_uses_socket_gethostname_if_dyno_env_set_and_dyno_names_disabled
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
with_dyno_name('Imladris', :'heroku.use_dyno_names' => false) do
|
27
|
+
assert_equal 'Rivendell', NewRelic::Agent::Hostname.get
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_shortens_to_prefix_if_using_dyno_names_and_matches
|
32
|
+
with_dyno_name('Imladris.1', :'heroku.use_dyno_names' => true,
|
33
|
+
:'heroku.dyno_name_prefixes_to_shorten' => ['Imladris']) do
|
34
|
+
assert_equal 'Imladris.*', NewRelic::Agent::Hostname.get
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_does_not_shorten_if_not_using_dyno_names
|
39
|
+
with_dyno_name('Imladris', :'heroku.use_dyno_names' => false,
|
40
|
+
:'heroku.dyno_name_prefixes_to_shorten' => ['Rivendell']) do
|
41
|
+
Socket.stubs(:gethostname).returns('Rivendell.1')
|
42
|
+
assert_equal 'Rivendell.1', NewRelic::Agent::Hostname.get
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_only_shortens_if_matches_prefix_and_dot
|
47
|
+
with_dyno_name('ImladrisImladrisFakeout.1',
|
48
|
+
:'heroku.use_dyno_names' => true,
|
49
|
+
:'heroku.dyno_name_prefixes_to_shorten' => ['Imladris']) do
|
50
|
+
assert_equal 'ImladrisImladrisFakeout.1', NewRelic::Agent::Hostname.get
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_shortens_to_prefixes_from_string
|
55
|
+
with_dyno_name('Imladris.1', :'heroku.use_dyno_names' => true,
|
56
|
+
:'heroku.dyno_name_prefixes_to_shorten' => 'Imladris') do
|
57
|
+
assert_equal 'Imladris.*', NewRelic::Agent::Hostname.get
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_shortens_to_prefixes_from_string_allows_csv
|
62
|
+
with_dyno_name('Imladris.1', :'heroku.use_dyno_names' => true,
|
63
|
+
:'heroku.dyno_name_prefixes_to_shorten' => 'Rivendell,Imladris') do
|
64
|
+
assert_equal 'Imladris.*', NewRelic::Agent::Hostname.get
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_shortens_to_prefixes_with_empty_string
|
69
|
+
with_dyno_name('Imladris.1', :'heroku.use_dyno_names' => true,
|
70
|
+
:'heroku.dyno_name_prefixes_to_shorten' => '') do
|
71
|
+
assert_equal 'Imladris.1', NewRelic::Agent::Hostname.get
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_shortens_to_prefixes_with_unsupported_object
|
76
|
+
with_dyno_name('Imladris.1', :'heroku.use_dyno_names' => true,
|
77
|
+
:'heroku.dyno_name_prefixes_to_shorten' => Object.new) do
|
78
|
+
expects_logging(:warn, includes('Object'))
|
79
|
+
assert_equal 'Imladris.1', NewRelic::Agent::Hostname.get
|
80
|
+
end
|
81
|
+
end
|
32
82
|
|
33
|
-
|
34
|
-
|
83
|
+
def with_dyno_name(dyno_name, config_options)
|
84
|
+
with_config(config_options) do
|
85
|
+
ENV['DYNO'] = dyno_name
|
86
|
+
yield
|
35
87
|
end
|
36
88
|
ensure
|
37
89
|
ENV.delete('DYNO')
|
@@ -206,19 +206,15 @@ class NewRelic::Agent::Instrumentation::ActionControllerSubscriberTest < Minites
|
|
206
206
|
end
|
207
207
|
|
208
208
|
def test_applies_txn_name_rules
|
209
|
-
|
210
|
-
'replacement' => 'taste')
|
211
|
-
NewRelic::Agent.instance.transaction_rules << rule
|
212
|
-
@subscriber.start('process_action.action_controller', :id, @entry_payload)
|
213
|
-
@subscriber.finish('process_action.action_controller', :id, @exit_payload)
|
209
|
+
rule_specs = [{'match_expression' => 'test', 'replacement' => 'taste'}]
|
214
210
|
|
215
|
-
|
216
|
-
.
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
211
|
+
with_transaction_renaming_rules(rule_specs) do
|
212
|
+
@subscriber.start('process_action.action_controller', :id, @entry_payload)
|
213
|
+
@subscriber.finish('process_action.action_controller', :id, @exit_payload)
|
214
|
+
end
|
215
|
+
|
216
|
+
assert_metrics_recorded(['Controller/taste/index'])
|
217
|
+
assert_metrics_not_recorded(['Controller/test/index'])
|
222
218
|
end
|
223
219
|
|
224
220
|
def test_record_queue_time_metrics
|
@@ -11,32 +11,6 @@ class NewRelic::Agent::MethodTracer::TraceExecutionScopedTest < Minitest::Test
|
|
11
11
|
NewRelic::Agent.agent.stats_engine.clear_stats
|
12
12
|
end
|
13
13
|
|
14
|
-
def test_get_stats_unscoped
|
15
|
-
fake_engine = mocked_object('stat_engine')
|
16
|
-
fake_engine.expects(:get_stats_no_scope).with('foob').returns('fakestats')
|
17
|
-
assert_equal 'fakestats', get_stats_unscoped('foob')
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_get_stats_scoped_scoped_only
|
21
|
-
fake_engine = mocked_object('stat_engine')
|
22
|
-
fake_engine.expects(:get_stats).with('foob', true, true).returns('fakestats')
|
23
|
-
assert_equal 'fakestats', get_stats_scoped('foob', true)
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_get_stats_scoped_no_scoped_only
|
27
|
-
fake_engine = mocked_object('stat_engine')
|
28
|
-
fake_engine.expects(:get_stats).with('foob', true, false).returns('fakestats')
|
29
|
-
assert_equal 'fakestats', get_stats_scoped('foob', false)
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_stat_engine
|
33
|
-
assert_equal agent_instance.stats_engine, stat_engine
|
34
|
-
end
|
35
|
-
|
36
|
-
def test_agent_instance
|
37
|
-
assert_equal NewRelic::Agent.instance, agent_instance
|
38
|
-
end
|
39
|
-
|
40
14
|
def test_metric_recording_outside_transaction
|
41
15
|
trace_execution_scoped(['foo']) do
|
42
16
|
# meh
|
@@ -120,7 +94,7 @@ class NewRelic::Agent::MethodTracer::TraceExecutionScopedTest < Minitest::Test
|
|
120
94
|
)
|
121
95
|
end
|
122
96
|
|
123
|
-
def
|
97
|
+
def test_metric_recording_with_metric_option_false
|
124
98
|
options = { :metric => false, :scoped_metric => false }
|
125
99
|
|
126
100
|
in_transaction('outer') do
|
@@ -130,24 +104,12 @@ class NewRelic::Agent::MethodTracer::TraceExecutionScopedTest < Minitest::Test
|
|
130
104
|
end
|
131
105
|
|
132
106
|
expected_values = { :call_count => 1 }
|
133
|
-
assert_metrics_recorded_exclusive(
|
134
|
-
'outer' => expected_values,
|
135
|
-
'bar' => expected_values
|
136
|
-
)
|
137
|
-
end
|
138
|
-
|
139
|
-
def test_set_if_nil
|
140
|
-
h = {}
|
141
|
-
set_if_nil(h, :foo)
|
142
|
-
assert h[:foo]
|
143
|
-
h[:bar] = false
|
144
|
-
set_if_nil(h, :bar)
|
145
|
-
assert !h[:bar]
|
107
|
+
assert_metrics_recorded_exclusive('outer' => expected_values)
|
146
108
|
end
|
147
109
|
|
148
110
|
def test_log_errors_base
|
149
111
|
ran = false
|
150
|
-
log_errors("name") do
|
112
|
+
NewRelic::Agent::MethodTracerHelpers.log_errors("name") do
|
151
113
|
ran = true
|
152
114
|
end
|
153
115
|
assert ran, "should run the contents of the block"
|
@@ -155,7 +117,7 @@ class NewRelic::Agent::MethodTracer::TraceExecutionScopedTest < Minitest::Test
|
|
155
117
|
|
156
118
|
def test_log_errors_with_return
|
157
119
|
ran = false
|
158
|
-
return_val = log_errors('name') do
|
120
|
+
return_val = NewRelic::Agent::MethodTracerHelpers.log_errors('name') do
|
159
121
|
ran = true
|
160
122
|
'happy trees'
|
161
123
|
end
|
@@ -169,7 +131,7 @@ class NewRelic::Agent::MethodTracer::TraceExecutionScopedTest < Minitest::Test
|
|
169
131
|
includes("Caught exception in name."),
|
170
132
|
instance_of(RuntimeError))
|
171
133
|
|
172
|
-
log_errors("name") do
|
134
|
+
NewRelic::Agent::MethodTracerHelpers.log_errors("name") do
|
173
135
|
raise "should not propagate out of block"
|
174
136
|
end
|
175
137
|
end
|
@@ -177,9 +139,9 @@ class NewRelic::Agent::MethodTracer::TraceExecutionScopedTest < Minitest::Test
|
|
177
139
|
def test_trace_execution_scoped_header
|
178
140
|
state = NewRelic::Agent::TransactionState.tl_get
|
179
141
|
stack = state.traced_method_stack
|
180
|
-
|
142
|
+
NewRelic::Agent::MethodTracerHelpers.expects(:log_errors).with(:trace_execution_scoped_header).yields
|
181
143
|
stack.expects(:push_frame).with(state, :method_tracer, 1.0)
|
182
|
-
trace_execution_scoped_header(state, 1.0)
|
144
|
+
NewRelic::Agent::MethodTracerHelpers.trace_execution_scoped_header(state, 1.0)
|
183
145
|
end
|
184
146
|
|
185
147
|
def test_trace_execution_scoped_calculates_exclusive_time
|
@@ -93,7 +93,7 @@ class NewRelic::Agent::MethodTracerTest < Minitest::Test
|
|
93
93
|
|
94
94
|
def test_record_metrics_does_not_raise_outside_transaction
|
95
95
|
state = NewRelic::Agent::TransactionState.tl_get
|
96
|
-
NewRelic::Agent::
|
96
|
+
NewRelic::Agent::MethodTracerHelpers.record_metrics(state, 'a', ['b'], 12, 10, :metric => true)
|
97
97
|
|
98
98
|
expected = { :call_count => 1, :total_call_time => 12, :total_exclusive_time => 10 }
|
99
99
|
assert_metrics_recorded('a' => expected, 'b' => expected)
|
@@ -378,6 +378,57 @@ class NewRelic::Agent::MethodTracerTest < Minitest::Test
|
|
378
378
|
assert_equal ['YY'], @scope_listener.scopes
|
379
379
|
end
|
380
380
|
|
381
|
+
def test_add_method_tracer_module_double_inclusion
|
382
|
+
mod = Module.new { def traced_method; end }
|
383
|
+
cls = Class.new { include mod }
|
384
|
+
|
385
|
+
mod.module_eval do
|
386
|
+
include NewRelic::Agent::MethodTracer
|
387
|
+
add_method_tracer :traced_method
|
388
|
+
end
|
389
|
+
|
390
|
+
cls.new.traced_method
|
391
|
+
end
|
392
|
+
|
393
|
+
# This test validates that including the MethodTracer module does not pollute
|
394
|
+
# the host class with any additional helper methods that are not part of the
|
395
|
+
# official public API.
|
396
|
+
def test_only_adds_methods_to_host_that_are_part_of_public_api
|
397
|
+
host_class = Class.new { include ::NewRelic::Agent::MethodTracer }
|
398
|
+
plain_class = Class.new
|
399
|
+
|
400
|
+
host_instance_methods = host_class.new.methods
|
401
|
+
plain_instance_methods = plain_class.new.methods
|
402
|
+
|
403
|
+
added_methods = host_instance_methods - plain_instance_methods
|
404
|
+
|
405
|
+
public_api_methods = [
|
406
|
+
'trace_execution_unscoped',
|
407
|
+
'trace_execution_scoped',
|
408
|
+
'trace_method_execution', # deprecated
|
409
|
+
'trace_method_execution_with_scope', # deprecated
|
410
|
+
'trace_method_execution_no_scope', # deprecated
|
411
|
+
'get_stats_scoped', # deprecated
|
412
|
+
'get_stats_unscoped' # deprecated
|
413
|
+
]
|
414
|
+
|
415
|
+
assert_equal(public_api_methods.sort, added_methods.map(&:to_s).sort)
|
416
|
+
end
|
417
|
+
|
418
|
+
def test_get_stats_unscoped
|
419
|
+
host_class = Class.new { include ::NewRelic::Agent::MethodTracer }
|
420
|
+
expected_stats = NewRelic::Agent.get_stats('foobar')
|
421
|
+
stats = host_class.new.get_stats_unscoped('foobar')
|
422
|
+
assert_same(expected_stats, stats)
|
423
|
+
end
|
424
|
+
|
425
|
+
def test_get_stats_scoped
|
426
|
+
host_class = Class.new { include ::NewRelic::Agent::MethodTracer }
|
427
|
+
expected_stats = NewRelic::Agent.get_stats('foobar', true)
|
428
|
+
stats = host_class.new.get_stats_scoped('foobar', false)
|
429
|
+
assert_same(expected_stats, stats)
|
430
|
+
end
|
431
|
+
|
381
432
|
def trace_no_push_scope
|
382
433
|
self.class.add_method_tracer :method_to_be_traced, 'X', :push_scope => false
|
383
434
|
method_to_be_traced 1,2,3,true,nil
|
@@ -653,6 +653,82 @@ class NewRelicServiceTest < Minitest::Test
|
|
653
653
|
refute @service.valid_to_marshal?({})
|
654
654
|
end
|
655
655
|
|
656
|
+
def test_supportability_metrics_with_item_count
|
657
|
+
NewRelic::Agent.drop_buffered_data
|
658
|
+
|
659
|
+
payload = ['eggs', 'spam']
|
660
|
+
@http_handle.respond_to(:foobar, 'foobar')
|
661
|
+
@service.send(:invoke_remote, :foobar, payload, :item_count => 12)
|
662
|
+
|
663
|
+
expected_size_bytes = @service.marshaller.dump(payload).size
|
664
|
+
expected_values = {
|
665
|
+
:call_count => 1,
|
666
|
+
:total_call_time => expected_size_bytes,
|
667
|
+
:total_exclusive_time => 12
|
668
|
+
}
|
669
|
+
|
670
|
+
assert_metrics_recorded(
|
671
|
+
'Supportability/invoke_remote' => { :call_count => 1 },
|
672
|
+
'Supportability/invoke_remote/foobar' => { :call_count => 1 },
|
673
|
+
'Supportability/invoke_remote_serialize' => { :call_count => 1 },
|
674
|
+
'Supportability/invoke_remote_serialize/foobar' => { :call_count => 1},
|
675
|
+
'Supportability/invoke_remote_size' => expected_values,
|
676
|
+
'Supportability/invoke_remote_size/foobar' => expected_values
|
677
|
+
)
|
678
|
+
end
|
679
|
+
|
680
|
+
def test_supportability_metrics_without_item_count
|
681
|
+
NewRelic::Agent.drop_buffered_data
|
682
|
+
|
683
|
+
payload = ['eggs', 'spam']
|
684
|
+
@http_handle.respond_to(:foobar, 'foobar')
|
685
|
+
@service.send(:invoke_remote, :foobar, payload)
|
686
|
+
|
687
|
+
expected_size_bytes = @service.marshaller.dump(payload).size
|
688
|
+
expected_values = {
|
689
|
+
:call_count => 1,
|
690
|
+
:total_call_time => expected_size_bytes,
|
691
|
+
:total_exclusive_time => 0
|
692
|
+
}
|
693
|
+
|
694
|
+
assert_metrics_recorded(
|
695
|
+
'Supportability/invoke_remote' => { :call_count => 1 },
|
696
|
+
'Supportability/invoke_remote/foobar' => { :call_count => 1 },
|
697
|
+
'Supportability/invoke_remote_serialize' => { :call_count => 1 },
|
698
|
+
'Supportability/invoke_remote_serialize/foobar' => { :call_count => 1},
|
699
|
+
'Supportability/invoke_remote_size' => expected_values,
|
700
|
+
'Supportability/invoke_remote_size/foobar' => expected_values
|
701
|
+
)
|
702
|
+
end
|
703
|
+
|
704
|
+
def test_supportability_metrics_with_serialization_failure
|
705
|
+
NewRelic::Agent.drop_buffered_data
|
706
|
+
|
707
|
+
payload = ['eggs', 'spam']
|
708
|
+
@http_handle.respond_to(:foobar, 'foobar')
|
709
|
+
@service.marshaller.stubs(:dump).raises(StandardError.new)
|
710
|
+
|
711
|
+
assert_raises(NewRelic::Agent::SerializationError) do
|
712
|
+
@service.send(:invoke_remote, :foobar, payload)
|
713
|
+
end
|
714
|
+
|
715
|
+
expected_values = { :call_count => 1 }
|
716
|
+
|
717
|
+
assert_metrics_recorded(
|
718
|
+
'Supportability/invoke_remote' => expected_values,
|
719
|
+
'Supportability/invoke_remote/foobar' => expected_values,
|
720
|
+
'Supportability/serialization_failure' => expected_values,
|
721
|
+
'Supportability/serialization_failure/foobar' => expected_values
|
722
|
+
)
|
723
|
+
|
724
|
+
assert_metrics_not_recorded([
|
725
|
+
'Supportability/invoke_remote_serialize',
|
726
|
+
'Supportability/invoke_remote_serialize/foobar',
|
727
|
+
'Supportability/invoke_remote_size',
|
728
|
+
'Supportability/invoke_remote_size/foobar'
|
729
|
+
])
|
730
|
+
end
|
731
|
+
|
656
732
|
def build_stats_hash(items={})
|
657
733
|
hash = NewRelic::Agent::StatsHash.new
|
658
734
|
items.each do |key, value|
|