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,89 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'..', 'test_helper'))
2
+ class NewRelic::VersionNumberTest < Test::Unit::TestCase
3
+
4
+ def test_comparison__first
5
+ versions = %w[1.0.0 0.1.0 0.0.1 10.0.1 1.10.0].map {|s| NewRelic::VersionNumber.new s }
6
+ assert_equal %w[0.0.1 0.1.0 1.0.0 1.10.0 10.0.1], versions.sort.map(&:to_s)
7
+ v0 = NewRelic::VersionNumber.new '1.2.3'
8
+ v1 = NewRelic::VersionNumber.new '1.2.2'
9
+ v3 = NewRelic::VersionNumber.new '1.2.2'
10
+ assert v0 > v1
11
+ assert v1 == v1
12
+ assert v1 == v3
13
+ end
14
+ def test_comparison__second
15
+ v0 = NewRelic::VersionNumber.new '1.2.0'
16
+ v1 = NewRelic::VersionNumber.new '2.2.2'
17
+ v3 = NewRelic::VersionNumber.new '1.1.2'
18
+ assert v0 < v1
19
+ assert v1 > v3
20
+ assert v3 < v0
21
+ end
22
+ def test_bug
23
+ v0 = NewRelic::VersionNumber.new '2.8.999'
24
+ v1 = NewRelic::VersionNumber.new '2.9.10'
25
+ assert v1 > v0
26
+ assert v0 <= v1
27
+ end
28
+ def test_long_version
29
+ v0 = NewRelic::VersionNumber.new '1.2.3.4'
30
+ v1 = NewRelic::VersionNumber.new '1.2.3.3'
31
+ v3 = NewRelic::VersionNumber.new '1.3'
32
+ assert v0 > v1
33
+ assert v0 < '1.2.3.5'
34
+ assert ! (v0 < '1.2.3.4')
35
+ assert v3 > v0
36
+ end
37
+ def test_sort
38
+ values = %w[1.1.1
39
+ 1.1.99
40
+ 1.1.999
41
+ 2.0.6
42
+ 2.6.5
43
+ 2.7
44
+ 2.7.1
45
+ 2.7.2
46
+ 2.7.2.0
47
+ 3
48
+ 999]
49
+ assert_equal values, values.map{|v| NewRelic::VersionNumber.new v}.sort.map(&:to_s)
50
+ end
51
+ def test_prerelease
52
+ v0 = NewRelic::VersionNumber.new '1.2.0.beta'
53
+ assert_equal [1,2,0,'beta'], v0.parts
54
+ assert v0 > '1.1.9.0'
55
+ assert v0 > '1.1.9.alpha'
56
+ assert v0 > '1.2.0.alpha'
57
+ assert v0 == '1.2.0.beta'
58
+ assert v0 < '1.2.1'
59
+ assert v0 < '1.2.0'
60
+ assert v0 < '1.2.0.c'
61
+ assert v0 < '1.2.0.0'
62
+
63
+ end
64
+ def test_compare_string
65
+ v0 = NewRelic::VersionNumber.new '1.2.0'
66
+ v1 = NewRelic::VersionNumber.new '2.2.2'
67
+ v3 = NewRelic::VersionNumber.new '1.1.2'
68
+ assert v0 < '2.2.2'
69
+ assert v1 > '1.1.2'
70
+ assert v3 < '1.2.0'
71
+ assert v0 == '1.2.0'
72
+ end
73
+ def test_4_numbers
74
+ v0 = NewRelic::VersionNumber.new '1.2.0'
75
+ v1 = NewRelic::VersionNumber.new '1.2.0.1'
76
+ v2 = NewRelic::VersionNumber.new '1.2.1.0'
77
+ v3 = NewRelic::VersionNumber.new '1.2.1.1'
78
+ assert v0 < v1
79
+ assert v1 < v2
80
+ assert v2 < v3
81
+ assert v0 < v3
82
+ assert v0 < '1.2.0.1'
83
+ assert v0 > '1.1.0.1'
84
+ end
85
+ def test_string
86
+ assert_equal '1.2.0', NewRelic::VersionNumber.new('1.2.0').to_s
87
+ assert_equal '1.2', NewRelic::VersionNumber.new('1.2').to_s
88
+ end
89
+ end
@@ -0,0 +1,29 @@
1
+
2
+ module TestContexts
3
+ def with_running_agent
4
+
5
+ context 'with running agent' do # this is needed for the nested setups
6
+
7
+ setup do
8
+ @log_data = StringIO.new
9
+ @log = Logger.new(@log_data)
10
+ NewRelic::Agent.manual_start :log => @log
11
+ @agent = NewRelic::Agent.instance
12
+ @agent.transaction_sampler.send :clear_builder
13
+ @agent.transaction_sampler.reset!
14
+ @agent.stats_engine.clear_stats
15
+ end
16
+
17
+ yield
18
+
19
+ def teardown
20
+ super
21
+ NewRelic::Agent.shutdown
22
+ @log_data.reset
23
+ NewRelic::Control.instance['dispatcher']=nil
24
+ NewRelic::Control.instance['dispatcher_instance_id']=nil
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,154 @@
1
+ module NewRelic; TEST = true; end unless defined? NewRelic::TEST
2
+ ENV['RAILS_ENV'] = 'test'
3
+ NEWRELIC_PLUGIN_DIR = File.expand_path(File.join(File.dirname(__FILE__),".."))
4
+ $LOAD_PATH << '.'
5
+ $LOAD_PATH << '../../..'
6
+ $LOAD_PATH << File.join(NEWRELIC_PLUGIN_DIR,"test")
7
+ $LOAD_PATH << File.join(NEWRELIC_PLUGIN_DIR,"ui/helpers")
8
+ $LOAD_PATH.uniq!
9
+
10
+ require 'rubygems'
11
+ # We can speed things up in tests that don't need to load rails.
12
+ # You can also run the tests in a mode without rails. Many tests
13
+ # will be skipped.
14
+
15
+ begin
16
+ require 'config/environment'
17
+ begin
18
+ require 'test_help'
19
+ rescue LoadError
20
+ # ignore load problems on test help - it doesn't exist in rails 3
21
+ end
22
+
23
+ rescue LoadError
24
+ # To run the tests against a standalone agent build, you need to
25
+ # add a rails app to the load path. It can be 2.* to 3.*. It should
26
+ # referenc newrelic_rpm in the Gemfile with a :path option pointing
27
+ # to this work directory.
28
+ guess = File.expand_path("../../../rpm", __FILE__)
29
+ if $LOAD_PATH.include? guess
30
+ puts "Unable to load Rails for New Relic tests. See note in test_helper.rb"
31
+ raise
32
+ else
33
+ $LOAD_PATH << guess
34
+ retry
35
+ end
36
+ end
37
+ require 'newrelic_rpm'
38
+
39
+ require 'test/unit'
40
+ require 'shoulda'
41
+ require 'test_contexts'
42
+ require 'mocha'
43
+ require 'mocha/integration/test_unit'
44
+ require 'mocha/integration/test_unit/assertion_counter'
45
+
46
+ class Test::Unit::TestCase
47
+ include Mocha::API
48
+
49
+ # we can delete this trick when we stop supporting rails2.0.x
50
+ if ENV['BRANCH'] != 'rails20'
51
+ # a hack because rails2.0.2 does not like double teardowns
52
+ def teardown
53
+ mocha_teardown
54
+ end
55
+ end
56
+ end
57
+
58
+ def assert_between(floor, ceiling, value, message="expected #{floor} <= #{value} <= #{ceiling}")
59
+ assert((floor <= value && value <= ceiling), message)
60
+ end
61
+
62
+ def check_metric_time(metric, value, delta)
63
+ time = NewRelic::Agent.get_stats(metric).total_call_time
64
+ assert_between((value - delta), (value + delta), time)
65
+ end
66
+
67
+ def check_metric_count(metric, value)
68
+ count = NewRelic::Agent.get_stats(metric).call_count
69
+ assert_equal(value, count, "should have the correct number of calls")
70
+ end
71
+
72
+ def check_unscoped_metric_count(metric, value)
73
+ count = NewRelic::Agent.get_stats_unscoped(metric).call_count
74
+ assert_equal(value, count, "should have the correct number of calls")
75
+ end
76
+
77
+ def generate_unscoped_metric_counts(*metrics)
78
+ metrics.inject({}) do |sum, metric|
79
+ sum[metric] = NewRelic::Agent.get_stats_no_scope(metric).call_count
80
+ sum
81
+ end
82
+ end
83
+
84
+ def generate_metric_counts(*metrics)
85
+ metrics.inject({}) do |sum, metric|
86
+ sum[metric] = NewRelic::Agent.get_stats(metric).call_count
87
+ sum
88
+ end
89
+ end
90
+
91
+ def assert_does_not_call_metrics(*metrics)
92
+ first_metrics = generate_metric_counts(*metrics)
93
+ yield
94
+ last_metrics = generate_metric_counts(*metrics)
95
+ assert_equal first_metrics, last_metrics, "should not have changed these metrics"
96
+ end
97
+
98
+ def assert_calls_metrics(*metrics)
99
+ first_metrics = generate_metric_counts(*metrics)
100
+ yield
101
+ last_metrics = generate_metric_counts(*metrics)
102
+ assert_not_equal first_metrics, last_metrics, "should have changed these metrics"
103
+ end
104
+
105
+ def assert_calls_unscoped_metrics(*metrics)
106
+ first_metrics = generate_unscoped_metric_counts(*metrics)
107
+ yield
108
+ last_metrics = generate_unscoped_metric_counts(*metrics)
109
+ assert_not_equal first_metrics, last_metrics, "should have changed these metrics"
110
+ end
111
+
112
+
113
+ def compare_metrics(expected, actual)
114
+ actual.delete_if {|a| a.include?('GC/cumulative') } # in case we are in REE
115
+ assert_equal(expected.to_a.sort, actual.to_a.sort, "extra: #{(actual - expected).to_a.inspect}; missing: #{(expected - actual).to_a.inspect}")
116
+ end
117
+
118
+ module TransactionSampleTestHelper
119
+ def make_sql_transaction(*sql)
120
+ sampler = NewRelic::Agent::TransactionSampler.new
121
+ sampler.notice_first_scope_push Time.now.to_f
122
+ sampler.notice_transaction '/path', nil, :jim => "cool"
123
+ sampler.notice_push_scope "a"
124
+
125
+ sampler.notice_transaction '/path/2', nil, :jim => "cool"
126
+
127
+ sql.each {|sql_statement| sampler.notice_sql(sql_statement, {:adapter => "test"}, 0 ) }
128
+
129
+ sleep 0.02
130
+ yield if block_given?
131
+ sampler.notice_pop_scope "a"
132
+ sampler.notice_scope_empty
133
+
134
+ sampler.samples[0]
135
+ end
136
+
137
+ def run_sample_trace_on(sampler, path='/path')
138
+ sampler.notice_first_scope_push Time.now.to_f
139
+ sampler.notice_transaction path, path, {}
140
+ sampler.notice_push_scope "Controller/sandwiches/index"
141
+ sampler.notice_sql("SELECT * FROM sandwiches WHERE bread = 'wheat'", nil, 0)
142
+ sampler.notice_push_scope "ab"
143
+ sampler.notice_sql("SELECT * FROM sandwiches WHERE bread = 'white'", nil, 0)
144
+ yield sampler if block_given?
145
+ sampler.notice_pop_scope "ab"
146
+ sampler.notice_push_scope "lew"
147
+ sampler.notice_sql("SELECT * FROM sandwiches WHERE bread = 'french'", nil, 0)
148
+ sampler.notice_pop_scope "lew"
149
+ sampler.notice_pop_scope "Controller/sandwiches/index"
150
+ sampler.notice_scope_empty
151
+ sampler.samples[0]
152
+ end
153
+
154
+ end
@@ -0,0 +1,357 @@
1
+ require 'pathname'
2
+ require File.expand_path('../google_pie_chart', __FILE__)
3
+ require 'new_relic/collection_helper'
4
+ require 'new_relic/metric_parser/metric_parser'
5
+ module NewRelic::DeveloperModeHelper
6
+ include NewRelic::CollectionHelper
7
+
8
+ private
9
+
10
+ # limit of how many detail/SQL rows we display - very large data sets (~10000+) crash browsers
11
+ def trace_row_display_limit
12
+ 2000
13
+ end
14
+
15
+ def trace_row_display_limit_reached
16
+ (!@detail_segment_count.nil? && @detail_segment_count > trace_row_display_limit) || @sample.sql_segments.length > trace_row_display_limit
17
+ end
18
+
19
+ # return the sample but post processed to strip out segments that normally don't show
20
+ # up in production (after the first execution, at least) such as application code loading
21
+ def stripped_sample(sample = @sample)
22
+ sample.omit_segments_with('(Rails/Application Code Loading)|(Database/.*/.+ Columns)')
23
+ end
24
+
25
+ # return the highest level in the call stack for the trace that is not rails or
26
+ # newrelic agent code
27
+ def application_caller(trace)
28
+ trace = strip_nr_from_backtrace(trace) unless params[:show_nr]
29
+ trace.each do |trace_line|
30
+ file, line, gem = file_and_line(trace_line)
31
+ unless file && exclude_file_from_stack_trace?(file, false, gem)
32
+ return trace_line
33
+ end
34
+ end
35
+ trace.last
36
+ end
37
+
38
+ def application_stack_trace(trace, include_rails = false)
39
+ trace = strip_nr_from_backtrace(trace) unless params[:show_nr]
40
+ trace.reject do |trace_line|
41
+ file, line, gem = file_and_line(trace_line)
42
+ file && exclude_file_from_stack_trace?(file, include_rails, gem)
43
+ end
44
+ end
45
+
46
+ def render_backtrace
47
+ if @segment[:backtrace]
48
+ content_tag('h3', 'Application Stack Trace') +
49
+ render(:partial => 'stack_trace')
50
+ end
51
+ end
52
+
53
+ def h(text)
54
+ text
55
+ end
56
+
57
+ def agent_views_path(path)
58
+ path
59
+ end
60
+
61
+ def url_for_source(trace_line)
62
+ file, line = file_and_line(trace_line)
63
+ return "#" if file.nil?
64
+ begin
65
+ file = Pathname.new(file).realpath
66
+ rescue Errno::ENOENT
67
+ # we hit this exception when Pathame.realpath fails for some reason; attempt a link to
68
+ # the file without a real path. It may also fail, only when the user clicks on this specific
69
+ # entry in the stack trace
70
+ rescue
71
+ # catch all other exceptions. We're going to create an invalid link below, but that's okay.
72
+ end
73
+ if using_textmate?
74
+ "txmt://open?url=file://#{file}&line=#{line}"
75
+ else
76
+ "show_source?file=#{file}&amp;line=#{line}&amp;anchor=selected_line"
77
+ end
78
+ end
79
+
80
+ def dev_name(metric_name)
81
+ NewRelic::MetricParser::MetricParser.parse(metric_name).developer_name
82
+ end
83
+
84
+ # write the metric label for a segment metric in the detail view
85
+ def write_segment_label(segment)
86
+ if source_available && segment[:backtrace] && (source_url = url_for_source(application_caller(segment[:backtrace])))
87
+ link_to dev_name(segment.metric_name), source_url
88
+ else
89
+ dev_name(segment.metric_name)
90
+ end
91
+ end
92
+
93
+ def source_available
94
+ true
95
+ end
96
+
97
+ # write the metric label for a segment metric in the summary table of metrics
98
+ def write_summary_segment_label(segment)
99
+ dev_name(segment.metric_name)
100
+ end
101
+
102
+ def write_stack_trace_line(trace_line)
103
+ link_to trace_line, url_for_source(trace_line)
104
+ end
105
+
106
+ # write a link to the source for a trace
107
+ def link_to_source(trace)
108
+ image_url = 'file/images/' + (using_textmate? ? "textmate.png" : "file_icon.png")
109
+
110
+ link_to "<img src=#{image_url} alt=\"View Source\" title=\"View Source\"/>", url_for_source(application_caller(trace))
111
+ end
112
+
113
+ # print the formatted timestamp for a segment
114
+ def timestamp(segment)
115
+ sprintf("%1.3f", segment.entry_timestamp)
116
+ end
117
+
118
+ def format_timestamp(time)
119
+ time.strftime("%H:%M:%S")
120
+ end
121
+
122
+ def colorize(value, yellow_threshold = 0.05, red_threshold = 0.15, s=to_ms(value))
123
+ if value > yellow_threshold
124
+ color = (value > red_threshold ? 'red' : 'orange')
125
+ "<font color=#{color}>#{s}</font>"
126
+ else
127
+ "#{s}"
128
+ end
129
+ end
130
+
131
+ def expanded_image_path()
132
+ '/newrelic/file/images/arrow-open.png'
133
+ end
134
+
135
+ def collapsed_image_path()
136
+ '/newrelic/file/images/arrow-close.png'
137
+ end
138
+
139
+ def explain_sql_url(segment)
140
+ "explain_sql?id=#{@sample.sample_id}&amp;segment=#{segment.segment_id}"
141
+ end
142
+
143
+ def segment_duration_value(segment)
144
+ link_to colorize(segment.duration, 0.05, 0.15, "#{with_delimiter(to_ms(segment.duration))} ms"), explain_sql_url(segment)
145
+ end
146
+
147
+ def line_wrap_sql(sql)
148
+ sql.gsub(/\,/,', ').squeeze(' ') if sql
149
+ end
150
+
151
+ def render_sample_details(sample)
152
+ @indentation_depth=0
153
+ # skip past the root segments to the first child, which is always the controller
154
+ first_segment = sample.root_segment.called_segments.first
155
+
156
+ # render the segments, then the css classes to indent them
157
+ render_segment_details(first_segment).to_s + render_indentation_classes(@indentation_depth).to_s
158
+ end
159
+
160
+ # the rows logger plugin disables the sql tracing functionality of the NewRelic agent -
161
+ # notify the user about this
162
+ def rows_logger_present?
163
+ File.exist?(File.join(File.dirname(__FILE__), "../../../rows_logger/init.rb"))
164
+ end
165
+
166
+ def expand_segment_image(segment, depth)
167
+ if depth > 0
168
+ if !segment.called_segments.empty?
169
+ row_class =segment_child_row_class(segment)
170
+ link_to_function("<img src=\"#{collapsed_image_path}\" id=\"image_#{row_class}\" class_for_children=\"#{row_class}\" class=\"#{(!segment.called_segments.empty?) ? 'parent_segment_image' : 'child_segment_image'}\"", "toggle_row_class(this)")
171
+ end
172
+ end
173
+ end
174
+
175
+ def segment_child_row_class(segment)
176
+ "segment#{segment.segment_id}"
177
+ end
178
+
179
+ def summary_pie_chart(sample, width, height)
180
+ pie_chart = GooglePieChart.new
181
+ pie_chart.color, pie_chart.width, pie_chart.height = '6688AA', width, height
182
+
183
+ chart_data = sample.breakdown_data(6)
184
+ chart_data.each { |s| pie_chart.add_data_point dev_name(s.metric_name), to_ms(s.exclusive_time) }
185
+
186
+ pie_chart.render
187
+ end
188
+
189
+ def segment_row_classes(segment, depth)
190
+ classes = []
191
+
192
+ classes << "segment#{segment.parent_segment.segment_id}" if depth > 1
193
+
194
+ classes << "view_segment" if segment.metric_name.index('View') == 0
195
+ classes << "summary_segment" if segment.is_a?(NewRelic::TransactionSample::CompositeSegment)
196
+
197
+ classes.join(' ')
198
+ end
199
+
200
+ # render_segment_details should be called before calling this method
201
+ def render_indentation_classes(depth)
202
+ styles = []
203
+ (1..depth).each do |d|
204
+ styles << ".segment_indent_level#{d} { display: inline-block; margin-left: #{(d-1)*20}px }"
205
+ end
206
+ content_tag("style", styles.join(' '))
207
+ end
208
+
209
+ def sql_link_mouseover_options(segment)
210
+ { :onmouseover => "sql_mouse_over(#{segment.segment_id})", :onmouseout => "sql_mouse_out(#{segment.segment_id})"}
211
+ end
212
+
213
+ def explain_sql_link(segment, child_sql = false)
214
+ link_to 'SQL', explain_sql_url(segment)+ '"' + sql_link_mouseover_options(segment).map {|k,v| "#{k}=\"#{v}\""}.join(' ')+ 'fake=\"'
215
+ end
216
+
217
+ def explain_sql_links(segment)
218
+ if segment[:sql]
219
+ explain_sql_link segment
220
+ else
221
+ links = []
222
+ segment.called_segments.each do |child|
223
+ if child[:sql]
224
+ links << explain_sql_link(child, true)
225
+ end
226
+ end
227
+ links[0..1].join(', ') + (links.length > 2?', ...':'')
228
+ end
229
+ end
230
+
231
+ private
232
+ # return three objects, the file path, the line in the file, and the gem the file belongs to
233
+ # if found
234
+ def file_and_line(stack_trace_line)
235
+ if stack_trace_line =~ /^(?:(\w+) \([\d.]*\) )?(.*):(\d+)/
236
+ return $2, $3, $1
237
+ else
238
+ return nil
239
+ end
240
+ end
241
+
242
+ def using_textmate?
243
+ NewRelic::Control.instance.use_textmate?
244
+ end
245
+
246
+
247
+ def render_segment_details(segment, depth=0)
248
+ @detail_segment_count ||= 0
249
+ @detail_segment_count += 1
250
+
251
+ return '' if @detail_segment_count > trace_row_display_limit
252
+
253
+ @indentation_depth = depth if depth > @indentation_depth
254
+ repeat = nil
255
+ if segment.is_a?(NewRelic::TransactionSample::CompositeSegment)
256
+ html = ''
257
+ else
258
+ repeat = segment.parent_segment.detail_segments.length if segment.parent_segment.is_a?(NewRelic::TransactionSample::CompositeSegment)
259
+ html = render(:partial => 'segment', :object => [segment, depth, repeat])
260
+ depth += 1
261
+ end
262
+
263
+ segment.called_segments.each do |child|
264
+ html << render_segment_details(child, depth)
265
+ end
266
+
267
+ html
268
+ end
269
+
270
+ def exclude_file_from_stack_trace?(file, include_rails, gem=nil)
271
+ return false if include_rails
272
+ return true if file !~ /\.(rb|java)/
273
+ return true if %w[rack activerecord activeresource activesupport actionpack railties].include? gem
274
+ %w[/actionmailer/
275
+ /activerecord
276
+ /activeresource
277
+ /activesupport
278
+ /lib/mongrel
279
+ /actionpack
280
+ /passenger/
281
+ /railties
282
+ benchmark.rb].each { |s| return true if file.include? s }
283
+ false
284
+ end
285
+
286
+ def show_view_link(title, page_name)
287
+ link_to_function("[#{title}]", "show_view('#{page_name}')");
288
+ end
289
+
290
+
291
+ def link_to(name, location)
292
+ location = "/newrelic/#{location}" unless /:\/\// =~ location
293
+ "<a href=\"#{location}\">#{name}</a>"
294
+ end
295
+
296
+ def link_to_if(predicate, text, location="")
297
+ if predicate
298
+ link_to(text, location)
299
+ else
300
+ text
301
+ end
302
+ end
303
+
304
+ def link_to_unless_current(text, hash)
305
+ unless params[hash.keys[0].to_s]
306
+ link_to(text,"?#{hash.keys[0]}=#{hash.values[0]}")
307
+ else
308
+ text
309
+ end
310
+ end
311
+
312
+ def cycle(even, odd)
313
+ @cycle ||= 'a'
314
+ if @cycle == 'a'
315
+ @cycle = 'b'
316
+ even
317
+ else
318
+ @cycle = 'a'
319
+ odd
320
+ end
321
+ end
322
+
323
+ def link_to_function(title, javascript)
324
+ "<a href=\"#\" onclick=\"#{javascript}; return false;\">#{title}</a>"
325
+ end
326
+
327
+ def mime_type_from_extension(extension)
328
+ extension = extension[/[^.]*$/].dncase
329
+ case extension
330
+ when 'png'; 'image/png'
331
+ when 'gif'; 'image/gif'
332
+ when 'jpg'; 'image/jpg'
333
+ when 'css'; 'text/css'
334
+ when 'js'; 'text/javascript'
335
+ else 'text/plain'
336
+ end
337
+ end
338
+ def to_ms(number)
339
+ (number*1000).round
340
+ end
341
+ def to_percentage(value)
342
+ (value * 100).round if value
343
+ end
344
+ def with_delimiter(val)
345
+ return '0' if val.nil?
346
+ parts = val.to_s.split('.')
347
+ parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
348
+ parts.join '.'
349
+ end
350
+
351
+ def profile_table(profile)
352
+ out = StringIO.new
353
+ printer = RubyProf::GraphHtmlPrinter.new(profile)
354
+ printer.print(out, :min_percent=>0.5)
355
+ out.string[/<body>(.*)<\/body>/im, 0].gsub('<table>', '<table class=profile>')
356
+ end
357
+ end
@@ -0,0 +1,48 @@
1
+
2
+ # A wrapper around the google charts service.
3
+ class GooglePieChart
4
+ attr_accessor :width, :height, :color
5
+
6
+ def initialize
7
+ # an array of [label, value]
8
+ @data = []
9
+ self.width = 300
10
+ self.height = 200
11
+ end
12
+
13
+ def add_data_point(label, value)
14
+ @data << [label, value]
15
+ @max = (@max.nil? || @max < value ? value : @max)
16
+ end
17
+
18
+ # render the chart to html by creating an image object and
19
+ # placing the correct URL to the google charts api
20
+ def render
21
+ labels = []
22
+ values = []
23
+ @data.each do |label, value|
24
+ labels << CGI::escape(label)
25
+ values << (value > 0 ? value * 100 / @max : value).round.to_s
26
+ end
27
+ params = {:cht => 'p', :chs => "#{width}x#{height}", :chd => "t:#{values.join(',')}", :chl => labels.join('|') }
28
+ params['chco'] = color if color
29
+
30
+ url = "http://chart.apis.google.com/chart?#{to_query(params)}"
31
+
32
+ alt_msg = "This pie chart is generated by Google Charts. You must be connected to the Internet to view this chart."
33
+ html = "<img id=\"pie_chart_image\" src=\"#{url}\" alt=\"#{alt_msg}\"/>"
34
+ return html
35
+ end
36
+
37
+ private
38
+ # Hash#to_query is not present in all supported rails platforms, so implement
39
+ # its equivalent here.
40
+ def to_query(params)
41
+ p = []
42
+ params.each do |k,v|
43
+ p << "#{k}=#{v}"
44
+ end
45
+
46
+ p.join "&"
47
+ end
48
+ end