newrelic_rpm 2.9.9 → 2.10.3

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.

Files changed (120) hide show
  1. data/CHANGELOG +117 -49
  2. data/bin/mongrel_rpm +2 -2
  3. data/install.rb +42 -33
  4. data/lib/new_relic/agent.rb +149 -39
  5. data/lib/new_relic/agent/agent.rb +139 -122
  6. data/lib/new_relic/agent/busy_calculator.rb +91 -0
  7. data/lib/new_relic/agent/collection_helper.rb +11 -2
  8. data/lib/new_relic/agent/error_collector.rb +33 -27
  9. data/lib/new_relic/agent/instrumentation/active_record_instrumentation.rb +30 -26
  10. data/lib/new_relic/agent/instrumentation/authlogic.rb +8 -0
  11. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +316 -105
  12. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +22 -0
  13. data/lib/new_relic/agent/instrumentation/memcache.rb +18 -12
  14. data/lib/new_relic/agent/instrumentation/merb/errors.rb +2 -1
  15. data/lib/new_relic/agent/instrumentation/metric_frame.rb +258 -0
  16. data/lib/new_relic/agent/instrumentation/net.rb +7 -11
  17. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +1 -1
  18. data/lib/new_relic/agent/instrumentation/rack.rb +109 -0
  19. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +6 -5
  20. data/lib/new_relic/agent/instrumentation/rails/errors.rb +7 -7
  21. data/lib/new_relic/agent/instrumentation/sinatra.rb +46 -0
  22. data/lib/new_relic/agent/method_tracer.rb +305 -150
  23. data/lib/new_relic/agent/sampler.rb +34 -0
  24. data/lib/new_relic/agent/samplers/cpu_sampler.rb +11 -1
  25. data/lib/new_relic/agent/samplers/delayed_job_lock_sampler.rb +37 -0
  26. data/lib/new_relic/agent/samplers/memory_sampler.rb +22 -10
  27. data/lib/new_relic/agent/samplers/object_sampler.rb +24 -0
  28. data/lib/new_relic/agent/shim_agent.rb +10 -0
  29. data/lib/new_relic/agent/stats_engine.rb +16 -278
  30. data/lib/new_relic/agent/stats_engine/metric_stats.rb +118 -0
  31. data/lib/new_relic/agent/stats_engine/samplers.rb +81 -0
  32. data/lib/new_relic/agent/stats_engine/transactions.rb +149 -0
  33. data/lib/new_relic/agent/transaction_sampler.rb +73 -67
  34. data/lib/new_relic/agent/worker_loop.rb +69 -68
  35. data/lib/new_relic/commands/deployments.rb +4 -6
  36. data/lib/new_relic/control.rb +121 -60
  37. data/lib/new_relic/control/external.rb +13 -0
  38. data/lib/new_relic/control/merb.rb +2 -0
  39. data/lib/new_relic/control/rails.rb +16 -6
  40. data/lib/new_relic/control/ruby.rb +8 -5
  41. data/lib/new_relic/control/sinatra.rb +18 -0
  42. data/lib/new_relic/delayed_job_injection.rb +25 -0
  43. data/lib/new_relic/histogram.rb +89 -0
  44. data/lib/new_relic/local_environment.rb +64 -30
  45. data/lib/new_relic/metric_data.rb +15 -6
  46. data/lib/new_relic/metric_parser.rb +14 -1
  47. data/lib/new_relic/metric_parser/active_record.rb +14 -0
  48. data/lib/new_relic/metric_parser/controller.rb +5 -2
  49. data/lib/new_relic/metric_parser/external.rb +50 -0
  50. data/lib/new_relic/metric_parser/other_transaction.rb +15 -0
  51. data/lib/new_relic/metric_parser/web_frontend.rb +14 -0
  52. data/lib/new_relic/metric_spec.rb +39 -20
  53. data/lib/new_relic/metrics.rb +9 -7
  54. data/lib/new_relic/noticed_error.rb +6 -8
  55. data/lib/new_relic/rack/metric_app.rb +5 -4
  56. data/lib/new_relic/rack/{newrelic.ru → mongrel_rpm.ru} +4 -4
  57. data/lib/new_relic/rack/newrelic.yml +1 -0
  58. data/lib/new_relic/{rack.rb → rack_app.rb} +0 -0
  59. data/lib/new_relic/recipes.rb +1 -1
  60. data/lib/new_relic/stats.rb +40 -26
  61. data/lib/new_relic/transaction_analysis.rb +5 -2
  62. data/lib/new_relic/transaction_sample.rb +134 -55
  63. data/lib/new_relic/version.rb +27 -20
  64. data/lib/new_relic_api.rb +67 -47
  65. data/lib/newrelic_rpm.rb +5 -5
  66. data/lib/tasks/tests.rake +2 -0
  67. data/newrelic.yml +69 -29
  68. data/test/active_record_fixtures.rb +2 -2
  69. data/test/config/newrelic.yml +4 -7
  70. data/test/config/test_control.rb +1 -2
  71. data/test/new_relic/agent/active_record_instrumentation_test.rb +115 -31
  72. data/test/new_relic/agent/agent_controller_test.rb +274 -0
  73. data/test/new_relic/agent/agent_test_controller.rb +42 -6
  74. data/test/new_relic/agent/busy_calculator_test.rb +79 -0
  75. data/test/new_relic/agent/collection_helper_test.rb +10 -3
  76. data/test/new_relic/agent/error_collector_test.rb +35 -17
  77. data/test/new_relic/agent/method_tracer_test.rb +60 -20
  78. data/test/new_relic/agent/metric_data_test.rb +2 -2
  79. data/test/new_relic/agent/metric_frame_test.rb +51 -0
  80. data/test/new_relic/agent/net_instrumentation_test.rb +77 -0
  81. data/test/new_relic/agent/{agent_test.rb → rpm_agent_test.rb} +26 -5
  82. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +79 -0
  83. data/test/new_relic/{samplers_test.rb → agent/stats_engine/samplers_test.rb} +23 -22
  84. data/test/new_relic/agent/{stats_engine_test.rb → stats_engine/stats_engine_test.rb} +19 -101
  85. data/test/new_relic/agent/task_instrumentation_test.rb +176 -0
  86. data/test/new_relic/agent/transaction_sample_builder_test.rb +2 -2
  87. data/test/new_relic/agent/transaction_sample_test.rb +53 -38
  88. data/test/new_relic/agent/transaction_sampler_test.rb +101 -33
  89. data/test/new_relic/agent/worker_loop_test.rb +16 -14
  90. data/test/new_relic/control_test.rb +26 -13
  91. data/test/new_relic/metric_parser_test.rb +31 -1
  92. data/test/new_relic/metric_spec_test.rb +2 -2
  93. data/test/new_relic/stats_test.rb +0 -8
  94. data/test/new_relic/version_number_test.rb +31 -1
  95. data/test/test_helper.rb +37 -1
  96. data/ui/controllers/newrelic_controller.rb +19 -11
  97. data/ui/helpers/google_pie_chart.rb +5 -11
  98. data/ui/helpers/newrelic_helper.rb +40 -35
  99. data/ui/views/layouts/newrelic_default.rhtml +7 -7
  100. data/ui/views/newrelic/_sample.rhtml +5 -1
  101. data/ui/views/newrelic/images/new-relic-rpm-desktop.gif +0 -0
  102. data/ui/views/newrelic/images/textmate.png +0 -0
  103. data/ui/views/newrelic/index.rhtml +13 -1
  104. data/ui/views/newrelic/show_sample.rhtml +5 -2
  105. data/ui/views/newrelic/stylesheets/style.css +54 -3
  106. metadata +65 -145
  107. data/Manifest +0 -143
  108. data/Rakefile +0 -22
  109. data/init.rb +0 -38
  110. data/lib/new_relic/agent/instrumentation/dispatcher_instrumentation.rb +0 -127
  111. data/lib/new_relic/agent/instrumentation/error_instrumentation.rb +0 -14
  112. data/lib/new_relic/agent/instrumentation/merb/dispatcher.rb +0 -13
  113. data/lib/new_relic/agent/instrumentation/rails/dispatcher.rb +0 -38
  114. data/lib/new_relic/agent/patch_const_missing.rb +0 -125
  115. data/lib/new_relic/agent/samplers/mongrel_sampler.rb +0 -22
  116. data/lib/new_relic/metric_parser/database.rb +0 -23
  117. data/newrelic_rpm.gemspec +0 -35
  118. data/test/new_relic/agent/classloader_patch_test.rb +0 -56
  119. data/test/new_relic/agent/controller_test.rb +0 -107
  120. data/test/new_relic/agent/dispatcher_instrumentation_test.rb +0 -70
