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,201 @@
1
+ require 'new_relic/transaction_sample'
2
+ module NewRelic
3
+ class TransactionSample
4
+ class Segment
5
+ attr_reader :entry_timestamp
6
+ # The exit timestamp will be relative except for the outermost sample which will
7
+ # have a timestamp.
8
+ attr_reader :exit_timestamp
9
+ attr_reader :parent_segment
10
+ attr_reader :metric_name
11
+ attr_reader :segment_id
12
+
13
+ def initialize(timestamp, metric_name, segment_id)
14
+ @entry_timestamp = timestamp
15
+ @metric_name = metric_name || '<unknown>'
16
+ @segment_id = segment_id || object_id
17
+ end
18
+
19
+ # sets the final timestamp on a segment to indicate the exit
20
+ # point of the segment
21
+ def end_trace(timestamp)
22
+ @exit_timestamp = timestamp
23
+ end
24
+
25
+ def add_called_segment(s)
26
+ @called_segments ||= []
27
+ @called_segments << s
28
+ s.parent_segment = self
29
+ end
30
+
31
+ def to_s
32
+ to_debug_str(0)
33
+ end
34
+
35
+ def to_json(options={})
36
+ hash = {
37
+ :entry_timestamp => @entry_timestamp,
38
+ :exit_timestamp => @exit_timestamp,
39
+ :metric_name => @metric_name,
40
+ :segment_id => @segment_id,
41
+ }
42
+
43
+ hash[:called_segments] = called_segments if !called_segments.empty?
44
+ hash[:params] = @params if @params && !@params.empty?
45
+
46
+ hash.to_json
47
+ end
48
+
49
+ def path_string
50
+ "#{metric_name}[#{called_segments.collect {|segment| segment.path_string }.join('')}]"
51
+ end
52
+ def to_s_compact
53
+ str = ""
54
+ str << metric_name
55
+ if called_segments.any?
56
+ str << "{#{called_segments.map { | cs | cs.to_s_compact }.join(",")}}"
57
+ end
58
+ str
59
+ end
60
+ def to_debug_str(depth)
61
+ tab = " " * depth
62
+ s = tab.clone
63
+ s << ">> #{'%3i ms' % (@entry_timestamp*1000)} [#{self.class.name.split("::").last}] #{metric_name} \n"
64
+ unless params.empty?
65
+ params.each do |k,v|
66
+ s << "#{tab} -#{'%-16s' % k}: #{v.to_s[0..80]}\n"
67
+ end
68
+ end
69
+ called_segments.each do |cs|
70
+ s << cs.to_debug_str(depth + 1)
71
+ end
72
+ s << tab + "<< "
73
+ s << case @exit_timestamp
74
+ when nil then ' n/a'
75
+ when Numeric then '%3i ms' % (@exit_timestamp*1000)
76
+ else @exit_timestamp.to_s
77
+ end
78
+ s << " #{metric_name}\n"
79
+ end
80
+
81
+ def called_segments
82
+ @called_segments || []
83
+ end
84
+
85
+ # return the total duration of this segment
86
+ def duration
87
+ (@exit_timestamp - @entry_timestamp).to_f
88
+ end
89
+
90
+ # return the duration of this segment without
91
+ # including the time in the called segments
92
+ def exclusive_duration
93
+ d = duration
94
+
95
+ called_segments.each do |segment|
96
+ d -= segment.duration
97
+ end
98
+ d
99
+ end
100
+ def count_segments
101
+ count = 1
102
+ called_segments.each { | seg | count += seg.count_segments }
103
+ count
104
+ end
105
+ # Walk through the tree and truncate the segments in a
106
+ # depth-first manner
107
+ def truncate(max)
108
+ return 1 unless @called_segments
109
+ total, self.called_segments = truncate_each_child(max - 1)
110
+ total+1
111
+ end
112
+
113
+ def truncate_each_child(max)
114
+ total = 0
115
+ accumulator = []
116
+ called_segments.each { | s |
117
+ if total == max
118
+ true
119
+ else
120
+ total += s.truncate(max - total)
121
+ accumulator << s
122
+ end
123
+ }
124
+ total
125
+ [total, accumulator]
126
+ end
127
+
128
+ def []=(key, value)
129
+ # only create a parameters field if a parameter is set; this will save
130
+ # bandwidth etc as most segments have no parameters
131
+ params[key] = value
132
+ end
133
+
134
+ def [](key)
135
+ params[key]
136
+ end
137
+
138
+ def params
139
+ @params ||= {}
140
+ end
141
+
142
+ # call the provided block for this segment and each
143
+ # of the called segments
144
+ def each_segment(&block)
145
+ block.call self
146
+
147
+ if @called_segments
148
+ @called_segments.each do |segment|
149
+ segment.each_segment(&block)
150
+ end
151
+ end
152
+ end
153
+
154
+ # call the provided block for this segment and each
155
+ # of the called segments while keeping track of nested segments
156
+ def each_segment_with_nest_tracking(&block)
157
+ summary = block.call self
158
+ summary.current_nest_count += 1 if summary
159
+
160
+ if @called_segments
161
+ @called_segments.each do |segment|
162
+ segment.each_segment_with_nest_tracking(&block)
163
+ end
164
+ end
165
+
166
+ summary.current_nest_count -= 1 if summary
167
+ end
168
+
169
+ def find_segment(id)
170
+ return self if @segment_id == id
171
+ called_segments.each do |segment|
172
+ found = segment.find_segment(id)
173
+ return found if found
174
+ end
175
+ nil
176
+ end
177
+
178
+ def explain_sql
179
+ NewRelic::Agent::Database.explain_sql(params[:sql],
180
+ params[:connection_config])
181
+ end
182
+
183
+ def obfuscated_sql
184
+ NewRelic::Agent::Database.obfuscate_sql(params[:sql])
185
+ end
186
+
187
+ def params=(p)
188
+ @params = p
189
+ end
190
+
191
+ def called_segments=(segments)
192
+ @called_segments = segments
193
+ end
194
+
195
+ protected
196
+ def parent_segment=(s)
197
+ @parent_segment = s
198
+ end
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,21 @@
1
+ require 'new_relic/transaction_sample'
2
+ require 'new_relic/transaction_sample/segment'
3
+ module NewRelic
4
+ class TransactionSample
5
+ class SummarySegment < Segment
6
+ def initialize(segment)
7
+ super segment.entry_timestamp, segment.metric_name, nil
8
+
9
+ add_segments segment.called_segments
10
+
11
+ end_trace segment.exit_timestamp
12
+ end
13
+
14
+ def add_segments(segments)
15
+ segments.collect do |segment|
16
+ SummarySegment.new(segment)
17
+ end.each {|segment| add_called_segment(segment)}
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,245 @@
1
+ require 'new_relic/transaction_sample/segment'
2
+ require 'new_relic/transaction_sample/summary_segment'
3
+ require 'new_relic/transaction_sample/fake_segment'
4
+ require 'new_relic/transaction_sample/composite_segment'
5
+ module NewRelic
6
+ # the number of segments that need to exist before we roll them up
7
+ # into one segment with multiple executions
8
+ COLLAPSE_SEGMENTS_THRESHOLD = 2
9
+
10
+ class TransactionSample
11
+
12
+ attr_accessor :params, :root_segment
13
+ attr_accessor :profile
14
+ attr_reader :root_segment
15
+ attr_reader :params
16
+ attr_reader :sample_id
17
+
18
+ @@start_time = Time.now
19
+
20
+ include TransactionAnalysis
21
+
22
+ def initialize(time = Time.now.to_f, sample_id = nil)
23
+ @sample_id = sample_id || object_id
24
+ @start_time = time
25
+ @root_segment = create_segment 0.0, "ROOT"
26
+ @params = {}
27
+ @params[:request_params] = {}
28
+ end
29
+
30
+ def count_segments
31
+ @root_segment.count_segments - 1 # don't count the root segment
32
+ end
33
+
34
+ # Truncates the transaction sample to a maximum length determined
35
+ # by the passed-in parameter. Operates recursively on the entire
36
+ # tree of transaction segments in a depth-first manner
37
+ def truncate(max)
38
+ count = count_segments
39
+ return if count < max
40
+ @root_segment.truncate(max + 1)
41
+
42
+ ensure_segment_count_set(count)
43
+ end
44
+
45
+ # makes sure that the parameter cache for segment count is set to
46
+ # the correct value
47
+ def ensure_segment_count_set(count)
48
+ params[:segment_count] ||= count
49
+ end
50
+
51
+ # offset from start of app
52
+ def timestamp
53
+ @start_time - @@start_time.to_f
54
+ end
55
+
56
+ # Used in the server only
57
+ def to_json(options = {}) #:nodoc:
58
+ map = {:sample_id => @sample_id,
59
+ :start_time => @start_time,
60
+ :root_segment => @root_segment}
61
+ if @params && !@params.empty?
62
+ map[:params] = @params
63
+ end
64
+ map.to_json
65
+ end
66
+
67
+ def start_time
68
+ Time.at(@start_time)
69
+ end
70
+
71
+ def path_string
72
+ @root_segment.path_string
73
+ end
74
+
75
+ def create_segment(relative_timestamp, metric_name, segment_id = nil)
76
+ raise TypeError.new("Frozen Transaction Sample") if frozen?
77
+ NewRelic::TransactionSample::Segment.new(relative_timestamp, metric_name, segment_id)
78
+ end
79
+
80
+ def duration
81
+ root_segment.duration
82
+ end
83
+
84
+ # Iterates recursively over each segment in the entire transaction
85
+ # sample tree
86
+ def each_segment(&block)
87
+ @root_segment.each_segment(&block)
88
+ end
89
+
90
+ # Iterates recursively over each segment in the entire transaction
91
+ # sample tree while keeping track of nested segments
92
+ def each_segment_with_nest_tracking(&block)
93
+ @root_segment.each_segment_with_nest_tracking(&block)
94
+ end
95
+
96
+ def to_s_compact
97
+ @root_segment.to_s_compact
98
+ end
99
+
100
+ # Searches the tree recursively for the segment with the given
101
+ # id. note that this is an internal id, not an ActiveRecord id
102
+ def find_segment(id)
103
+ @root_segment.find_segment(id)
104
+ end
105
+
106
+ def to_s
107
+ s = "Transaction Sample collected at #{start_time}\n"
108
+ s << " {\n"
109
+ s << " Path: #{params[:path]} \n"
110
+
111
+ params.each do |k,v|
112
+ next if k == :path
113
+ s << " #{k}: " <<
114
+ case v
115
+ when Enumerable then v.map(&:to_s).sort.join("; ")
116
+ when String then v
117
+ when Float then '%6.3s' % v
118
+ when nil then ''
119
+ else
120
+ raise "unexpected value type for #{k}: '#{v}' (#{v.class})"
121
+ end << "\n"
122
+ end
123
+ s << " }\n\n"
124
+ s << @root_segment.to_debug_str(0)
125
+ end
126
+
127
+ # return a new transaction sample that treats segments
128
+ # with the given regular expression in their name as if they
129
+ # were never called at all. This allows us to strip out segments
130
+ # from traces captured in development environment that would not
131
+ # normally show up in production (like Rails/Application Code Loading)
132
+ def omit_segments_with(regex)
133
+ regex = Regexp.new(regex)
134
+
135
+ sample = TransactionSample.new(@start_time, sample_id)
136
+
137
+ params.each {|k,v| sample.params[k] = v}
138
+
139
+ delta = build_segment_with_omissions(sample, 0.0, @root_segment, sample.root_segment, regex)
140
+ sample.root_segment.end_trace(@root_segment.exit_timestamp - delta)
141
+ sample.profile = self.profile
142
+ sample
143
+ end
144
+
145
+ # Return a new transaction sample that can be sent to the New
146
+ # Relic service. This involves potentially one or more of the
147
+ # following options
148
+ #
149
+ # :explain_sql : run EXPLAIN on all queries whose response times equal the value for this key
150
+ # (for example :explain_sql => 2.0 would explain everything over 2 seconds. 0.0 would explain everything.)
151
+ # :keep_backtraces : keep backtraces, significantly increasing size of trace (off by default)
152
+ # :record_sql => [ :raw | :obfuscated] : copy over the sql, obfuscating if necessary
153
+ def prepare_to_send(options={})
154
+ sample = TransactionSample.new(@start_time, sample_id)
155
+
156
+ sample.params.merge! self.params
157
+
158
+ begin
159
+ build_segment_for_transfer(sample, @root_segment, sample.root_segment, options)
160
+ ensure
161
+ NewRelic::Agent::Database.close_connections
162
+ end
163
+
164
+ sample.root_segment.end_trace(@root_segment.exit_timestamp)
165
+ sample
166
+ end
167
+
168
+ def params=(params)
169
+ @params = params
170
+ end
171
+
172
+ private
173
+
174
+ # This is badly in need of refactoring
175
+ def build_segment_with_omissions(new_sample, time_delta, source_segment, target_segment, regex)
176
+ source_segment.called_segments.each do |source_called_segment|
177
+ # if this segment's metric name matches the given regular expression, bail
178
+ # here and increase the amount of time that we reduce the target sample with
179
+ # by this omitted segment's duration.
180
+ do_omit = regex =~ source_called_segment.metric_name
181
+
182
+ if do_omit
183
+ time_delta += source_called_segment.duration
184
+ else
185
+ target_called_segment = new_sample.create_segment(
186
+ source_called_segment.entry_timestamp - time_delta,
187
+ source_called_segment.metric_name,
188
+ source_called_segment.segment_id)
189
+
190
+ target_segment.add_called_segment target_called_segment
191
+ source_called_segment.params.each do |k,v|
192
+ target_called_segment[k]=v
193
+ end
194
+
195
+ time_delta = build_segment_with_omissions(
196
+ new_sample, time_delta, source_called_segment, target_called_segment, regex)
197
+ target_called_segment.end_trace(source_called_segment.exit_timestamp - time_delta)
198
+ end
199
+ end
200
+
201
+ return time_delta
202
+ end
203
+
204
+ # see prepare_to_send for what we do with options
205
+ #
206
+ # This is badly in need of refactoring
207
+ def build_segment_for_transfer(new_sample, source_segment, target_segment, options)
208
+ source_segment.called_segments.each do |source_called_segment|
209
+ target_called_segment = new_sample.create_segment(
210
+ source_called_segment.entry_timestamp,
211
+ source_called_segment.metric_name,
212
+ source_called_segment.segment_id)
213
+
214
+ target_segment.add_called_segment target_called_segment
215
+ source_called_segment.params.each do |k,v|
216
+ case k
217
+ when :backtrace
218
+ target_called_segment[k]=v if options[:keep_backtraces]
219
+ when :sql
220
+ # run an EXPLAIN on this sql if specified.
221
+ if options[:record_sql] && options[:record_sql] &&
222
+ options[:explain_sql] &&
223
+ source_called_segment.duration > options[:explain_sql].to_f
224
+ target_called_segment[:explain_plan] = source_called_segment.explain_sql
225
+ end
226
+
227
+ target_called_segment[:sql] = case options[:record_sql]
228
+ when :raw then v
229
+ when :obfuscated then NewRelic::Agent::Database.obfuscate_sql(v)
230
+ else raise "Invalid value for record_sql: #{options[:record_sql]}"
231
+ end if options[:record_sql]
232
+ when :connection_config
233
+ # don't copy it
234
+ else
235
+ target_called_segment[k]=v
236
+ end
237
+ end
238
+
239
+ build_segment_for_transfer(new_sample, source_called_segment, target_called_segment, options)
240
+ target_called_segment.end_trace(source_called_segment.exit_timestamp)
241
+ end
242
+ end
243
+
244
+ end
245
+ end
@@ -0,0 +1,14 @@
1
+ # Represents url mapping rules stored on the server. These rules should be applied
2
+ # to URLs which are not normalized into controller class/action by Rails routes.
3
+ # Insantiated strictly by Marshal.
4
+ class NewRelic::UrlRule
5
+ attr_reader :match_expression, :replacement, :eval_order, :terminate_chain
6
+
7
+ def apply url
8
+ return nil
9
+ end
10
+
11
+ class RuleSet
12
+
13
+ end
14
+ end
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/ruby
2
+ module NewRelic
3
+ module VERSION #:nodoc:
4
+ MAJOR = 3
5
+ MINOR = 2
6
+ TINY = 0
7
+ BUILD = 2 #'0' # Set to nil for a release, 'beta1', 'alpha', etc for prerelease builds
8
+ STRING = [MAJOR, MINOR, TINY, BUILD].compact.join('.')
9
+ end
10
+
11
+ # Helper class for managing version comparisons
12
+ class VersionNumber
13
+ attr_reader :parts
14
+ include Comparable
15
+ def initialize(version_string)
16
+ version_string ||= '1.0.0'
17
+ @parts = version_string.split('.').map{|n| n =~ /^\d+$/ ? n.to_i : n}
18
+ end
19
+ def major_version; @parts[0]; end
20
+ def minor_version; @parts[1]; end
21
+ def tiny_version; @parts[2]; end
22
+
23
+ def <=>(other)
24
+ other = self.class.new(other) if other.is_a? String
25
+ self.class.compare(self.parts, other.parts)
26
+ end
27
+
28
+ def to_s
29
+ @parts.join(".")
30
+ end
31
+
32
+ def hash
33
+ @parts.hash
34
+ end
35
+
36
+ def eql? other
37
+ (self <=> other) == 0
38
+ end
39
+
40
+ private
41
+ def self.compare(parts1, parts2)
42
+ a, b = parts1.first, parts2.first
43
+ case
44
+ when a.nil? && b.nil? then 0
45
+ when a.nil? then b.is_a?(Fixnum) ? -1 : 1
46
+ when b.nil? then -compare(parts2, parts1)
47
+ when a.to_s == b.to_s then compare(parts1[1..-1], parts2[1..-1])
48
+ when a.is_a?(String) then b.is_a?(Fixnum) ? -1 : (a <=> b)
49
+ when b.is_a?(String) then -compare(parts2, parts1)
50
+ else # they are both fixnums, not nil
51
+ a <=> b
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,49 @@
1
+ # == New Relic Initialization
2
+ #
3
+ # When installed as a gem, you can activate the New Relic agent one of the following ways:
4
+ #
5
+ # For Rails, add:
6
+ # config.gem 'newrelic_rpm'
7
+ # to your initialization sequence.
8
+ #
9
+ # For merb, do
10
+ # dependency 'newrelic_rpm'
11
+ # in the Merb config/init.rb
12
+ #
13
+ # For Sinatra, do
14
+ # require 'newrelic_rpm'
15
+ # after requiring 'sinatra'.
16
+ #
17
+ # For other frameworks, or to manage the agent manually, invoke NewRelic::Agent#manual_start
18
+ # directly.
19
+ #
20
+ require 'new_relic/control'
21
+ if defined?(Merb) && defined?(Merb::BootLoader)
22
+ module NewRelic
23
+ class MerbBootLoader < Merb::BootLoader
24
+ after Merb::BootLoader::ChooseAdapter
25
+ def self.run
26
+ NewRelic::Control.instance.init_plugin
27
+ end
28
+ end
29
+ end
30
+ elsif defined? Rails
31
+ if Rails.respond_to?(:version) && Rails.version =~ /^3/
32
+ module NewRelic
33
+ class Railtie < Rails::Railtie
34
+
35
+ initializer "newrelic_rpm.start_plugin" do |app|
36
+ NewRelic::Control.instance.init_plugin(:config => app.config)
37
+ end
38
+ end
39
+ end
40
+ else
41
+ # After verison 2.0 of Rails we can access the configuration directly.
42
+ # We need it to add dev mode routes after initialization finished.
43
+ config = nil
44
+ config = Rails.configuration if Rails.respond_to?(:configuration)
45
+ NewRelic::Control.instance.init_plugin :config => config
46
+ end
47
+ else
48
+ NewRelic::Control.instance.init_plugin
49
+ end
data/lib/tasks/all.rb ADDED
@@ -0,0 +1,4 @@
1
+ # This is required to load in task definitions from merb
2
+ Dir.glob(File.join(File.dirname(__FILE__),'*.rake')) do |file|
3
+ load file
4
+ end
@@ -0,0 +1,7 @@
1
+ # run unit tests for the NewRelic Agent
2
+ namespace :newrelic do
3
+ desc "install a default config/newrelic.yml file"
4
+ task :install do
5
+ load File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "install.rb"))
6
+ end
7
+ end
@@ -0,0 +1,19 @@
1
+ # run unit tests for the NewRelic Agent
2
+ begin
3
+ require 'rake/test_task'
4
+ rescue LoadError => e
5
+ end
6
+
7
+ if defined? Rake::TestTask
8
+ namespace :test do
9
+ AGENT_HOME = File.expand_path(File.join(File.dirname(__FILE__), "..",".."))
10
+ Rake::TestTask.new(:newrelic) do |t|
11
+ t.libs << "#{AGENT_HOME}/test"
12
+ t.libs << "#{AGENT_HOME}/lib"
13
+ t.pattern = "#{AGENT_HOME}/test/**/*_test.rb"
14
+ t.verbose = true
15
+ end
16
+ Rake::Task['test:newrelic'].comment = "Run the unit tests for the Agent"
17
+ task :newrelic => :environment
18
+ end
19
+ end