newrelic_rpm 3.6.5.130 → 3.6.6.147

Sign up to get free protection for your applications and to get access to all the features.
Files changed (240) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +27 -3
  3. data/Gemfile +1 -14
  4. data/Rakefile +15 -5
  5. data/config.dot +1 -1
  6. data/lib/new_relic/agent/agent.rb +15 -0
  7. data/lib/new_relic/agent/agent_logger.rb +19 -14
  8. data/lib/new_relic/agent/configuration/defaults.rb +4 -3
  9. data/lib/new_relic/agent/configuration/environment_source.rb +6 -4
  10. data/lib/new_relic/agent/configuration/manager.rb +7 -2
  11. data/lib/new_relic/agent/configuration/mask_defaults.rb +1 -2
  12. data/lib/new_relic/agent/cross_app_monitor.rb +5 -4
  13. data/lib/new_relic/agent/cross_app_tracing.rb +0 -1
  14. data/lib/new_relic/agent/error_collector.rb +30 -1
  15. data/lib/new_relic/agent/http_clients/curb_wrappers.rb +67 -0
  16. data/lib/new_relic/agent/http_clients/httpclient_wrappers.rb +59 -0
  17. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +12 -0
  18. data/lib/new_relic/agent/instrumentation/active_merchant.rb +3 -3
  19. data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +3 -3
  20. data/lib/new_relic/agent/instrumentation/authlogic.rb +3 -3
  21. data/lib/new_relic/agent/instrumentation/curb.rb +179 -0
  22. data/lib/new_relic/agent/instrumentation/data_mapper.rb +3 -3
  23. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +35 -26
  24. data/lib/new_relic/agent/instrumentation/httpclient.rb +46 -0
  25. data/lib/new_relic/agent/instrumentation/merb/controller.rb +3 -3
  26. data/lib/new_relic/agent/instrumentation/puma.rb +23 -0
  27. data/lib/new_relic/agent/instrumentation/rack.rb +40 -0
  28. data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +4 -4
  29. data/lib/new_relic/agent/instrumentation/rails/errors.rb +0 -1
  30. data/lib/new_relic/agent/instrumentation/sequel.rb +0 -1
  31. data/lib/new_relic/agent/instrumentation/sunspot.rb +1 -1
  32. data/lib/new_relic/agent/internal_agent_error.rb +18 -0
  33. data/lib/new_relic/agent/new_relic_service.rb +2 -8
  34. data/lib/new_relic/agent/request_sampler.rb +4 -6
  35. data/lib/new_relic/agent/samplers/cpu_sampler.rb +0 -1
  36. data/lib/new_relic/agent/stats.rb +9 -0
  37. data/lib/new_relic/agent/stats_engine/stats_hash.rb +44 -6
  38. data/lib/new_relic/agent/system_info.rb +1 -1
  39. data/lib/new_relic/agent/thread_profiler.rb +6 -6
  40. data/lib/new_relic/agent/transaction.rb +1 -1
  41. data/lib/new_relic/agent/transaction_info.rb +0 -1
  42. data/lib/new_relic/agent/transaction_sample_builder.rb +6 -5
  43. data/lib/new_relic/agent/transaction_sampler.rb +1 -1
  44. data/lib/new_relic/commands/deployments.rb +6 -0
  45. data/lib/new_relic/commands/install.rb +2 -2
  46. data/lib/new_relic/control/frameworks/rails.rb +1 -2
  47. data/lib/new_relic/control/instrumentation.rb +2 -2
  48. data/lib/new_relic/control/server_methods.rb +1 -2
  49. data/lib/new_relic/delayed_job_injection.rb +0 -40
  50. data/lib/new_relic/helper.rb +0 -1
  51. data/lib/new_relic/latest_changes.rb +1 -1
  52. data/lib/new_relic/local_environment.rb +9 -4
  53. data/lib/new_relic/metric_spec.rb +19 -3
  54. data/lib/new_relic/noticed_error.rb +2 -1
  55. data/lib/new_relic/rack/agent_hooks.rb +0 -1
  56. data/lib/new_relic/rack/developer_mode.rb +1 -1
  57. data/lib/new_relic/rack/error_collector.rb +42 -21
  58. data/lib/new_relic/recipes.rb +0 -1
  59. data/lib/new_relic/transaction_analysis.rb +0 -1
  60. data/lib/new_relic/transaction_sample/segment.rb +4 -4
  61. data/lib/new_relic/version.rb +1 -1
  62. data/lib/sequel/extensions/newrelic_instrumentation.rb +6 -7
  63. data/lib/sequel/plugins/newrelic_instrumentation.rb +0 -1
  64. data/lib/tasks/install.rake +2 -2
  65. data/newrelic_rpm.gemspec +11 -1
  66. data/test/active_record_fixtures.rb +2 -2
  67. data/test/agent_helper.rb +46 -3
  68. data/test/config/newrelic.yml +2 -2
  69. data/test/multiverse/.gitignore +2 -0
  70. data/test/multiverse/lib/multiverse/envfile.rb +6 -9
  71. data/test/multiverse/lib/multiverse/environment.rb +0 -1
  72. data/test/multiverse/lib/multiverse/output_collector.rb +43 -11
  73. data/test/multiverse/lib/multiverse/runner.rb +37 -5
  74. data/test/multiverse/lib/multiverse/suite.rb +149 -67
  75. data/test/multiverse/script/run_one +4 -2
  76. data/test/multiverse/script/runner +1 -5
  77. data/test/multiverse/suites/active_record/Envfile +3 -2
  78. data/test/multiverse/suites/active_record/ar_method_aliasing.rb +13 -12
  79. data/test/multiverse/suites/active_record/config/newrelic.yml +0 -3
  80. data/test/multiverse/suites/agent_only/audit_log_test.rb +30 -34
  81. data/test/multiverse/suites/agent_only/before_suite.rb +7 -0
  82. data/test/multiverse/suites/agent_only/config/newrelic.yml +1 -7
  83. data/test/multiverse/suites/agent_only/cross_application_tracing_test.rb +12 -20
  84. data/test/multiverse/suites/agent_only/http_response_code_test.rb +16 -34
  85. data/test/multiverse/suites/agent_only/key_transactions_test.rb +18 -28
  86. data/test/multiverse/suites/agent_only/logging_test.rb +25 -49
  87. data/test/multiverse/suites/agent_only/marshaling_test.rb +30 -38
  88. data/test/multiverse/suites/agent_only/pipe_manager_test.rb +12 -6
  89. data/test/multiverse/suites/agent_only/rename_rule_test.rb +30 -38
  90. data/test/multiverse/suites/agent_only/rum_instrumentation_test.rb +16 -18
  91. data/test/multiverse/suites/agent_only/service_timeout_test.rb +6 -7
  92. data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +26 -32
  93. data/test/multiverse/suites/agent_only/ssl_test.rb +10 -14
  94. data/test/multiverse/suites/agent_only/start_up_test.rb +1 -1
  95. data/test/multiverse/suites/agent_only/testing_app.rb +2 -0
  96. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +23 -24
  97. data/test/multiverse/suites/config_file_loading/Envfile +6 -2
  98. data/test/multiverse/suites/config_file_loading/config_file_loading_test.rb +8 -4
  99. data/test/multiverse/suites/curb/Envfile +19 -0
  100. data/test/multiverse/suites/curb/config/newrelic.yml +19 -0
  101. data/test/multiverse/suites/curb/curb_test.rb +195 -0
  102. data/test/multiverse/suites/datamapper/Envfile +2 -0
  103. data/test/multiverse/suites/datamapper/config/newrelic.yml +0 -2
  104. data/test/multiverse/suites/datamapper/datamapper_test.rb +6 -10
  105. data/test/multiverse/suites/deferred_instrumentation/Envfile +19 -0
  106. data/test/multiverse/suites/deferred_instrumentation/config/newrelic.yml +22 -0
  107. data/test/multiverse/suites/deferred_instrumentation/sinatra_test.rb +103 -0
  108. data/test/multiverse/suites/excon/config/newrelic.yml +0 -2
  109. data/test/multiverse/suites/excon/excon_test.rb +3 -3
  110. data/test/multiverse/suites/httpclient/Envfile +15 -0
  111. data/test/multiverse/suites/httpclient/config/newrelic.yml +19 -0
  112. data/test/multiverse/suites/httpclient/httpclient_test.rb +70 -0
  113. data/test/multiverse/suites/net_http/config/newrelic.yml +0 -2
  114. data/test/multiverse/suites/net_http/net_http_test.rb +9 -4
  115. data/test/multiverse/suites/padrino/Envfile +2 -0
  116. data/test/multiverse/suites/padrino/config/newrelic.yml +0 -3
  117. data/test/multiverse/suites/padrino/padrino_test.rb +5 -4
  118. data/test/multiverse/suites/rails/Envfile +3 -0
  119. data/test/multiverse/suites/rails/app.rb +1 -0
  120. data/test/multiverse/suites/rails/bad_instrumentation_test.rb +31 -0
  121. data/test/multiverse/suites/rails/config/newrelic.yml +2 -3
  122. data/test/multiverse/suites/rails/error_tracing_test.rb +32 -41
  123. data/test/multiverse/suites/rails/gc_instrumentation_test.rb +6 -16
  124. data/test/multiverse/suites/rails/queue_time_test.rb +4 -20
  125. data/test/multiverse/suites/rails/request_statistics_test.rb +7 -32
  126. data/test/multiverse/suites/rails/view_instrumentation_test.rb +6 -10
  127. data/test/multiverse/suites/resque/config/newrelic.yml +1 -3
  128. data/test/multiverse/suites/resque/instrumentation_test.rb +10 -7
  129. data/test/multiverse/suites/sequel/Envfile +8 -0
  130. data/test/multiverse/suites/sequel/config/newrelic.yml +0 -3
  131. data/test/multiverse/suites/sequel/sequel_test.rb +1 -2
  132. data/test/multiverse/suites/sidekiq/Envfile +0 -12
  133. data/test/multiverse/suites/sidekiq/config/newrelic.yml +1 -3
  134. data/test/multiverse/suites/sidekiq/sidekiq_instrumentation_test.rb +44 -100
  135. data/test/multiverse/suites/sinatra/config/newrelic.yml +0 -3
  136. data/test/multiverse/suites/sinatra/ignoring_test.rb +8 -5
  137. data/test/multiverse/suites/sinatra/sinatra_classic_test.rb +8 -1
  138. data/test/multiverse/suites/sinatra/sinatra_error_tracing_test.rb +9 -12
  139. data/test/multiverse/suites/sinatra/sinatra_metric_explosion_test.rb +9 -8
  140. data/test/multiverse/suites/sinatra/sinatra_modular_test.rb +1 -1
  141. data/test/multiverse/suites/sinatra/sinatra_routes_test.rb +6 -5
  142. data/test/multiverse/suites/sinatra/sinatra_test_cases.rb +10 -13
  143. data/test/multiverse/suites/typhoeus/config/newrelic.yml +0 -2
  144. data/test/multiverse/suites/typhoeus/typhoeus_test.rb +7 -4
  145. data/test/multiverse/test/suite_examples/one/a/a_test.rb +0 -1
  146. data/test/multiverse/test/suite_examples/one/a/config/newrelic.yml +0 -1
  147. data/test/multiverse/test/suite_examples/one/b/b_test.rb +0 -1
  148. data/test/multiverse/test/suite_examples/one/b/config/newrelic.yml +0 -1
  149. data/test/new_relic/agent/agent/connect_test.rb +1 -1
  150. data/test/new_relic/agent/agent/start_test.rb +0 -1
  151. data/test/new_relic/agent/agent/start_worker_thread_test.rb +0 -1
  152. data/test/new_relic/agent/agent_logger_test.rb +37 -3
  153. data/test/new_relic/agent/agent_test.rb +23 -1
  154. data/test/new_relic/agent/browser_monitoring_test.rb +0 -1
  155. data/test/new_relic/agent/busy_calculator_test.rb +2 -2
  156. data/test/new_relic/agent/configuration/environment_source_test.rb +22 -0
  157. data/test/new_relic/agent/error_collector/notice_error_test.rb +1 -1
  158. data/test/new_relic/agent/error_collector_test.rb +95 -13
  159. data/test/new_relic/agent/event_listener_test.rb +0 -1
  160. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +23 -0
  161. data/test/new_relic/agent/instrumentation/active_record_subscriber_test.rb +4 -2
  162. data/test/new_relic/agent/instrumentation/instrumentation_test.rb +0 -1
  163. data/test/new_relic/agent/instrumentation/queue_time_test.rb +16 -11
  164. data/test/new_relic/agent/instrumentation/rack_test.rb +0 -1
  165. data/test/new_relic/agent/memcache_instrumentation_test.rb +7 -7
  166. data/test/{multiverse/suites/agent_only/test_trace_method_with_punctuation.rb → new_relic/agent/method_interrobang_test.rb} +3 -5
  167. data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +1 -2
  168. data/test/{multiverse/suites/agent_only → new_relic/agent}/method_visibility_test.rb +17 -29
  169. data/test/new_relic/agent/new_relic_service_test.rb +1 -1
  170. data/test/new_relic/agent/pipe_service_test.rb +1 -1
  171. data/test/new_relic/agent/request_sampler_test.rb +10 -10
  172. data/test/new_relic/agent/rpm_agent_test.rb +1 -2
  173. data/test/new_relic/agent/stats_hash_test.rb +83 -5
  174. data/test/new_relic/agent/stats_test.rb +0 -1
  175. data/test/new_relic/agent/thread_profiler_test.rb +7 -7
  176. data/test/new_relic/agent/threaded_test.rb +1 -2
  177. data/test/new_relic/agent/transaction/pop_test.rb +0 -1
  178. data/test/{multiverse/suites/agent_only/test_trace_transaction_with_punctuation.rb → new_relic/agent/transaction_interrobang_test.rb} +2 -4
  179. data/test/new_relic/agent/transaction_sample_builder_test.rb +13 -0
  180. data/test/new_relic/agent/transaction_test.rb +7 -5
  181. data/test/new_relic/agent/worker_loop_test.rb +0 -1
  182. data/test/new_relic/agent_test.rb +0 -27
  183. data/test/new_relic/collection_helper_test.rb +17 -17
  184. data/test/new_relic/control/class_methods_test.rb +1 -1
  185. data/test/new_relic/control_test.rb +6 -6
  186. data/test/new_relic/dependency_detection_test.rb +28 -0
  187. data/test/new_relic/evil_server.rb +0 -1
  188. data/test/new_relic/fake_collector.rb +20 -2
  189. data/test/new_relic/fake_server.rb +0 -12
  190. data/test/new_relic/http_client_test_cases.rb +20 -24
  191. data/test/new_relic/metric_spec_test.rb +18 -0
  192. data/test/new_relic/multiverse_helpers.rb +164 -0
  193. data/test/new_relic/rack/agent_hooks_test.rb +0 -1
  194. data/test/new_relic/rack/all_test.rb +0 -1
  195. data/test/new_relic/rack/deferred_instrumentation_test.rb +35 -0
  196. data/test/new_relic/rack/developer_mode_helper_test.rb +8 -9
  197. data/test/new_relic/rack/developer_mode_test.rb +0 -2
  198. data/test/new_relic/rack/error_collector_test.rb +52 -8
  199. data/test/new_relic/transaction_sample/composite_segment_test.rb +0 -1
  200. data/test/new_relic/transaction_sample/fake_segment_test.rb +0 -1
  201. data/test/new_relic/transaction_sample/segment_test.rb +0 -1
  202. data/test/new_relic/transaction_sample/summary_segment_test.rb +0 -1
  203. data/test/performance/README.md +162 -0
  204. data/test/performance/lib/performance.rb +28 -0
  205. data/test/performance/lib/performance/console_reporter.rb +51 -0
  206. data/test/performance/lib/performance/hako_client.rb +31 -0
  207. data/test/performance/lib/performance/hako_reporter.rb +26 -0
  208. data/test/performance/lib/performance/instrumentation/cpu_usage.rb +26 -0
  209. data/test/performance/lib/performance/instrumentation/gc_stats.rb +53 -0
  210. data/test/performance/lib/performance/instrumentation/perf_tools.rb +30 -0
  211. data/test/performance/lib/performance/instrumentor.rb +110 -0
  212. data/test/performance/lib/performance/json_reporter.rb +15 -0
  213. data/test/performance/lib/performance/result.rb +80 -0
  214. data/test/performance/lib/performance/runner.rb +207 -0
  215. data/test/performance/lib/performance/test_case.rb +65 -0
  216. data/test/performance/lib/performance/timer.rb +38 -0
  217. data/test/performance/script/mega-runner +37 -0
  218. data/test/performance/script/runner +81 -0
  219. data/test/performance/suites/startup.rb +12 -0
  220. data/test/performance/suites/transaction_tracing.rb +66 -0
  221. data/test/script/ci_agent-tests_runner.sh +4 -4
  222. data/test/script/ci_multiverse_runner.sh +3 -3
  223. data/test/test_helper.rb +0 -11
  224. data/ui/helpers/developer_mode_helper.rb +1 -1
  225. data/ui/views/layouts/newrelic_default.rhtml +1 -1
  226. data/ui/views/newrelic/_segment.rhtml +2 -2
  227. data/ui/views/newrelic/_segment_limit_message.rhtml +1 -1
  228. data/ui/views/newrelic/_show_sample_detail.rhtml +1 -1
  229. data/ui/views/newrelic/_show_sample_sql.rhtml +4 -4
  230. data/ui/views/newrelic/_stack_trace.rhtml +2 -2
  231. data/ui/views/newrelic/file/javascript/transaction_sample.js +3 -3
  232. data/ui/views/newrelic/file/stylesheets/style.css +13 -13
  233. data/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection.rb +18 -4
  234. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/metric_parser.rb +0 -1
  235. metadata +186 -17
  236. metadata.gz.sig +0 -0
  237. data/test/multiverse/suites/active_record/encoding_test.rb +0 -30
  238. data/test/multiverse/suites/agent_only/no_dns_resolv.rb +0 -21
  239. data/test/multiverse/suites/sidekiq/app.rb +0 -25
  240. data/test/new_relic/delayed_job_injection_test.rb +0 -25
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ require 'logger'
6
+
7
+ $: << File.expand_path(File.dirname(__FILE__))
8
+
9
+ require 'performance/result'
10
+ require 'performance/runner'
11
+ require 'performance/test_case'
12
+ require 'performance/timer'
13
+ require 'performance/instrumentor'
14
+ require 'performance/console_reporter'
15
+ require 'performance/json_reporter'
16
+ require 'performance/hako_client'
17
+ require 'performance/hako_reporter'
18
+
19
+ module Performance
20
+ def self.logger
21
+ log_path = ENV['LOG'] || $stderr
22
+ @logger ||= Logger.new(log_path)
23
+ end
24
+
25
+ def self.log_path=(path)
26
+ @logger = Logger.new(path)
27
+ end
28
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ module Performance
6
+ class ConsoleReporter
7
+ def initialize(results, elapsed, options={})
8
+ @results = results
9
+ @elapsed = elapsed
10
+ @options = options
11
+ end
12
+
13
+ def report
14
+ failures = @results.select { |result| result.failure? }
15
+ successes = @results - failures
16
+ puts "#{@results.size} tests, #{failures.size} failures, #{@elapsed} s total"
17
+ report_successful_results(successes) if successes.any?
18
+ report_failed_results(failures) if failures.any?
19
+ end
20
+
21
+ def report_successful_results(results)
22
+ puts ''
23
+ results.each do |result|
24
+ puts "#{result.identifier}: #{result.elapsed} s"
25
+ unless @options[:brief]
26
+ result.measurements.each do |key, value|
27
+ puts " #{key}: #{value}"
28
+ end
29
+ end
30
+ unless result.artifacts.empty?
31
+ puts " artifacts:"
32
+ result.artifacts.each do |artifact|
33
+ puts " #{artifact}"
34
+ end
35
+ end
36
+ puts '' if !@options[:brief] || !result.artifacts.empty?
37
+ end
38
+ end
39
+
40
+ def report_failed_results(results)
41
+ puts ''
42
+ results.each do |failure|
43
+ puts "FAILED: #{failure.identifier}"
44
+ e = failure.exception
45
+ puts "#{e['class']}: #{e['message']}"
46
+ puts failure.exception['backtrace'].map { |l| " #{l}" }.join("\n")
47
+ end
48
+ puts ''
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ require 'json'
6
+ require 'net/http'
7
+ require 'uri'
8
+
9
+ module Performance
10
+ class HakoClient
11
+ BASE_URI = 'http://hako.pdx.vm.datanerd.us'
12
+
13
+ def initialize(token)
14
+ @token = token
15
+ end
16
+
17
+ def submit(result)
18
+ body = JSON.dump('result' => result.to_h)
19
+
20
+ uri = URI(BASE_URI + "/api/results")
21
+ req = Net::HTTP::Post.new(uri.to_s)
22
+ req.body = body
23
+ req.content_type = 'application/json'
24
+ req['Authorization'] = "Token token=\"#{@token}\""
25
+
26
+ Net::HTTP.start(uri.host, uri.port) do |conn|
27
+ conn.request(req)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ module Performance
6
+ class HakoReporter
7
+ def initialize(results, elapsed, options={})
8
+ @results = results
9
+ @token = ENV['HAKO_TOKEN'] || options[:hako_token]
10
+ end
11
+
12
+ def report
13
+ Performance.logger.info("Uploading #{@results.size} results to Hako")
14
+ client = HakoClient.new(@token)
15
+ @results.each do |result|
16
+ rsp = client.submit(result)
17
+ case rsp
18
+ when Net::HTTPSuccess
19
+ Performance.logger.debug("Successfully posted result to Hako")
20
+ else
21
+ Performance.logger.error("Failed to post results to Hako: #{rsp.inspect}")
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ module Performance
6
+ module Instrumentation
7
+ class CpuUsage < Instrumentor
8
+ on_by_default
9
+
10
+ def before(*)
11
+ @times_before = Process.times
12
+ end
13
+
14
+ def after(*)
15
+ @times_after = Process.times
16
+ end
17
+
18
+ def results
19
+ {
20
+ :cpu_time_user => @times_after.utime - @times_before.utime,
21
+ :cpu_time_system => @times_after.stime - @times_before.stime
22
+ }
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ module Performance
6
+ module Instrumentation
7
+ class MRIGCStats < Instrumentor
8
+ platforms :mri_193, :mri_20
9
+ on_by_default
10
+
11
+ def before(*)
12
+ @stats_before = GC.stat
13
+ end
14
+
15
+ def after(*)
16
+ @stats_after = GC.stat
17
+ end
18
+
19
+ def results
20
+ res = {
21
+ :gc_runs => @stats_after[:count] - @stats_before[:count],
22
+ :live_objects => @stats_after[:heap_live_num] - @stats_before[:heap_live_num]
23
+ }
24
+ if RUBY_VERSION >= "2.0.0"
25
+ res[:allocations] = @stats_after[:total_allocated_object] - @stats_before[:total_allocated_object]
26
+ end
27
+ res
28
+ end
29
+ end
30
+
31
+ class REEGCStats < Instrumentor
32
+ platforms :ree
33
+ on_by_default
34
+
35
+ def before(*)
36
+ @allocations_before = ObjectSpace.allocated_objects
37
+ @live_objects_before = ObjectSpace.live_objects
38
+ end
39
+
40
+ def after(*)
41
+ @allocations_after = ObjectSpace.allocated_objects
42
+ @live_objects_after = ObjectSpace.live_objects
43
+ end
44
+
45
+ def results
46
+ {
47
+ :allocations => @allocations_after - @allocations_before,
48
+ :live_objects => @live_objects_after - @live_objects_before,
49
+ }
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ module Performance
6
+ module Instrumentation
7
+ class PerfToolsProfile < Instrumentor
8
+ platforms :mri_19, :mri_20
9
+
10
+ def self.setup
11
+ require 'tmpdir'
12
+ require 'perftools'
13
+ end
14
+
15
+ def before(test, test_name)
16
+ @profile_dir = Dir.mktmpdir('profile')
17
+ @profile_path = File.join(@profile_dir, "profile")
18
+ PerfTools::CpuProfiler.start(@profile_path)
19
+ end
20
+
21
+ def after(test, test_name)
22
+ PerfTools::CpuProfiler.stop
23
+ output_profile_path = artifact_path(test, test_name, "dot")
24
+ system("pprof.rb --dot #{@profile_path} >#{output_profile_path}")
25
+ @artifacts << output_profile_path
26
+ FileUtils.remove_entry_secure(@profile_dir)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,110 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ module Performance
6
+ module Instrumentation
7
+ def self.current_platform_matches?(p)
8
+ is_jruby = defined?(JRUBY_VERSION)
9
+ is_ree = defined?(RUBY_DESCRIPTION) && RUBY_DESCRIPTION =~ /MBARI/
10
+ case p
11
+ when :jruby then is_jruby
12
+ when :mri then !is_jruby
13
+ when :ree then !is_jruby && is_ree
14
+ when :mri_18 then !is_jruby && RUBY_VERSION =~ /^1\.8\./
15
+ when :mri_19 then !is_jruby && RUBY_VERSION =~ /^1\.9\./
16
+ when :mri_193 then !is_jruby && RUBY_VERSION =~ /^1\.9\.3/
17
+ when :mri_20 then !is_jruby && RUBY_VERSION =~ /^2\.0\./
18
+ end
19
+ end
20
+
21
+ def self.load_instrumentors
22
+ dir = File.expand_path(File.join(File.dirname(__FILE__), 'instrumentation'))
23
+ Dir.glob(File.join(dir, "*.rb")).each do |filename|
24
+ require filename
25
+ end
26
+ end
27
+
28
+ def self.default_instrumentors
29
+ Instrumentor.subclasses.select do |cls|
30
+ cls.on_by_default? && cls.supported?
31
+ end
32
+ end
33
+
34
+ def self.instrumentor_class_by_name(name)
35
+ begin
36
+ cls = self.const_get(name)
37
+ if cls.supported?
38
+ cls
39
+ else
40
+ Performance.logger.warn("Instrumentor '#{name}' is unsupported on this platform")
41
+ nil
42
+ end
43
+ rescue NameError => e
44
+ Performance.logger.error("Failed to load instrumentor '#{name}': #{e.inspect}")
45
+ nil
46
+ end
47
+ end
48
+
49
+ class Instrumentor
50
+ def self.inherited(cls)
51
+ @subclasses ||= []
52
+ @subclasses << cls
53
+ end
54
+
55
+ def self.subclasses
56
+ @subclasses || []
57
+ end
58
+
59
+ def self.platforms(*args)
60
+ @supported_platforms = args
61
+ end
62
+
63
+ def self.supported?
64
+ (
65
+ @supported_platforms.nil? ||
66
+ @supported_platforms.any? { |p| Instrumentation.current_platform_matches?(p) }
67
+ )
68
+ end
69
+
70
+ def self.on_by_default
71
+ @on_by_default = true
72
+ end
73
+
74
+ def self.on_by_default?
75
+ @on_by_default
76
+ end
77
+
78
+ attr_reader :artifacts
79
+
80
+ def initialize(artifacts_dir)
81
+ @artifacts_dir = artifacts_dir
82
+ reset
83
+ end
84
+
85
+ def reset
86
+ @artifacts = []
87
+ end
88
+
89
+ def pretty_name
90
+ self.class.name.split("::").last
91
+ end
92
+
93
+ def artifacts_dir_for(test_case, test_name)
94
+ path = File.join(@artifacts_dir, test_case.class.name, test_name)
95
+ FileUtils.mkdir_p(path)
96
+ path
97
+ end
98
+
99
+ def artifact_path(test_case, test_name, extension)
100
+ File.join(artifacts_dir_for(test_case, test_name), "#{pretty_name}.#{extension}")
101
+ end
102
+
103
+ def before(*); end
104
+ def after(*); end
105
+ def results; {}; end
106
+ end
107
+ end
108
+ end
109
+
110
+ Performance::Instrumentation.load_instrumentors
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ module Performance
6
+ class JSONReporter
7
+ def initialize(results, elapsed, options={})
8
+ @results = results
9
+ end
10
+
11
+ def report
12
+ puts JSON.dump(@results.map { |result| result.to_h })
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,80 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ module Performance
6
+ class Result
7
+ attr_reader :test_name, :measurements, :tags, :timer, :artifacts
8
+ attr_accessor :exception
9
+
10
+ def initialize(test_case, test_name)
11
+ @test_case = test_case
12
+ @test_name = test_name
13
+ @measurements = {}
14
+ @tags = {}
15
+ @timer = Timer.new
16
+ @artifacts = []
17
+ end
18
+
19
+ def exception=(e)
20
+ if e.is_a?(Exception)
21
+ @exception = {
22
+ 'class' => e.class.name,
23
+ 'message' => e.message,
24
+ 'backtrace' => e.backtrace
25
+ }
26
+ else
27
+ @exception = e
28
+ end
29
+ end
30
+
31
+ def elapsed=(elapsed)
32
+ @elapsed = elapsed
33
+ end
34
+
35
+ def elapsed
36
+ @elapsed || @timer.elapsed
37
+ end
38
+
39
+ def failure?
40
+ elapsed.nil? || !@exception.nil?
41
+ end
42
+
43
+ def suite_name
44
+ @test_case.is_a?(String) ? @test_case : @test_case.name
45
+ end
46
+
47
+ def identifier
48
+ "#{suite_name}##{@test_name}"
49
+ end
50
+
51
+ def measurements_hash
52
+ @measurements.merge(:elapsed => elapsed)
53
+ end
54
+
55
+ def to_h
56
+ {
57
+ "suite" => suite_name,
58
+ "name" => @test_name,
59
+ "measurements" => measurements_hash,
60
+ "tags" => @tags,
61
+ "exception" => @exception,
62
+ "artifacts" => @artifacts
63
+ }
64
+ end
65
+
66
+ def self.from_hash(hash)
67
+ elapsed = hash['measurements'].delete('elapsed')
68
+ result = self.new(hash['suite'], hash['name'])
69
+ result.measurements.merge! hash['measurements']
70
+ result.tags.merge! hash['tags']
71
+ result.exception = hash['exception']
72
+ result.elapsed = elapsed
73
+ result
74
+ end
75
+
76
+ def inspect
77
+ "<Performance::Result #{identifier}: #{elapsed} s, results=#{@results.inspect}>"
78
+ end
79
+ end
80
+ end