@@ -10,15 +10,15 @@
10
10
  # dependency 'newrelic_rpm'
11
11
  # in the Merb config/init.rb
12
12
  #
13
+ # For Sinatra, do
14
+ # require 'newrelic_rpm'
15
+ # after requiring 'sinatra'.
16
+ #
13
17
  # For other frameworks, or to manage the agent manually, invoke NewRelic::Agent#manual_start
14
18
  # directly.
15
19
  #
16
20
  require 'new_relic/control'
17
21
 
18
- def log!(message)
19
- STDERR.puts "[NewRelic] #{message}"
20
- end
21
-
22
22
  # After verison 2.0 of Rails we can access the configuration directly.
23
23
  # We need it to add dev mode routes after initialization finished.
24
24
  if defined? Rails.configuration
@@ -34,7 +34,7 @@ elsif defined? Merb
34
34
  NewRelic::Control.instance.init_plugin
35
35
  end
36
36
  end
37
- end
37
+ end
38
38
  else
39
39
  NewRelic::Control.instance.init_plugin
40
40
  end
@@ -1,4 +1,5 @@
1
1
  # run unit tests for the NewRelic Agent
2
+
2
3
  if defined? Rake::TestTask
3
4
  namespace :test do
4
5
  AGENT_HOME = File.expand_path(File.join(File.dirname(__FILE__), "..",".."))
