genki-newrelic_rpm 2.10.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +316 -0
- data/LICENSE +37 -0
- data/Manifest +156 -0
- data/README.md +138 -0
- data/Rakefile +22 -0
- data/bin/mongrel_rpm +33 -0
- data/bin/newrelic_cmd +4 -0
- data/cert/cacert.pem +34 -0
- data/genki-newrelic_rpm.gemspec +32 -0
- data/init.rb +38 -0
- data/install.rb +37 -0
- data/lib/new_relic/agent.rb +280 -0
- data/lib/new_relic/agent/agent.rb +627 -0
- data/lib/new_relic/agent/chained_call.rb +13 -0
- data/lib/new_relic/agent/collection_helper.rb +61 -0
- data/lib/new_relic/agent/error_collector.rb +125 -0
- data/lib/new_relic/agent/instrumentation/active_merchant.rb +18 -0
- data/lib/new_relic/agent/instrumentation/active_record_instrumentation.rb +83 -0
- data/lib/new_relic/agent/instrumentation/authlogic.rb +8 -0
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +368 -0
- data/lib/new_relic/agent/instrumentation/data_mapper.rb +90 -0
- data/lib/new_relic/agent/instrumentation/dispatcher_instrumentation.rb +132 -0
- data/lib/new_relic/agent/instrumentation/memcache.rb +21 -0
- data/lib/new_relic/agent/instrumentation/merb/controller.rb +26 -0
- data/lib/new_relic/agent/instrumentation/merb/dispatcher.rb +13 -0
- data/lib/new_relic/agent/instrumentation/merb/errors.rb +8 -0
- data/lib/new_relic/agent/instrumentation/net.rb +12 -0
- data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +20 -0
- data/lib/new_relic/agent/instrumentation/rack.rb +77 -0
- data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +59 -0
- data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +27 -0
- data/lib/new_relic/agent/instrumentation/rails/dispatcher.rb +38 -0
- data/lib/new_relic/agent/instrumentation/rails/errors.rb +27 -0
- data/lib/new_relic/agent/instrumentation/sinatra.rb +39 -0
- data/lib/new_relic/agent/method_tracer.rb +277 -0
- data/lib/new_relic/agent/patch_const_missing.rb +125 -0
- data/lib/new_relic/agent/sampler.rb +12 -0
- data/lib/new_relic/agent/samplers/cpu_sampler.rb +49 -0
- data/lib/new_relic/agent/samplers/memory_sampler.rb +137 -0
- data/lib/new_relic/agent/samplers/mongrel_sampler.rb +22 -0
- data/lib/new_relic/agent/shim_agent.rb +21 -0
- data/lib/new_relic/agent/stats_engine.rb +24 -0
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +111 -0
- data/lib/new_relic/agent/stats_engine/samplers.rb +71 -0
- data/lib/new_relic/agent/stats_engine/transactions.rb +155 -0
- data/lib/new_relic/agent/transaction_sampler.rb +319 -0
- data/lib/new_relic/agent/worker_loop.rb +118 -0
- data/lib/new_relic/commands/deployments.rb +145 -0
- data/lib/new_relic/commands/new_relic_commands.rb +30 -0
- data/lib/new_relic/control.rb +436 -0
- data/lib/new_relic/control/external.rb +13 -0
- data/lib/new_relic/control/merb.rb +22 -0
- data/lib/new_relic/control/rails.rb +143 -0
- data/lib/new_relic/control/ruby.rb +34 -0
- data/lib/new_relic/control/sinatra.rb +14 -0
- data/lib/new_relic/histogram.rb +89 -0
- data/lib/new_relic/local_environment.rb +285 -0
- data/lib/new_relic/merbtasks.rb +6 -0
- data/lib/new_relic/metric_data.rb +44 -0
- data/lib/new_relic/metric_parser.rb +120 -0
- data/lib/new_relic/metric_parser/action_mailer.rb +9 -0
- data/lib/new_relic/metric_parser/active_merchant.rb +26 -0
- data/lib/new_relic/metric_parser/active_record.rb +25 -0
- data/lib/new_relic/metric_parser/controller.rb +54 -0
- data/lib/new_relic/metric_parser/controller_cpu.rb +38 -0
- data/lib/new_relic/metric_parser/errors.rb +6 -0
- data/lib/new_relic/metric_parser/external.rb +50 -0
- data/lib/new_relic/metric_parser/mem_cache.rb +12 -0
- data/lib/new_relic/metric_parser/view.rb +61 -0
- data/lib/new_relic/metric_parser/web_frontend.rb +14 -0
- data/lib/new_relic/metric_parser/web_service.rb +9 -0
- data/lib/new_relic/metric_spec.rb +52 -0
- data/lib/new_relic/metrics.rb +7 -0
- data/lib/new_relic/noticed_error.rb +25 -0
- data/lib/new_relic/rack/metric_app.rb +56 -0
- data/lib/new_relic/rack/newrelic.ru +25 -0
- data/lib/new_relic/rack/newrelic.yml +25 -0
- data/lib/new_relic/rack_app.rb +5 -0
- data/lib/new_relic/recipes.rb +82 -0
- data/lib/new_relic/stats.rb +360 -0
- data/lib/new_relic/transaction_analysis.rb +121 -0
- data/lib/new_relic/transaction_sample.rb +583 -0
- data/lib/new_relic/version.rb +54 -0
- data/lib/new_relic_api.rb +315 -0
- data/lib/newrelic_rpm.rb +40 -0
- data/lib/tasks/all.rb +4 -0
- data/lib/tasks/install.rake +7 -0
- data/lib/tasks/tests.rake +13 -0
- data/newrelic.yml +214 -0
- data/recipes/newrelic.rb +6 -0
- data/test/active_record_fixtures.rb +55 -0
- data/test/config/newrelic.yml +46 -0
- data/test/config/test_control.rb +39 -0
- data/test/new_relic/agent/active_record_instrumentation_test.rb +234 -0
- data/test/new_relic/agent/agent_controller_test.rb +107 -0
- data/test/new_relic/agent/agent_test.rb +117 -0
- data/test/new_relic/agent/agent_test_controller.rb +44 -0
- data/test/new_relic/agent/classloader_patch_test.rb +56 -0
- data/test/new_relic/agent/collection_helper_test.rb +118 -0
- data/test/new_relic/agent/dispatcher_instrumentation_test.rb +76 -0
- data/test/new_relic/agent/error_collector_test.rb +155 -0
- data/test/new_relic/agent/method_tracer_test.rb +335 -0
- data/test/new_relic/agent/metric_data_test.rb +56 -0
- data/test/new_relic/agent/mock_ar_connection.rb +40 -0
- data/test/new_relic/agent/mock_scope_listener.rb +23 -0
- data/test/new_relic/agent/net_instrumentation_test.rb +51 -0
- data/test/new_relic/agent/stats_engine/metric_stats_test.rb +79 -0
- data/test/new_relic/agent/stats_engine/samplers_test.rb +78 -0
- data/test/new_relic/agent/stats_engine/stats_engine_test.rb +177 -0
- data/test/new_relic/agent/task_instrumentation_test.rb +67 -0
- data/test/new_relic/agent/testable_agent.rb +13 -0
- data/test/new_relic/agent/transaction_sample_builder_test.rb +195 -0
- data/test/new_relic/agent/transaction_sample_test.rb +146 -0
- data/test/new_relic/agent/transaction_sampler_test.rb +387 -0
- data/test/new_relic/agent/worker_loop_test.rb +103 -0
- data/test/new_relic/control_test.rb +94 -0
- data/test/new_relic/deployments_api_test.rb +68 -0
- data/test/new_relic/environment_test.rb +75 -0
- data/test/new_relic/metric_parser_test.rb +172 -0
- data/test/new_relic/metric_spec_test.rb +177 -0
- data/test/new_relic/shim_agent_test.rb +9 -0
- data/test/new_relic/stats_test.rb +291 -0
- data/test/new_relic/version_number_test.rb +74 -0
- data/test/test_helper.rb +38 -0
- data/test/ui/newrelic_controller_test.rb +14 -0
- data/test/ui/newrelic_helper_test.rb +53 -0
- data/ui/controllers/newrelic_controller.rb +214 -0
- data/ui/helpers/google_pie_chart.rb +55 -0
- data/ui/helpers/newrelic_helper.rb +314 -0
- data/ui/views/layouts/newrelic_default.rhtml +47 -0
- data/ui/views/newrelic/_explain_plans.rhtml +27 -0
- data/ui/views/newrelic/_sample.rhtml +15 -0
- data/ui/views/newrelic/_segment.rhtml +28 -0
- data/ui/views/newrelic/_segment_limit_message.rhtml +1 -0
- data/ui/views/newrelic/_segment_row.rhtml +14 -0
- data/ui/views/newrelic/_show_sample_detail.rhtml +24 -0
- data/ui/views/newrelic/_show_sample_sql.rhtml +20 -0
- data/ui/views/newrelic/_show_sample_summary.rhtml +3 -0
- data/ui/views/newrelic/_sql_row.rhtml +11 -0
- data/ui/views/newrelic/_stack_trace.rhtml +30 -0
- data/ui/views/newrelic/_table.rhtml +12 -0
- data/ui/views/newrelic/explain_sql.rhtml +42 -0
- data/ui/views/newrelic/images/arrow-close.png +0 -0
- data/ui/views/newrelic/images/arrow-open.png +0 -0
- data/ui/views/newrelic/images/blue_bar.gif +0 -0
- data/ui/views/newrelic/images/file_icon.png +0 -0
- data/ui/views/newrelic/images/gray_bar.gif +0 -0
- 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 +45 -0
- data/ui/views/newrelic/javascript/prototype-scriptaculous.js +7288 -0
- data/ui/views/newrelic/javascript/transaction_sample.js +107 -0
- data/ui/views/newrelic/sample_not_found.rhtml +2 -0
- data/ui/views/newrelic/show_sample.rhtml +77 -0
- data/ui/views/newrelic/show_source.rhtml +3 -0
- data/ui/views/newrelic/stylesheets/style.css +433 -0
- data/ui/views/newrelic/threads.rhtml +52 -0
- metadata +327 -0
@@ -0,0 +1,117 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
|
2
|
+
##require 'new_relic/agent/agent'
|
3
|
+
##require 'new_relic/local_environment'
|
4
|
+
|
5
|
+
class AgentTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
attr_reader :agent
|
8
|
+
|
9
|
+
# Fake out the agent to think mongrel is running
|
10
|
+
def setup
|
11
|
+
NewRelic::Agent.manual_start
|
12
|
+
@agent = NewRelic::Agent.instance
|
13
|
+
end
|
14
|
+
def teardown
|
15
|
+
NewRelic::Control.instance['app_name']=nil
|
16
|
+
NewRelic::Control.instance['dispatcher']=nil
|
17
|
+
NewRelic::Control.instance['dispatcher_instance_id']=nil
|
18
|
+
end
|
19
|
+
def test_agent_setup
|
20
|
+
assert NewRelic::Agent.instance.class == NewRelic::Agent::Agent
|
21
|
+
assert_raise RuntimeError do
|
22
|
+
NewRelic::Control.instance.init_plugin :agent_enabled => false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_public_apis
|
27
|
+
assert_raise RuntimeError do
|
28
|
+
NewRelic::Agent.set_sql_obfuscator(:unknown) do |sql|
|
29
|
+
puts sql
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
ignore_called = false
|
34
|
+
NewRelic::Agent.ignore_error_filter do |e|
|
35
|
+
ignore_called = true
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
NewRelic::Agent.notice_error(ActionController::RoutingError.new("message"), :x => "y")
|
39
|
+
assert ignore_called
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_startup_shutdown
|
43
|
+
@agent = NewRelic::Agent::ShimAgent.instance
|
44
|
+
@agent.shutdown
|
45
|
+
assert (not @agent.started?)
|
46
|
+
@agent.start
|
47
|
+
assert !@agent.started?
|
48
|
+
# this installs the real agent:
|
49
|
+
NewRelic::Agent.manual_start
|
50
|
+
@agent = NewRelic::Agent.instance
|
51
|
+
assert @agent != NewRelic::Agent::ShimAgent.instance
|
52
|
+
assert @agent.started?
|
53
|
+
@agent.shutdown
|
54
|
+
assert !@agent.started?
|
55
|
+
@agent.start
|
56
|
+
assert @agent.started?
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_manual_overrides
|
60
|
+
NewRelic::Agent.manual_start :app_name => "testjobs", :dispatcher_instance_id => "mailer"
|
61
|
+
assert_equal "testjobs", NewRelic::Control.instance.app_names[0]
|
62
|
+
assert_equal "mailer", NewRelic::Control.instance.dispatcher_instance_id
|
63
|
+
end
|
64
|
+
def test_restart
|
65
|
+
NewRelic::Agent.manual_start :app_name => "noapp", :dispatcher_instance_id => ""
|
66
|
+
NewRelic::Agent.manual_start :app_name => "testjobs", :dispatcher_instance_id => "mailer"
|
67
|
+
assert_equal "testjobs", NewRelic::Control.instance.app_names[0]
|
68
|
+
assert_equal "mailer", NewRelic::Control.instance.dispatcher_instance_id
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_set_record_sql
|
72
|
+
@agent.set_record_sql(false)
|
73
|
+
assert !Thread::current[:record_sql]
|
74
|
+
NewRelic::Agent.disable_sql_recording do
|
75
|
+
assert_equal false, Thread::current[:record_sql]
|
76
|
+
NewRelic::Agent.disable_sql_recording do
|
77
|
+
assert_equal false, Thread::current[:record_sql]
|
78
|
+
end
|
79
|
+
assert_equal false, Thread::current[:record_sql]
|
80
|
+
end
|
81
|
+
assert !Thread::current[:record_sql], Thread::current[:record_sql]
|
82
|
+
ensure
|
83
|
+
@agent.set_record_sql(nil)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_version
|
87
|
+
assert_match /\d\.\d+\.\d+/, NewRelic::VERSION::STRING
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_invoke_remote__ignore_non_200_results
|
91
|
+
NewRelic::Agent::Agent.class_eval do
|
92
|
+
public :invoke_remote
|
93
|
+
end
|
94
|
+
response_mock = mock()
|
95
|
+
Net::HTTP.any_instance.stubs(:request).returns(response_mock)
|
96
|
+
response_mock.stubs(:message).returns("bogus error")
|
97
|
+
|
98
|
+
for code in %w[500 504 400 302 503] do
|
99
|
+
assert_raise NewRelic::Agent::IgnoreSilentlyException, "Ignore #{code}" do
|
100
|
+
response_mock.stubs(:code).returns(code)
|
101
|
+
NewRelic::Agent.agent.invoke_remote :get_data_report_period, 0
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
def test_invoke_remote__throw_other_errors
|
106
|
+
NewRelic::Agent::Agent.class_eval do
|
107
|
+
public :invoke_remote
|
108
|
+
end
|
109
|
+
response_mock = Net::HTTPSuccess.new nil, nil, nil
|
110
|
+
response_mock.stubs(:body).returns("")
|
111
|
+
Marshal.stubs(:load).raises(RuntimeError, "marshal issue")
|
112
|
+
Net::HTTP.any_instance.stubs(:request).returns(response_mock)
|
113
|
+
assert_raise RuntimeError do
|
114
|
+
NewRelic::Agent.agent.invoke_remote :get_data_report_period, 0xFEFE
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Defining a test controller class with a superclass, used to
|
2
|
+
# verify correct attribute inheritence
|
3
|
+
class NewRelic::Agent::SuperclassController < ActionController::Base
|
4
|
+
def base_action
|
5
|
+
render :text => 'none'
|
6
|
+
end
|
7
|
+
end
|
8
|
+
# This is a controller class used in testing controller instrumentation
|
9
|
+
class NewRelic::Agent::AgentTestController < NewRelic::Agent::SuperclassController
|
10
|
+
filter_parameter_logging :social_security_number
|
11
|
+
|
12
|
+
def rescue_action(e) raise e end
|
13
|
+
|
14
|
+
ActionController::Routing::Routes.draw do | map |
|
15
|
+
map.connect ':controller/:action.:format'
|
16
|
+
end
|
17
|
+
|
18
|
+
def index
|
19
|
+
render :text => params.inspect
|
20
|
+
end
|
21
|
+
def _filter_parameters(params)
|
22
|
+
filter_parameters params
|
23
|
+
end
|
24
|
+
def action_to_render
|
25
|
+
render :text => params.inspect
|
26
|
+
end
|
27
|
+
def action_to_ignore
|
28
|
+
render :text => 'unmeasured'
|
29
|
+
end
|
30
|
+
def action_to_ignore_apdex
|
31
|
+
render :text => 'unmeasured'
|
32
|
+
end
|
33
|
+
def entry_action
|
34
|
+
perform_action_with_newrelic_trace('internal_action') do
|
35
|
+
internal_action
|
36
|
+
end
|
37
|
+
end
|
38
|
+
private
|
39
|
+
def internal_action
|
40
|
+
perform_action_with_newrelic_trace(:name => 'internal_traced_action', :force => true) do
|
41
|
+
render :text => 'internal action'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
|
2
|
+
|
3
|
+
class ClassLoaderPatchTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def test_const_undefined
|
6
|
+
require 'new_relic/agent/patch_const_missing'
|
7
|
+
ClassLoadingWatcher.background_thread = Thread.current
|
8
|
+
|
9
|
+
# try loading some non-existent class
|
10
|
+
NewRelic::Control.instance.log.expects(:error).at_least_once.with{|args| args =~ /Agent background thread.*:FooBar/}
|
11
|
+
NewRelic::Control.instance.log.expects(:error).with{|args| args =~ /Agent background thread.*:FooBaz/}.never
|
12
|
+
|
13
|
+
ClassLoadingWatcher.enable_warning
|
14
|
+
assert_raise NameError do
|
15
|
+
FooBar::Bat
|
16
|
+
end
|
17
|
+
|
18
|
+
ClassLoadingWatcher.disable_warning
|
19
|
+
assert_raise NameError do
|
20
|
+
FooBaz::Bat
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_require
|
25
|
+
require 'new_relic/agent/patch_const_missing'
|
26
|
+
ClassLoadingWatcher.background_thread = Thread.current
|
27
|
+
|
28
|
+
# try loading some non-existent class
|
29
|
+
NewRelic::Control.instance.log.expects(:error).at_least_once.with{|args| args =~ /Agent background thread.*rational/}
|
30
|
+
NewRelic::Control.instance.log.expects(:error).with{|args| args =~ /Agent background thread.*pstore/}.never
|
31
|
+
|
32
|
+
ClassLoadingWatcher.enable_warning
|
33
|
+
require('rational') # standard library probably not loaded yet
|
34
|
+
|
35
|
+
ClassLoadingWatcher.disable_warning
|
36
|
+
|
37
|
+
require 'pstore' # standard library probably not loaded yet
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_load
|
41
|
+
require 'new_relic/agent/patch_const_missing'
|
42
|
+
ClassLoadingWatcher.background_thread = Thread.current
|
43
|
+
|
44
|
+
# try loading some non-existent class
|
45
|
+
NewRelic::Control.instance.log.expects(:error).with{|args| args =~ /Agent background thread.*tsort/}.at_least_once
|
46
|
+
NewRelic::Control.instance.log.expects(:error).with{|args| args =~ /Agent background thread.*getoptlong/}.never
|
47
|
+
|
48
|
+
ClassLoadingWatcher.enable_warning
|
49
|
+
|
50
|
+
load 'tsort.rb' # standard library probably not loaded yet
|
51
|
+
|
52
|
+
ClassLoadingWatcher.disable_warning
|
53
|
+
|
54
|
+
load 'getoptlong.rb' # standard library probably not loaded yet
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
|
2
|
+
require 'ostruct'
|
3
|
+
require 'active_record_fixtures'
|
4
|
+
class NewRelic::Agent::CollectionHelperTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
NewRelic::Agent.manual_start
|
9
|
+
end
|
10
|
+
def teardown
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
include NewRelic::Agent::CollectionHelper
|
15
|
+
def test_string
|
16
|
+
val = ('A'..'Z').to_a.join * 100
|
17
|
+
assert_equal val.first(256) + "...", normalize_params(val)
|
18
|
+
end
|
19
|
+
def test_array
|
20
|
+
new_array = normalize_params [ 1000 ] * 50
|
21
|
+
assert_equal 20, new_array.size
|
22
|
+
assert_equal '1000', new_array[0]
|
23
|
+
end
|
24
|
+
def test_boolean
|
25
|
+
np = normalize_params(NewRelic::Control.instance.settings)
|
26
|
+
assert_equal false, np['enabled']
|
27
|
+
end
|
28
|
+
class MyString < String; end
|
29
|
+
def test_kind_of_string
|
30
|
+
s = MyString.new "This is a string"
|
31
|
+
assert_equal "This is a string", s.to_s
|
32
|
+
assert_equal MyString, s.class
|
33
|
+
assert_equal String, s.to_s.class
|
34
|
+
params = normalize_params(:val => [s])
|
35
|
+
assert_equal String, params[:val][0].class
|
36
|
+
assert_equal String, flatten(s).class
|
37
|
+
assert_equal String, truncate(s, 2).class
|
38
|
+
end
|
39
|
+
def test_number
|
40
|
+
np = normalize_params({ 'one' => 1.0, 'two' => '2'})
|
41
|
+
end
|
42
|
+
def test_nil
|
43
|
+
np = normalize_params({ nil => 1.0, 'two' => nil})
|
44
|
+
assert_equal "1.0", np['']
|
45
|
+
assert_equal nil, np['two']
|
46
|
+
end
|
47
|
+
def test_hash
|
48
|
+
val = ('A'..'Z').to_a.join * 100
|
49
|
+
assert_equal Hash["ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF..." => (("0"*256) + "...")], normalize_params({ val => '0' * 512 })
|
50
|
+
end
|
51
|
+
class MyHash < Hash
|
52
|
+
|
53
|
+
end
|
54
|
+
# Test to ensure that hash subclasses are properly converted
|
55
|
+
def test_hash_subclass
|
56
|
+
h = MyHash.new
|
57
|
+
h[:mine] = 'mine'
|
58
|
+
custom_params = { :one => {:hash => { :a => :b}, :myhash => h }}
|
59
|
+
nh = normalize_params(custom_params)
|
60
|
+
myhash = custom_params[:one][:myhash]
|
61
|
+
assert_equal MyHash, myhash.class
|
62
|
+
myhash = nh[:one][:myhash]
|
63
|
+
assert_equal Hash, myhash.class
|
64
|
+
end
|
65
|
+
|
66
|
+
class MyEnumerable
|
67
|
+
include Enumerable
|
68
|
+
|
69
|
+
def each
|
70
|
+
yield "1"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_enumerable
|
75
|
+
e = MyEnumerable.new
|
76
|
+
custom_params = { :one => {:hash => { :a => :b}, :myenum => e }}
|
77
|
+
nh = normalize_params(custom_params)
|
78
|
+
myenum = nh[:one][:myenum]
|
79
|
+
assert_match /MyEnumerable/, myenum
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_stringio
|
83
|
+
# Verify StringIO works like this normally:
|
84
|
+
s = StringIO.new "start" + ("foo bar bat " * 1000)
|
85
|
+
val = nil
|
86
|
+
s.each { | entry | val = entry; break }
|
87
|
+
assert_match /^startfoo bar/, val
|
88
|
+
|
89
|
+
# make sure stringios aren't affected by calling normalize_params:
|
90
|
+
s = StringIO.new "start" + ("foo bar bat " * 1000)
|
91
|
+
v = normalize_params({ :foo => s.string })
|
92
|
+
s.each { | entry | val = entry; break }
|
93
|
+
assert_match /^startfoo bar/, val
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_object
|
97
|
+
assert_equal ["foo", '#<OpenStruct>'], normalize_params(['foo', OpenStruct.new('z'=>'q')])
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_strip_backtrace
|
101
|
+
begin
|
102
|
+
ActiveRecordFixtures.setup
|
103
|
+
# ActiveRecordFixtures::Order.add_delay
|
104
|
+
ActiveRecordFixtures::Order.find 0
|
105
|
+
flunk "should throw"
|
106
|
+
rescue => e
|
107
|
+
#puts e
|
108
|
+
#puts e.backtrace.join("\n")
|
109
|
+
#puts "\n\n"
|
110
|
+
clean_trace = strip_nr_from_backtrace(e.backtrace)
|
111
|
+
assert_equal 0, clean_trace.grep(/newrelic_rpm/).size, clean_trace.grep(/newrelic_rpm/)
|
112
|
+
assert_equal 0, clean_trace.grep(/trace/).size, clean_trace.grep(/trace/)
|
113
|
+
assert_equal 3, clean_trace.grep(/find/).size, "should see three frames with 'find' in them (#{e}): \n#{clean_trace.join("\n")}"
|
114
|
+
ensure
|
115
|
+
ActiveRecordFixtures.teardown
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
|
2
|
+
|
3
|
+
class NewRelic::Agent::DispatcherInstrumentationTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
class FunnyDispatcher
|
6
|
+
include NewRelic::Agent::Instrumentation::DispatcherInstrumentation
|
7
|
+
def newrelic_response_code; end
|
8
|
+
end
|
9
|
+
def setup
|
10
|
+
super
|
11
|
+
NewRelic::Agent.manual_start
|
12
|
+
NewRelic::Agent.instance.stats_engine.clear_stats
|
13
|
+
@instance_busy = NewRelic::Agent.agent.stats_engine.get_stats('Instance/Busy')
|
14
|
+
@dispatch_stat = NewRelic::Agent.agent.stats_engine.get_stats 'HttpDispatcher'
|
15
|
+
@mongrel_queue_stat = NewRelic::Agent.agent.stats_engine.get_stats 'WebFrontend/Mongrel/Average Queue Time'
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_normal_call
|
19
|
+
d = FunnyDispatcher.new
|
20
|
+
assert_equal 0, NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.busy_count
|
21
|
+
d.newrelic_dispatcher_start
|
22
|
+
sleep 1.0
|
23
|
+
assert_equal 1, NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.busy_count
|
24
|
+
d.newrelic_dispatcher_finish
|
25
|
+
assert_equal 0, NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.busy_count
|
26
|
+
assert_nil Thread.current[:newrelic_t0]
|
27
|
+
NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.harvest_busy
|
28
|
+
|
29
|
+
assert_equal 1, @instance_busy.call_count
|
30
|
+
assert_equal 1, @dispatch_stat.call_count
|
31
|
+
assert_equal 0, @mongrel_queue_stat.call_count
|
32
|
+
assert @dispatch_stat.total_call_time >= 1.0, "Total call time must be at least one second"
|
33
|
+
assert @instance_busy.total_call_time > 0.9 && @instance_busy.total_call_time <= 1.0, "instance busy = #{@instance_busy.inspect}"
|
34
|
+
end
|
35
|
+
def test_histogram
|
36
|
+
d = FunnyDispatcher.new
|
37
|
+
d.newrelic_dispatcher_start
|
38
|
+
d.newrelic_dispatcher_finish
|
39
|
+
bucket = NewRelic::Agent.instance.stats_engine.metrics.find { | m | m =~ /^Response Times/ }
|
40
|
+
assert_not_nil bucket
|
41
|
+
bucket_stats = NewRelic::Agent.instance.stats_engine.get_stats(bucket)
|
42
|
+
assert_equal 1, bucket_stats.call_count
|
43
|
+
end
|
44
|
+
def test_ignore_zero_counts
|
45
|
+
assert_equal 0, @instance_busy.call_count, "Problem with test--instance busy not starting off at zero."
|
46
|
+
NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.harvest_busy
|
47
|
+
NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.harvest_busy
|
48
|
+
NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.harvest_busy
|
49
|
+
assert_equal 0, @instance_busy.call_count
|
50
|
+
end
|
51
|
+
def test_recursive_call
|
52
|
+
d0 = FunnyDispatcher.new
|
53
|
+
d1 = FunnyDispatcher.new
|
54
|
+
|
55
|
+
assert_equal 0, @instance_busy.call_count, "Problem with test--instance busy not starting off at zero."
|
56
|
+
|
57
|
+
NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.harvest_busy
|
58
|
+
NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.harvest_busy
|
59
|
+
assert_equal 0, @instance_busy.call_count
|
60
|
+
|
61
|
+
assert_equal 0, NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.busy_count
|
62
|
+
d0.newrelic_dispatcher_start
|
63
|
+
assert_equal 1, NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.busy_count
|
64
|
+
d1.newrelic_dispatcher_start
|
65
|
+
assert_equal 2, NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.busy_count
|
66
|
+
sleep 1
|
67
|
+
d0.newrelic_dispatcher_finish
|
68
|
+
assert_equal 1, NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.busy_count
|
69
|
+
d1.newrelic_dispatcher_finish
|
70
|
+
assert_equal 0, NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.busy_count
|
71
|
+
assert_nil Thread.current[:newrelic_t0]
|
72
|
+
NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.harvest_busy
|
73
|
+
assert_equal 1, @instance_busy.call_count
|
74
|
+
assert @instance_busy.total_call_time.between?(1.8, 2.1), "Should be about 200%: #{@instance_busy.total_call_time}"
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
|
2
|
+
##require 'new_relic/agent/error_collector'
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
|
6
|
+
class FakeRequest
|
7
|
+
attr_reader :path
|
8
|
+
|
9
|
+
def initialize(path)
|
10
|
+
@path = path
|
11
|
+
end
|
12
|
+
|
13
|
+
def referer
|
14
|
+
"test_referer"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
|
19
|
+
|
20
|
+
def setup
|
21
|
+
@error_collector = NewRelic::Agent::ErrorCollector.new(nil)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_simple
|
25
|
+
@error_collector.notice_error(Exception.new("message"), FakeRequest.new('/myurl/'), 'path', {:x => 'y'})
|
26
|
+
|
27
|
+
old_errors = []
|
28
|
+
errors = @error_collector.harvest_errors(old_errors)
|
29
|
+
|
30
|
+
assert_equal errors.length, 1
|
31
|
+
|
32
|
+
err = errors.first
|
33
|
+
assert_equal 'message', err.message
|
34
|
+
assert_equal 'y', err.params[:request_params][:x]
|
35
|
+
assert err.params[:request_uri] == '/myurl/'
|
36
|
+
assert err.params[:request_referer] == "test_referer"
|
37
|
+
assert err.path == 'path'
|
38
|
+
assert err.exception_class == 'Exception'
|
39
|
+
|
40
|
+
# the collector should now return an empty array since nothing
|
41
|
+
# has been added since its last harvest
|
42
|
+
errors = @error_collector.harvest_errors(nil)
|
43
|
+
assert errors.length == 0
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_long_message
|
47
|
+
#yes, times 500. it's a 5000 byte string. Assuming strings are
|
48
|
+
#still 1 byte / char.
|
49
|
+
@error_collector.notice_error(Exception.new("1234567890" * 500), FakeRequest.new('/myurl/'), 'path', {:x => 'y'})
|
50
|
+
|
51
|
+
old_errors = []
|
52
|
+
errors = @error_collector.harvest_errors(old_errors)
|
53
|
+
|
54
|
+
assert_equal errors.length, 1
|
55
|
+
|
56
|
+
err = errors.first
|
57
|
+
assert_equal ('1234567890' * 500)[0..4096], err.message
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_collect_failover
|
61
|
+
@error_collector.notice_error(Exception.new("message"), nil, 'first', {:x => 'y'})
|
62
|
+
|
63
|
+
errors = @error_collector.harvest_errors([])
|
64
|
+
|
65
|
+
@error_collector.notice_error(Exception.new("message"), nil, 'second', {:x => 'y'})
|
66
|
+
@error_collector.notice_error(Exception.new("message"), nil, 'path', {:x => 'y'})
|
67
|
+
@error_collector.notice_error(Exception.new("message"), nil, 'path', {:x => 'y'})
|
68
|
+
|
69
|
+
errors = @error_collector.harvest_errors(errors)
|
70
|
+
|
71
|
+
assert_equal 1, errors.length
|
72
|
+
assert_equal 'first', errors.first.path
|
73
|
+
|
74
|
+
# add two more
|
75
|
+
@error_collector.notice_error(Exception.new("message"), nil, 'path', {:x => 'y'})
|
76
|
+
@error_collector.notice_error(Exception.new("message"), nil, 'last', {:x => 'y'})
|
77
|
+
|
78
|
+
errors = @error_collector.harvest_errors(nil)
|
79
|
+
assert_equal 5, errors.length
|
80
|
+
assert_equal 'second', errors.first.path
|
81
|
+
assert_equal 'last', errors.last.path
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_queue_overflow
|
86
|
+
|
87
|
+
max_q_length = 20 # for some reason I can't read the constant in ErrorCollector
|
88
|
+
|
89
|
+
silence_stream(::STDERR) do
|
90
|
+
(max_q_length + 5).times do |n|
|
91
|
+
@error_collector.notice_error(Exception.new("exception #{n}"), nil, "path", {:x => n})
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
errors = @error_collector.harvest_errors([])
|
96
|
+
assert errors.length == max_q_length
|
97
|
+
errors.each_index do |i|
|
98
|
+
err = errors.shift
|
99
|
+
assert_equal i.to_s, err.params[:request_params][:x], err.params.inspect
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Why would anyone undef these methods?
|
104
|
+
class TestClass
|
105
|
+
undef to_s
|
106
|
+
undef inspect
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
def test_supported_param_types
|
111
|
+
|
112
|
+
types = [[1, '1'],
|
113
|
+
[1.1, '1.1'],
|
114
|
+
['hi', 'hi'],
|
115
|
+
[:hi, :hi],
|
116
|
+
[Exception.new("test"), "#<Exception>"],
|
117
|
+
[TestClass.new, "#<NewRelic::Agent::ErrorCollectorTest::TestClass>"]
|
118
|
+
]
|
119
|
+
|
120
|
+
|
121
|
+
types.each do |test|
|
122
|
+
@error_collector.notice_error(Exception.new("message"), nil, 'path', {:x => test[0]})
|
123
|
+
|
124
|
+
assert_equal test[1], @error_collector.harvest_errors([])[0].params[:request_params][:x]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
def test_exclude
|
130
|
+
@error_collector.ignore(["ActionController::RoutingError"])
|
131
|
+
|
132
|
+
@error_collector.notice_error(ActionController::RoutingError.new("message"), nil, 'path', {:x => 'y'})
|
133
|
+
|
134
|
+
errors = @error_collector.harvest_errors([])
|
135
|
+
|
136
|
+
assert_equal 0, errors.length
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_exclude_block
|
140
|
+
@error_collector.ignore_error_filter do |e|
|
141
|
+
if e.is_a? ActionController::RoutingError
|
142
|
+
nil
|
143
|
+
else
|
144
|
+
e
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
@error_collector.notice_error(ActionController::RoutingError.new("message"), nil, 'path', {:x => 'y'})
|
149
|
+
|
150
|
+
errors = @error_collector.harvest_errors([])
|
151
|
+
|
152
|
+
assert_equal 0, errors.length
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|