dolores_rpm 3.2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. data/CHANGELOG +559 -0
  2. data/LICENSE +64 -0
  3. data/README.rdoc +179 -0
  4. data/bin/mongrel_rpm +33 -0
  5. data/bin/newrelic +13 -0
  6. data/bin/newrelic_cmd +5 -0
  7. data/cert/cacert.pem +118 -0
  8. data/cert/oldsite.pem +28 -0
  9. data/cert/site.pem +27 -0
  10. data/dolores_rpm-3.3.4.fork.gem +0 -0
  11. data/install.rb +9 -0
  12. data/lib/conditional_vendored_dependency_detection.rb +3 -0
  13. data/lib/conditional_vendored_metric_parser.rb +5 -0
  14. data/lib/new_relic/agent/agent.rb +1311 -0
  15. data/lib/new_relic/agent/beacon_configuration.rb +110 -0
  16. data/lib/new_relic/agent/browser_monitoring.rb +102 -0
  17. data/lib/new_relic/agent/busy_calculator.rb +99 -0
  18. data/lib/new_relic/agent/chained_call.rb +13 -0
  19. data/lib/new_relic/agent/database.rb +203 -0
  20. data/lib/new_relic/agent/error_collector.rb +251 -0
  21. data/lib/new_relic/agent/instrumentation/active_merchant.rb +27 -0
  22. data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +68 -0
  23. data/lib/new_relic/agent/instrumentation/authlogic.rb +19 -0
  24. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +424 -0
  25. data/lib/new_relic/agent/instrumentation/data_mapper.rb +57 -0
  26. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +52 -0
  27. data/lib/new_relic/agent/instrumentation/memcache.rb +80 -0
  28. data/lib/new_relic/agent/instrumentation/merb/controller.rb +41 -0
  29. data/lib/new_relic/agent/instrumentation/merb/errors.rb +29 -0
  30. data/lib/new_relic/agent/instrumentation/metric_frame/pop.rb +80 -0
  31. data/lib/new_relic/agent/instrumentation/metric_frame.rb +332 -0
  32. data/lib/new_relic/agent/instrumentation/net.rb +29 -0
  33. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +36 -0
  34. data/lib/new_relic/agent/instrumentation/queue_time.rb +210 -0
  35. data/lib/new_relic/agent/instrumentation/rack.rb +98 -0
  36. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +114 -0
  37. data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +42 -0
  38. data/lib/new_relic/agent/instrumentation/rails/active_record_instrumentation.rb +115 -0
  39. data/lib/new_relic/agent/instrumentation/rails/errors.rb +42 -0
  40. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +118 -0
  41. data/lib/new_relic/agent/instrumentation/rails3/active_record_instrumentation.rb +122 -0
  42. data/lib/new_relic/agent/instrumentation/rails3/errors.rb +37 -0
  43. data/lib/new_relic/agent/instrumentation/sinatra.rb +58 -0
  44. data/lib/new_relic/agent/instrumentation/sunspot.rb +29 -0
  45. data/lib/new_relic/agent/instrumentation/unicorn_instrumentation.rb +21 -0
  46. data/lib/new_relic/agent/instrumentation.rb +9 -0
  47. data/lib/new_relic/agent/method_tracer.rb +528 -0
  48. data/lib/new_relic/agent/sampler.rb +50 -0
  49. data/lib/new_relic/agent/samplers/cpu_sampler.rb +58 -0
  50. data/lib/new_relic/agent/samplers/delayed_job_lock_sampler.rb +40 -0
  51. data/lib/new_relic/agent/samplers/memory_sampler.rb +144 -0
  52. data/lib/new_relic/agent/samplers/object_sampler.rb +26 -0
  53. data/lib/new_relic/agent/shim_agent.rb +29 -0
  54. data/lib/new_relic/agent/sql_sampler.rb +267 -0
  55. data/lib/new_relic/agent/stats_engine/metric_stats.rb +187 -0
  56. data/lib/new_relic/agent/stats_engine/samplers.rb +95 -0
  57. data/lib/new_relic/agent/stats_engine/transactions.rb +208 -0
  58. data/lib/new_relic/agent/stats_engine.rb +25 -0
  59. data/lib/new_relic/agent/transaction_sample_builder.rb +101 -0
  60. data/lib/new_relic/agent/transaction_sampler.rb +397 -0
  61. data/lib/new_relic/agent/worker_loop.rb +89 -0
  62. data/lib/new_relic/agent.rb +454 -0
  63. data/lib/new_relic/collection_helper.rb +75 -0
  64. data/lib/new_relic/command.rb +85 -0
  65. data/lib/new_relic/commands/deployments.rb +105 -0
  66. data/lib/new_relic/commands/install.rb +80 -0
  67. data/lib/new_relic/control/class_methods.rb +53 -0
  68. data/lib/new_relic/control/configuration.rb +202 -0
  69. data/lib/new_relic/control/frameworks/external.rb +16 -0
  70. data/lib/new_relic/control/frameworks/merb.rb +31 -0
  71. data/lib/new_relic/control/frameworks/rails.rb +164 -0
  72. data/lib/new_relic/control/frameworks/rails3.rb +75 -0
  73. data/lib/new_relic/control/frameworks/ruby.rb +42 -0
  74. data/lib/new_relic/control/frameworks/sinatra.rb +20 -0
  75. data/lib/new_relic/control/frameworks.rb +10 -0
  76. data/lib/new_relic/control/instance_methods.rb +179 -0
  77. data/lib/new_relic/control/instrumentation.rb +100 -0
  78. data/lib/new_relic/control/logging_methods.rb +143 -0
  79. data/lib/new_relic/control/profiling.rb +25 -0
  80. data/lib/new_relic/control/server_methods.rb +114 -0
  81. data/lib/new_relic/control.rb +46 -0
  82. data/lib/new_relic/data_serialization.rb +157 -0
  83. data/lib/new_relic/delayed_job_injection.rb +46 -0
  84. data/lib/new_relic/language_support.rb +69 -0
  85. data/lib/new_relic/local_environment.rb +414 -0
  86. data/lib/new_relic/merbtasks.rb +6 -0
  87. data/lib/new_relic/metric_data.rb +51 -0
  88. data/lib/new_relic/metric_spec.rb +75 -0
  89. data/lib/new_relic/metrics.rb +9 -0
  90. data/lib/new_relic/noticed_error.rb +24 -0
  91. data/lib/new_relic/rack/browser_monitoring.rb +68 -0
  92. data/lib/new_relic/rack/developer_mode.rb +268 -0
  93. data/lib/new_relic/recipes.rb +73 -0
  94. data/lib/new_relic/stats.rb +388 -0
  95. data/lib/new_relic/timer_lib.rb +27 -0
  96. data/lib/new_relic/transaction_analysis/segment_summary.rb +49 -0
  97. data/lib/new_relic/transaction_analysis.rb +77 -0
  98. data/lib/new_relic/transaction_sample/composite_segment.rb +27 -0
  99. data/lib/new_relic/transaction_sample/fake_segment.rb +9 -0
  100. data/lib/new_relic/transaction_sample/segment.rb +201 -0
  101. data/lib/new_relic/transaction_sample/summary_segment.rb +21 -0
  102. data/lib/new_relic/transaction_sample.rb +245 -0
  103. data/lib/new_relic/url_rule.rb +14 -0
  104. data/lib/new_relic/version.rb +55 -0
  105. data/lib/newrelic_rpm.rb +49 -0
  106. data/lib/tasks/all.rb +4 -0
  107. data/lib/tasks/install.rake +7 -0
  108. data/lib/tasks/tests.rake +19 -0
  109. data/newrelic.yml +265 -0
  110. data/recipes/newrelic.rb +6 -0
  111. data/test/active_record_fixtures.rb +77 -0
  112. data/test/config/newrelic.yml +48 -0
  113. data/test/config/test_control.rb +48 -0
  114. data/test/new_relic/agent/agent/connect_test.rb +410 -0
  115. data/test/new_relic/agent/agent/start_test.rb +255 -0
  116. data/test/new_relic/agent/agent/start_worker_thread_test.rb +153 -0
  117. data/test/new_relic/agent/agent_test.rb +139 -0
  118. data/test/new_relic/agent/agent_test_controller.rb +77 -0
  119. data/test/new_relic/agent/agent_test_controller_test.rb +363 -0
  120. data/test/new_relic/agent/apdex_from_server_test.rb +9 -0
  121. data/test/new_relic/agent/beacon_configuration_test.rb +108 -0
  122. data/test/new_relic/agent/browser_monitoring_test.rb +278 -0
  123. data/test/new_relic/agent/busy_calculator_test.rb +81 -0
  124. data/test/new_relic/agent/database_test.rb +162 -0
  125. data/test/new_relic/agent/error_collector/notice_error_test.rb +257 -0
  126. data/test/new_relic/agent/error_collector_test.rb +175 -0
  127. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +538 -0
  128. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +36 -0
  129. data/test/new_relic/agent/instrumentation/instrumentation_test.rb +11 -0
  130. data/test/new_relic/agent/instrumentation/metric_frame/pop_test.rb +172 -0
  131. data/test/new_relic/agent/instrumentation/metric_frame_test.rb +50 -0
  132. data/test/new_relic/agent/instrumentation/net_instrumentation_test.rb +84 -0
  133. data/test/new_relic/agent/instrumentation/queue_time_test.rb +387 -0
  134. data/test/new_relic/agent/instrumentation/rack_test.rb +35 -0
  135. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +184 -0
  136. data/test/new_relic/agent/memcache_instrumentation_test.rb +143 -0
  137. data/test/new_relic/agent/method_tracer/class_methods/add_method_tracer_test.rb +164 -0
  138. data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +234 -0
  139. data/test/new_relic/agent/method_tracer_test.rb +386 -0
  140. data/test/new_relic/agent/mock_scope_listener.rb +23 -0
  141. data/test/new_relic/agent/rpm_agent_test.rb +149 -0
  142. data/test/new_relic/agent/sampler_test.rb +19 -0
  143. data/test/new_relic/agent/shim_agent_test.rb +20 -0
  144. data/test/new_relic/agent/sql_sampler_test.rb +160 -0
  145. data/test/new_relic/agent/stats_engine/metric_stats/harvest_test.rb +150 -0
  146. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +82 -0
  147. data/test/new_relic/agent/stats_engine/samplers_test.rb +99 -0
  148. data/test/new_relic/agent/stats_engine_test.rb +185 -0
  149. data/test/new_relic/agent/transaction_sample_builder_test.rb +195 -0
  150. data/test/new_relic/agent/transaction_sampler_test.rb +955 -0
  151. data/test/new_relic/agent/worker_loop_test.rb +66 -0
  152. data/test/new_relic/agent_test.rb +175 -0
  153. data/test/new_relic/collection_helper_test.rb +149 -0
  154. data/test/new_relic/command/deployments_test.rb +68 -0
  155. data/test/new_relic/control/class_methods_test.rb +62 -0
  156. data/test/new_relic/control/configuration_test.rb +72 -0
  157. data/test/new_relic/control/logging_methods_test.rb +185 -0
  158. data/test/new_relic/control_test.rb +254 -0
  159. data/test/new_relic/data_serialization_test.rb +208 -0
  160. data/test/new_relic/delayed_job_injection_test.rb +16 -0
  161. data/test/new_relic/local_environment_test.rb +72 -0
  162. data/test/new_relic/metric_data_test.rb +125 -0
  163. data/test/new_relic/metric_spec_test.rb +95 -0
  164. data/test/new_relic/rack/all_test.rb +11 -0
  165. data/test/new_relic/rack/browser_monitoring_test.rb +84 -0
  166. data/test/new_relic/rack/developer_mode_helper_test.rb +141 -0
  167. data/test/new_relic/rack/developer_mode_test.rb +43 -0
  168. data/test/new_relic/stats_test.rb +426 -0
  169. data/test/new_relic/transaction_analysis/segment_summary_test.rb +91 -0
  170. data/test/new_relic/transaction_analysis_test.rb +121 -0
  171. data/test/new_relic/transaction_sample/composite_segment_test.rb +35 -0
  172. data/test/new_relic/transaction_sample/fake_segment_test.rb +17 -0
  173. data/test/new_relic/transaction_sample/segment_test.rb +389 -0
  174. data/test/new_relic/transaction_sample/summary_segment_test.rb +31 -0
  175. data/test/new_relic/transaction_sample_subtest_test.rb +56 -0
  176. data/test/new_relic/transaction_sample_test.rb +164 -0
  177. data/test/new_relic/version_number_test.rb +89 -0
  178. data/test/test_contexts.rb +29 -0
  179. data/test/test_helper.rb +154 -0
  180. data/ui/helpers/developer_mode_helper.rb +357 -0
  181. data/ui/helpers/google_pie_chart.rb +48 -0
  182. data/ui/views/layouts/newrelic_default.rhtml +47 -0
  183. data/ui/views/newrelic/_explain_plans.rhtml +27 -0
  184. data/ui/views/newrelic/_sample.rhtml +20 -0
  185. data/ui/views/newrelic/_segment.rhtml +28 -0
  186. data/ui/views/newrelic/_segment_limit_message.rhtml +1 -0
  187. data/ui/views/newrelic/_segment_row.rhtml +12 -0
  188. data/ui/views/newrelic/_show_sample_detail.rhtml +24 -0
  189. data/ui/views/newrelic/_show_sample_sql.rhtml +24 -0
  190. data/ui/views/newrelic/_show_sample_summary.rhtml +3 -0
  191. data/ui/views/newrelic/_sql_row.rhtml +16 -0
  192. data/ui/views/newrelic/_stack_trace.rhtml +15 -0
  193. data/ui/views/newrelic/_table.rhtml +12 -0
  194. data/ui/views/newrelic/explain_sql.rhtml +43 -0
  195. data/ui/views/newrelic/file/images/arrow-close.png +0 -0
  196. data/ui/views/newrelic/file/images/arrow-open.png +0 -0
  197. data/ui/views/newrelic/file/images/blue_bar.gif +0 -0
  198. data/ui/views/newrelic/file/images/file_icon.png +0 -0
  199. data/ui/views/newrelic/file/images/gray_bar.gif +0 -0
  200. data/ui/views/newrelic/file/images/new-relic-rpm-desktop.gif +0 -0
  201. data/ui/views/newrelic/file/images/new_relic_rpm_desktop.gif +0 -0
  202. data/ui/views/newrelic/file/images/textmate.png +0 -0
  203. data/ui/views/newrelic/file/javascript/jquery-1.4.2.js +6240 -0
  204. data/ui/views/newrelic/file/javascript/transaction_sample.js +120 -0
  205. data/ui/views/newrelic/file/stylesheets/style.css +490 -0
  206. data/ui/views/newrelic/index.rhtml +71 -0
  207. data/ui/views/newrelic/sample_not_found.rhtml +2 -0
  208. data/ui/views/newrelic/show_sample.rhtml +80 -0
  209. data/ui/views/newrelic/show_source.rhtml +3 -0
  210. data/ui/views/newrelic/threads.rhtml +53 -0
  211. data/vendor/gems/dependency_detection-0.0.1.build/LICENSE +5 -0
  212. data/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection/version.rb +3 -0
  213. data/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection.rb +62 -0
  214. data/vendor/gems/metric_parser-0.1.0.pre1/lib/metric_parser.rb +1 -0
  215. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/action_mailer.rb +14 -0
  216. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/active_merchant.rb +31 -0
  217. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/active_record.rb +33 -0
  218. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/apdex.rb +89 -0
  219. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/background_transaction.rb +7 -0
  220. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/client.rb +46 -0
  221. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller.rb +67 -0
  222. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller_cpu.rb +43 -0
  223. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller_ext.rb +17 -0
  224. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/database.rb +48 -0
  225. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/database_pool.rb +24 -0
  226. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/dot_net.rb +28 -0
  227. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/dot_net_parser.rb +17 -0
  228. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/errors.rb +11 -0
  229. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/external.rb +55 -0
  230. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/frontend.rb +40 -0
  231. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/gc.rb +20 -0
  232. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/hibernate_session.rb +7 -0
  233. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/java.rb +31 -0
  234. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/java_parser.rb +17 -0
  235. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/jsp.rb +34 -0
  236. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/jsp_tag.rb +7 -0
  237. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/mem_cache.rb +55 -0
  238. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/metric_parser.rb +122 -0
  239. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/orm.rb +27 -0
  240. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/other_transaction.rb +40 -0
  241. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet.rb +7 -0
  242. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet_context_listener.rb +7 -0
  243. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet_filter.rb +7 -0
  244. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/solr.rb +27 -0
  245. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/solr_request_handler.rb +15 -0
  246. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/spring.rb +54 -0
  247. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/spring_controller.rb +6 -0
  248. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/spring_view.rb +6 -0
  249. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/struts_action.rb +20 -0
  250. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/struts_result.rb +20 -0
  251. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/version.rb +5 -0
  252. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/view.rb +70 -0
  253. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/web_frontend.rb +18 -0
  254. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/web_service.rb +14 -0
  255. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/web_transaction.rb +133 -0
  256. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser.rb +64 -0
  257. metadata +398 -0