@@ -9,5 +10,6 @@ if defined? Rake::TestTask
9
10
  t.verbose = true
10
11
  end
11
12
  Rake::Task['test:newrelic'].comment = "Run the unit tests for the Agent"
13
+ task :default => :newrelic
12
14
  end
13
15
  end
@@ -14,7 +14,7 @@ common: &default_settings
14
14
  # New Relic RPM service.
15
15
  license_key: '<%= license_key %>'
16
16
 
17
- # Agent Enabled
17
+ # Agent Enabled (Rails Only)
18
18
  # Use this setting to force the agent to run or not run.
19
19
  # Default is 'auto' which means the agent will install and run only
20
20
  # if a valid dispatcher such as Mongrel is running. This prevents
@@ -29,15 +29,19 @@ common: &default_settings
29
29
  # into a RPM "application" on your home dashboard page. If you want
30
30
  # to map this instance into multiple apps, like "AJAX Requests" and
31
31
  # "All UI" then specify a semicolon separated list of up to three
32
- # distinct names. This setting does not prevent you from manually
33
- # defining applications.
32
+ # distinct names. If you comment this out, it defaults to the
33
+ # capitalized RAILS_ENV (i.e., Production, Staging, etc)
34
34
  app_name: My Application
35
35
 
36
- # When 'enabled' is turned on, the agent collects performance data
37
- # by inserting lightweight tracers on key methods inside the rails
38
- # framework and asynchronously aggregating and reporting this
39
- # performance data to the NewRelic RPM service at newrelic.com.
40
- enabled: false
36
+ # When "true", the agent collects performance data about your
37
+ # application and reports this data to the NewRelic RPM service at
38
+ # newrelic.com. This global switch is normally overridden for each
39
+ # environment below. (formerly called 'enabled')
40
+ monitor_mode: true
41
+
42
+ # Developer mode should be off in every environment but
43
+ # development as it has very high overhead in memory.
44
+ developer_mode: false
41
45
 
42
46
  # The newrelic agent generates its own log file to keep its logging
43
47
  # information separate from that of your application. Specify its
@@ -88,9 +92,12 @@ common: &default_settings
88
92
 
89
93
 
90
94
  # Tells transaction tracer and error collector (when enabled)
91
- # whether or not to capture HTTP params. When true, the RoR
92
- # filter_parameter_logging mechanism is used so that sensitive
93
- # parameters are not recorded
95
+ # whether or not to capture HTTP params. When true, frameworks can
96
+ # exclude HTTP parameters from being captured.
97
+ # Rails: the RoR filter_parameter_logging excludes parameters
98
+ # Java: create a config setting called "ignored_params" and set it to
99
+ # a comma separated list of HTTP parameter names.
100
+ # ex: ignored_params: credit_card, ssn, password
94
101
  capture_params: false
95
102
 
96
103
 
@@ -124,6 +131,15 @@ common: &default_settings
124
131
  # then capture and send to RPM the current stack trace. This is
