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,50 @@
1
+ # A Sampler is used to capture meaningful metrics in a background thread
2
+ # periodically. They will either be invoked once a minute just before the
3
+ # data is sent to the agent (default) or every 10 seconds, when #use_harvest_sampler?
4
+ # returns false.
5
+ #
6
+ # Samplers can be added to New Relic by subclassing NewRelic::Agent::Sampler.
7
+ # Instances are created when the agent is enabled and installed. Subclasses
8
+ # are registered for instantiation automatically.
9
+ module NewRelic
10
+ module Agent
11
+ class Sampler
12
+
13
+ # Exception denotes a sampler is not available and it will not be registered.
14
+ class Unsupported < StandardError; end
15
+
16
+ attr_accessor :stats_engine
17
+ attr_reader :id
18
+ @sampler_classes = []
19
+
20
+ def self.inherited(subclass)
21
+ @sampler_classes << subclass
22
+ end
23
+
24
+ # Override with check. Called before instantiating.
25
+ def self.supported_on_this_platform?
26
+ true
27
+ end
28
+
29
+ # Override to use the periodic sampler instead of running the sampler on the
30
+ # minute during harvests.
31
+ def self.use_harvest_sampler?
32
+ true
33
+ end
34
+
35
+ def self.sampler_classes
36
+ @sampler_classes
37
+ end
38
+
39
+ def initialize(id)
40
+ @id = id
41
+ end
42
+
43
+ def poll
44
+ raise "Implement in the subclass"
45
+ end
46
+
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,58 @@
1
+ require 'new_relic/agent/sampler'
2
+
3
+ module NewRelic
4
+ module Agent
5
+ module Samplers
6
+ class CpuSampler < NewRelic::Agent::Sampler
7
+ attr_reader :last_time
8
+ def initialize
9
+ super :cpu
10
+ poll
11
+ end
12
+
13
+ def user_util_stats
14
+ stats_engine.get_stats_no_scope("CPU/User/Utilization")
15
+ end
16
+ def system_util_stats
17
+ stats_engine.get_stats_no_scope("CPU/System/Utilization")
18
+ end
19
+ def usertime_stats
20
+ stats_engine.get_stats_no_scope("CPU/User Time")
21
+ end
22
+ def systemtime_stats
23
+ stats_engine.get_stats_no_scope("CPU/System Time")
24
+ end
25
+
26
+ def self.supported_on_this_platform?
27
+ # Process.times on JRuby reports wall clock elapsed time,
28
+ # not actual cpu time used, so we cannot use this sampler there.
29
+ not defined?(JRuby)
30
+ end
31
+
32
+ def poll
33
+ now = Time.now
34
+ t = Process.times
35
+ if @last_time
36
+ elapsed = now - @last_time
37
+ return if elapsed < 1 # Causing some kind of math underflow
38
+ num_processors = NewRelic::Control.instance.local_env.processors || 1
39
+ usertime = t.utime - @last_utime
40
+ systemtime = t.stime - @last_stime
41
+
42
+ systemtime_stats.record_data_point(systemtime) if systemtime >= 0
43
+ usertime_stats.record_data_point(usertime) if usertime >= 0
44
+
45
+ # Calculate the true utilization by taking cpu times and dividing by
46
+ # elapsed time X num_processors.
47
+ user_util_stats.record_data_point usertime / (elapsed * num_processors)
48
+ system_util_stats.record_data_point systemtime / (elapsed * num_processors)
49
+ end
50
+ @last_utime = t.utime
51
+ @last_stime = t.stime
52
+ @last_time = now
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,40 @@
1
+ require 'new_relic/agent/sampler'
2
+ require 'new_relic/delayed_job_injection'
3
+
4
+ module NewRelic
5
+ module Agent
6
+ module Samplers
7
+ class DelayedJobLockSampler < NewRelic::Agent::Sampler
8
+ def initialize
9
+ super :delayed_job_lock
10
+ raise Unsupported, "DJ instrumentation disabled" if NewRelic::Control.instance['disable_dj']
11
+ raise Unsupported, "No DJ worker present" unless NewRelic::DelayedJobInjection.worker_name
12
+ end
13
+
14
+ def stats
15
+ stats_engine.get_stats("Custom/DJ Locked Jobs", false)
16
+ end
17
+
18
+ def local_env
19
+ NewRelic::Control.instance.local_env
20
+ end
21
+
22
+ def worker_name
23
+ local_env.dispatcher_instance_id
24
+ end
25
+
26
+ def locked_jobs
27
+ Delayed::Job.count(:conditions => {:locked_by => NewRelic::DelayedJobInjection.worker_name})
28
+ end
29
+
30
+ def self.supported_on_this_platform?
31
+ defined?(Delayed::Job)
32
+ end
33
+
34
+ def poll
35
+ stats.record_data_point locked_jobs
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,144 @@
1
+ require 'new_relic/agent/sampler'
2
+
3
+ module NewRelic
4
+ module Agent
5
+ module Samplers
6
+
7
+ class MemorySampler < NewRelic::Agent::Sampler
8
+ attr_accessor :sampler
9
+
10
+ def initialize
11
+ super :memory
12
+ # macos, linux, solaris
13
+ if defined? JRuby
14
+ @sampler = JavaHeapSampler.new
15
+ elsif platform =~ /linux/
16
+ @sampler = ProcStatus.new
17
+ if !@sampler.can_run?
18
+ NewRelic::Agent.instance.warn.debug "Error attempting to use /proc/#{$$}/status file for reading memory. Using ps command instead."
19
+ @sampler = ShellPS.new("ps -o rsz")
20
+ else
21
+ NewRelic::Agent.instance.log.debug "Using /proc/#{$$}/status for reading process memory."
22
+ end
23
+ elsif platform =~ /darwin9/ # 10.5
24
+ @sampler = ShellPS.new("ps -o rsz")
25
+ elsif platform =~ /darwin1[01]/ # 10.6 & 10.7
26
+ @sampler = ShellPS.new("ps -o rss")
27
+ elsif platform =~ /freebsd/
28
+ @sampler = ShellPS.new("ps -o rss")
29
+ elsif platform =~ /solaris/
30
+ @sampler = ShellPS.new("/usr/bin/ps -o rss -p")
31
+ end
32
+
33
+ raise Unsupported, "Unsupported platform for getting memory: #{platform}" if @sampler.nil?
34
+ raise Unsupported, "Unable to run #{@sampler}" unless @sampler.can_run?
35
+ end
36
+
37
+ def self.supported_on_this_platform?
38
+ defined?(JRuby) or platform =~ /linux|darwin9|darwin10|freebsd|solaris/
39
+ end
40
+
41
+ def self.platform
42
+ if RUBY_PLATFORM =~ /java/
43
+ %x[uname -s].downcase
44
+ else
45
+ RUBY_PLATFORM.downcase
46
+ end
47
+ end
48
+ def platform
49
+ NewRelic::Agent::Samplers::MemorySampler.platform
50
+ end
51
+
52
+ def stats
53
+ stats_engine.get_stats("Memory/Physical", false)
54
+ end
55
+ def poll
56
+ sample = @sampler.get_sample
57
+ stats.record_data_point sample if sample
58
+ stats
59
+ end
60
+ class Base
61
+ def can_run?
62
+ return false if @broken
63
+ m = get_memory rescue nil
64
+ m && m > 0
65
+ end
66
+ def get_sample
67
+ return nil if @broken
68
+ begin
69
+ m = get_memory
70
+ if m.nil?
71
+ NewRelic::Agent.instance.log.error "Unable to get the resident memory for process #{$$}. Disabling memory sampler."
72
+ @broken = true
73
+ end
74
+ return m
75
+ rescue => e
76
+ NewRelic::Agent.instance.log.error "Unable to get the resident memory for process #{$$}. (#{e})"
77
+ NewRelic::Agent.instance.log.debug e.backtrace.join("\n ")
78
+ NewRelic::Agent.instance.log.error "Disabling memory sampler."
79
+ @broken = true
80
+ return nil
81
+ end
82
+ end
83
+ end
84
+
85
+ class JavaHeapSampler < Base
86
+
87
+ def get_memory
88
+ raise "Can't sample Java heap unless running in JRuby" unless defined? JRuby
89
+ java.lang.Runtime.getRuntime.totalMemory / (1024 * 1024).to_f rescue nil
90
+ end
91
+ def to_s
92
+ "JRuby Java heap sampler"
93
+ end
94
+ end
95
+
96
+ class ShellPS < Base
97
+ def initialize(command)
98
+ super()
99
+ @command = command
100
+ end
101
+ # Returns the amount of resident memory this process is using in MB
102
+ #
103
+ def get_memory
104
+ process = $$
105
+ memory = `#{@command} #{process}`.split("\n")[1].to_f / 1024.0 rescue nil
106
+ # if for some reason the ps command doesn't work on the resident os,
107
+ # then don't execute it any more.
108
+ raise "Faulty command: `#{@command} #{process}`" if memory.nil? || memory <= 0
109
+ memory
110
+ end
111
+ def to_s
112
+ "shell command sampler: #{@command}"
113
+ end
114
+ end
115
+
116
+ # ProcStatus
117
+ #
118
+ # A class that samples memory by reading the file /proc/$$/status, which is specific to linux
119
+ #
120
+ class ProcStatus < Base
121
+
122
+ # Returns the amount of resident memory this process is using in MB
123
+ #
124
+ def get_memory
125
+ File.open(proc_status_file, "r") do |f|
126
+ while !f.eof?
127
+ if f.readline =~ /RSS:\s*(\d+) kB/i
128
+ return $1.to_f / 1024.0
129
+ end
130
+ end
131
+ end
132
+ raise "Unable to find RSS in #{proc_status_file}"
133
+ end
134
+ def proc_status_file
135
+ "/proc/#{$$}/status"
136
+ end
137
+ def to_s
138
+ "proc status file sampler: #{proc_status_file}"
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,26 @@
1
+ require 'new_relic/agent/sampler'
2
+
3
+ module NewRelic
4
+ module Agent
5
+ module Samplers
6
+ class ObjectSampler < NewRelic::Agent::Sampler
7
+
8
+ def initialize
9
+ super :objects
10
+ end
11
+
12
+ def stats
13
+ stats_engine.get_stats_no_scope("GC/objects")
14
+ end
15
+
16
+ def self.supported_on_this_platform?
17
+ defined?(ObjectSpace) && ObjectSpace.respond_to?(:live_objects)
18
+ end
19
+
20
+ def poll
21
+ stats.record_data_point(ObjectSpace.live_objects)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ # This agent is loaded by the plug when the plug-in is disabled
2
+ # It recreates just enough of the API to not break any clients that
3
+ # invoke the Agent.
4
+ module NewRelic
5
+ module Agent
6
+ class ShimAgent < NewRelic::Agent::Agent
7
+ def self.instance
8
+ @instance ||= self.new
9
+ end
10
+ def initialize
11
+ super
12
+ @stats_engine.extend NewRelic::Agent::StatsEngine::Shim
13
+ @stats_engine.extend NewRelic::Agent::StatsEngine::Transactions::Shim
14
+ @transaction_sampler.extend NewRelic::Agent::TransactionSampler::Shim
15
+ @sql_sampler.extend NewRelic::Agent::SqlSampler::Shim
16
+ @error_collector.extend NewRelic::Agent::ErrorCollector::Shim
17
+ end
18
+ def after_fork *args; end
19
+ def start *args; end
20
+ def shutdown *args; end
21
+ def serialize; end
22
+ def merge_data_from *args; end
23
+ def push_trace_execution_flag *args; end
24
+ def pop_trace_execution_flag *args; end
25
+ def browser_timing_header; "" end
26
+ def browser_timing_footer; "" end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,267 @@
1
+ require 'new_relic/agent'
2
+ require 'new_relic/control'
3
+ module NewRelic
4
+ module Agent
5
+
6
+ class SqlSampler
7
+
8
+ # Module defining methods stubbed out when the agent is disabled
9
+ module Shim #:nodoc:
10
+ def notice_scope_empty(*args); end
11
+ def notice_first_scope_push(*args); end
12
+ def notice_transaction(*args); end
13
+ end
14
+
15
+ attr_reader :disabled
16
+
17
+ # this is for unit tests only
18
+ attr_reader :sql_traces
19
+
20
+ def initialize
21
+ configure!
22
+ @sql_traces = {}
23
+ clear_transaction_data
24
+
25
+ # This lock is used to synchronize access to the @last_sample
26
+ # and related variables. It can become necessary on JRuby or
27
+ # any 'honest-to-god'-multithreaded system
28
+ @samples_lock = Mutex.new
29
+ end
30
+
31
+ def configure!
32
+ @explain_threshold = config.fetch('explain_threshold', 0.5).to_f
33
+ @explain_enabled = config.fetch('explain_enabled', true)
34
+ @stack_trace_threshold = config.fetch('stack_trace_threshold',
35
+ 0.5).to_f
36
+ end
37
+
38
+ def config
39
+ control = NewRelic::Control.instance
40
+ control.fetch('slow_sql',
41
+ control.fetch('transaction_tracer', {}))
42
+ end
43
+
44
+ # Enable the sql sampler - this also registers it with
45
+ # the statistics engine.
46
+ def enable
47
+ @disabled = false
48
+ NewRelic::Agent.instance.stats_engine.sql_sampler = self
49
+ end
50
+
51
+ # Disable the sql sampler - this also deregisters it
52
+ # with the statistics engine.
53
+ def disable
54
+ @disabled = true
55
+ NewRelic::Agent.instance.stats_engine.remove_sql_sampler(self)
56
+ end
57
+
58
+ def enabled?
59
+ !@disabled
60
+ end
61
+
62
+ def notice_transaction(path, uri=nil, params={})
63
+ transaction_data.set_transaction_info(path, uri, params) if !disabled && transaction_data
64
+ end
65
+
66
+ def notice_first_scope_push(time)
67
+ create_transaction_data
68
+ end
69
+
70
+ def create_transaction_data
71
+ Thread.current[:new_relic_sql_data] = TransactionSqlData.new
72
+ end
73
+
74
+ def transaction_data
75
+ Thread.current[:new_relic_sql_data]
76
+ end
77
+
78
+ def clear_transaction_data
79
+ Thread.current[:new_relic_sql_data] = nil
80
+ end
81
+
82
+ # This is called when we are done with the transaction.
83
+ def notice_scope_empty(time=Time.now)
84
+ data = transaction_data
85
+ clear_transaction_data
86
+
87
+ if data.sql_data.count > 0
88
+ @samples_lock.synchronize do
89
+ NewRelic::Agent.instance.log.debug "Harvesting #{data.sql_data.count} slow transaction sql statement(s)"
90
+ #FIXME get tx name and uri
91
+ harvest_slow_sql data
92
+ end
93
+ end
94
+ end
95
+
96
+ # this should always be called under the @samples_lock
97
+ def harvest_slow_sql(transaction_sql_data)
98
+ transaction_sql_data.sql_data.each do |sql_item|
99
+ normalized_sql = sql_item.normalize
100
+ sql_trace = @sql_traces[normalized_sql]
101
+ if sql_trace
102
+ sql_trace.aggregate(sql_item, transaction_sql_data.path,
103
+ transaction_sql_data.uri)
104
+ else
105
+ @sql_traces[normalized_sql] = SqlTrace.new(normalized_sql,
106
+ sql_item, transaction_sql_data.path, transaction_sql_data.uri)
107
+ end
108
+ end
109
+
110
+ end
111
+
112
+ def notice_sql(sql, metric_name, config, duration)
113
+ return unless transaction_data
114
+ if NewRelic::Agent.is_sql_recorded?
115
+ if duration > @explain_threshold
116
+ backtrace = caller.join("\n")
117
+ transaction_data.sql_data << SlowSql.new(sql, metric_name, config,
118
+ duration, backtrace)
119
+ end
120
+ end
121
+ end
122
+
123
+ def merge(sql_traces)
124
+ @samples_lock.synchronize do
125
+ #FIXME we need to merge the sql_traces array back into the @sql_traces hash
126
+ # @sql_traces.merge! sql_traces
127
+ end
128
+ end
129
+
130
+ def harvest
131
+ return [] if disabled
132
+ result = []
133
+ @samples_lock.synchronize do
134
+ result = @sql_traces.values
135
+ @sql_traces = {}
136
+ end
137
+ slowest = result.sort{|a,b| b.max_call_time <=> a.max_call_time}[0,10]
138
+ slowest.each {|trace| trace.prepare_to_send }
139
+ slowest
140
+ end
141
+
142
+ # reset samples without rebooting the web server
143
+ def reset!
144
+ end
145
+ end
146
+
147
+ class TransactionSqlData
148
+ attr_reader :path
149
+ attr_reader :uri
150
+ attr_reader :params
151
+ attr_reader :sql_data
152
+
153
+ def initialize
154
+ @sql_data = []
155
+ end
156
+
157
+ def set_transaction_info(path, uri, params)
158
+ @path = path
159
+ @uri = uri
160
+ @params = params
161
+ end
162
+ end
163
+
164
+ class SlowSql
165
+ attr_reader :sql
166
+ attr_reader :metric_name
167
+ attr_reader :duration
168
+ attr_reader :backtrace
169
+
170
+ def initialize(sql, metric_name, config, duration, backtrace = nil)
171
+ @sql = sql
172
+ @metric_name = metric_name
173
+ @config = config
174
+ @duration = duration
175
+ @backtrace = backtrace
176
+ end
177
+
178
+ def obfuscate
179
+ NewRelic::Agent::Database.obfuscate_sql(@sql)
180
+ end
181
+
182
+ def normalize
183
+ NewRelic::Agent::Database::Obfuscator.instance \
184
+ .default_sql_obfuscator(@sql).gsub(/\?\s*\,\s*/, '').gsub(/\s/, '')
185
+ end
186
+
187
+ def explain
188
+ NewRelic::Agent::Database.explain_sql(@sql, @config)
189
+ end
190
+ end
191
+
192
+ class SqlTrace < MethodTraceStats
193
+ attr_reader :path
194
+ attr_reader :url
195
+ attr_reader :sql_id
196
+ attr_reader :sql
197
+ attr_reader :database_metric_name
198
+ attr_reader :params
199
+
200
+ def initialize(normalized_query, slow_sql, path, uri)
201
+ super()
202
+ @params = {} #FIXME
203
+ @sql_id = consistent_hash(normalized_query)
204
+ set_primary slow_sql, path, uri
205
+ record_data_point slow_sql.duration
206
+ end
207
+
208
+ def set_primary(slow_sql, path, uri)
209
+ @slow_sql = slow_sql
210
+ @sql = slow_sql.sql
211
+ @database_metric_name = slow_sql.metric_name
212
+ @path = path
213
+ @url = uri
214
+ # FIXME
215
+ @params[:backtrace] = slow_sql.backtrace if slow_sql.backtrace
216
+ end
217
+
218
+ def aggregate(slow_sql, path, uri)
219
+ if slow_sql.duration > max_call_time
220
+ set_primary slow_sql, path, uri
221
+ end
222
+
223
+ record_data_point slow_sql.duration
224
+ end
225
+
226
+ def prepare_to_send
227
+ begin
228
+ params[:explain_plan] = @slow_sql.explain if need_to_explain?
229
+ ensure
230
+ NewRelic::Agent::Database.close_connections
231
+ end
232
+ @sql = @slow_sql.obfuscate if need_to_obfuscate?
233
+ end
234
+
235
+ def agent_config
236
+ control = NewRelic::Control.instance
237
+ control.fetch('slow_sql',
238
+ control.fetch('transaction_tracer', {}))
239
+ end
240
+
241
+ def need_to_obfuscate?
242
+ agent_config['record_sql'] == 'obfuscated'
243
+ end
244
+
245
+ def need_to_explain?
246
+ agent_config['explain_enabled']
247
+ end
248
+
249
+ def to_json(*a)
250
+ [@path, @url, @sql_id, @sql, @database_metric_name, @call_count, @total_call_time, @min_call_time, @max_call_time, @params].to_json(*a)
251
+ end
252
+
253
+ private
254
+
255
+ def consistent_hash(string)
256
+ if NewRelic::LanguageSupport.using_version?('1.9.2')
257
+ # String#hash is salted differently on every VM start in 1.9
258
+ # modulo ensures sql_id fits in an INT(11)
259
+ require 'digest/md5'
260
+ Digest::MD5.hexdigest(string).hex.modulo(2**31-1)
261
+ else
262
+ string.hash
263
+ end
264
+ end
265
+ end
266
+ end
267
+ end