@@ -0,0 +1,424 @@
1
+ require 'new_relic/agent/instrumentation/metric_frame'
2
+ require 'new_relic/agent/instrumentation/queue_time'
3
+ module NewRelic
4
+ module Agent
5
+ module Instrumentation
6
+ # == NewRelic instrumentation for controller actions and tasks
7
+ #
8
+ # This instrumentation is applied to the action controller to collect
9
+ # metrics for every web request.
10
+ #
11
+ # It can also be used to capture performance information for
12
+ # background tasks and other non-web transactions, including
13
+ # detailed transaction traces and traced errors.
14
+ #
15
+ # For details on how to instrument background tasks see
16
+ # ClassMethods#add_transaction_tracer and
17
+ # #perform_action_with_newrelic_trace
18
+ #
19
+ module ControllerInstrumentation
20
+
21
+ def self.included(clazz) # :nodoc:
22
+ clazz.extend(ClassMethods)
23
+ end
24
+
25
+ # This module is for importing stubs when the agent is disabled
26
+ module ClassMethodsShim # :nodoc:
27
+ def newrelic_ignore(*args); end
28
+ def newrelic_ignore_apdex(*args); end
29
+ end
30
+
31
+ module Shim # :nodoc:
32
+ def self.included(clazz)
33
+ clazz.extend(ClassMethodsShim)
34
+ end
35
+ def newrelic_notice_error(*args); end
36
+ def new_relic_trace_controller_action(*args); yield; end
37
+ def newrelic_metric_path; end
38
+ def perform_action_with_newrelic_trace(*args); yield; end
39
+ end
40
+
41
+ module ClassMethods
42
+ # Have NewRelic ignore actions in this controller. Specify the actions as hash options
43
+ # using :except and :only. If no actions are specified, all actions are ignored.
44
+ def newrelic_ignore(specifiers={})
45
+ newrelic_ignore_aspect('do_not_trace', specifiers)
46
+ end
47
+ # Have NewRelic omit apdex measurements on the given actions. Typically used for
48
+ # actions that are not user facing or that skew your overall apdex measurement.
49
+ # Accepts :except and :only options, as with #newrelic_ignore.
50
+ def newrelic_ignore_apdex(specifiers={})
51
+ newrelic_ignore_aspect('ignore_apdex', specifiers)
52
+ end
53
+
54
+ def newrelic_ignore_aspect(property, specifiers={}) # :nodoc:
55
+ if specifiers.empty?
56
+ self.newrelic_write_attr property, true
57
+ elsif ! (Hash === specifiers)
58
+ logger.error "newrelic_#{property} takes an optional hash with :only and :except lists of actions (illegal argument type '#{specifiers.class}')"
59
+ else
60
+ self.newrelic_write_attr property, specifiers
61
+ end
62
+ end
63
+
64
+ # Should be monkey patched into the controller class implemented
65
+ # with the inheritable attribute mechanism.
66
+ def newrelic_write_attr(attr_name, value) # :nodoc:
67
+ instance_variable_set "@#{attr_name}", value
68
+ end
69
+ def newrelic_read_attr(attr_name) # :nodoc:
70
+ instance_variable_get "@#{attr_name}"
71
+ end
72
+
73
+ # Add transaction tracing to the given method. This will treat
74
+ # the given method as a main entrypoint for instrumentation, just
75
+ # like controller actions are treated by default. Useful especially
76
+ # for background tasks.
77
+ #
78
+ # Example for background job:
79
+ # class Job
80
+ # include NewRelic::Agent::Instrumentation::ControllerInstrumentation
81
+ # def run(task)
82
+ # ...
83
+ # end
84
+ # # Instrument run so tasks show up under task.name. Note single
85
+ # # quoting to defer eval to runtime.
86
+ # add_transaction_tracer :run, :name => '#{args[0].name}'
87
+ # end
88
+ #
89
+ # Here's an example of a controller that uses a dispatcher
90
+ # action to invoke operations which you want treated as top
91
+ # level actions, so they aren't all lumped into the invoker
92
+ # action.
93
+ #
94
+ # MyController < ActionController::Base
95
+ # include NewRelic::Agent::Instrumentation::ControllerInstrumentation
96
+ # # dispatch the given op to the method given by the service parameter.
97
+ # def invoke_operation
98
+ # op = params['operation']
99
+ # send op
100
+ # end
101
+ # # Ignore the invoker to avoid double counting
102
+ # newrelic_ignore :only => 'invoke_operation'
103
+ # # Instrument the operations:
104
+ # add_transaction_tracer :print
105
+ # add_transaction_tracer :show
106
+ # add_transaction_tracer :forward
107
+ # end
108
+ #
109
+ # Here's an example of how to pass contextual information into the transaction
110
+ # so it will appear in transaction traces:
111
+ #
112
+ # class Job
113
+ # include NewRelic::Agent::Instrumentation::ControllerInstrumentation
114
+ # def process(account)
115
+ # ...
116
+ # end
117
+ # # Include the account name in the transaction details. Note the single
118
+ # # quotes to defer eval until call time.
119
+ # add_transaction_tracer :process, :params => '{ :account_name => args[0].name }'
120
+ # end
121
+ #
122
+ # See NewRelic::Agent::Instrumentation::ControllerInstrumentation#perform_action_with_newrelic_trace
123
+ # for the full list of available options.
124
+ #
125
+ def add_transaction_tracer(method, options={})
126
+ # The metric path:
127
+ options[:name] ||= method.to_s
128
+ # create the argument list:
129
+ options_arg = []
130
+ options.each do |key, value|
131
+ valuestr = case
132
+ when value.is_a?(Symbol)
133
+ value.inspect
134
+ when key == :params
135
+ value.to_s
136
+ else
137
+ %Q["#{value.to_s}"]
138
+ end
139
+ options_arg << %Q[:#{key} => #{valuestr}]
140
+ end
141
+ class_eval <<-EOC
142
+ def #{method.to_s}_with_newrelic_transaction_trace(*args, &block)
143
+ perform_action_with_newrelic_trace(#{options_arg.join(',')}) do
144
+ #{method.to_s}_without_newrelic_transaction_trace(*args, &block)
145
+ end
146
+ end
147
+ EOC
148
+ alias_method "#{method.to_s}_without_newrelic_transaction_trace", method.to_s
149
+ alias_method method.to_s, "#{method.to_s}_with_newrelic_transaction_trace"
150
+ NewRelic::Control.instance.log.debug("Traced transaction: class = #{self.name}, method = #{method.to_s}, options = #{options.inspect}")
151
+ end
152
+ end
153
+
154
+ # Must be implemented in the controller class:
155
+ # Determine the path that is used in the metric name for
156
+ # the called controller action. Of the form controller_path/action_name
157
+ #
158
+ def newrelic_metric_path(action_name_override = nil) # :nodoc:
159
+ raise "Not implemented!"
160
+ end
161
+
162
+ # Yield to the given block with NewRelic tracing. Used by
163
+ # default instrumentation on controller actions in Rails and Merb.
164
+ # But it can also be used in custom instrumentation of controller
165
+ # methods and background tasks.
166
+ #
167
+ # This is the method invoked by instrumentation added by the
168
+ # <tt>ClassMethods#add_transaction_tracer</tt>.
169
+ #
170
+ # Here's a more verbose version of the example shown in
171
+ # <tt>ClassMethods#add_transaction_tracer</tt> using this method instead of
172
+ # #add_transaction_tracer.
173
+ #
174
+ # Below is a controller with an +invoke_operation+ action which
175
+ # dispatches to more specific operation methods based on a
176
+ # parameter (very dangerous, btw!). With this instrumentation,
177
+ # the +invoke_operation+ action is ignored but the operation
178
+ # methods show up in New Relic as if they were first class controller
179
+ # actions
180
+ #
181
+ # MyController < ActionController::Base
182
+ # include NewRelic::Agent::Instrumentation::ControllerInstrumentation
183
+ # # dispatch the given op to the method given by the service parameter.
184
+ # def invoke_operation
185
+ # op = params['operation']
186
+ # perform_action_with_newrelic_trace(:name => op) do
187
+ # send op, params['message']
188
+ # end
189
+ # end
190
+ # # Ignore the invoker to avoid double counting
191
+ # newrelic_ignore :only => 'invoke_operation'
192
+ # end
193
+ #
194
+ #
195
+ # When invoking this method explicitly as in the example above, pass in a
196
+ # block to measure with some combination of options:
197
+ #
198
+ # * <tt>:category => :controller</tt> indicates that this is a
199
+ # controller action and will appear with all the other actions. This
200
+ # is the default.
201
+ # * <tt>:category => :task</tt> indicates that this is a
202
+ # background task and will show up in New Relic with other background
203
+ # tasks instead of in the controllers list
204
+ # * <tt>:category => :rack</tt> if you are instrumenting a rack
205
+ # middleware call. The <tt>:name</tt> is optional, useful if you
206
+ # have more than one potential transaction in the #call.
207
+ # * <tt>:category => :uri</tt> indicates that this is a
208
+ # web transaction whose name is a normalized URI, where 'normalized'
209
+ # means the URI does not have any elements with data in them such
210
+ # as in many REST URIs.
211
+ # * <tt>:name => action_name</tt> is used to specify the action
212
+ # name used as part of the metric name
213
+ # * <tt>:params => {...}</tt> to provide information about the context
214
+ # of the call, used in transaction trace display, for example:
215
+ # <tt>:params => { :account => @account.name, :file => file.name }</tt>
216
+ # These are treated similarly to request parameters in web transactions.
217
+ #
218
+ # Seldomly used options:
219
+ #
220
+ # * <tt>:force => true</tt> indicates you should capture all
221
+ # metrics even if the #newrelic_ignore directive was specified
222
+ # * <tt>:class_name => aClass.name</tt> is used to override the name
223
+ # of the class when used inside the metric name. Default is the
224
+ # current class.
225
+ # * <tt>:path => metric_path</tt> is *deprecated* in the public API. It
226
+ # allows you to set the entire metric after the category part. Overrides
227
+ # all the other options.
228
+ # * <tt>:request => Rack::Request#new(env)</tt> is used to pass in a
229
+ # request object that may respond to uri and referer.
230
+ #
231
+ # If a single argument is passed in, it is treated as a metric
232
+ # path. This form is deprecated.
233
+ def perform_action_with_newrelic_trace(*args, &block)
234
+
235
+ # Skip instrumentation based on the value of 'do_not_trace' and if
236
+ # we aren't calling directly with a block.
237
+ if !block_given? && do_not_trace?
238
+ # Also ignore all instrumentation in the call sequence
239
+ NewRelic::Agent.disable_all_tracing do
240
+ return perform_action_without_newrelic_trace(*args)
241
+ end
242
+ end
243
+
244
+ return perform_action_with_newrelic_profile(args, &block) if NewRelic::Control.instance.profiling?
245
+
246
+ frame_data = _push_metric_frame(block_given? ? args : [])
247
+ begin
248
+ NewRelic::Agent.trace_execution_scoped frame_data.recorded_metrics, :force => frame_data.force_flag do
249
+ frame_data.start_transaction
250
+ begin
251
+ NewRelic::Agent::BusyCalculator.dispatcher_start frame_data.start
252
+ if block_given?
253
+ yield
254
+ else
255
+ perform_action_without_newrelic_trace(*args)
256
+ end
257
+ rescue Exception => e
258
+ frame_data.notice_error(e)
259
+ raise
260
+ end
261
+ end
262
+ ensure
263
+ NewRelic::Agent::BusyCalculator.dispatcher_finish
264
+ # Look for a metric frame in the thread local and process it.
265
+ # Clear the thread local when finished to ensure it only gets called once.
266
+ frame_data.record_apdex unless ignore_apdex?
267
+
268
+ frame_data.pop
269
+ end
270
+ end
271
+
272
+ protected
273
+ # Should be implemented in the dispatcher class
274
+ def newrelic_response_code; end
275
+
276
+ def newrelic_request_headers
277
+ self.respond_to?(:request) && self.request.respond_to?(:headers) && self.request.headers
278
+ end
279
+
280
+ # overrideable method to determine whether to trace an action
281
+ # or not - you may override this in your controller and supply
282
+ # your own logic for ignoring transactions.
283
+ def do_not_trace?
284
+ _is_filtered?('do_not_trace')
285
+ end
286
+
287
+ # overrideable method to determine whether to trace an action
288
+ # for purposes of apdex measurement - you can use this to
289
+ # ignore things like api calls or other fast non-user-facing
290
+ # actions
291
+ def ignore_apdex?
292
+ _is_filtered?('ignore_apdex')
293
+ end
294
+
295
+ private
296
+
297
+ # Profile the instrumented call. Dev mode only. Experimental
298
+ # - should definitely not be used on production applications
299
+ def perform_action_with_newrelic_profile(args)
300
+ frame_data = _push_metric_frame(block_given? ? args : [])
301
+ val = nil
302
+ NewRelic::Agent.trace_execution_scoped frame_data.metric_name do
303
+ MetricFrame.current(true).start_transaction
304
+ NewRelic::Agent.disable_all_tracing do
305
+ # turn on profiling
306
+ profile = RubyProf.profile do
307
+ if block_given?
308
+ val = yield
309
+ else
310
+ val = perform_action_without_newrelic_trace(*args)
311
+ end
312
+ end
313
+ NewRelic::Agent.instance.transaction_sampler.notice_profile profile
314
+ end
315
+ end
316
+ return val
317
+ ensure
318
+ frame_data.pop
319
+ end
320
+
321
+ # Write a metric frame onto a thread local if there isn't already one there.
322
+ # If there is one, just update it.
323
+ def _push_metric_frame(args) # :nodoc:
324
+ frame_data = NewRelic::Agent::Instrumentation::MetricFrame.current(true)
325
+
326
+ frame_data.apdex_start ||= _detect_upstream_wait(frame_data.start)
327
+ _record_queue_length
328
+ # If a block was passed in, then the arguments represent options for the instrumentation,
329
+ # not app method arguments.
330
+ if args.any?
331
+ if args.last.is_a?(Hash)
332
+ options = args.last
333
+ frame_data.force_flag = options[:force]
334
+ frame_data.request = options[:request] if options[:request]
335
+ end
336
+ category, path, available_params = _convert_args_to_path(args)
337
+ else
338
+ category = 'Controller'
339
+ path = newrelic_metric_path
340
+ available_params = self.respond_to?(:params) ? self.params : {}
341
+ end
342
+ frame_data.request ||= self.request if self.respond_to? :request
343
+ frame_data.push(category + '/'+ path)
344
+ frame_data.filtered_params = (respond_to? :filter_parameters) ? filter_parameters(available_params) : available_params
345
+ frame_data
346
+ end
347
+
348
+ def _convert_args_to_path(args)
349
+ options = args.last.is_a?(Hash) ? args.pop : {}
350
+ params = options[:params] || {}
351
+ category = case options[:category]
352
+ when :controller, nil then 'Controller'
353
+ when :task then 'OtherTransaction/Background' # 'Task'
354
+ when :rack then 'Controller/Rack' #'WebTransaction/Rack'
355
+ when :uri then 'Controller' #'WebTransaction/Uri'
356
+ when :sinatra then 'Controller/Sinatra' #'WebTransaction/Uri'
357
+ # for internal use only
358
+ else options[:category].to_s
359
+ end
360
+ unless path = options[:path]
361
+ action = options[:name] || args.first
362
+ metric_class = options[:class_name] || (self.is_a?(Class) ? self.name : self.class.name)
363
+ path = metric_class
364
+ path += ('/' + action) if action
365
+ end
366
+ [category, path, params]
367
+ end
368
+
369
+ # Filter out a request if it matches one of our parameters for
370
+ # ignoring it - the key is either 'do_not_trace' or 'ignore_apdex'
371
+ def _is_filtered?(key)
372
+ ignore_actions = self.class.newrelic_read_attr(key) if self.class.respond_to? :newrelic_read_attr
373
+ case ignore_actions
374
+ when nil; false
375
+ when Hash
376
+ only_actions = Array(ignore_actions[:only])
377
+ except_actions = Array(ignore_actions[:except])
378
+ only_actions.include?(action_name.to_sym) || (except_actions.any? && !except_actions.include?(action_name.to_sym))
379
+ else
380
+ true
381
+ end
382
+ end
383
+ # Take a guess at a measure representing the number of requests waiting in mongrel
384
+ # or heroku.
385
+ def _record_queue_length
386
+ if newrelic_request_headers
387
+ if queue_depth = newrelic_request_headers['HTTP_X_HEROKU_QUEUE_DEPTH']
388
+ queue_depth = queue_depth.to_i rescue nil
389
+ elsif mongrel = NewRelic::Control.instance.local_env.mongrel
390
+ # Always subtrace 1 for the active mongrel
391
+ queue_depth = [mongrel.workers.list.length.to_i - 1, 0].max rescue nil
392
+ end
393
+ NewRelic::Agent.agent.stats_engine.get_stats_no_scope('Mongrel/Queue Length').trace_call(queue_depth) if queue_depth
394
+ end
395
+ end
396
+
397
+ include NewRelic::Agent::Instrumentation::QueueTime
398
+
399
+ # Return a Time instance representing the upstream start time.
400
+ # now is a Time instance to fall back on if no other candidate
401
+ # for the start time is found.
402
+ def _detect_upstream_wait(now)
403
+ queue_start = nil
404
+ if newrelic_request_headers
405
+ queue_start = parse_frontend_headers(newrelic_request_headers)
406
+ Thread.current[:newrelic_queue_time] = (now.to_f - queue_start.to_f) if queue_start
407
+ end
408
+ queue_start || now
409
+ rescue Exception => e
410
+ NewRelic::Control.instance.log.error("Error detecting upstream wait time: #{e}")
411
+ NewRelic::Control.instance.log.debug("#{e.backtrace[0..20]}")
412
+ now
413
+ end
414
+
415
+ # returns the NewRelic::MethodTraceStats object associated
416
+ # with the dispatcher time measurement
417
+ def _dispatch_stat
418
+ NewRelic::Agent.agent.stats_engine.get_stats_no_scope 'HttpDispatcher'
419
+ end
420
+
421
+ end
422
+ end
423
+ end
424
+ end
@@ -0,0 +1,57 @@
1
+ # NewRelic instrumentation for DataMapper
2
+ # For now, we have to refer to all db metrics as "ActiveRecord"
3
+ if defined? DataMapper
4
+
5
+ DataMapper::Model.class_eval do
6
+ add_method_tracer :get, 'ActiveRecord/#{self.name}/find'
7
+ add_method_tracer :first, 'ActiveRecord/#{self.name}/find'
8
+ add_method_tracer :first_or_create, 'ActiveRecord/#{self.name}/find'
9
+ add_method_tracer :all, 'ActiveRecord/#{self.name}/find_all'
10
+ end
11
+ DataMapper::Resource.class_eval do
12
+
13
+ @@my_sql_defined = defined? ActiveRecord::ConnectionAdapters::MysqlAdapter
14
+ @@postgres_defined = defined? ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
15
+
16
+ for method in [:query] do
17
+ add_method_tracer method, 'ActiveRecord/#{self.class.name[/[^:]*$/]}/execute'
18
+ add_method_tracer method, 'ActiveRecord/all', :push_scope => false
19
+ end
20
+ for method in [:update, :save] do
21
+ add_method_tracer method, 'ActiveRecord/#{self.class.name[/[^:]*$/]}/save'
22
+ add_method_tracer method, 'ActiveRecord/save', :push_scope => false
23
+ end
24
+ add_method_tracer :destroy, 'ActiveRecord/#{self.class.name[/[^:]*$/]}/destroy'
25
+ add_method_tracer :destroy, 'ActiveRecord/destroy', :push_scope => false
26
+
27
+ def log_with_newrelic_instrumentation(sql, name, &block)
28
+ # if we aren't in a blamed context, then add one so that we can
29
+ # see that controllers are calling SQL directly we check
30
+ # scope_depth vs 2 since the controller is 1
31
+ if NewRelic::Agent.instance.transaction_sampler.scope_depth < 2
32
+ self.class.trace_method_execution "Database/DirectSQL", true, true do
33
+ log_with_capture_sql(sql, name, &block)
34
+ end
35
+ else
36
+ log_with_capture_sql(sql, name, &block)
37
+ end
38
+ end
39
+
40
+ def log_with_capture_sql(sql, name, &block)
41
+ if @@my_sql_defined && self.is_a?(ActiveRecord::ConnectionAdapters::MysqlAdapter)
42
+ config = @config
43
+ elsif @@postgres_defined && self.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
44
+ config = @config
45
+ else
46
+ config = nil
47
+ end
48
+
49
+ t0 = Time.now
50
+ result = log_without_newrelic_instrumentation(sql, name, &block)
51
+
52
+ NewRelic::Agent.instance.transaction_sampler.notice_sql(sql, config, (Time.now - t0).to_f)
53
+
54
+ result
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,52 @@
1
+ require 'new_relic/agent/instrumentation/controller_instrumentation'
2
+
3
+ DependencyDetection.defer do
4
+ @name = :delayed_job
5
+
6
+ depends_on do
7
+ !NewRelic::Control.instance['disable_dj']
8
+ end
9
+
10
+ depends_on do
11
+ # double check because of old JRuby bug
12
+ defined?(::Delayed) && defined?(::Delayed::Job) &&
13
+ Delayed::Job.method_defined?(:invoke_job)
14
+ end
15
+
16
+ executes do
17
+ NewRelic::Agent.logger.debug 'Installing DelayedJob instrumentation'
18
+ end
19
+
20
+ executes do
21
+ Delayed::Job.class_eval do
22
+ include NewRelic::Agent::Instrumentation::ControllerInstrumentation
23
+ if self.instance_methods.include?('name') || self.instance_methods.include?(:name)
24
+ add_transaction_tracer "invoke_job", :category => 'OtherTransaction/DelayedJob', :path => '#{self.name}'
25
+ else
26
+ add_transaction_tracer "invoke_job", :category => 'OtherTransaction/DelayedJob'
27
+ end
28
+ end
29
+ end
30
+
31
+ executes do
32
+ Delayed::Job.instance_eval do
33
+ if self.respond_to?('after_fork')
34
+ if method_defined?(:after_fork)
35
+ def after_fork_with_newrelic
36
+ NewRelic::Agent.after_fork(:force_reconnect => true)
37
+ after_fork_without_newrelic
38
+ end
39
+
40
+ alias_method :after_fork_without_newrelic, :after_fork
41
+ alias_method :after_fork, :after_fork_with_newrelic
42
+ else
43
+ def after_fork
44
+ NewRelic::Agent.after_fork(:force_reconnect => true)
45
+ super
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,80 @@
1
+ # NOTE there are multiple implementations of the MemCache client in Ruby,
2
+ # each with slightly different API's and semantics.
3
+ # See:
4
+ # http://www.deveiate.org/code/Ruby-MemCache/ (Gem: Ruby-MemCache)
5
+ # http://seattlerb.rubyforge.org/memcache-client/ (Gem: memcache-client)
6
+ # http://github.com/mperham/dalli (Gem: dalli)
7
+
8
+ module NewRelic
9
+ module Agent
10
+ module Instrumentation
11
+ module Memcache
12
+ module_function
13
+ def instrument_methods(the_class, method_names)
14
+ method_names.each do |method_name|
15
+ next unless the_class.method_defined? method_name.to_sym
16
+ the_class.class_eval <<-EOD
17
+ def #{method_name}_with_newrelic_trace(*args, &block)
18
+ metrics = ["Memcache/#{method_name}",
19
+ (NewRelic::Agent::Instrumentation::MetricFrame.recording_web_transaction? ? 'Memcache/allWeb' : 'Memcache/allOther')]
20
+ self.class.trace_execution_scoped(metrics) do
21
+ t0 = Time.now
22
+ begin
23
+ #{method_name}_without_newrelic_trace(*args, &block)
24
+ ensure
25
+ #{memcache_key_snippet(method_name)}
26
+ end
27
+ end
28
+ end
29
+ alias #{method_name}_without_newrelic_trace #{method_name}
30
+ alias #{method_name} #{method_name}_with_newrelic_trace
31
+ EOD
32
+ end
33
+ end
34
+ def memcache_key_snippet(method_name)
35
+ return "" unless NewRelic::Control.instance['capture_memcache_keys']
36
+ "NewRelic::Agent.instance.transaction_sampler.notice_nosql(args.first.inspect, (Time.now - t0).to_f) rescue nil"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ DependencyDetection.defer do
44
+ @name = :memcache
45
+
46
+ depends_on do
47
+ !NewRelic::Control.instance['disable_memcache_instrumentation']
48
+ end
49
+
50
+ depends_on do
51
+ defined?(::MemCache) || defined?(::Memcached) ||
52
+ defined?(::Dalli::Client) || defined?(::Spymemcached)
53
+ end
54
+
55
+ executes do
56
+ commands = %w[get get_multi set add incr decr delete replace append prepend]
57
+ if defined? ::MemCache
58
+ NewRelic::Agent::Instrumentation::Memcache.instrument_methods(::MemCache,
59
+ commands)
60
+ NewRelic::Agent.logger.debug 'Installing MemCache instrumentation'
61
+ end
62
+ if defined? ::Memcached
63
+ commands << 'cas'
64
+ NewRelic::Agent::Instrumentation::Memcache.instrument_methods(::Memcached,
65
+ commands)
66
+ NewRelic::Agent.logger.debug 'Installing Memcached instrumentation'
67
+ end
68
+ if defined? ::Dalli::Client
69
+ NewRelic::Agent::Instrumentation::Memcache.instrument_methods(::Dalli::Client,
70
+ commands)
71
+ NewRelic::Agent.logger.debug 'Installing Dalli Memcache instrumentation'
72
+ end
73
+ if defined? ::Spymemcached
74
+ commands << 'multiget'
75
+ NewRelic::Agent::Instrumentation::Memcache.instrument_methods(::Spymemcached,
76
+ commands)
77
+ NewRelic::Agent.logger.debug 'Installing Spymemcached instrumentation'
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,41 @@
1
+ require 'set'
2
+
3
+ DependencyDetection.defer do
4
+ @name = :merb_controller
5
+
6
+ depends_on do
7
+ defined?(Merb) && defined?(Merb::Controller)
8
+ end
9
+
10
+ executes do
11
+ NewRelic::Agent.logger.debug 'Installing Merb Controller instrumentation'
12
+ end
13
+
14
+ executes do
15
+ require 'merb-core/controller/merb_controller'
16
+
17
+ Merb::Controller.class_eval do
18
+ include NewRelic::Agent::Instrumentation::ControllerInstrumentation
19
+
20
+ class_inheritable_accessor :do_not_trace
21
+ class_inheritable_accessor :ignore_apdex
22
+
23
+ def self.newrelic_write_attr(attr_name, value) # :nodoc:
24
+ self.send "#{attr_name}=", attr_name, value
25
+ end
26
+
27
+ def self.newrelic_read_attr(attr_name) # :nodoc:
28
+ self.send attr_name
29
+ end
30
+
31
+ protected
32
+ # determine the path that is used in the metric name for
33
+ # the called controller action
34
+ def newrelic_metric_path
35
+ "#{controller_name}/#{action_name}"
36
+ end
37
+ alias_method :perform_action_without_newrelic_trace, :_dispatch
38
+ alias_method :_dispatch, :perform_action_with_newrelic_trace
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,29 @@
1
+ DependencyDetection.defer do
2
+ @name = :merb_error
3
+
4
+ depends_on do
5
+ defined?(Merb) && defined?(Merb::Dispatcher) && defined?(Merb::Dispatcher::DefaultException)
6
+ end
7
+
8
+ depends_on do
9
+ Merb::Dispatcher::DefaultException.respond_to?(:before)
10
+ end
11
+
12
+ executes do
13
+ NewRelic::Agent.logger.debug 'Installing Merb Errors instrumentation'
14
+ end
15
+
16
+ executes do
17
+
18
+ # Hook in the notification to merb
19
+ error_notifier = Proc.new {
20
+ if request.exceptions #check that there's actually an exception
21
+ # Note, this assumes we have already captured the other information such as uri and params in the MetricFrame.
22
+ NewRelic::Agent::Instrumentation::MetricFrame.notice_error(request.exceptions.first)
23
+ end
24
+ }
25
+ Merb::Dispatcher::DefaultException.before error_notifier
26
+ Exceptions.before error_notifier
27
+
28
+ end
29
+ end