125
132
  # helpful for pinpointing where long SQL calls originate from
126
133
  stack_trace_threshold: 0.500
134
+
135
+ # Determines whether the agent will capture query plans for slow
136
+ # SQL queries. Only supported in mysql and postgres. Should be
137
+ # set to false when using other adapters.
138
+ # explain_enabled: true
139
+
140
+ # Threshold for query execution time below which query plans will not
141
+ # not be captured. Relevant only when `explain_enabled` is true.
142
+ # explain_threshold: 0.5
127
143
 
128
144
  # Error collector captures information about uncaught exceptions and
129
145
  # sends them to RPM for viewing
@@ -134,43 +150,67 @@ common: &default_settings
134
150
  # product levels
135
151
  enabled: true
136
152
 
137
- # Tells error collector whether or not to capture a source snippet
138
- # around the place of the error when errors are View related.
153
+ # Rails Only - tells error collector whether or not to capture a
154
+ # source snippet around the place of the error when errors are View
155
+ # related.
139
156
  capture_source: true
140
157
 
141
158
  # To stop specific errors from reporting to RPM, set this property
142
- # to comma separated values
159
+ # to comma separated values. Default is to ignore routing errors
160
+ # which are how 404's get triggered.
143
161
  #
144
- #ignore_errors: ActionController::RoutingError, ...
162
+ ignore_errors: ActionController::RoutingError
145
163
 
146
164
  # (Advanced) Uncomment this to ensure the cpu and memory samplers
147
165
  # won't run. Useful when you are using the agent to monitor an
148
166
  # external resource
149
167
  # disable_samplers: true
168
+
169
+ # If you aren't interested in visibility in these areas, you can disable
170
+ # the instrumentation to reduce overhead.
171
+ #
172
+ # disable_view_instrumentation: true
173
+ # disable_activerecord_instrumentation: true
174
+ # disable_memcache_instrumentation: true
175
+ # disable_dj: true
176
+
177
+ # Certain types of instrumentation such as GC stats will not work if
178
+ # you are running multi-threaded. Please let us know.
179
+ # multi_threaded = false
150
180
 
151
- # override default settings based on your application's environment
181
+ # Application Environments
182
+ # ------------------------------------------
183
+ # Environment specific settings are in this section.
184
+ # For Rails applications, RAILS_ENV is used to determine the environment
185
+ # For Java applications, pass -Dnewrelic.environment <environment> to set
186
+ # the environment
152
187
 
153
188
  # NOTE if your application has other named environments, you should
154
189
  # provide newrelic conifguration settings for these enviromnents here.
155
190
 
156
191
  development:
157
192
  <<: *default_settings
158
- # Turn off communication to RPM service in development mode.
193
+ # Turn off communication to RPM service in development mode (also
194
+ # 'enabled').
159
195
  # NOTE: for initial evaluation purposes, you may want to temporarily
160
196
  # turn the agent on in development mode.
161
- enabled: false
162
-
163
- # When running in Developer Mode, the New Relic Agent will present
164
- # performance information on the last 100 transactions you have
165
- # executed since starting the mongrel. to view this data, go to
166
- # http://localhost:3000/newrelic
167
- developer: true
197
+ monitor_mode: false
198
+
199
+ # Rails Only - when running in Developer Mode, the New Relic Agent will
200
+ # present performance information on the last 100 transactions you have
201
+ # executed since starting the mongrel.
202
+ # NOTE: There is substantial overhead when running in developer mode.
203
+ # Do not use for production or load testing.
204
+ developer_mode: true
205
+
206
+ # Enable textmate links
207
+ # textmate: true
168
208
 
169
209
  test:
170
210
  <<: *default_settings
171
- # it almost never makes sense to turn on the agent when running
211
+ # It almost never makes sense to turn on the agent when running
172
212
  # unit, functional or integration tests or the like.
173
- enabled: false
213
+ monitor_mode: false
174
214
 
175
215
  # Turn on the agent in production for 24x7 monitoring. NewRelic
176
216
  # testing shows an average performance impact of < 5 ms per
@@ -178,12 +218,12 @@ test:
178
218
  # incurring any user-visible performance degredation.
179
219
  production:
180
220
  <<: *default_settings
181
- enabled: true
221
+ monitor_mode: true
182
222
 
