newrelic_rpm 3.9.1.236 → 3.9.2.239

Sign up to get free protection for your applications and to get access to all the features.
Files changed (220) hide show
  1. data.tar.gz.sig +2 -4
  2. data/CHANGELOG +96 -2
  3. data/lib/new_relic/agent.rb +47 -4
  4. data/lib/new_relic/agent/agent.rb +51 -26
  5. data/lib/new_relic/agent/agent_logger.rb +4 -0
  6. data/lib/new_relic/agent/configuration.rb +2 -32
  7. data/lib/new_relic/agent/configuration/default_source.rb +153 -118
  8. data/lib/new_relic/agent/configuration/dotted_hash.rb +52 -0
  9. data/lib/new_relic/agent/configuration/environment_source.rb +1 -1
  10. data/lib/new_relic/agent/configuration/manager.rb +101 -2
  11. data/lib/new_relic/agent/configuration/manual_source.rb +17 -0
  12. data/lib/new_relic/agent/configuration/server_source.rb +12 -4
  13. data/lib/new_relic/agent/configuration/yaml_source.rb +46 -22
  14. data/lib/new_relic/agent/cross_app_monitor.rb +1 -1
  15. data/lib/new_relic/agent/cross_app_tracing.rb +1 -1
  16. data/lib/new_relic/agent/database/obfuscation_helpers.rb +55 -14
  17. data/lib/new_relic/agent/database/obfuscator.rb +22 -7
  18. data/lib/new_relic/agent/database/postgres_explain_obfuscator.rb +6 -8
  19. data/lib/new_relic/agent/error_collector.rb +24 -16
  20. data/lib/new_relic/agent/event_loop.rb +189 -0
  21. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +8 -17
  22. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +1 -1
  23. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +1 -1
  24. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +17 -16
  25. data/lib/new_relic/agent/instrumentation/ignore_actions.rb +41 -0
  26. data/lib/new_relic/agent/instrumentation/merb/controller.rb +0 -11
  27. data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +1 -1
  28. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +0 -8
  29. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +1 -9
  30. data/lib/new_relic/agent/instrumentation/rails4/action_controller.rb +0 -18
  31. data/lib/new_relic/agent/instrumentation/rubyprof.rb +1 -1
  32. data/lib/new_relic/agent/instrumentation/sidekiq.rb +1 -1
  33. data/lib/new_relic/agent/instrumentation/sinatra.rb +12 -1
  34. data/lib/new_relic/agent/instrumentation/sinatra/transaction_namer.rb +1 -1
  35. data/lib/new_relic/agent/method_tracer.rb +33 -39
  36. data/lib/new_relic/agent/new_relic_service.rb +35 -156
  37. data/lib/new_relic/agent/new_relic_service/encoders.rb +34 -0
  38. data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +50 -0
  39. data/lib/new_relic/agent/new_relic_service/marshaller.rb +52 -0
  40. data/lib/new_relic/agent/new_relic_service/pruby_marshaller.rb +52 -0
  41. data/lib/new_relic/agent/threading/backtrace_node.rb +1 -1
  42. data/lib/new_relic/agent/traced_method_stack.rb +16 -2
  43. data/lib/new_relic/agent/transaction.rb +0 -4
  44. data/lib/new_relic/collection_helper.rb +2 -2
  45. data/lib/new_relic/control/frameworks/rails.rb +3 -0
  46. data/lib/new_relic/control/instrumentation.rb +6 -2
  47. data/lib/new_relic/json_wrapper.rb +47 -25
  48. data/lib/new_relic/language_support.rb +0 -4
  49. data/lib/new_relic/latest_changes.rb +2 -2
  50. data/lib/new_relic/rack/developer_mode.rb +4 -3
  51. data/lib/new_relic/recipes/capistrano3.rb +2 -2
  52. data/lib/new_relic/recipes/capistrano_legacy.rb +1 -1
  53. data/lib/new_relic/timer_lib.rb +1 -1
  54. data/lib/new_relic/version.rb +2 -2
  55. data/lib/tasks/config.html.erb +28 -0
  56. data/lib/tasks/config.rake +134 -0
  57. data/lib/tasks/config.text.erb +7 -0
  58. data/lib/tasks/install.rake +0 -63
  59. data/newrelic.yml +7 -0
  60. data/test/active_record_fixtures.rb +4 -4
  61. data/test/agent_helper.rb +58 -18
  62. data/test/environments/lib/environments/runner.rb +1 -1
  63. data/test/environments/rails21/Gemfile +1 -1
  64. data/test/environments/rails21/config/boot.rb +1 -1
  65. data/test/environments/rails22/Gemfile +1 -1
  66. data/test/environments/rails22/config/boot.rb +1 -1
  67. data/test/environments/rails23/config/boot.rb +2 -2
  68. data/test/environments/rails30/Gemfile +1 -1
  69. data/test/environments/rails31/Gemfile +1 -1
  70. data/test/environments/rails32/Gemfile +1 -1
  71. data/test/environments/rails40/Gemfile +1 -1
  72. data/test/environments/rails41/Gemfile +1 -1
  73. data/test/fixtures/cross_agent_tests/labels.json +104 -0
  74. data/test/fixtures/cross_agent_tests/sql_obfuscation/README.md +23 -0
  75. data/test/fixtures/cross_agent_tests/sql_obfuscation/back_quoted_identifiers.mysql.obfuscated +1 -0
  76. data/test/fixtures/cross_agent_tests/sql_obfuscation/back_quoted_identifiers.mysql.sql +1 -0
  77. data/test/fixtures/cross_agent_tests/sql_obfuscation/comment_delimiters_in_strings.obfuscated +1 -0
  78. data/test/fixtures/cross_agent_tests/sql_obfuscation/comment_delimiters_in_strings.sql +1 -0
  79. data/test/fixtures/cross_agent_tests/sql_obfuscation/double_quoted_identifiers.postgres.obfuscated +1 -0
  80. data/test/fixtures/cross_agent_tests/sql_obfuscation/double_quoted_identifiers.postgres.sql +1 -0
  81. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comment_in_string.obfuscated +2 -0
  82. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comment_in_string.sql +2 -0
  83. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comments_with_quotes.obfuscated +1 -0
  84. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comments_with_quotes.sql +2 -0
  85. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_cstyle.obfuscated +1 -0
  86. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_cstyle.sql +1 -0
  87. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_doubledash.obfuscated +2 -0
  88. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_doubledash.sql +2 -0
  89. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_hash.obfuscated +1 -0
  90. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_hash.sql +1 -0
  91. data/test/fixtures/cross_agent_tests/sql_obfuscation/escape_string_constants.postgres.obfuscated +1 -0
  92. data/test/fixtures/cross_agent_tests/sql_obfuscation/escape_string_constants.postgres.sql +4 -0
  93. data/test/fixtures/cross_agent_tests/sql_obfuscation/malformed/unterminated_double_quoted_string.mysql.sql +1 -0
  94. data/test/fixtures/cross_agent_tests/sql_obfuscation/malformed/unterminated_single_quoted_string.sql +1 -0
  95. data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_comments_and_quotes.obfuscated +1 -0
  96. data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_comments_and_quotes.sql +2 -0
  97. data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_quotes_comments_and_newlines.obfuscated +1 -0
  98. data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_quotes_comments_and_newlines.sql +4 -0
  99. data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_quotes_end_of_line_comments.obfuscated +1 -0
  100. data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_quotes_end_of_line_comments.sql +3 -0
  101. data/test/fixtures/cross_agent_tests/sql_obfuscation/multiple_literal_types.mysql.obfuscated +1 -0
  102. data/test/fixtures/cross_agent_tests/sql_obfuscation/multiple_literal_types.mysql.sql +1 -0
  103. data/test/fixtures/cross_agent_tests/sql_obfuscation/numbers_in_identifiers.obfuscated +1 -0
  104. data/test/fixtures/cross_agent_tests/sql_obfuscation/numbers_in_identifiers.sql +1 -0
  105. data/test/fixtures/cross_agent_tests/sql_obfuscation/numeric_literals.obfuscated +1 -0
  106. data/test/fixtures/cross_agent_tests/sql_obfuscation/numeric_literals.sql +1 -0
  107. data/test/fixtures/cross_agent_tests/sql_obfuscation/quote_delimiters_in_comments.obfuscated +1 -0
  108. data/test/fixtures/cross_agent_tests/sql_obfuscation/quote_delimiters_in_comments.sql +1 -0
  109. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_double_quoted.mysql.obfuscated +1 -0
  110. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_double_quoted.mysql.sql +1 -0
  111. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_single_quoted.obfuscated +1 -0
  112. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_single_quoted.sql +1 -0
  113. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_backslash_and_twin_single_quotes.obfuscated +1 -0
  114. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_backslash_and_twin_single_quotes.sql +4 -0
  115. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_double_quote.obfuscated +1 -0
  116. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_double_quote.sql +1 -0
  117. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_newline.obfuscated +1 -0
  118. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_newline.sql +2 -0
  119. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_single_quote.mysql.obfuscated +1 -0
  120. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_single_quote.mysql.sql +1 -0
  121. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_escaped_quotes.mysql.obfuscated +1 -0
  122. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_escaped_quotes.mysql.sql +1 -0
  123. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_backslash.obfuscated +1 -0
  124. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_backslash.sql +4 -0
  125. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash.mysql.obfuscated +1 -0
  126. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash.mysql.sql +1 -0
  127. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash_single_quoted.obfuscated +1 -0
  128. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash_single_quoted.sql +1 -0
  129. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_quote.obfuscated +1 -0
  130. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_quote.sql +1 -0
  131. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_twin_single_quotes.obfuscated +1 -0
  132. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_twin_single_quotes.sql +1 -0
  133. data/test/multiverse/lib/multiverse/output_collector.rb +1 -1
  134. data/test/multiverse/lib/multiverse/runner.rb +1 -1
  135. data/test/multiverse/lib/multiverse/suite.rb +19 -4
  136. data/test/multiverse/suites/agent_only/audit_log_test.rb +1 -38
  137. data/test/multiverse/suites/agent_only/collector_exception_handling_test.rb +25 -35
  138. data/test/multiverse/suites/agent_only/config/newrelic.yml +2 -0
  139. data/test/multiverse/suites/agent_only/encoding_handling_test.rb +1 -0
  140. data/test/multiverse/suites/agent_only/harvest_timestamps_test.rb +1 -1
  141. data/test/multiverse/suites/agent_only/keepalive_test.rb +29 -0
  142. data/test/multiverse/suites/agent_only/labels_test.rb +89 -0
  143. data/test/multiverse/suites/agent_only/marshaling_test.rb +1 -3
  144. data/test/multiverse/suites/agent_only/service_timeout_test.rb +1 -1
  145. data/test/multiverse/suites/agent_only/start_up_test.rb +9 -1
  146. data/test/multiverse/suites/capistrano/config/deploy.rb +6 -2
  147. data/test/multiverse/suites/capistrano/deployment_test.rb +12 -4
  148. data/test/multiverse/suites/config_file_loading/config_file_loading_test.rb +29 -1
  149. data/test/multiverse/suites/curb/Envfile +6 -2
  150. data/test/multiverse/suites/datamapper/Envfile +0 -4
  151. data/test/multiverse/suites/deferred_instrumentation/Envfile +0 -4
  152. data/test/multiverse/suites/deferred_instrumentation/sinatra_test.rb +1 -1
  153. data/test/multiverse/suites/excon/Envfile +5 -4
  154. data/test/multiverse/suites/excon/excon_test.rb +1 -1
  155. data/test/multiverse/suites/httpclient/Envfile +0 -4
  156. data/test/multiverse/suites/marshalling/Envfile +12 -0
  157. data/test/multiverse/suites/marshalling/config/newrelic.yml +20 -0
  158. data/test/multiverse/suites/marshalling/marshalling_test.rb +60 -0
  159. data/test/multiverse/suites/mongo/helpers/mongo_operation_tests.rb +1 -1
  160. data/test/multiverse/suites/mongo/helpers/mongo_replica_set.rb +1 -1
  161. data/test/multiverse/suites/mongo/helpers/mongo_server.rb +4 -4
  162. data/test/multiverse/suites/padrino/Envfile +0 -5
  163. data/test/multiverse/suites/padrino/padrino_test.rb +1 -1
  164. data/test/multiverse/suites/rack/rack_auto_instrumentation_test.rb +1 -1
  165. data/test/multiverse/suites/rails/gc_instrumentation_test.rb +2 -1
  166. data/test/multiverse/suites/rails/ignore_test.rb +22 -0
  167. data/test/multiverse/suites/rails/rails2_app/config/boot.rb +2 -2
  168. data/test/multiverse/suites/rails/rails2_app/config/routes.rb +1 -0
  169. data/test/multiverse/suites/resque/Envfile +0 -4
  170. data/test/multiverse/suites/sequel/Envfile +0 -5
  171. data/test/multiverse/suites/sinatra/sinatra_classic_test.rb +1 -1
  172. data/test/multiverse/suites/sinatra/sinatra_modular_test.rb +1 -1
  173. data/test/multiverse/suites/sinatra/sinatra_test_cases.rb +22 -0
  174. data/test/multiverse/suites/typhoeus/Envfile +1 -4
  175. data/test/new_relic/agent/agent/start_worker_thread_test.rb +1 -13
  176. data/test/new_relic/agent/agent_logger_test.rb +11 -0
  177. data/test/new_relic/agent/agent_test.rb +43 -20
  178. data/test/new_relic/agent/audit_logger_test.rb +7 -3
  179. data/test/new_relic/agent/commands/thread_profiler_session_test.rb +0 -1
  180. data/test/new_relic/agent/commands/xray_session_collection_test.rb +1 -1
  181. data/test/new_relic/agent/configuration/dotted_hash_test.rb +53 -0
  182. data/test/new_relic/agent/configuration/manager_test.rb +99 -6
  183. data/test/new_relic/agent/configuration/manual_source_test.rb +18 -0
  184. data/test/new_relic/agent/configuration/orphan_configuration_test.rb +1 -1
  185. data/test/new_relic/agent/configuration/yaml_source_test.rb +8 -4
  186. data/test/new_relic/agent/database/sql_obfuscation_test.rb +76 -0
  187. data/test/new_relic/agent/database_test.rb +2 -38
  188. data/test/new_relic/agent/error_collector/notice_error_test.rb +21 -3
  189. data/test/new_relic/agent/error_collector_test.rb +15 -2
  190. data/test/new_relic/agent/event_loop_test.rb +202 -0
  191. data/test/new_relic/agent/instrumentation/active_record_helper_test.rb +4 -0
  192. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +283 -182
  193. data/test/new_relic/agent/method_tracer_test.rb +1 -2
  194. data/test/new_relic/agent/new_relic_service_test.rb +83 -27
  195. data/test/new_relic/agent/pipe_channel_manager_test.rb +6 -6
  196. data/test/new_relic/agent/rpm_agent_test.rb +1 -8
  197. data/test/new_relic/agent/sql_sampler_test.rb +10 -8
  198. data/test/new_relic/agent/threading/backtrace_service_test.rb +1 -1
  199. data/test/new_relic/agent/traced_method_stack_test.rb +45 -13
  200. data/test/new_relic/agent/transaction_sample_builder_test.rb +1 -2
  201. data/test/new_relic/agent/transaction_test.rb +3 -3
  202. data/test/new_relic/agent_test.rb +47 -8
  203. data/test/new_relic/collection_helper_test.rb +5 -5
  204. data/test/new_relic/control/instrumentation_test.rb +56 -0
  205. data/test/new_relic/control_test.rb +4 -3
  206. data/test/new_relic/fake_collector.rb +7 -2
  207. data/test/new_relic/http_client_test_cases.rb +4 -4
  208. data/test/new_relic/latest_changes_test.rb +3 -3
  209. data/test/new_relic/transaction_sample/segment_test.rb +0 -1
  210. data/test/new_relic/transaction_sample_test.rb +19 -2
  211. data/test/performance/lib/performance/runner.rb +4 -4
  212. data/test/performance/suites/marshalling.rb +46 -30
  213. data/test/performance/suites/sql_obfuscation.rb +30 -0
  214. data/test/test_helper.rb +1 -1
  215. data/ui/helpers/developer_mode_helper.rb +2 -2
  216. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/java.rb +1 -1
  217. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/view.rb +1 -1
  218. metadata +84 -3
  219. metadata.gz.sig +0 -0
  220. data/test/environments/rails23/config/environments/development.rb +0 -11
