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,414 @@
1
+ require 'set'
2
+ require 'new_relic/version'
3
+
4
+ module NewRelic
5
+ # An instance of LocalEnvironment is responsible for determining
6
+ # three things:
7
+ #
8
+ # * Framework - :rails, :rails3, :merb, :ruby, :external, :test
9
+ # * Dispatcher - A supported dispatcher, or nil (:mongrel, :thin, :passenger, :webrick, etc)
10
+ # * Dispatcher Instance ID, which distinguishes agents on a single host from each other
11
+ #
12
+ # If the environment can't be determined, it will be set to
13
+ # nil and dispatcher_instance_id will have nil.
14
+ #
15
+ # NewRelic::LocalEnvironment should be accessed through NewRelic::Control#env (via the NewRelic::Control singleton).
16
+ class LocalEnvironment
17
+
18
+ # mongrel, thin, webrick, or possibly nil
19
+ attr_accessor :dispatcher
20
+ # used to distinguish instances of a dispatcher from each other, may be nil
21
+ attr_writer :dispatcher_instance_id
22
+ # rails, rails3, merb, external, ruby, test, etc
23
+ attr_accessor :framework
24
+ # The number of cpus, if detected, or nil - many platforms do not
25
+ # support this :(
26
+ attr_reader :processors
27
+ alias environment dispatcher
28
+
29
+ def initialize
30
+ # Extend self with any any submodules of LocalEnvironment. These can override
31
+ # the discover methods to discover new framworks and dispatchers.
32
+ NewRelic::LocalEnvironment.constants.each do | const |
33
+ mod = NewRelic::LocalEnvironment.const_get const
34
+ self.extend mod if mod.instance_of? Module
35
+ end
36
+
37
+ discover_framework
38
+ discover_dispatcher
39
+ @dispatcher = nil if @dispatcher == :none
40
+ @gems = Set.new
41
+ @plugins = Set.new
42
+ @config = Hash.new
43
+ end
44
+
45
+ # Add the given key/value pair to the app environment
46
+ # settings. Must pass either a value or a block. Block
47
+ # is called to get the value and any raised errors are
48
+ # silently ignored.
49
+ def append_environment_value(name, value = nil)
50
+ value = yield if block_given?
51
+ @config[name] = value if value
52
+ rescue Exception
53
+ # puts "#{e}\n #{e.backtrace.join("\n ")}"
54
+ raise if @framework == :test
55
+ end
56
+
57
+ # yields to the block and appends the returned value to the list
58
+ # of gems - this catches errors that might be raised in the block
59
+ def append_gem_list
60
+ @gems += yield
61
+ rescue Exception => e
62
+ # puts "#{e}\n #{e.backtrace.join("\n ")}"
63
+ raise if @framework == :test
64
+ end
65
+
66
+ # yields to the block and appends the returned value to the list
67
+ # of plugins - this catches errors that might be raised in the block
68
+ def append_plugin_list
69
+ @plugins += yield
70
+ rescue Exception
71
+ # puts "#{e}\n #{e.backtrace.join("\n ")}"
72
+ raise if @framework == :test
73
+ end
74
+
75
+ # An instance id pulled from either @dispatcher_instance_id or by
76
+ # splitting out the first part of the running file
77
+ def dispatcher_instance_id
78
+ if @dispatcher_instance_id.nil?
79
+ if @dispatcher.nil?
80
+ @dispatcher_instance_id = File.basename($0).split(".").first
81
+ end
82
+ end
83
+ @dispatcher_instance_id
84
+ end
85
+
86
+ # Interrogates some common ruby constants for useful information
87
+ # about what kind of ruby environment the agent is running in
88
+ def gather_ruby_info
89
+ append_environment_value('Ruby version'){ RUBY_VERSION }
90
+ append_environment_value('Ruby description'){ RUBY_DESCRIPTION } if defined? ::RUBY_DESCRIPTION
91
+ append_environment_value('Ruby platform') { RUBY_PLATFORM }
92
+ append_environment_value('Ruby patchlevel') { RUBY_PATCHLEVEL }
93
+ # room here for other ruby implementations, when.
94
+ if defined? ::JRUBY_VERSION
95
+ gather_jruby_info
96
+ end
97
+ end
98
+
99
+ # like gather_ruby_info but for the special case of JRuby
100
+ def gather_jruby_info
101
+ append_environment_value('JRuby version') { JRUBY_VERSION }
102
+ append_environment_value('Java VM version') { ENV_JAVA['java.vm.version']}
103
+ end
104
+
105
+ # See what the number of cpus is, works only on some linux variants
106
+ def gather_cpu_info
107
+ return unless File.readable? '/proc/cpuinfo'
108
+ @processors = append_environment_value('Processors') do
109
+ processors = File.readlines('/proc/cpuinfo').select { |line| line =~ /^processor\s*:/ }.size
110
+ raise "Cannot determine the number of processors in /proc/cpuinfo" unless processors > 0
111
+ processors
112
+ end
113
+ end
114
+
115
+ # Grabs the architecture string from either `uname -p` or the env
116
+ # variable PROCESSOR_ARCHITECTURE
117
+ def gather_architecture_info
118
+ append_environment_value('Arch') { `uname -p` } ||
119
+ append_environment_value('Arch') { ENV['PROCESSOR_ARCHITECTURE'] }
120
+ end
121
+
122
+ # gathers OS info from either `uname -v`, `uname -s`, or the OS
123
+ # env variable
124
+ def gather_os_info
125
+ append_environment_value('OS version') { `uname -v` }
126
+ append_environment_value('OS') { `uname -s` } ||
127
+ append_environment_value('OS') { ENV['OS'] }
128
+ end
129
+
130
+ # Gathers the architecture and cpu info
131
+ def gather_system_info
132
+ gather_architecture_info
133
+ gather_cpu_info
134
+ end
135
+
136
+ # Looks for a capistrano file indicating the current revision
137
+ def gather_revision_info
138
+ rev_file = File.join(NewRelic::Control.instance.root, "REVISION")
139
+ if File.readable?(rev_file) && File.size(rev_file) < 64
140
+ append_environment_value('Revision') do
141
+ File.open(rev_file) { | file | file.readline.strip }
142
+ end
143
+ end
144
+ end
145
+
146
+ # The name of the AR database adapter for the current environment and
147
+ # the current schema version
148
+ def gather_ar_adapter_info
149
+
150
+ append_environment_value 'Database adapter' do
151
+ if defined?(ActiveRecord) && defined?(ActiveRecord::Base) &&
152
+ ActiveRecord::Base.respond_to?(:configurations)
153
+ config = ActiveRecord::Base.configurations[NewRelic::Control.instance.env]
154
+ if config
155
+ config['adapter']
156
+ end
157
+ end
158
+ end
159
+ append_environment_value 'Database schema version' do
160
+ ActiveRecord::Migrator.current_version
161
+ end
162
+ end
163
+
164
+ # Datamapper version
165
+ def gather_dm_adapter_info
166
+ append_environment_value 'DataMapper version' do
167
+ require 'dm-core/version'
168
+ DataMapper::VERSION
169
+ end
170
+ end
171
+
172
+ # sensing for which adapter is defined, then appends the relevant
173
+ # config information
174
+ def gather_db_info
175
+ # room here for more database adapters, when.
176
+ if defined? ::ActiveRecord
177
+ gather_ar_adapter_info
178
+ end
179
+ if defined? ::DataMapper
180
+ gather_dm_adapter_info
181
+ end
182
+ end
183
+
184
+ # Collect base statistics about the environment and record them for
185
+ # comparison and change detection.
186
+ def gather_environment_info
187
+ append_environment_value 'Framework', @framework.to_s
188
+ append_environment_value 'Dispatcher', @dispatcher.to_s if @dispatcher
189
+ append_environment_value 'Dispatcher instance id', @dispatcher_instance_id if @dispatcher_instance_id
190
+ append_environment_value('Environment') { NewRelic::Control.instance.env }
191
+
192
+ # miscellaneous other helpful debugging information
193
+ gather_ruby_info
194
+ gather_system_info
195
+ gather_revision_info
196
+ gather_db_info
197
+ end
198
+
199
+ # Take a snapshot of the environment information for this application
200
+ # Returns an associative array
201
+ def snapshot
202
+ i = @config.to_a
203
+ i << [ 'Plugin List', @plugins.to_a] if not @plugins.empty?
204
+ i << [ 'Gems', @gems.to_a] if not @gems.empty?
205
+ i
206
+ end
207
+
208
+ # it's a working jruby if it has the runtime method, and object
209
+ # space is enabled
210
+ def working_jruby?
211
+ !(defined?(::JRuby) && JRuby.respond_to?(:runtime) && !JRuby.runtime.is_object_space_enabled)
212
+ end
213
+
214
+ # Runs through all the objects in ObjectSpace to find the first one that
215
+ # match the provided class
216
+ def find_class_in_object_space(klass)
217
+ ObjectSpace.each_object(klass) do |x|
218
+ return x
219
+ end
220
+ return nil
221
+ end
222
+
223
+ # Sets the @mongrel instance variable if we can find a Mongrel::HttpServer
224
+ def mongrel
225
+ return @mongrel if @mongrel
226
+ if defined?(::Mongrel) && defined?(::Mongrel::HttpServer) && working_jruby?
227
+ @mongrel = find_class_in_object_space(::Mongrel::HttpServer)
228
+ end
229
+ @mongrel
230
+ end
231
+
232
+ private
233
+
234
+ # Although you can override the framework with NEWRELIC_DISPATCHER this
235
+ # is not advisable since it implies certain api's being available.
236
+ def discover_dispatcher
237
+ @dispatcher ||= ENV['NEWRELIC_DISPATCHER'] && ENV['NEWRELIC_DISPATCHER'].to_sym
238
+ @dispatcher ||= ENV['NEW_RELIC_DISPATCHER'] && ENV['NEW_RELIC_DISPATCHER'].to_sym
239
+ dispatchers = %w[passenger torquebox glassfish thin mongrel litespeed webrick fastcgi unicorn sinatra]
240
+ while dispatchers.any? && @dispatcher.nil?
241
+ send 'check_for_'+(dispatchers.shift)
242
+ end
243
+ end
244
+
245
+ def discover_framework
246
+ # Although you can override the framework with NEWRELIC_FRAMEWORK this
247
+ # is not advisable since it implies certain api's being available.
248
+ #
249
+ # Note that the odd defined? sequence is necessary to work around a bug in an older version
250
+ # of JRuby.
251
+ @framework ||= case
252
+ when ENV['NEWRELIC_FRAMEWORK'] then ENV['NEWRELIC_FRAMEWORK'].to_sym
253
+ when ENV['NEW_RELIC_FRAMEWORK'] then ENV['NEW_RELIC_FRAMEWORK'].to_sym
254
+ when defined?(::NewRelic::TEST) then :test
255
+ when defined?(::Merb) && defined?(::Merb::Plugins) then :merb
256
+ when defined?(::Rails) then check_rails_version
257
+ when defined?(::Sinatra) && defined?(::Sinatra::Base) then :sinatra
258
+ when defined?(::NewRelic::IA) then :external
259
+ else :ruby
260
+ end
261
+ end
262
+
263
+ def check_rails_version
264
+ if Rails::VERSION::MAJOR < 3
265
+ :rails
266
+ else
267
+ :rails3
268
+ end
269
+ end
270
+
271
+ def check_for_torquebox
272
+ return unless defined?(::JRuby) &&
273
+ ( org.torquebox::TorqueBox rescue nil)
274
+ @dispatcher = :torquebox
275
+ end
276
+
277
+ def check_for_glassfish
278
+ return unless defined?(::JRuby) &&
279
+ (((com.sun.grizzly.jruby.rack.DefaultRackApplicationFactory rescue nil) &&
280
+ defined?(com::sun::grizzly::jruby::rack::DefaultRackApplicationFactory)) ||
281
+ (jruby_rack? && defined?(::GlassFish::Server)))
282
+ @dispatcher = :glassfish
283
+ end
284
+
285
+ def check_for_trinidad
286
+ return unless defined?(::JRuby) && jruby_rack? && defined?(::Trinidad::Server)
287
+ @dispatcher = :trinidad
288
+ end
289
+
290
+ def jruby_rack?
291
+ ((org.jruby.rack.DefaultRackApplicationFactory rescue nil) &&
292
+ defined?(org::jruby::rack::DefaultRackApplicationFactory))
293
+ end
294
+
295
+ def check_for_webrick
296
+ return unless defined?(::WEBrick) && defined?(::WEBrick::VERSION)
297
+ @dispatcher = :webrick
298
+ if defined?(::OPTIONS) && OPTIONS.respond_to?(:fetch)
299
+ # OPTIONS is set by script/server
300
+ @dispatcher_instance_id = OPTIONS.fetch(:port)
301
+ end
302
+ @dispatcher_instance_id = default_port unless @dispatcher_instance_id
303
+ end
304
+
305
+ def check_for_fastcgi
306
+ return unless defined?(::FCGI)
307
+ @dispatcher = :fastcgi
308
+ end
309
+
310
+ # this case covers starting by mongrel_rails
311
+ def check_for_mongrel
312
+ return unless defined?(::Mongrel) && defined?(::Mongrel::HttpServer)
313
+ @dispatcher = :mongrel
314
+
315
+ # Get the port from the server if it's started
316
+
317
+ if mongrel && mongrel.respond_to?(:port)
318
+ @dispatcher_instance_id = mongrel.port.to_s
319
+ end
320
+
321
+ # Get the port from the configurator if one was created
322
+ if @dispatcher_instance_id.nil? && defined?(::Mongrel::Configurator)
323
+ ObjectSpace.each_object(Mongrel::Configurator) do |mongrel|
324
+ @dispatcher_instance_id = mongrel.defaults[:port] && mongrel.defaults[:port].to_s
325
+ end unless defined?(::JRuby) && !JRuby.runtime.is_object_space_enabled
326
+ end
327
+
328
+ # Still can't find the port. Let's look at ARGV to fall back
329
+ @dispatcher_instance_id = default_port if @dispatcher_instance_id.nil?
330
+ end
331
+
332
+ def check_for_unicorn
333
+ if (defined?(::Unicorn) && defined?(::Unicorn::HttpServer)) && working_jruby?
334
+ v = find_class_in_object_space(::Unicorn::HttpServer)
335
+ @dispatcher = :unicorn if v
336
+ end
337
+ end
338
+
339
+ def check_for_sinatra
340
+ return unless defined?(::Sinatra) && defined?(::Sinatra::Base)
341
+
342
+ begin
343
+ version = ::Sinatra::VERSION
344
+ rescue
345
+ $stderr.puts("Error determining Sinatra version")
346
+ end
347
+
348
+ if ::NewRelic::VersionNumber.new('0.9.2') > version
349
+ $stderr.puts("Your Sinatra version is #{version}, we highly recommend upgrading to >=0.9.2")
350
+ end
351
+
352
+ @dispatcher = :sinatra
353
+ end
354
+
355
+ def check_for_thin
356
+ if defined?(::Thin) && defined?(::Thin::Server)
357
+ # This case covers the thin web dispatcher
358
+ # Same issue as above- we assume only one instance per process
359
+ ObjectSpace.each_object(Thin::Server) do |thin_dispatcher|
360
+ @dispatcher = :thin
361
+ backend = thin_dispatcher.backend
362
+ # We need a way to uniquely identify and distinguish agents. The port
363
+ # works for this. When using sockets, use the socket file name.
364
+ if backend.respond_to? :port
365
+ @dispatcher_instance_id = backend.port
366
+ elsif backend.respond_to? :socket
367
+ @dispatcher_instance_id = backend.socket
368
+ else
369
+ raise "Unknown thin backend: #{backend}"
370
+ end
371
+ end # each thin instance
372
+ end
373
+ if defined?(::Thin) && defined?(::Thin::VERSION) && !@dispatcher
374
+ @dispatcher = :thin
375
+ @dispatcher_instance_id = default_port
376
+ end
377
+ end
378
+
379
+ def check_for_litespeed
380
+ if caller.pop =~ /fcgi-bin\/RailsRunner\.rb/
381
+ @dispatcher = :litespeed
382
+ end
383
+ end
384
+
385
+ def check_for_passenger
386
+ if (defined?(::Passenger) && defined?(::Passenger::AbstractServer)) || defined?(::IN_PHUSION_PASSENGER)
387
+ @dispatcher = :passenger
388
+ end
389
+ end
390
+
391
+
392
+ def default_port
393
+ require 'optparse'
394
+ # If nothing else is found, use the 3000 default
395
+ default_port = 3000
396
+ OptionParser.new do |opts|
397
+ opts.on("-p", "--port=port", String) { | p | default_port = p }
398
+ opts.parse(ARGV.clone) rescue nil
399
+ end
400
+ default_port
401
+ end
402
+
403
+ public
404
+ # outputs a human-readable description
405
+ def to_s
406
+ s = "LocalEnvironment["
407
+ s << @framework.to_s
408
+ s << ";dispatcher=#{@dispatcher}" if @dispatcher
409
+ s << ";instance=#{@dispatcher_instance_id}" if @dispatcher_instance_id
410
+ s << "]"
411
+ end
412
+
413
+ end
414
+ end
@@ -0,0 +1,6 @@
1
+ namespace :newrelic do
2
+ desc "Install the developer mode newrelic.yml file"
3
+ task :default do
4
+ load File.expand_path(File.join(__FILE__,"..","..","install.rb"))
5
+ end
6
+ end
@@ -0,0 +1,51 @@
1
+ module NewRelic
2
+ class MetricData
3
+ # nil, or a NewRelic::MetricSpec object if we have no cached ID
4
+ attr_accessor :metric_spec
5
+ # nil or a cached integer ID for the metric from the collector.
6
+ attr_accessor :metric_id
7
+ # the actual statistics object
8
+ attr_accessor :stats
9
+
10
+ def initialize(metric_spec, stats, metric_id)
11
+ @metric_spec = metric_spec
12
+ self.stats = stats
13
+ self.metric_id = metric_id
14
+ end
15
+
16
+ def eql?(o)
17
+ (metric_spec.eql? o.metric_spec) && (stats.eql? o.stats)
18
+ end
19
+
20
+ def original_spec
21
+ @original_spec || @metric_spec
22
+ end
23
+
24
+ # assigns a new metric spec, and retains the old metric spec as
25
+ # @original_spec if it exists currently
26
+ def metric_spec= new_spec
27
+ @original_spec = @metric_spec if @metric_spec
28
+ @metric_spec = new_spec
29
+ end
30
+
31
+ def hash
32
+ metric_spec.hash ^ stats.hash
33
+ end
34
+
35
+ # Serialize with all attributes, but if the metric id is not nil, then don't send the metric spec
36
+ def to_json(*a)
37
+ %Q[{"metric_spec":#{metric_id ? 'null' : metric_spec.to_json},"stats":{"total_exclusive_time":#{stats.total_exclusive_time},"min_call_time":#{stats.min_call_time},"call_count":#{stats.call_count},"sum_of_squares":#{stats.sum_of_squares},"total_call_time":#{stats.total_call_time},"max_call_time":#{stats.max_call_time}},"metric_id":#{metric_id ? metric_id : 'null'}}]
38
+ end
39
+
40
+ def to_s
41
+ if metric_spec
42
+ "#{metric_spec.name}(#{metric_spec.scope}): #{stats}"
43
+ else
44
+ "#{metric_id}: #{stats}"
45
+ end
46
+ end
47
+ def inspect
48
+ "#<MetricData metric_spec:#{metric_spec.inspect}, stats:#{stats.inspect}, metric_id:#{metric_id.inspect}>"
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,75 @@
1
+ # this struct uniquely defines a metric, optionally inside
2
+ # the call scope of another metric
3
+ class NewRelic::MetricSpec
4
+ attr_accessor :name
5
+ attr_accessor :scope
6
+
7
+ # the maximum length of a metric name or metric scope
8
+ MAX_LENGTH = 255
9
+ # Need a "zero-arg" constructor so it can be instantiated from java (using
10
+ # jruby) for sending responses to ruby agents from the java collector.
11
+ #
12
+ def initialize(metric_name = '', metric_scope = '')
13
+ self.name = (metric_name || '') && metric_name[0...MAX_LENGTH]
14
+ self.scope = metric_scope && metric_scope[0...MAX_LENGTH]
15
+ end
16
+
17
+ # truncates the name and scope to the MAX_LENGTH
18
+ def truncate!
19
+ self.name = name[0...MAX_LENGTH] if name && name.size > MAX_LENGTH
20
+ self.scope = scope[0...MAX_LENGTH] if scope && scope.size > MAX_LENGTH
21
+ end
22
+
23
+ def ==(o)
24
+ self.eql?(o)
25
+ end
26
+
27
+ def eql? o
28
+ self.class == o.class &&
29
+ name.eql?(o.name) &&
30
+ # coerce scope to a string and compare
31
+ scope.to_s == o.scope.to_s
32
+ end
33
+
34
+ def hash
35
+ h = name.hash
36
+ h ^= scope.hash unless scope.nil?
37
+ h
38
+ end
39
+ # return a new metric spec if the given regex
40
+ # matches the name or scope.
41
+ def sub(pattern, replacement, apply_to_scope = true)
42
+ NewRelic::Control.instance.log.warn("The sub method on metric specs is deprecated") rescue nil
43
+ return nil if name !~ pattern &&
44
+ (!apply_to_scope || scope.nil? || scope !~ pattern)
45
+ new_name = name.sub(pattern, replacement)[0...MAX_LENGTH]
46
+
47
+ if apply_to_scope
48
+ new_scope = (scope && scope.sub(pattern, replacement)[0...MAX_LENGTH])
49
+ else
50
+ new_scope = scope
51
+ end
52
+
53
+ self.class.new new_name, new_scope
54
+ end
55
+
56
+ def to_s
57
+ return name if scope.empty?
58
+ "#{name}:#{scope}"
59
+ end
60
+
61
+ def inspect
62
+ "#<NewRelic::MetricSpec '#{name}':'#{scope}'>"
63
+ end
64
+
65
+ def to_json(*a)
66
+ {'name' => name,
67
+ 'scope' => scope}.to_json(*a)
68
+ end
69
+
70
+ def <=>(o)
71
+ namecmp = self.name <=> o.name
72
+ return namecmp if namecmp != 0
73
+ return (self.scope || '') <=> (o.scope || '')
74
+ end
75
+ end
@@ -0,0 +1,9 @@
1
+ module NewRelic
2
+ module Metrics
3
+ CONTROLLER = "Controller"
4
+ DISPATCHER = "HttpDispatcher"
5
+ ACTIVE_RECORD = "ActiveRecord"
6
+ USER_TIME = "CPU/User Time"
7
+ MEMORY = "Memory/Physical"
8
+ end
9
+ end
@@ -0,0 +1,24 @@
1
+ # This class encapsulates an error that was noticed by New Relic in a managed app.
2
+ class NewRelic::NoticedError
3
+ extend NewRelic::CollectionHelper
4
+ attr_accessor :path, :timestamp, :params, :exception_class, :message
5
+
6
+ def initialize(path, data, exception, timestamp = Time.now)
7
+ self.path = path
8
+ self.params = NewRelic::NoticedError.normalize_params(data)
9
+
10
+ self.exception_class = exception.is_a?(Exception) ? exception.class.name : 'Error'
11
+
12
+ if exception.respond_to?('original_exception')
13
+ self.message = exception.original_exception.message.to_s
14
+ else
15
+ self.message = (exception || '<no message>').to_s
16
+ end
17
+
18
+ # clamp long messages to 4k so that we don't send a lot of
19
+ # overhead across the wire
20
+ self.message = self.message[0..4095] if self.message.length > 4096
21
+
22
+ self.timestamp = timestamp
23
+ end
24
+ end
@@ -0,0 +1,68 @@
1
+ require 'rack'
2
+
3
+ module NewRelic::Rack
4
+ class BrowserMonitoring
5
+
6
+ def initialize(app, options = {})
7
+ @app = app
8
+ end
9
+
10
+ # method required by Rack interface
11
+ def call(env)
12
+
13
+ # clear out the thread locals we use in case this is a static request
14
+ Thread.current[:newrelic_most_recent_transaction] = nil
15
+ Thread.current[:newrelic_start_time] = Time.now
16
+ Thread.current[:newrelic_queue_time] = 0
17
+
18
+ result = @app.call(env) # [status, headers, response]
19
+
20
+ if (NewRelic::Agent.browser_timing_header != "") && should_instrument?(result[0], result[1])
21
+ response_string = autoinstrument_source(result[2], result[1])
22
+
23
+ if (response_string)
24
+ Rack::Response.new(response_string, result[0], result[1]).finish
25
+ else
26
+ result
27
+ end
28
+ else
29
+ result
30
+ end
31
+ end
32
+
33
+ def should_instrument?(status, headers)
34
+ status == 200 && headers["Content-Type"] && headers["Content-Type"].include?("text/html")
35
+ end
36
+
37
+ def autoinstrument_source(response, headers)
38
+ source = nil
39
+ response.each {|fragment| (source) ? (source << fragment) : (source = fragment)}
40
+ return nil unless source
41
+
42
+ body_start = source.index("<body")
43
+ body_close = source.rindex("</body>")
44
+
45
+ if body_start && body_close
46
+ footer = NewRelic::Agent.browser_timing_footer
47
+ header = NewRelic::Agent.browser_timing_header
48
+
49
+ if source.include?('X-UA-Compatible')
50
+ # put at end of header if UA-Compatible meta tag found
51
+ head_pos = source.index("</head>")
52
+ elsif head_open = source.index("<head")
53
+ # put at the beginning of the header
54
+ head_pos = source.index(">", head_open) + 1
55
+ else
56
+ # put the header right above body start
57
+ head_pos = body_start
58
+ end
59
+
60
+ source = source[0..(head_pos-1)] + header + source[head_pos..(body_close-1)] + footer + source[body_close..-1]
61
+
62
+ headers['Content-Length'] = source.length.to_s if headers['Content-Length']
63
+ end
64
+
65
+ source
66
+ end
67
+ end
68
+ end