183
- # many applications have a staging environment which behaves
223
+ # Many applications have a staging environment which behaves
184
224
  # identically to production. Support for that environment is provided
185
225
  # here. By default, the staging environment has the agent turned on.
186
226
  staging:
187
227
  <<: *default_settings
188
- enabled: true
228
+ monitor_mode: true
189
229
  app_name: My Application (Staging)
@@ -39,9 +39,9 @@ module ActiveRecordFixtures
39
39
  has_and_belongs_to_many :orders, :class_name => 'ActiveRecordFixtures::Order'
40
40
  def self.setup
41
41
  connection.create_table self.table_name, :force => true do |t|
42
- t.column :order_id, :integer
42
+ # no other columns
43
43
  end
44
- connection.create_table 'orders_shipments', :force => true do |t|
44
+ connection.create_table 'orders_shipments', :force => true, :id => false do |t|
45
45
  t.column :order_id, :integer
46
46
  t.column :shipment_id, :integer
47
47
  end
@@ -8,11 +8,11 @@ test:
8
8
  <<: *default_settings
9
9
  host: localhost
10
10
  port: 3000
11
- log_level: debug
11
+ log_level: info
12
12
  capture_params: true
13
- enabled: false
14
- developer: true
15
- monitor_daemons: false
13
+ agent_enabled: false
14
+ monitor_mode: false
15
+ developer_mode: true
16
16
  disable_samplers: true
17
17
  api_host: 127.0.0.1
18
18
  api_port: 443
@@ -29,9 +29,6 @@ test:
29
29
  yval: yes
30
30
  sval: sure
31
31
 
32
- # checks for loading classes on the background thread
33
- check_bg_loading: true
34
-
35
32
  transaction_tracer:
36
33
  record_sql: raw
37
34
  transaction_threshold: Apdex_f # case insensitive
@@ -1,7 +1,6 @@
1
1
  require 'new_relic/control/rails'
2
- require 'new_relic/agent/agent_test_controller'
3
2
 
4
- class NewRelic::Control::Test < NewRelic::Control::Rails
3
+ class NewRelic::Control::Test < NewRelic::Control::Rails #:nodoc:
5
4
  def env
6
5
  'test'
7
6
  end
@@ -2,23 +2,28 @@ require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper
2
2
  require 'active_record_fixtures'
3
3
 
4
4
  class ActiveRecordInstrumentationTest < Test::Unit::TestCase
5
-
5
+ include NewRelic::Agent::Instrumentation::ControllerInstrumentation
6
6
  def setup
7
+ super
7
8
  NewRelic::Agent.manual_start
8
- NewRelic::Agent.instance.stats_engine.clear_stats
9
9
  ActiveRecordFixtures.setup
10
- NewRelic::Agent.instance.transaction_sampler.harvest
10
+ NewRelic::Agent.instance.transaction_sampler.reset!
11
+ NewRelic::Agent.instance.stats_engine.clear_stats
11
12
  rescue
12
13
  puts e
13
14
  puts e.backtrace.join("\n")
14
15
  end
15
16
 
16
17
  def teardown
18
+ super
17
19
  ActiveRecordFixtures.teardown
20
+ NewRelic::Agent.shutdown
18
21
  end
22
+
19
23
  def test_agent_setup
20
24
  assert NewRelic::Agent.instance.class == NewRelic::Agent::Agent
21
25
  end
26
+
22
27
  def test_finder
23
28
  ActiveRecordFixtures::Order.create :id => 0, :name => 'jeff'
24
29
  ActiveRecordFixtures::Order.find(:all)
@@ -27,6 +32,9 @@ class ActiveRecordInstrumentationTest < Test::Unit::TestCase
27
32
  ActiveRecordFixtures::Order.find_all_by_name "jeff"
28
33
  s = NewRelic::Agent.get_stats("ActiveRecord/ActiveRecordFixtures::Order/find")
29
34
  assert_equal 2, s.call_count
35
+ ActiveRecordFixtures::Order.exists?(["name=?", 'jeff'])
36
+ s = NewRelic::Agent.get_stats("ActiveRecord/ActiveRecordFixtures::Order/find")
37
+ assert_equal 3, s.call_count if NewRelic::Control.instance.rails_version > '2.3.4'
30
38
  end
31
39
 
32
40
  # multiple duplicate find calls should only cause metric trigger on the first