@@ -0,0 +1,76 @@
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 File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper'))
6
+
7
+ module NewRelic::Agent::Database
8
+ class SqlObfuscationTest < Minitest::Test
9
+ attr_reader :obfuscator
10
+
11
+ def self.input_files(subdir=nil)
12
+ fixture_dir = File.join(cross_agent_tests_dir, "sql_obfuscation")
13
+ fixture_dir = File.join(fixture_dir, subdir) if subdir
14
+ Dir["#{fixture_dir}/*.sql"]
15
+ end
16
+
17
+ def self.adapter_from_input_file(input_file)
18
+ case input_file
19
+ when /\.postgres\.sql$/ then :postgresql
20
+ when /\.mysql\.sql$/ then :mysql
21
+ else nil
22
+ end
23
+ end
24
+
25
+ def self.name_for_input_file(input_file)
26
+ adapter = adapter_from_input_file(input_file)
27
+ basename = File.basename(input_file)
28
+ name = basename.gsub(/\.(postgres|mysql)?\.sql$/, '')
29
+ name += "_#{adapter}" if adapter
30
+ name
31
+ end
32
+
33
+ def obfuscated_filename(query_file)
34
+ query_file.gsub(".sql", ".obfuscated")
35
+ end
36
+
37
+ def strip_comments(text)
38
+ text.gsub(/^\s*#.*/, '').strip
39
+ end
40
+
41
+ def read_query(input_file)
42
+ adapter = self.class.adapter_from_input_file(input_file)
43
+ query = strip_comments(File.read(input_file))
44
+
45
+ if adapter
46
+ query = NewRelic::Agent::Database::Statement.new(query)
47
+ query.adapter = adapter.to_sym
48
+ end
49
+
50
+ query
51
+ end
52
+
53
+ # Normal queries
54
+ input_files.each do |input_file|
55
+ name = name_for_input_file(input_file)
56
+
57
+ define_method("test_sql_obfuscation_#{name}") do
58
+ query = read_query(input_file)
59
+ expected_obfuscated = File.read(obfuscated_filename(input_file))
60
+ actual_obfuscated = NewRelic::Agent::Database.obfuscate_sql(query)
61
+ assert_equal(expected_obfuscated, actual_obfuscated, "Failed to obfuscate query from #{input_file}\nQuery: #{query}")
62
+ end
63
+ end
64
+
65
+ # Malformed queries
66
+ input_files('malformed').each do |input_file|
67
+ name = name_for_input_file(input_file)
68
+
69
+ define_method("test_sql_obfuscation_malformed_#{name}") do
70
+ query = read_query(input_file)
71
+ actual_obfuscated = NewRelic::Agent::Database.obfuscate_sql(query)
72
+ assert_equal(NewRelic::Agent::Database::Obfuscator::FAILED_TO_OBFUSCATE_MESSAGE, actual_obfuscated, "Failed to obfuscate malformed query from #{input_file}\nQuery: #{query}")
73
+ end
74
+ end
75
+ end
76
+ end
@@ -297,44 +297,8 @@ class NewRelic::Agent::DatabaseTest < Minitest::Test
297
297
  assert_equal([], NewRelic::Agent::Database.explain_sql('SELECT', config, &@explainer))
298
298
  end
299
299
 
300
- def test_obfuscation_mysql_basic
301
- insert = %q[INSERT INTO `X` values("test",0, 1 , 2, 'test')]
302
- assert_equal("INSERT INTO `X` values(?,?, ? , ?, ?)",
303
- NewRelic::Agent::Database.obfuscate_sql(insert))
304
- select = %q[SELECT `table`.`column` FROM `table` WHERE `table`.`column` = 'value' AND `table`.`other_column` = "other value" LIMIT 1]
305
- assert_equal(%q[SELECT `table`.`column` FROM `table` WHERE `table`.`column` = ? AND `table`.`other_column` = ? LIMIT ?],
306
- NewRelic::Agent::Database.obfuscate_sql(select))
307
- end
308
-
309
- def test_obfuscation_postgresql_basic
310
- insert = NewRelic::Agent::Database::Statement.new(%q[INSERT INTO "X" values('test',0, 1 , 2, 'test')])
311
- insert.adapter = :postgresql
312
- assert_equal('INSERT INTO "X" values(?,?, ? , ?, ?)',
313
- NewRelic::Agent::Database.obfuscate_sql(insert))
314
- select = NewRelic::Agent::Database::Statement.new(%q[SELECT "table"."column" FROM "table" WHERE "table"."column" = 'value' AND "table"."other_column" = 'other value' LIMIT 1])
315
- select.adapter = :postgresql
316
- assert_equal(%q[SELECT "table"."column" FROM "table" WHERE "table"."column" = ? AND "table"."other_column" = ? LIMIT ?],
317
- NewRelic::Agent::Database.obfuscate_sql(select))
318
- end
319
-
320
- def test_obfuscation_escaped_literals
321
- insert = %q[INSERT INTO X values('', 'jim''s ssn',0, 1 , 'jim''s son''s son', """jim''s"" hat", "\"jim''s secret\"")]
322
- assert_equal("INSERT INTO X values(?, ?,?, ? , ?, ?, ?)",
323
- NewRelic::Agent::Database.obfuscate_sql(insert))
324
- end
325
-
326
- def test_obfuscation_mysql_integers_in_identifiers
327
- select = %q[SELECT * FROM `table_007` LIMIT 1]
328
- assert_equal(%q[SELECT * FROM `table_007` LIMIT ?],
329
- NewRelic::Agent::Database.obfuscate_sql(select))
330
- end
331
-
332
- def test_obfuscation_postgresql_integers_in_identifiers
333
- select = NewRelic::Agent::Database::Statement.new(%q[SELECT * FROM "table_007" LIMIT 1])
334
- select.adapter = :postgresql
335
- assert_equal(%q[SELECT * FROM "table_007" LIMIT ?],
336
- NewRelic::Agent::Database.obfuscate_sql(select))
337
- end
300
+ # See SqlObfuscationTest, which uses cross agent tests for the basic SQL
301
+ # obfuscation test cases.
338
302
 
339
303
  def test_obfuscation_of_truncated_query
340
304
  insert = "INSERT INTO data (blah) VALUES ('abcdefg..."
@@ -191,20 +191,33 @@ class NewRelic::Agent::ErrorCollector::NoticeErrorTest < Minitest::Test
191
191
 
192
192
  def test_filtered_by_error_filter_empty
193
193
  # should return right away when there's no filter
194
- @ignore_filter = nil
195
194
  assert !filtered_by_error_filter?(nil)
196
195
  end
197
196
 
198
197
  def test_filtered_by_error_filter_positive
199
198
  error = mocked_error
200
- @ignore_filter = lambda { |x| assert_equal error, x; false }
199
+ self.class.class_eval do
200
+ define_method(:ignore_filter_proc) do |e|
201
+ assert_equal(error, e)
202
+ false
203
+ end
204
+ end
201
205
  assert filtered_by_error_filter?(error)
206
+ ensure
207
+ self.class.class_eval { undef :ignore_filter_proc }
202
208
  end
203
209
 
204
210
  def test_filtered_by_error_filter_negative
205
211
  error = mocked_error
206
- @ignore_filter = lambda { |x| assert_equal error, x; true }
212
+ self.class.class_eval do
213
+ define_method(:ignore_filter_proc) do |e|
214
+ assert_equal(error, e)
215
+ true
216
+ end
217
+ end
207
218
  assert !filtered_by_error_filter?(error)
219
+ ensure
220
+ self.class.class_eval { undef :ignore_filter_proc }
208
221
  end
209
222
 
210
223
  def test_error_is_ignored_positive
@@ -240,4 +253,9 @@ class NewRelic::Agent::ErrorCollector::NoticeErrorTest < Minitest::Test
240
253
  yield NewRelic::Agent::ErrorCollector.new
241
254
  end
242
255
  end
256
+
257
+ def ignore_error_filter
258
+ @ignore_filter
259
+ end
260
+
243
261
  end
@@ -20,6 +20,7 @@ class NewRelic::Agent::ErrorCollectorTest < Minitest::Test
20
20
 
21
21
  def teardown
22
22
  super
23
+ NewRelic::Agent::ErrorCollector.ignore_error_filter = nil
23
24
  NewRelic::Agent::TransactionState.tl_clear_for_testing
24
25
  NewRelic::Agent.config.reset_to_defaults
25
26
  end
@@ -183,7 +184,7 @@ class NewRelic::Agent::ErrorCollectorTest < Minitest::Test
183
184
  end
184
185
 
185
186
  def test_exclude_block
186
- @error_collector.ignore_error_filter &wrapped_filter_proc
187
+ @error_collector.class.ignore_error_filter = wrapped_filter_proc
187
188
 
188
189
  @error_collector.notice_error(IOError.new("message"), :metric => 'path', :request_params => {:x => 'y'})
189
190
  @error_collector.notice_error(StandardError.new("message"), :metric => 'path', :request_params => {:x => 'y'})
@@ -194,7 +195,7 @@ class NewRelic::Agent::ErrorCollectorTest < Minitest::Test
194
195
  end
195
196
 
196
197
  def test_failure_in_exclude_block
197
- @error_collector.ignore_error_filter do
198
+ @error_collector.class.ignore_error_filter = Proc.new do
198
199
  raise "HAHAHAHAH, error in the filter for ignoring errors!"
199
200
  end
200
201
 
@@ -205,6 +206,18 @@ class NewRelic::Agent::ErrorCollectorTest < Minitest::Test
205
206
  assert_equal 1, errors.length
206
207
  end
207
208
 
209
+ def test_failure_block_assigned_with_different_instance
210
+ @error_collector.class.ignore_error_filter = Proc.new do |*_|
211
+ # meh, ignore 'em all!
212
+ nil
213
+ end
214
+
215
+ new_error_collector = NewRelic::Agent::ErrorCollector.new
216
+ new_error_collector.notice_error(StandardError.new("message"))
217
+
218
+ assert_empty new_error_collector.harvest!
219
+ end
220
+
208
221
  def test_obfuscates_error_messages_when_high_security_is_set
209
222
  with_config(:high_security => true) do
210
223
  @error_collector.notice_error(StandardError.new("YO SQL BAD: serect * flom test where foo = 'bar'"))
@@ -0,0 +1,202 @@
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 File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
6
+
7
+ class NewRelic::Agent::EventLoopTest < Minitest::Test
8
+ def setup
9
+ freeze_time
10
+ @loop = NewRelic::Agent::EventLoop.new
11
+ end
12
+
13
+ def test_fire_after
14
+ call_count = 0
15
+
16
+ @loop.on(:event) { call_count += 1 }
17
+ @loop.fire_after(3, :event)
18
+
19
+ @loop.run_once(true)
20
+ assert_equal(0, call_count)
21
+
22
+ advance_loop(1)
23
+ assert_equal(0, call_count)
24
+
25
+ advance_loop(2)
26
+ assert_equal(1, call_count)
27
+
28
+ advance_loop(5)
29
+ assert_equal(1, call_count)
30
+ end
31
+
32
+ def test_fire_every
33
+ call_count = 0
34
+
35
+ @loop.on(:event) do
36
+ call_count += 1
37
+ end
38
+
39
+ @loop.fire_every(3, :event)
40
+
41
+ @loop.run_once(true)
42
+ assert_equal(0, call_count)
43
+
44
+ advance_loop(2)
45
+ assert_equal(0, call_count)
46
+
47
+ advance_loop(1)
48
+ assert_equal(1, call_count)
49
+
50
+ advance_loop(4)
51
+ assert_equal(2, call_count)
52
+ end
53
+
54
+ def test_fire_resets_associated_timers
55
+ call_count = 0
56
+
57
+ @loop.on(:event) { call_count += 1 }
58
+ @loop.fire_every(10, :event)
59
+
60
+ advance_loop(5)
61
+ @loop.fire(:event)
62
+ @loop.run_once(true)
63
+ assert_equal(1, call_count)
64
+
65
+ advance_loop(5)
66
+ assert_equal(1, call_count)
67
+
68
+ advance_loop(5)
69
+ assert_equal(2, call_count)
70
+ end
71
+
72
+ def test_adjust_period_larger
73
+ call_count = 0
74
+ @loop.on(:e) { call_count += 1 }
75
+
76
+ @loop.fire_every(10, :e)
77
+ @loop.run_once(true)
78
+
79
+ advance_loop(9)
80
+ assert_equal(0, call_count)
81
+
82
+ @loop.fire_every(15, :e)
83
+ @loop.run_once(true)
84
+ assert_equal(0, call_count)
85
+
86
+ advance_loop(1)
87
+ assert_equal(0, call_count)
88
+
89
+ advance_loop(5)
90
+ assert_equal(1, call_count)
91
+ end
92
+
93
+ def test_adjust_period_smaller
94
+ call_count = 0
95
+ @loop.on(:e) { call_count += 1 }
96
+ @loop.fire_every(10, :e)
97
+
98
+ @loop.run_once(true)
99
+ assert_equal(0, call_count)
100
+
101
+ advance_loop(5)
102
+ assert_equal(0, call_count)
103
+
104
+ @loop.fire_every(2, :e)
105
+ @loop.run_once(true)
106
+ assert_equal(1, call_count)
107
+
108
+ advance_loop(1)
109
+ assert_equal(1, call_count)
110
+
111
+ advance_loop(1)
112
+ assert_equal(2, call_count)
113
+ end
114
+
115
+ def test_on
116
+ call_count = 0
117
+ @loop.on(:evt) do
118
+ call_count += 1
119
+ end
120
+ @loop.fire(:evt)
121
+ @loop.run_once(true)
122
+ assert_equal(1, call_count)
123
+ end
124
+
125
+ def test_on_with_payload
126
+ call_count = 0
127
+ @loop.on(:evt) do |amount|
128
+ call_count += amount
129
+ end
130
+ @loop.fire(:evt, 42)
131
+ @loop.run_once(true)
132
+ assert_equal(42, call_count)
133
+ end
134
+
135
+ def test_manual_fire_resets_timers
136
+ call_count = 0
137
+ @loop.on(:e) { call_count += 1 }
138
+ @loop.fire_every(4, :e)
139
+
140
+ advance_loop(3)
141
+ assert_equal(0, call_count)
142
+
143
+ @loop.fire(:e)
144
+ @loop.run_once(true)
145
+ assert_equal(1, call_count)
146
+
147
+ advance_loop(3)
148
+ assert_equal(1, call_count)
149
+
150
+ advance_loop(1)
151
+ assert_equal(2, call_count)
152
+ end
153
+
154
+ def test_exceptions_do_not_exit_loop
155
+ call_count = 0
156
+ @loop.on(:e) { raise StandardError.new }
157
+ @loop.on(:e) { call_count += 1 }
158
+ @loop.on(:e) { raise StandardError.new }
159
+
160
+ @loop.fire(:e)
161
+
162
+ @loop.run_once(true)
163
+ assert_equal(1, call_count)
164
+ end
165
+
166
+ def test_timer_period_reset_from_event
167
+ call_count = 0
168
+ @loop.on(:e ) { call_count += 1 }
169
+ @loop.on(:reset_period) { @loop.fire_every(30, :e) }
170
+
171
+ @loop.fire_every( 5, :e )
172
+ @loop.fire_after(31, :reset_period)
173
+
174
+ advance_loop(3) # total time 3
175
+ assert_equal(0, call_count)
176
+
177
+ advance_loop(2) # total time 5
178
+ assert_equal(1, call_count)
179
+
180
+ advance_loop(5) # total time 10
181
+ assert_equal(2, call_count)
182
+
183
+ advance_loop(20) # total time 30
184
+ assert_equal(6, call_count)
185
+
186
+ advance_loop(29) # total time 59
187
+ assert_equal(6, call_count)
188
+
189
+ advance_loop(1) # total time 60
190
+ assert_equal(7, call_count)
191
+
192
+ advance_loop(60) # total time 120
193
+ assert_equal(9, call_count)
194
+ end
195
+
196
+ def advance_loop(n)
197
+ n.times do
198
+ advance_time(1)
199
+ @loop.run_once(true)
200
+ end
201
+ end
202
+ end
@@ -39,6 +39,10 @@ class NewRelic::Agent::Instrumentation::ActiveRecordHelperTest < Minitest::Test
39
39
  assert_nil ActiveRecordHelper.metric_for_name('Model Columns')
40
40
  end
41
41
 
42
+ def test_metric_for_name_with_integer_returns_nil
43
+ assert_nil ActiveRecordHelper.metric_for_name(1)
44
+ end
45
+
42
46
  def test_rollup_metrics_for_lists_rollups
43
47
  NewRelic::Agent::Transaction.stubs(:recording_web_transaction?).returns(true)
44
48
  base_metric = 'ActiveRecord/Namespace::Model/find'
@@ -3,242 +3,343 @@
3
3
  # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
4
 
5
5
  require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper'))
6
- class NewRelic::Agent::Instrumentation::ControllerInstrumentationTest < Minitest::Test
7
- require 'new_relic/agent/instrumentation/controller_instrumentation'
8
- class TestObject
9
- include NewRelic::Agent::Instrumentation::ControllerInstrumentation
10
6
 
11
- def public_transaction(*args); end
7
+ module NewRelic::Agent::Instrumentation
8
+ class ControllerInstrumentationTest < Minitest::Test
12
9
 
13
- protected
14
- def protected_transaction(*args); end
10
+ class TestObject
11
+ include ControllerInstrumentation
15
12
 
16
- private
17
- def private_transaction(*args); end
13
+ def public_transaction(*args); end
18
14
 
19
- add_transaction_tracer :public_transaction
20
- add_transaction_tracer :protected_transaction
21
- add_transaction_tracer :private_transaction
22
- end
15
+ protected
16
+ def protected_transaction(*args); end
23
17
 
24
- def setup
25
- NewRelic::Agent.drop_buffered_data
26
- @object = TestObject.new
27
- @dummy_headers = { :request => 'headers' }
28
- @txn_namer = NewRelic::Agent::Instrumentation::ControllerInstrumentation::TransactionNamer
29
- end
18
+ private
19
+ def private_transaction(*args); end
30
20
 
31
- def teardown
32
- NewRelic::Agent.instance.stats_engine.clear_stats
33
- end
21
+ add_transaction_tracer :public_transaction
22
+ add_transaction_tracer :protected_transaction
23
+ add_transaction_tracer :private_transaction
24
+ end
34
25
 
35
- def test_apdex_recorded
36
- @object.public_transaction
37
- assert_metrics_recorded("Apdex")
38
- end
26
+ class TestParent
27
+ include ControllerInstrumentation
39
28
 
40
- def test_apdex_ignored
41
- @object.stubs(:ignore_apdex?).returns(true)
42
- @object.public_transaction
43
- assert_metrics_not_recorded("Apdex")
44
- end
29
+ newrelic_ignore_apdex
45
30
 
46
- def test_transaction_name_calls_newrelic_metric_path
47
- @object.stubs(:newrelic_metric_path).returns('some/wacky/path')
48
- assert_equal('Controller/some/wacky/path', @txn_namer.name(nil, @object, :controller))
49
- end
31
+ def foo(*args); end
50
32
 
51
- def test_transaction_name_applies_category_and_path
52
- assert_equal('Controller/metric/path',
53
- @txn_namer.name(nil,
54
- @object,
55
- :controller,
56
- :path => 'metric/path'))
57
- assert_equal('OtherTransaction/Background/metric/path',
58
- @txn_namer.name(nil,
59
- @object,
60
- :task,
61
- :path => 'metric/path'))
62
- assert_equal('Controller/Rack/metric/path',
63
- @txn_namer.name(nil,
64
- @object,
65
- :rack,
66
- :path => 'metric/path'))
67
- assert_equal('Controller/metric/path',
68
- @txn_namer.name(nil,
69
- @object,
70
- :uri,
71
- :path => 'metric/path'))
72
- assert_equal('Controller/Sinatra/metric/path',
73
- @txn_namer.name(nil,
74
- @object,
75
- :sinatra,
76
- :path => 'metric/path'))
77
- assert_equal('Blarg/metric/path',
78
- @txn_namer.name(nil,
79
- @object,
80
- 'Blarg',
81
- :path => 'metric/path'))
82
- end
33
+ add_transaction_tracer :foo
34
+ end
83
35
 
84
- def test_transaction_name_uses_class_name_if_path_not_specified
85
- assert_equal('Controller/NewRelic::Agent::Instrumentation::ControllerInstrumentationTest::TestObject',
86
- @txn_namer.name(nil, @object, :controller))
87
- end
36
+ class TestChild < TestParent
37
+ def bar(*args); end
88
38
 
89
- def test_transaction_name_applies_action_name_if_specified_and_not_path
90
- assert_equal('Controller/NewRelic::Agent::Instrumentation::ControllerInstrumentationTest::TestObject/action',
91
- @txn_namer.name(nil,
92
- @object,
93
- :controller,
94
- :name => 'action'))
95
- end
39
+ add_transaction_tracer :bar
40
+ end
96
41
 
97
- def test_transaction_path_name
98
- result = @txn_namer.path_name(@object)
99
- assert_equal("NewRelic::Agent::Instrumentation::ControllerInstrumentationTest::TestObject", result)
100
- end
42
+ def setup
43
+ NewRelic::Agent.drop_buffered_data
44
+ @object = TestObject.new
45
+ @dummy_headers = { :request => 'headers' }
46
+ @txn_namer = ControllerInstrumentation::TransactionNamer
47
+ end
101
48
 
102
- def test_transaction_path_name_with_name
103
- result = @txn_namer.path_name(@object, :name => "test")
104
- assert_equal("NewRelic::Agent::Instrumentation::ControllerInstrumentationTest::TestObject/test", result)
105
- end
49
+ def teardown
50
+ NewRelic::Agent.instance.stats_engine.clear_stats
51
+ end
106
52
 
107
- def test_transaction_path_name_with_overridden_class_name
108
- result = @txn_namer.path_name(@object, :name => "perform", :class_name => 'Resque')
109
- assert_equal("Resque/perform", result)
110
- end
53
+ def test_apdex_recorded
54
+ @object.public_transaction
55
+ assert_metrics_recorded("Apdex")
56
+ end
111
57
 
112
- def test_add_transaction_tracer_should_not_double_instrument
113
- TestObject.expects(:alias_method).never
114
- TestObject.class_eval do
115
- add_transaction_tracer :public_transaction
116
- add_transaction_tracer :protected_transaction
117
- add_transaction_tracer :private_transaction
58
+ def test_apdex_ignored
59
+ @object.stubs(:ignore_apdex?).returns(true)
60
+ @object.public_transaction
61
+ assert_metrics_not_recorded("Apdex")
118
62
  end
119
- obj = TestObject.new
120
- end
121
63
 
122
- def test_add_transaction_tracer_defines_with_method
123
- assert TestObject.method_defined? :public_transaction_with_newrelic_transaction_trace
124
- end
64
+ def test_apdex_ignored_if_ignored_in_parent_class
65
+ obj = TestChild.new
125
66
 
126
- def test_add_transaction_tracer_defines_without_method
127
- assert TestObject.method_defined? :public_transaction_without_newrelic_transaction_trace
128
- end
67
+ obj.foo
68
+ obj.bar
129
69
 
130
- def test_parse_punctuation
131
- ['?', '!', '='].each do |punctuation_mark|
132
- result = TestObject.parse_punctuation("foo#{punctuation_mark}")
133
- assert_equal ['foo', punctuation_mark], result
70
+ assert_metrics_not_recorded("Apdex")
134
71
  end
135
- end
136
72
 
137
- def test_argument_list
138
- options = {:foo => :bar, :params => '{ :account_name => args[0].name }', :far => 7}
139
- result = TestObject.generate_argument_list(options)
140
- expected = [":far => \"7\"", ":foo => :bar", ":params => { :account_name => args[0].name }"]
141
- assert_equal expected.sort, result.sort
142
- end
73
+ def test_children_respect_parental_ignore_rules_with_only
74
+ parent = Class.new do
75
+ include ControllerInstrumentation
143
76
 
144
- def test_build_method_names
145
- result = TestObject.build_method_names('foo', '?')
146
- expected = ["foo_with_newrelic_transaction_trace?", "foo_without_newrelic_transaction_trace?"]
147
- assert_equal expected, result
148
- end
77
+ newrelic_ignore(:only => :foo)
149
78
 
150
- def test_already_added_transaction_tracer_returns_true_if_with_method_defined
151
- with_method_name = 'public_transaction_with_newrelic_transaction_trace'
152
- assert TestObject.already_added_transaction_tracer?(TestObject, with_method_name)
153
- end
79
+ def foo(*args); end
80
+ def foo2(*args); end
81
+ end
154
82
 
155
- # ControllerInstrumentation historically was used to instrument Rails 2
156
- # controllers, and in this case is called without a block. In that case, and
157
- # that case *only*, we want to try to call params on the host object to
158
- # extract request params.
159
- #
160
- # In the more modern usage where it's called with a block we do *not* want to
161
- # call params on the host object. This is important because doing so could
162
- # actually crash in some cases.
163
- def test_should_not_call_params_on_host_if_called_with_block
164
- host_class = Class.new do
165
- include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
166
-
167
- # It's a more realistic test if the host class actually responds to params
168
- def params
169
- raise 'no!'
83
+ child = Class.new(parent) do
84
+ newrelic_ignore(:only => :bar)
85
+
86
+ def bar(*args); end
87
+ def bar2(*args); end
170
88
  end
171
89
 
172
- def doit
173
- perform_action_with_newrelic_trace do
174
- # nothing
175
- end
90
+ key = ControllerInstrumentation::NR_DO_NOT_TRACE_KEY
91
+
92
+ assert IgnoreActions.is_filtered?(key, child, :foo )
93
+ assert IgnoreActions.is_filtered?(key, child, :bar )
94
+ refute IgnoreActions.is_filtered?(key, child, :foo2)
95
+ refute IgnoreActions.is_filtered?(key, child, :bar2)
96
+ end
97
+
98
+ def test_children_respect_parental_ignore_rules_with_except
99
+ parent = Class.new do
100
+ include ControllerInstrumentation
101
+
102
+ newrelic_ignore(:except => :foo)
103
+
104
+ def foo(*args); end
105
+ def foo2(*args); end
106
+ end
107
+
108
+ child = Class.new(parent) do
109
+ newrelic_ignore(:except => :bar)
110
+
111
+ def bar(*args); end
112
+ def bar2(*args); end
176
113
  end
114
+
115
+ key = ControllerInstrumentation::NR_DO_NOT_TRACE_KEY
116
+
117
+ assert IgnoreActions.is_filtered?(key, child, :foo )
118
+ assert IgnoreActions.is_filtered?(key, child, :bar )
119
+ assert IgnoreActions.is_filtered?(key, child, :foo2)
120
+ assert IgnoreActions.is_filtered?(key, child, :bar2)
177
121
  end
178
122
 
179
- host = host_class.new
180
- host.expects(:params).never
181
- host.doit
182
- end
123
+ def test_children_respect_parental_ignore_rules_with_except_and_only
124
+ parent = Class.new do
125
+ include ControllerInstrumentation
126
+
127
+ newrelic_ignore(:only => :foo)
128
+
129
+ def foo(*args); end
130
+ def foo2(*args); end
131
+ end
183
132
 
184
- def test_should_not_call_params_on_host_if_no_block_given_but_does_not_respond_to_params
185
- host_class = Class.new do
186
- include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
133
+ child = Class.new(parent) do
134
+ newrelic_ignore(:except => :foo)
187
135
 
188
- def doit
189
- perform_action_with_newrelic_trace
136
+ def bar(*args); end
190
137
  end
191
138
 
192
- def perform_action_without_newrelic_trace; end
139
+ key = ControllerInstrumentation::NR_DO_NOT_TRACE_KEY
140
+
141
+ assert IgnoreActions.is_filtered?(key, child, :foo )
142
+ assert IgnoreActions.is_filtered?(key, child, :bar )
143
+ assert IgnoreActions.is_filtered?(key, child, :foo2)
193
144
  end
194
145
 
195
- host = host_class.new
196
- refute host.respond_to?(:params)
197
- host.doit
198
- end
146
+ def test_transaction_name_calls_newrelic_metric_path
147
+ @object.stubs(:newrelic_metric_path).returns('some/wacky/path')
148
+ assert_equal('Controller/some/wacky/path', @txn_namer.name(nil, @object, :controller))
149
+ end
150
+
151
+ def test_transaction_name_applies_category_and_path
152
+ assert_equal('Controller/metric/path',
153
+ @txn_namer.name(nil,
154
+ @object,
155
+ :controller,
156
+ :path => 'metric/path'))
157
+ assert_equal('OtherTransaction/Background/metric/path',
158
+ @txn_namer.name(nil,
159
+ @object,
160
+ :task,
161
+ :path => 'metric/path'))
162
+ assert_equal('Controller/Rack/metric/path',
163
+ @txn_namer.name(nil,
164
+ @object,
165
+ :rack,
166
+ :path => 'metric/path'))
167
+ assert_equal('Controller/metric/path',
168
+ @txn_namer.name(nil,
169
+ @object,
170
+ :uri,
171
+ :path => 'metric/path'))
172
+ assert_equal('Controller/Sinatra/metric/path',
173
+ @txn_namer.name(nil,
174
+ @object,
175
+ :sinatra,
176
+ :path => 'metric/path'))
177
+ assert_equal('Blarg/metric/path',
178
+ @txn_namer.name(nil,
179
+ @object,
180
+ 'Blarg',
181
+ :path => 'metric/path'))
182
+ end
199
183
 
200
- def test_should_call_params_on_host_if_no_block_given_and_host_responds
201
- host_class = Class.new do
202
- include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
184
+ def test_transaction_name_uses_class_name_if_path_not_specified
185
+ assert_equal('Controller/NewRelic::Agent::Instrumentation::ControllerInstrumentationTest::TestObject',
186
+ @txn_namer.name(nil, @object, :controller))
187
+ end
203
188
 
204
- attr_reader :params_called
189
+ def test_transaction_name_applies_action_name_if_specified_and_not_path
190
+ assert_equal('Controller/NewRelic::Agent::Instrumentation::ControllerInstrumentationTest::TestObject/action',
191
+ @txn_namer.name(nil,
192
+ @object,
193
+ :controller,
194
+ :name => 'action'))
195
+ end
196
+
197
+ def test_transaction_path_name
198
+ result = @txn_namer.path_name(@object)
199
+ assert_equal("NewRelic::Agent::Instrumentation::ControllerInstrumentationTest::TestObject", result)
200
+ end
205
201
 
206
- def params
207
- @params_called = true
208
- {}
202
+ def test_transaction_path_name_with_name
203
+ result = @txn_namer.path_name(@object, :name => "test")
204
+ assert_equal("NewRelic::Agent::Instrumentation::ControllerInstrumentationTest::TestObject/test", result )
205
+ end
206
+
207
+ def test_transaction_path_name_with_overridden_class_name
208
+ result = @txn_namer.path_name(@object, :name => "perform", :class_name => 'Resque')
209
+ assert_equal("Resque/perform", result)
210
+ end
211
+
212
+ def test_add_transaction_tracer_should_not_double_instrument
213
+ TestObject.expects(:alias_method).never
214
+ TestObject.class_eval do
215
+ add_transaction_tracer :public_transaction
216
+ add_transaction_tracer :protected_transaction
217
+ add_transaction_tracer :private_transaction
209
218
  end
219
+ TestObject.new
220
+ end
210
221
 
211
- def doit
212
- perform_action_with_newrelic_trace
222
+ def test_add_transaction_tracer_defines_with_method
223
+ assert TestObject.method_defined? :public_transaction_with_newrelic_transaction_trace
224
+ end
225
+
226
+ def test_add_transaction_tracer_defines_without_method
227
+ assert TestObject.method_defined? :public_transaction_without_newrelic_transaction_trace
228
+ end
229
+
230
+ def test_parse_punctuation
231
+ ['?', '!', '='].each do |punctuation_mark|
232
+ result = TestObject.parse_punctuation("foo#{punctuation_mark}")
233
+ assert_equal ['foo', punctuation_mark], result
213
234
  end
235
+ end
214
236
 
215
- def perform_action_without_newrelic_trace; end
237
+ def test_argument_list
238
+ options = {:foo => :bar, :params => '{ :account_name => args[0].name }', :far => 7}
239
+ result = TestObject.generate_argument_list(options)
240
+ expected = [":far => \"7\"", ":foo => :bar", ":params => { :account_name => args[0].name }"]
241
+ assert_equal expected.sort, result.sort
216
242
  end
217
243
 
218
- host = host_class.new
219
- host.doit
220
- assert host.params_called
221
- end
244
+ def test_build_method_names
245
+ result = TestObject.build_method_names('foo', '?')
246
+ expected = ["foo_with_newrelic_transaction_trace?", "foo_without_newrelic_transaction_trace?"]
247
+ assert_equal expected, result
248
+ end
222
249
 
223
- class UserError < StandardError
224
- end
250
+ def test_already_added_transaction_tracer_returns_true_if_with_method_defined
251
+ with_method_name = 'public_transaction_with_newrelic_transaction_trace'
252
+ assert TestObject.already_added_transaction_tracer?(TestObject, with_method_name)
253
+ end
225
254
 
226
- def test_failure_during_starting_shouldnt_override_error_raised
227
- host_class = Class.new do
228
- include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
255
+ # ControllerInstrumentation historically was used to instrument Rails 2
256
+ # controllers, and in this case is called without a block. In that case, and
257
+ # that case *only*, we want to try to call params on the host object to
258
+ # extract request params.
259
+ #
260
+ # In the more modern usage where it's called with a block we do *not* want to
261
+ # call params on the host object. This is important because doing so could
262
+ # actually crash in some cases.
263
+ def test_should_not_call_params_on_host_if_called_with_block
264
+ host_class = Class.new do
265
+ include ControllerInstrumentation
266
+
267
+ # It's a more realistic test if the host class actually responds to params
268
+ def params
269
+ raise 'no!'
270
+ end
229
271
 
230
- def doit
231
- perform_action_with_newrelic_trace do
232
- raise UserError.new
272
+ def doit
273
+ perform_action_with_newrelic_trace do
274
+ # nothing
275
+ end
233
276
  end
234
277
  end
278
+
279
+ host = host_class.new
280
+ host.expects(:params).never
281
+ host.doit
235
282
  end
236
283
 
237
- NewRelic::Agent::Transaction.stubs(:start).returns(nil)
284
+ def test_should_not_call_params_on_host_if_no_block_given_but_does_not_respond_to_params
285
+ host_class = Class.new do
286
+ include ControllerInstrumentation
238
287
 
239
- host = host_class.new
240
- assert_raises(UserError) do
288
+ def doit
289
+ perform_action_with_newrelic_trace
290
+ end
291
+
292
+ def perform_action_without_newrelic_trace; end
293
+ end
294
+
295
+ host = host_class.new
296
+ refute host.respond_to?(:params)
297
+ host.doit
298
+ end
299
+
300
+ def test_should_call_params_on_host_if_no_block_given_and_host_responds
301
+ host_class = Class.new do
302
+ include ControllerInstrumentation
303
+
304
+ attr_reader :params_called
305
+
306
+ def params
307
+ @params_called = true
308
+ {}
309
+ end
310
+
311
+ def doit
312
+ perform_action_with_newrelic_trace
313
+ end
314
+
315
+ def perform_action_without_newrelic_trace; end
316
+ end
317
+
318
+ host = host_class.new
241
319
  host.doit
320
+ assert host.params_called
321
+ end
322
+
323
+ class UserError < StandardError
324
+ end
325
+
326
+ def test_failure_during_starting_shouldnt_override_error_raised
327
+ host_class = Class.new do
328
+ include ControllerInstrumentation
329
+
330
+ def doit
331
+ perform_action_with_newrelic_trace do
332
+ raise UserError.new
333
+ end
334
+ end
335
+ end
336
+
337
+ NewRelic::Agent::Transaction.stubs(:start).returns(nil)
338
+
339
+ host = host_class.new
340
+ assert_raises(UserError) do
341
+ host.doit
342
+ end
242
343
  end
243
344
  end
244
345
  end