newrelic_rpm 2.8.0
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/LICENSE +37 -0
- data/README +93 -0
- data/Rakefile +38 -0
- data/install.rb +37 -0
- data/lib/new_relic/agent.rb +26 -0
- data/lib/new_relic/agent/agent.rb +762 -0
- data/lib/new_relic/agent/chained_call.rb +13 -0
- data/lib/new_relic/agent/collection_helper.rb +81 -0
- data/lib/new_relic/agent/error_collector.rb +105 -0
- data/lib/new_relic/agent/instrumentation/active_record_instrumentation.rb +95 -0
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +151 -0
- data/lib/new_relic/agent/instrumentation/data_mapper.rb +90 -0
- data/lib/new_relic/agent/instrumentation/dispatcher_instrumentation.rb +105 -0
- data/lib/new_relic/agent/instrumentation/memcache.rb +18 -0
- data/lib/new_relic/agent/instrumentation/merb/controller.rb +17 -0
- data/lib/new_relic/agent/instrumentation/merb/dispatcher.rb +15 -0
- data/lib/new_relic/agent/instrumentation/merb/errors.rb +6 -0
- data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +35 -0
- data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +27 -0
- data/lib/new_relic/agent/instrumentation/rails/dispatcher.rb +30 -0
- data/lib/new_relic/agent/instrumentation/rails/errors.rb +23 -0
- data/lib/new_relic/agent/instrumentation/rails/rails.rb +6 -0
- data/lib/new_relic/agent/method_tracer.rb +171 -0
- data/lib/new_relic/agent/patch_const_missing.rb +31 -0
- data/lib/new_relic/agent/samplers/cpu.rb +29 -0
- data/lib/new_relic/agent/samplers/memory.rb +55 -0
- data/lib/new_relic/agent/samplers/mongrel.rb +26 -0
- data/lib/new_relic/agent/stats_engine.rb +241 -0
- data/lib/new_relic/agent/synchronize.rb +40 -0
- data/lib/new_relic/agent/transaction_sampler.rb +281 -0
- data/lib/new_relic/agent/worker_loop.rb +128 -0
- data/lib/new_relic/api/deployments.rb +92 -0
- data/lib/new_relic/config.rb +194 -0
- data/lib/new_relic/config/merb.rb +35 -0
- data/lib/new_relic/config/rails.rb +113 -0
- data/lib/new_relic/config/ruby.rb +9 -0
- data/lib/new_relic/local_environment.rb +108 -0
- data/lib/new_relic/merbtasks.rb +6 -0
- data/lib/new_relic/metric_data.rb +26 -0
- data/lib/new_relic/metric_spec.rb +39 -0
- data/lib/new_relic/metrics.rb +7 -0
- data/lib/new_relic/noticed_error.rb +21 -0
- data/lib/new_relic/shim_agent.rb +95 -0
- data/lib/new_relic/stats.rb +359 -0
- data/lib/new_relic/transaction_analysis.rb +122 -0
- data/lib/new_relic/transaction_sample.rb +499 -0
- data/lib/new_relic/version.rb +111 -0
- data/lib/new_relic_api.rb +275 -0
- data/lib/newrelic_rpm.rb +27 -0
- data/lib/tasks/agent_tests.rake +14 -0
- data/lib/tasks/all.rb +4 -0
- data/lib/tasks/install.rake +7 -0
- data/newrelic.yml +137 -0
- data/recipes/newrelic.rb +46 -0
- data/test/config/newrelic.yml +26 -0
- data/test/config/test_config.rb +9 -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/model_fixture.rb +17 -0
- data/test/new_relic/agent/tc_active_record.rb +91 -0
- data/test/new_relic/agent/tc_agent.rb +112 -0
- data/test/new_relic/agent/tc_collection_helper.rb +104 -0
- data/test/new_relic/agent/tc_controller.rb +98 -0
- data/test/new_relic/agent/tc_dispatcher_instrumentation.rb +52 -0
- data/test/new_relic/agent/tc_error_collector.rb +127 -0
- data/test/new_relic/agent/tc_method_tracer.rb +306 -0
- data/test/new_relic/agent/tc_stats_engine.rb +218 -0
- data/test/new_relic/agent/tc_synchronize.rb +37 -0
- data/test/new_relic/agent/tc_transaction_sample.rb +175 -0
- data/test/new_relic/agent/tc_transaction_sample_builder.rb +200 -0
- data/test/new_relic/agent/tc_transaction_sampler.rb +305 -0
- data/test/new_relic/agent/tc_worker_loop.rb +101 -0
- data/test/new_relic/agent/testable_agent.rb +13 -0
- data/test/new_relic/tc_config.rb +36 -0
- data/test/new_relic/tc_deployments_api.rb +37 -0
- data/test/new_relic/tc_environment.rb +94 -0
- data/test/new_relic/tc_metric_spec.rb +150 -0
- data/test/new_relic/tc_shim_agent.rb +9 -0
- data/test/new_relic/tc_stats.rb +141 -0
- data/test/test_helper.rb +39 -0
- data/test/ui/tc_newrelic_helper.rb +44 -0
- data/ui/controllers/newrelic_controller.rb +200 -0
- data/ui/helpers/google_pie_chart.rb +55 -0
- data/ui/helpers/newrelic_helper.rb +286 -0
- data/ui/views/layouts/newrelic_default.rhtml +49 -0
- data/ui/views/newrelic/_explain_plans.rhtml +27 -0
- data/ui/views/newrelic/_sample.rhtml +12 -0
- data/ui/views/newrelic/_segment.rhtml +28 -0
- data/ui/views/newrelic/_segment_row.rhtml +14 -0
- data/ui/views/newrelic/_show_sample_detail.rhtml +22 -0
- data/ui/views/newrelic/_show_sample_sql.rhtml +19 -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 +45 -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/gray_bar.gif +0 -0
- data/ui/views/newrelic/index.rhtml +37 -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 +62 -0
- data/ui/views/newrelic/show_source.rhtml +3 -0
- data/ui/views/newrelic/stylesheets/style.css +394 -0
- metadata +180 -0
data/recipes/newrelic.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# To be included in Capistrano deploy.rb files
|
2
|
+
#
|
3
|
+
# Defined deploy:notify_rpm which will send information about the deploy to RPM.
|
4
|
+
# The task will run on app servers except where no_release is true.
|
5
|
+
# If it fails, it will not affect the task execution or do a rollback.
|
6
|
+
#
|
7
|
+
|
8
|
+
make_notify_task = lambda do
|
9
|
+
|
10
|
+
namespace :newrelic do
|
11
|
+
|
12
|
+
# on all deployments, notify RPM
|
13
|
+
desc "Record a deployment in New Relic RPM (rpm.newrelic.com)"
|
14
|
+
task :notice_deployment, :roles => :app, :except => {:no_release => true } do
|
15
|
+
rails_env = fetch(:rails_env, "production")
|
16
|
+
from_revision = source.next_revision(current_revision)
|
17
|
+
log_command = source.log(from_revision)
|
18
|
+
# I don't believe this will work if rpm is installed as a gem, or
|
19
|
+
# if they put the plugin elsewhere. Need to revisit.
|
20
|
+
script = [ "vendor/plugins/newrelic_rpm/lib/new_relic_api.rb" ] <<
|
21
|
+
"deployments" <<
|
22
|
+
"-u" << ENV['USER'] <<
|
23
|
+
"-r" << current_revision <<
|
24
|
+
"-c"
|
25
|
+
script = script.map { | arg | "'#{arg}'" }.join(" ")
|
26
|
+
begin
|
27
|
+
run "cd #{current_release}; #{log_command} | script/runner -e #{rails_env} #{script}" do | io, stream_id, output |
|
28
|
+
logger.trace(output)
|
29
|
+
end
|
30
|
+
rescue CommandError
|
31
|
+
logger.info "unable to notify New Relic of the deployment... skipping"
|
32
|
+
end
|
33
|
+
# For rollbacks, let's update the deployment we created with an indication of the failure:
|
34
|
+
#on_rollback do
|
35
|
+
# run(command.gsub(/Subject:.*\\n/, "Subject: #{ENV['USER']} deployed a ROLLBACK\\n"))
|
36
|
+
#end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
instance = Capistrano::Configuration.instance
|
42
|
+
if instance
|
43
|
+
instance.load make_notify_task
|
44
|
+
else
|
45
|
+
make_notify_task.call
|
46
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# This is the config file loaded when running unit tests locally.
|
2
|
+
|
3
|
+
test:
|
4
|
+
erb_value: <%= 'hey'*3 %>
|
5
|
+
host: localhost
|
6
|
+
port: 3000
|
7
|
+
log_level: debug
|
8
|
+
capture_params: true
|
9
|
+
enabled: false
|
10
|
+
developer: true
|
11
|
+
monitor_daemons: false
|
12
|
+
message: '<%= generated_for_user %>'
|
13
|
+
license_key: '<%= license_key %>'
|
14
|
+
transaction_tracer:
|
15
|
+
enabled: true
|
16
|
+
record_sql: raw
|
17
|
+
transaction_threshold: 0.500
|
18
|
+
explain_threshold: 0.1
|
19
|
+
explain_enabled: true
|
20
|
+
stack_trace_threshold: 0.1
|
21
|
+
|
22
|
+
error_collector:
|
23
|
+
enabled: true
|
24
|
+
capture_source: true
|
25
|
+
|
26
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
class << self
|
4
|
+
def test_connection(config)
|
5
|
+
@connect ||= Connection.new
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Connection
|
11
|
+
attr_accessor :throw
|
12
|
+
attr_reader :disconnected
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@disconnected = false
|
16
|
+
@throw = false
|
17
|
+
end
|
18
|
+
|
19
|
+
def disconnect!()
|
20
|
+
@disconnected = true
|
21
|
+
end
|
22
|
+
|
23
|
+
def find()
|
24
|
+
# used to test that we've instrumented this...
|
25
|
+
end
|
26
|
+
|
27
|
+
def select_rows(s)
|
28
|
+
execute(s)
|
29
|
+
end
|
30
|
+
def execute(s)
|
31
|
+
fail "" if @throw
|
32
|
+
if s != "EXPLAIN #{::SQL_STATEMENT}"
|
33
|
+
fail "Unexpected sql statement #{s}"
|
34
|
+
end
|
35
|
+
s
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
class NewRelic::Agent::MockScopeListener
|
3
|
+
|
4
|
+
attr_reader :scope
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@scope = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def notice_first_scope_push(time)
|
11
|
+
end
|
12
|
+
|
13
|
+
def notice_push_scope(scope, time)
|
14
|
+
@scope[scope] = true
|
15
|
+
end
|
16
|
+
|
17
|
+
def notice_pop_scope(scope, time)
|
18
|
+
end
|
19
|
+
|
20
|
+
def notice_scope_empty(time)
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# A test model object
|
2
|
+
# Be sure and call setup and teardown
|
3
|
+
class NewRelic::Agent::ModelFixture < ActiveRecord::Base
|
4
|
+
self.table_name = 'test_data'
|
5
|
+
def self.setup
|
6
|
+
connection.create_table :test_data, :force => true do |t|
|
7
|
+
t.column :name, :string
|
8
|
+
end
|
9
|
+
connection.setup_slow
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.teardown
|
13
|
+
connection.teardown_slow
|
14
|
+
connection.drop_table :test_data
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
|
2
|
+
require 'new_relic/agent/model_fixture'
|
3
|
+
|
4
|
+
|
5
|
+
class ActiveRecordInstrumentationTests < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
super
|
9
|
+
begin
|
10
|
+
NewRelic::Agent::ModelFixture.setup
|
11
|
+
rescue => e
|
12
|
+
puts e
|
13
|
+
raise e
|
14
|
+
end
|
15
|
+
@agent = NewRelic::Agent.instance
|
16
|
+
@agent.start :test, :test
|
17
|
+
@agent.transaction_sampler.harvest_slowest_sample
|
18
|
+
end
|
19
|
+
|
20
|
+
def teardown
|
21
|
+
@agent.shutdown
|
22
|
+
@agent.stats_engine.harvest_timeslice_data Hash.new, Hash.new
|
23
|
+
NewRelic::Agent::ModelFixture.teardown
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_finder
|
28
|
+
NewRelic::Agent::ModelFixture.create :id => 0, :name => 'jeff'
|
29
|
+
NewRelic::Agent::ModelFixture.find(:all)
|
30
|
+
s = NewRelic::Agent.get_stats("ActiveRecord/NewRelic::Agent::ModelFixture/find")
|
31
|
+
assert_equal 1, s.call_count
|
32
|
+
NewRelic::Agent::ModelFixture.find_all_by_name "jeff"
|
33
|
+
s = NewRelic::Agent.get_stats("ActiveRecord/NewRelic::Agent::ModelFixture/find")
|
34
|
+
assert_equal 2, s.call_count
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_run_explains
|
38
|
+
NewRelic::Agent::ModelFixture.find(:all)
|
39
|
+
sample = @agent.transaction_sampler.harvest_slowest_sample
|
40
|
+
segment = sample.root_segment.called_segments.first.called_segments.first
|
41
|
+
assert_equal "SELECT * FROM `test_data`", segment.params[:sql].strip
|
42
|
+
NewRelic::TransactionSample::Segment.any_instance.expects(:explain_sql).returns([])
|
43
|
+
sample = sample.prepare_to_send(:obfuscate_sql => true, :explain_enabled => true, :explain_sql => 0.0)
|
44
|
+
segment = sample.root_segment.called_segments.first.called_segments.first
|
45
|
+
end
|
46
|
+
def test_prepare_to_send
|
47
|
+
NewRelic::Agent::ModelFixture.find(:all)
|
48
|
+
sample = @agent.transaction_sampler.harvest_slowest_sample
|
49
|
+
segment = sample.root_segment.called_segments.first.called_segments.first
|
50
|
+
assert_match /^SELECT /, segment.params[:sql]
|
51
|
+
assert segment.duration > 0.0, "Segment duration must be greater than zero."
|
52
|
+
sample = sample.prepare_to_send(:record_sql => :raw, :explain_enabled => true, :explain_sql => 0.0)
|
53
|
+
segment = sample.root_segment.called_segments.first.called_segments.first
|
54
|
+
assert_match /^SELECT /, segment.params[:sql]
|
55
|
+
explanations = segment.params[:explanation]
|
56
|
+
assert_not_nil explanations, "No explains in segment: #{segment}"
|
57
|
+
assert_equal 1, explanations.size,"No explains in segment: #{segment}"
|
58
|
+
assert_equal 1, explanations.first.size
|
59
|
+
|
60
|
+
end
|
61
|
+
def test_transaction
|
62
|
+
|
63
|
+
NewRelic::Agent::ModelFixture.find(:all)
|
64
|
+
sample = @agent.transaction_sampler.harvest_slowest_sample
|
65
|
+
sample = sample.prepare_to_send(:obfuscate_sql => true, :explain_enabled => true, :explain_sql => 0.0)
|
66
|
+
segment = sample.root_segment.called_segments.first.called_segments.first
|
67
|
+
assert_nil segment.params[:sql], "SQL should have been removed."
|
68
|
+
explanations = segment.params[:explanation]
|
69
|
+
assert_not_nil explanations, "No explains in segment: #{segment}"
|
70
|
+
assert_equal 1, explanations.size,"No explains in segment: #{segment}"
|
71
|
+
assert_equal 1, explanations.first.size
|
72
|
+
|
73
|
+
if isPostgres?
|
74
|
+
assert_equal Array, explanations.class
|
75
|
+
assert_equal Array, explanations[0].class
|
76
|
+
assert_equal Array, explanations[0][0].class
|
77
|
+
assert_match /Seq Scan on test_data/, explanations[0][0].join(";")
|
78
|
+
else
|
79
|
+
assert_equal "1;SIMPLE;test_data;ALL;;;;;1;", explanations.first.first.join(";")
|
80
|
+
end
|
81
|
+
|
82
|
+
s = NewRelic::Agent.get_stats("ActiveRecord/NewRelic::Agent::ModelFixture/find")
|
83
|
+
assert_equal 1, s.call_count
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
def isPostgres?
|
88
|
+
NewRelic::Agent::ModelFixture.configurations[RAILS_ENV]['adapter'] =~ /postgres/
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,112 @@
|
|
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
|
+
require 'net/http'
|
5
|
+
|
6
|
+
class AgentTests < ActiveSupport::TestCase
|
7
|
+
|
8
|
+
attr_reader :agent
|
9
|
+
|
10
|
+
# Fake out the agent to think mongrel is running
|
11
|
+
def setup
|
12
|
+
@agent = NewRelic::Agent.instance
|
13
|
+
@agent.start :test, :test
|
14
|
+
end
|
15
|
+
|
16
|
+
# Remove the port method so it won't think mongrel
|
17
|
+
# is available
|
18
|
+
def teardown
|
19
|
+
@agent.shutdown
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_public_apis
|
24
|
+
begin
|
25
|
+
NewRelic::Agent.set_sql_obfuscator(:unknown) do |sql|
|
26
|
+
puts sql
|
27
|
+
end
|
28
|
+
fail
|
29
|
+
rescue
|
30
|
+
# ok
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
ignore_called = false
|
35
|
+
NewRelic::Agent.ignore_error_filter do |e|
|
36
|
+
ignore_called = true
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
NewRelic::Agent.agent.error_collector.notice_error('path', nil, {:x => 'y'}, ActionController::RoutingError.new("message"))
|
41
|
+
|
42
|
+
assert ignore_called
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_startup_shutdown
|
46
|
+
@agent.shutdown
|
47
|
+
assert (not @agent.started?)
|
48
|
+
@agent.start "ruby", "test1"
|
49
|
+
assert @agent.started?
|
50
|
+
@agent.shutdown
|
51
|
+
@agent.start "ruby", "test2"
|
52
|
+
end
|
53
|
+
def test_setup_log_default
|
54
|
+
assert @agent.log.instance_of?(Logger), @agent.log
|
55
|
+
logfile = @agent.log.instance_eval { @logdev.filename }
|
56
|
+
assert_match /\/log\/newrelic_agent\..*\.log$/,logfile
|
57
|
+
@agent.shutdown
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_classloading_patch
|
61
|
+
require 'new_relic/agent/patch_const_missing'
|
62
|
+
NewRelic::Agent::Agent.newrelic_set_agent_thread(Thread.current)
|
63
|
+
# try loading some non-existent class
|
64
|
+
NewRelic::Config.instance.log.expects(:warn).at_least_once.with{|args| args =~ /calling const_missing.*:FooBar/}
|
65
|
+
NewRelic::Config.instance.log.expects(:warn).with{|args| args =~ /calling const_missing.*:FooBaz/}.never
|
66
|
+
NewRelic::Agent::Agent.newrelic_enable_warning
|
67
|
+
assert_raise NameError do
|
68
|
+
FooBar::Bat
|
69
|
+
end
|
70
|
+
NewRelic::Agent::Agent.newrelic_disable_warning
|
71
|
+
assert_raise NameError do
|
72
|
+
FooBaz::Bat
|
73
|
+
end
|
74
|
+
end
|
75
|
+
def test_info
|
76
|
+
props = NewRelic::Config.instance.app_config_info
|
77
|
+
list = props.assoc('Plugin List').last.sort
|
78
|
+
assert_equal 4, (list & %w[active_merchant active_scaffold acts_as_list acts_as_state_machine ]).size, list.join("\n")
|
79
|
+
assert_equal 'mysql', props.assoc('Database adapter').last
|
80
|
+
end
|
81
|
+
def test_version
|
82
|
+
assert_match /\d\.\d\.\d+/, NewRelic::VERSION::STRING
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_invoke_remote__ignore_non_200_results
|
86
|
+
NewRelic::Agent::Agent.class_eval do
|
87
|
+
public :invoke_remote
|
88
|
+
end
|
89
|
+
response_mock = mock()
|
90
|
+
Net::HTTP.any_instance.stubs(:request).returns(response_mock)
|
91
|
+
response_mock.stubs(:message).returns("bogus error")
|
92
|
+
|
93
|
+
for code in %w[500 504 400 302 503] do
|
94
|
+
assert_raise NewRelic::Agent::IgnoreSilentlyException, "Ignore #{code}" do
|
95
|
+
response_mock.stubs(:code).returns(code)
|
96
|
+
NewRelic::Agent.agent.invoke_remote :get_data_report_period, 0
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
def test_invoke_remote__throw_other_errors
|
101
|
+
NewRelic::Agent::Agent.class_eval do
|
102
|
+
public :invoke_remote
|
103
|
+
end
|
104
|
+
response_mock = Net::HTTPSuccess.new nil, nil, nil
|
105
|
+
response_mock.stubs(:body).returns("")
|
106
|
+
Marshal.stubs(:load).raises(RuntimeError, "marshal issue")
|
107
|
+
Net::HTTP.any_instance.stubs(:request).returns(response_mock)
|
108
|
+
assert_raise RuntimeError do
|
109
|
+
NewRelic::Agent.agent.invoke_remote :get_data_report_period, 0xFEFE
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
|
2
|
+
require 'ostruct'
|
3
|
+
require 'new_relic/agent/model_fixture'
|
4
|
+
|
5
|
+
class NewRelic::Agent::CollectionHelperTests < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
super
|
9
|
+
NewRelic::Agent::ModelFixture.setup
|
10
|
+
NewRelic::Agent.instance.start :test, :test
|
11
|
+
end
|
12
|
+
def teardown
|
13
|
+
NewRelic::Agent::ModelFixture.teardown
|
14
|
+
NewRelic::Agent.instance.shutdown
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
include NewRelic::Agent::CollectionHelper
|
19
|
+
def test_string
|
20
|
+
val = ('A'..'Z').to_a.join * 100
|
21
|
+
assert_equal val.first(256) + "...", normalize_params(val)
|
22
|
+
end
|
23
|
+
def test_array
|
24
|
+
new_array = normalize_params [ 1000 ] * 50
|
25
|
+
assert_equal 20, new_array.size
|
26
|
+
assert_equal '1000', new_array[0]
|
27
|
+
end
|
28
|
+
def test_boolean
|
29
|
+
np = normalize_params(APP_CONFIG)
|
30
|
+
assert_equal false, np['disable_ui']
|
31
|
+
end
|
32
|
+
def test_coercible_string
|
33
|
+
s = CoercibleString.new "This is a string"
|
34
|
+
assert_equal "This is a string", s.to_s
|
35
|
+
assert_equal CoercibleString, s.class
|
36
|
+
assert_equal String, s.to_s.class
|
37
|
+
params = normalize_params(:val => [s])
|
38
|
+
assert_equal String, params[:val][0].class
|
39
|
+
assert_equal String, flatten(s).class
|
40
|
+
assert_equal String, truncate(s, 2).class
|
41
|
+
end
|
42
|
+
def test_number
|
43
|
+
np = normalize_params({ 'one' => 1.0, 'two' => '2'})
|
44
|
+
end
|
45
|
+
def test_nil
|
46
|
+
np = normalize_params({ nil => 1.0, 'two' => nil})
|
47
|
+
assert_equal "1.0", np['']
|
48
|
+
assert_equal nil, np['two']
|
49
|
+
end
|
50
|
+
def test_hash
|
51
|
+
val = ('A'..'Z').to_a.join * 100
|
52
|
+
assert_equal Hash["ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF..." => (("0"*256) + "...")], normalize_params({ val => '0' * 512 })
|
53
|
+
end
|
54
|
+
class MyHash < Hash
|
55
|
+
|
56
|
+
end
|
57
|
+
# Test to ensure that hash subclasses are properly converted
|
58
|
+
def test_hash_subclass
|
59
|
+
h = MyHash.new
|
60
|
+
h[:mine] = 'mine'
|
61
|
+
custom_params = { :one => {:hash => { :a => :b}, :myhash => h }}
|
62
|
+
nh = normalize_params(custom_params)
|
63
|
+
myhash = custom_params[:one][:myhash]
|
64
|
+
assert_equal MyHash, myhash.class
|
65
|
+
myhash = nh[:one][:myhash]
|
66
|
+
assert_equal Hash, myhash.class
|
67
|
+
end
|
68
|
+
|
69
|
+
class MyEnumerable
|
70
|
+
include Enumerable
|
71
|
+
|
72
|
+
def each
|
73
|
+
yield "1"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_enumerable
|
78
|
+
e = MyEnumerable.new
|
79
|
+
custom_params = { :one => {:hash => { :a => :b}, :myenum => e }}
|
80
|
+
nh = normalize_params(custom_params)
|
81
|
+
myenum = nh[:one][:myenum]
|
82
|
+
assert_equal ["1"], myenum
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def test_object
|
87
|
+
assert_equal ["foo", '#<OpenStruct z="q">'], normalize_params(['foo', OpenStruct.new('z'=>'q')])
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_strip_backtrace
|
91
|
+
begin
|
92
|
+
NewRelic::Agent::ModelFixture.find 0
|
93
|
+
flunk "should throw"
|
94
|
+
rescue => e
|
95
|
+
# puts e
|
96
|
+
# puts e.backtrace.join("\n")
|
97
|
+
# puts "\n\n"
|
98
|
+
clean_trace = strip_nr_from_backtrace(e.backtrace)
|
99
|
+
assert_equal 0, clean_trace.grep(/newrelic_rpm/).size, clean_trace.grep(/newrelic_rpm/)
|
100
|
+
assert_equal 0, clean_trace.grep(/trace/).size, clean_trace.grep(/trace/)
|
101
|
+
assert_equal 3, clean_trace.grep(/find/).size, "should see three frames with 'find' in them: \n#{clean_trace.join("\n")}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|