@@ -55,18 +63,18 @@ class ActiveRecordInstrumentationTest < Test::Unit::TestCase
55
63
  # metrics = NewRelic::Agent.instance.stats_engine.metrics.select { |mname| mname =~ /ActiveRecord\/ActiveRecordFixtures::Order\// }.sort
56
64
  expected = %W[
57
65
  ActiveRecord/all
58
- ActiveRecord/create
59
66
  ActiveRecord/find
60
- ActiveRecord/ActiveRecordFixtures::Order/create
61
67
  ActiveRecord/ActiveRecordFixtures::Order/find
62
68
  ]
69
+ expected += %W[Database/SQL/insert] if defined?(JRuby)
70
+ expected += %W[ActiveRecord/create Database/SQL/other ActiveRecord/ActiveRecordFixtures::Order/create] unless defined?(JRuby)
63
71
  expected += %W[ActiveRecord/save ActiveRecord/ActiveRecordFixtures::Order/save] if NewRelic::Control.instance.rails_version < '2.1.0'
64
72
  compare_metrics expected, metrics
65
73
  assert_equal 1, NewRelic::Agent.get_stats("ActiveRecord/ActiveRecordFixtures::Order/find").call_count
66
- assert_equal 1, NewRelic::Agent.get_stats("ActiveRecord/ActiveRecordFixtures::Order/create").call_count
74
+ assert_equal (defined?(JRuby) ? 0 : 1), NewRelic::Agent.get_stats("ActiveRecord/ActiveRecordFixtures::Order/create").call_count
67
75
  end
68
76
  def test_join_metrics
69
- m = ActiveRecordFixtures::Order.create :id => 0, :name => 'jeff'
77
+ m = ActiveRecordFixtures::Order.create :name => 'jeff'
70
78
  m = ActiveRecordFixtures::Order.find(m.id)
71
79
  s = m.shipments.create
72
80
  m.shipments.to_a
@@ -75,57 +83,104 @@ class ActiveRecordInstrumentationTest < Test::Unit::TestCase
75
83
  metrics = NewRelic::Agent.instance.stats_engine.metrics
76
84
  # This doesn't work on hudson because the sampler metrics creep in.
77
85
  # metrics = NewRelic::Agent.instance.stats_engine.metrics.select { |mname| mname =~ /ActiveRecord\/ActiveRecordFixtures::Order\// }.sort
78
- compare_metrics %W[
86
+ expected_metrics = %W[
79
87
  ActiveRecord/all
80
88
  ActiveRecord/destroy
81
89
  ActiveRecord/ActiveRecordFixtures::Order/destroy
82
90
  Database/SQL/insert
83
91
  Database/SQL/delete
84
- ActiveRecord/create
85
92
  ActiveRecord/find
86
- ActiveRecord/ActiveRecordFixtures::Order/create
87
93
  ActiveRecord/ActiveRecordFixtures::Order/find
88
94
  ActiveRecord/ActiveRecordFixtures::Shipment/find
95
+ ]
96
+
97
+ expected_metrics += %W[Database/SQL/other Database/SQL/show ActiveRecord/create
89
98
  ActiveRecord/ActiveRecordFixtures::Shipment/create
90
- ], metrics
99
+ ActiveRecord/ActiveRecordFixtures::Order/create
100
+ ] unless defined? JRuby
101
+
102
+ compare_metrics expected_metrics, metrics
103
+ # This number may be different with different db adapters, not sure
104
+ # assert_equal 17, NewRelic::Agent.get_stats("ActiveRecord/all").call_count
105
+ assert_equal NewRelic::Agent.get_stats("ActiveRecord/all").total_exclusive_time, NewRelic::Agent.get_stats("ActiveRecord/all").total_call_time unless defined?(RUBY_DESCRIPTION) && RUBY_DESCRIPTION =~ /Enterprise Edition/
91
106
  assert_equal 1, NewRelic::Agent.get_stats("ActiveRecord/ActiveRecordFixtures::Order/find").call_count
92
107
  assert_equal 1, NewRelic::Agent.get_stats("ActiveRecord/ActiveRecordFixtures::Shipment/find").call_count
93
- assert_equal 1, NewRelic::Agent.get_stats("Database/SQL/insert").call_count
108
+ assert_equal 1, NewRelic::Agent.get_stats("Database/SQL/insert").call_count unless defined? JRuby
109
+ assert_equal 3, NewRelic::Agent.get_stats("Database/SQL/insert").call_count if defined? JRuby
94
110
  assert_equal 1, NewRelic::Agent.get_stats("Database/SQL/delete").call_count
95
111
  end
96
112
  def test_direct_sql
97
- list = ActiveRecordFixtures::Order.connection.select_rows "select * from #{ActiveRecordFixtures::Order.table_name}"
113
+ assert_nil NewRelic::Agent::Instrumentation::MetricFrame.current
114
+ assert_equal nil, NewRelic::Agent.instance.stats_engine.scope_name
115
+ assert_equal 0, NewRelic::Agent.instance.stats_engine.metrics.size, NewRelic::Agent.instance.stats_engine.metrics.inspect
116
+ ActiveRecordFixtures::Order.connection.select_rows "select * from #{ActiveRecordFixtures::Order.table_name}"
98
117
  metrics = NewRelic::Agent.instance.stats_engine.metrics
99
118
  compare_metrics %W[
100
119
  ActiveRecord/all
101
120
  Database/SQL/select
102
121
  ], metrics
103
- assert_equal 1, NewRelic::Agent.get_stats("Database/SQL/select").call_count
122
+ assert_equal 1, NewRelic::Agent.instance.stats_engine.get_stats_no_scope("Database/SQL/select").call_count, NewRelic::Agent.instance.stats_engine.get_stats_no_scope("Database/SQL/select")
104
123
  end
105
124
 
106
- def test_run_explains
125
+ def test_other_sql
126
+ list = ActiveRecordFixtures::Order.connection.execute "begin"
127
+ metrics = NewRelic::Agent.instance.stats_engine.metrics
128
+ compare_metrics %W[
129
+ ActiveRecord/all
130
+ Database/SQL/other
131
+ ], metrics
132
+ assert_equal 1, NewRelic::Agent.get_stats_no_scope("Database/SQL/other").call_count
133
+ end
134
+
135
+ def test_show_sql
136
+ list = ActiveRecordFixtures::Order.connection.execute "show tables"
137
+ metrics = NewRelic::Agent.instance.stats_engine.metrics
138
+ compare_metrics %W[
139
+ ActiveRecord/all
140
+ Database/SQL/show
141
+ ], metrics
142
+ assert_equal 1, NewRelic::Agent.get_stats_no_scope("Database/SQL/show").call_count
143
+ end
144
+
145
+ def test_blocked_instrumentation
107
146
  ActiveRecordFixtures::Order.add_delay
108
- ActiveRecordFixtures::Order.find(:all)
109
-
147
+ NewRelic::Agent.disable_all_tracing do
148
+ perform_action_with_newrelic_trace :name => 'bogosity' do
149
+ ActiveRecordFixtures::Order.find(:all)
150
+ end
151
+ end
152
+ assert_nil NewRelic::Agent.instance.transaction_sampler.last_sample
153
+ metrics = NewRelic::Agent.instance.stats_engine.metrics
154
+ compare_metrics [], metrics
155
+ end
156
+ def test_run_explains
157
+ perform_action_with_newrelic_trace :name => 'bogosity' do
158
+ ActiveRecordFixtures::Order.add_delay
159
+ ActiveRecordFixtures::Order.find(:all)
160
+ end
110
161
  sample = NewRelic::Agent.instance.transaction_sampler.last_sample
111
162
 
112
- segment = sample.root_segment.called_segments.first.called_segments.first
163
+ segment = sample.root_segment.called_segments.first.called_segments.first.called_segments.first
113
164
  assert_match /^SELECT \* FROM ["`]?#{ActiveRecordFixtures::Order.table_name}["`]?$/i, segment.params[:sql].strip
114
165
  NewRelic::TransactionSample::Segment.any_instance.expects(:explain_sql).returns([])
115
166
  sample = sample.prepare_to_send(:obfuscate_sql => true, :explain_enabled => true, :explain_sql => 0.0)
116
167
  segment = sample.root_segment.called_segments.first.called_segments.first
117
168
  end
118
169
  def test_prepare_to_send
119
- ActiveRecordFixtures::Order.add_delay
120
- ActiveRecordFixtures::Order.find(:all)
121
-
170
+ perform_action_with_newrelic_trace :name => 'bogosity' do
171
+ ActiveRecordFixtures::Order.add_delay
172
+ ActiveRecordFixtures::Order.find(:all)
173
+ end
122
174
  sample = NewRelic::Agent.instance.transaction_sampler.last_sample
175
+ assert_not_nil sample
176
+ assert_equal 3, sample.count_segments, sample.to_s
123
177
  #
124
- sql_segment = sample.root_segment.called_segments.first.called_segments.first
178
+ sql_segment = sample.root_segment.called_segments.first.called_segments.first.called_segments.first rescue nil
179
+ assert_not_nil sql_segment, sample.to_s
125
180
  assert_match /^SELECT /, sql_segment.params[:sql]
126
181
  assert sql_segment.duration > 0.0, "Segment duration must be greater than zero."
127
182
  sample = sample.prepare_to_send(:record_sql => :raw, :explain_enabled => true, :explain_sql => 0.0)
128
- sql_segment = sample.root_segment.called_segments.first.called_segments.first
183
+ sql_segment = sample.root_segment.called_segments.first.called_segments.first.called_segments.first
129
184
  assert_match /^SELECT /, sql_segment.params[:sql]
130
185
  explanations = sql_segment.params[:explanation]
131
186
  if isMysql? || isPostgres?
@@ -135,13 +190,16 @@ class ActiveRecordInstrumentationTest < Test::Unit::TestCase
135
190
  end
136
191
  end
137
192
  def test_transaction
138
- ActiveRecordFixtures::Order.add_delay
139
- ActiveRecordFixtures::Order.find(:all)
193
+ sample = NewRelic::Agent.instance.transaction_sampler.reset!
194
+ perform_action_with_newrelic_trace :name => 'bogosity' do
195
+ ActiveRecordFixtures::Order.add_delay
196
+ ActiveRecordFixtures::Order.find(:all)
197
+ end
140
198
 
141
199
  sample = NewRelic::Agent.instance.transaction_sampler.last_sample
142
200
 
143
201
  sample = sample.prepare_to_send(:obfuscate_sql => true, :explain_enabled => true, :explain_sql => 0.0)
144
- segment = sample.root_segment.called_segments.first.called_segments.first
202
+ segment = sample.root_segment.called_segments.first.called_segments.first.called_segments.first
145
203
  assert_nil segment.params[:sql], "SQL should have been removed."
146
204
  explanations = segment.params[:explanation]
147
205
  if isMysql? || isPostgres?
@@ -177,12 +235,38 @@ class ActiveRecordInstrumentationTest < Test::Unit::TestCase
177
235
  end
178
236
  end
179
237
 
180
- private
181
- def compare_metrics expected_list, actual_list
182
- actual = Set.new actual_list
183
- expected = Set.new expected_list
184
- assert_equal expected, actual, "extra: #{(actual - expected).to_a.join(", ")}; missing: #{(expected - actual).to_a.join(", ")}"
238
+ # This is to make sure the all metric is recorded for exceptional cases
239
+ def test_error_handling
240
+ # have the AR select throw an error
241
+ ActiveRecordFixtures::Order.connection.stubs(:log_info).with do | sql, x, y |
242
+ raise "Error" if sql =~ /select/
243
+ true
244
+ end
245
+ ActiveRecordFixtures::Order.connection.select_rows "select * from #{ActiveRecordFixtures::Order.table_name}" rescue nil
246
+ metrics = NewRelic::Agent.instance.stats_engine.metrics
247
+ compare_metrics %W[
248
+ ActiveRecord/all
249
+ Database/SQL/select
250
+ ], metrics
251
+ assert_equal 1, NewRelic::Agent.get_stats("Database/SQL/select").call_count
252
+ assert_equal 1, NewRelic::Agent.get_stats("ActiveRecord/all").call_count
185
253
  end
254
+
255
+ def test_rescue_handling
256
+ begin
257
+ ActiveRecordFixtures::Order.transaction do
258
+ raise ActiveRecord::ActiveRecordError.new('preserve-me!')
259
+ end
260
+ rescue ActiveRecord::ActiveRecordError => e
261
+ assert_equal 'preserve-me!', e.message
262
+ rescue
263
+ fail "Rescue2: Got something COMPLETELY unexpected: $!:#{$!.inspect}"
264
+ end
265
+
266
+ end
267
+
268
+ private
269
+
186
270
  def isPostgres?
187
271
  ActiveRecordFixtures::Order.configurations[RAILS_ENV]['adapter'] =~ /postgres/
188
272
  end