newrelic_rpm 3.11.2.286 → 3.12.0.288

Sign up to get free protection for your applications and to get access to all the features.
Files changed (269) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -2
  3. data/.yardopts +2 -0
  4. data/CHANGELOG +39 -4
  5. data/README.md +4 -2
  6. data/lib/new_relic/agent.rb +229 -214
  7. data/lib/new_relic/agent/agent.rb +23 -12
  8. data/lib/new_relic/agent/attribute_filter.rb +242 -0
  9. data/lib/new_relic/agent/attribute_processing.rb +62 -0
  10. data/lib/new_relic/agent/commands/xray_session_collection.rb +4 -1
  11. data/lib/new_relic/agent/configuration/default_source.rb +284 -30
  12. data/lib/new_relic/agent/configuration/high_security_source.rb +0 -8
  13. data/lib/new_relic/agent/configuration/manager.rb +1 -1
  14. data/lib/new_relic/agent/configuration/server_source.rb +86 -31
  15. data/lib/new_relic/agent/configuration/yaml_source.rb +1 -1
  16. data/lib/new_relic/agent/cross_app_monitor.rb +8 -13
  17. data/lib/new_relic/agent/cross_app_tracing.rb +15 -15
  18. data/lib/new_relic/agent/custom_event_aggregator.rb +6 -2
  19. data/lib/new_relic/agent/database.rb +15 -2
  20. data/lib/new_relic/agent/datastores.rb +52 -38
  21. data/lib/new_relic/agent/datastores/metric_helper.rb +2 -1
  22. data/lib/new_relic/agent/encoding_normalizer.rb +82 -0
  23. data/lib/new_relic/agent/error_collector.rb +125 -169
  24. data/lib/new_relic/agent/hash_extensions.rb +26 -0
  25. data/lib/new_relic/agent/http_clients/excon_wrappers.rb +13 -11
  26. data/lib/new_relic/agent/http_clients/uri_util.rb +9 -0
  27. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +1 -3
  28. data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +1 -1
  29. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +1 -1
  30. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +12 -5
  31. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +6 -7
  32. data/lib/new_relic/agent/instrumentation/curb.rb +6 -6
  33. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +4 -4
  34. data/lib/new_relic/agent/instrumentation/grape.rb +4 -3
  35. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +6 -3
  36. data/lib/new_relic/agent/instrumentation/rails/errors.rb +9 -3
  37. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +6 -1
  38. data/lib/new_relic/agent/instrumentation/rails3/errors.rb +9 -7
  39. data/lib/new_relic/agent/instrumentation/rails4/errors.rb +8 -6
  40. data/lib/new_relic/agent/instrumentation/resque.rb +2 -3
  41. data/lib/new_relic/agent/instrumentation/sidekiq.rb +3 -3
  42. data/lib/new_relic/agent/instrumentation/typhoeus.rb +2 -2
  43. data/lib/new_relic/agent/javascript_instrumentor.rb +24 -16
  44. data/lib/new_relic/agent/parameter_filtering.rb +8 -1
  45. data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +2 -2
  46. data/lib/new_relic/agent/sql_sampler.rb +1 -0
  47. data/lib/new_relic/agent/stats.rb +0 -4
  48. data/lib/new_relic/agent/stats_engine/metric_stats.rb +5 -3
  49. data/lib/new_relic/agent/stats_engine/stats_hash.rb +4 -0
  50. data/lib/new_relic/agent/supported_versions.rb +2 -2
  51. data/lib/new_relic/agent/traced_method_stack.rb +3 -3
  52. data/lib/new_relic/agent/transaction.rb +141 -118
  53. data/lib/new_relic/agent/transaction/attributes.rb +161 -0
  54. data/lib/new_relic/agent/transaction/developer_mode_sample_buffer.rb +4 -4
  55. data/lib/new_relic/agent/transaction/trace.rb +150 -0
  56. data/lib/new_relic/agent/transaction/trace_node.rb +190 -0
  57. data/lib/new_relic/agent/transaction/transaction_sample_buffer.rb +2 -2
  58. data/lib/new_relic/agent/transaction_event_aggregator.rb +23 -7
  59. data/lib/new_relic/agent/transaction_sample_builder.rb +37 -62
  60. data/lib/new_relic/agent/transaction_sampler.rb +29 -66
  61. data/lib/new_relic/cli/commands/install.rb +2 -2
  62. data/lib/new_relic/coerce.rb +15 -28
  63. data/lib/new_relic/json_wrapper.rb +14 -73
  64. data/lib/new_relic/noticed_error.rb +81 -5
  65. data/lib/new_relic/rack/browser_monitoring.rb +14 -19
  66. data/lib/new_relic/rack/developer_mode.rb +68 -14
  67. data/lib/new_relic/rack/developer_mode/segment_summary.rb +56 -0
  68. data/lib/new_relic/version.rb +2 -2
  69. data/newrelic.yml +19 -196
  70. data/test/agent_helper.rb +42 -36
  71. data/test/config/newrelic.yml +0 -1
  72. data/test/environments/rails40/Gemfile +1 -1
  73. data/test/environments/rails41/Gemfile +1 -1
  74. data/test/environments/rails42/Gemfile +1 -1
  75. data/test/fixtures/cross_agent_tests/attribute_configuration.json +35 -0
  76. data/test/fixtures/cross_agent_tests/sql_obfuscation/README.md +19 -12
  77. data/test/fixtures/cross_agent_tests/sql_obfuscation/sql_obfuscation.json +365 -0
  78. data/test/multiverse/lib/multiverse/suite.rb +5 -1
  79. data/test/multiverse/suites/active_record/active_record_test.rb +8 -8
  80. data/test/multiverse/suites/agent_only/agent_attributes_test.rb +145 -0
  81. data/test/multiverse/suites/agent_only/cross_application_tracing_test.rb +8 -0
  82. data/test/multiverse/suites/agent_only/custom_queue_time_test.rb +5 -1
  83. data/test/multiverse/suites/agent_only/encoding_handling_test.rb +6 -6
  84. data/test/multiverse/suites/agent_only/marshaling_test.rb +1 -1
  85. data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +2 -3
  86. data/test/multiverse/suites/agent_only/synthetics_test.rb +3 -3
  87. data/test/multiverse/suites/agent_only/testing_app.rb +4 -0
  88. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +1 -1
  89. data/test/multiverse/suites/agent_only/utilization_data_collection_test.rb +9 -7
  90. data/test/multiverse/suites/curb/Envfile +5 -6
  91. data/test/multiverse/suites/curb/curb_test.rb +4 -5
  92. data/test/multiverse/suites/datamapper/datamapper_test.rb +2 -2
  93. data/test/multiverse/suites/excon/Envfile +11 -4
  94. data/test/multiverse/suites/excon/excon_test.rb +5 -5
  95. data/test/multiverse/suites/grape/config/newrelic.yml +1 -0
  96. data/test/multiverse/suites/grape/grape_test.rb +76 -12
  97. data/test/multiverse/suites/grape/grape_test_api.rb +16 -0
  98. data/test/multiverse/suites/high_security/config/newrelic.yml +43 -3
  99. data/test/multiverse/suites/high_security/high_security_test.rb +165 -9
  100. data/test/multiverse/suites/httpclient/Envfile +5 -1
  101. data/test/multiverse/suites/httpclient/httpclient_test.rb +2 -2
  102. data/test/multiverse/suites/memcached/Envfile +1 -1
  103. data/test/multiverse/suites/mongo/Envfile +8 -1
  104. data/test/multiverse/suites/mongo/helpers/mongo_operation_tests.rb +29 -29
  105. data/test/multiverse/suites/mongo/mongo_unsupported_version_test.rb +43 -8
  106. data/test/multiverse/suites/rack/rack_parameter_filtering_test.rb +13 -3
  107. data/test/multiverse/suites/rails/Envfile +3 -3
  108. data/test/multiverse/suites/rails/error_tracing_test.rb +52 -31
  109. data/test/multiverse/suites/rails/gc_instrumentation_test.rb +1 -1
  110. data/test/multiverse/suites/rails/ignore_test.rb +1 -1
  111. data/test/multiverse/suites/rails/parameter_capture_test.rb +108 -40
  112. data/test/multiverse/suites/rails/request_statistics_test.rb +10 -4
  113. data/test/multiverse/suites/rails/view_instrumentation_test.rb +24 -24
  114. data/test/multiverse/suites/resque/instrumentation_test.rb +46 -12
  115. data/test/multiverse/suites/sequel/sequel_extension_test.rb +8 -8
  116. data/test/multiverse/suites/sequel/sequel_helpers.rb +11 -11
  117. data/test/multiverse/suites/sequel/sequel_plugin_test.rb +11 -11
  118. data/test/multiverse/suites/sidekiq/Envfile +1 -4
  119. data/test/multiverse/suites/sidekiq/after_suite.rb +9 -0
  120. data/test/multiverse/suites/sidekiq/sidekiq_instrumentation_test.rb +49 -16
  121. data/test/multiverse/suites/sidekiq/test_worker.rb +1 -2
  122. data/test/multiverse/suites/sinatra/Envfile +1 -1
  123. data/test/multiverse/suites/sinatra/config/newrelic.yml +1 -0
  124. data/test/multiverse/suites/sinatra/sinatra_classic_test.rb +0 -4
  125. data/test/multiverse/suites/sinatra/sinatra_modular_test.rb +0 -4
  126. data/test/multiverse/suites/sinatra/sinatra_parameter_capture_test.rb +65 -0
  127. data/test/multiverse/suites/sinatra/sinatra_test_cases.rb +0 -11
  128. data/test/multiverse/suites/typhoeus/Envfile +8 -2
  129. data/test/multiverse/suites/typhoeus/typhoeus_test.rb +4 -4
  130. data/test/new_relic/agent/agent/connect_test.rb +13 -9
  131. data/test/new_relic/agent/agent_test.rb +34 -24
  132. data/test/new_relic/agent/attribute_filter_test.rb +218 -0
  133. data/test/new_relic/agent/attribute_processing_test.rb +160 -0
  134. data/test/new_relic/agent/configuration/default_source_test.rb +88 -0
  135. data/test/new_relic/agent/configuration/manager_test.rb +3 -4
  136. data/test/new_relic/agent/configuration/orphan_configuration_test.rb +3 -1
  137. data/test/new_relic/agent/configuration/server_source_test.rb +39 -0
  138. data/test/new_relic/agent/cross_app_monitor_test.rb +6 -30
  139. data/test/new_relic/agent/cross_app_tracing_test.rb +12 -12
  140. data/test/new_relic/agent/database/sql_obfuscation_test.rb +39 -65
  141. data/test/new_relic/agent/datastores/metric_helper_test.rb +36 -0
  142. data/test/new_relic/agent/encoding_normalizer_test.rb +66 -0
  143. data/test/new_relic/agent/error_collector_test.rb +181 -34
  144. data/test/new_relic/agent/hash_extensions_test.rb +34 -0
  145. data/test/new_relic/agent/instrumentation/action_controller_subscriber_test.rb +20 -23
  146. data/test/new_relic/agent/instrumentation/action_view_subscriber_test.rb +12 -12
  147. data/test/new_relic/agent/instrumentation/active_record_subscriber_test.rb +5 -5
  148. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +4 -4
  149. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +21 -11
  150. data/test/new_relic/agent/javascript_instrumentor_test.rb +69 -45
  151. data/test/new_relic/agent/pipe_service_test.rb +2 -2
  152. data/test/new_relic/agent/stats_engine/gc_profiler_test.rb +1 -1
  153. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +8 -7
  154. data/test/new_relic/agent/stats_engine/stats_hash_test.rb +2 -2
  155. data/test/new_relic/agent/threading/backtrace_node_test.rb +2 -2
  156. data/test/new_relic/agent/transaction/attributes_test.rb +276 -0
  157. data/test/new_relic/agent/transaction/developer_mode_sample_buffer_test.rb +10 -10
  158. data/test/new_relic/agent/transaction/trace_node_test.rb +361 -0
  159. data/test/new_relic/agent/transaction/trace_test.rb +394 -0
  160. data/test/new_relic/agent/transaction/xray_sample_buffer_test.rb +1 -1
  161. data/test/new_relic/agent/transaction_event_aggregator_test.rb +127 -57
  162. data/test/new_relic/agent/transaction_sample_builder_test.rb +70 -78
  163. data/test/new_relic/agent/transaction_sampler_test.rb +76 -185
  164. data/test/new_relic/agent/transaction_test.rb +283 -135
  165. data/test/new_relic/agent_test.rb +27 -12
  166. data/test/new_relic/cli/commands/install_test.rb +27 -0
  167. data/test/new_relic/coerce_test.rb +0 -59
  168. data/test/new_relic/data_container_tests.rb +5 -5
  169. data/test/new_relic/fake_collector.rb +27 -9
  170. data/test/new_relic/filtering_test_app.rb +2 -1
  171. data/test/new_relic/http_client_test_cases.rb +16 -16
  172. data/test/new_relic/json_wrapper_test.rb +0 -54
  173. data/test/new_relic/marshalling_test_cases.rb +1 -0
  174. data/test/new_relic/multiverse_helpers.rb +144 -0
  175. data/test/new_relic/noticed_error_test.rb +112 -9
  176. data/test/new_relic/rack/browser_monitoring_test.rb +12 -7
  177. data/test/new_relic/{transaction_analysis → rack/developer_mode}/segment_summary_test.rb +5 -4
  178. data/test/new_relic/rack/developer_mode_test.rb +17 -3
  179. data/test/new_relic/rack/error_collector_test.rb +1 -1
  180. data/test/performance/lib/performance/instrumentation/stackprof.rb +1 -1
  181. data/test/performance/script/runner +2 -2
  182. data/test/performance/suites/active_record.rb +3 -3
  183. data/test/performance/suites/agent_attributes.rb +62 -0
  184. data/test/performance/suites/rack_middleware.rb +78 -28
  185. data/test/performance/suites/transaction_tracing.rb +35 -0
  186. data/test/test_helper.rb +9 -1
  187. data/ui/helpers/developer_mode_helper.rb +16 -23
  188. data/ui/views/newrelic/_sample.rhtml +3 -3
  189. data/ui/views/newrelic/_segment.rhtml +1 -1
  190. data/ui/views/newrelic/_show_sample_summary.rhtml +1 -1
  191. data/ui/views/newrelic/show_sample.rhtml +5 -4
  192. metadata +23 -80
  193. data/lib/new_relic/agent/transaction/force_persist_sample_buffer.rb +0 -25
  194. data/lib/new_relic/transaction_analysis.rb +0 -80
  195. data/lib/new_relic/transaction_analysis/segment_summary.rb +0 -53
  196. data/lib/new_relic/transaction_sample.rb +0 -207
  197. data/lib/new_relic/transaction_sample/composite_segment.rb +0 -31
  198. data/lib/new_relic/transaction_sample/fake_segment.rb +0 -13
  199. data/lib/new_relic/transaction_sample/segment.rb +0 -197
  200. data/lib/new_relic/transaction_sample/summary_segment.rb +0 -25
  201. data/lib/new_relic/url_rule.rb +0 -18
  202. data/test/fixtures/cross_agent_tests/sql_obfuscation/back_quoted_identifiers.mysql.obfuscated +0 -1
  203. data/test/fixtures/cross_agent_tests/sql_obfuscation/back_quoted_identifiers.mysql.sql +0 -1
  204. data/test/fixtures/cross_agent_tests/sql_obfuscation/comment_delimiters_in_strings.obfuscated +0 -1
  205. data/test/fixtures/cross_agent_tests/sql_obfuscation/comment_delimiters_in_strings.sql +0 -1
  206. data/test/fixtures/cross_agent_tests/sql_obfuscation/double_quoted_identifiers.postgres.obfuscated +0 -1
  207. data/test/fixtures/cross_agent_tests/sql_obfuscation/double_quoted_identifiers.postgres.sql +0 -1
  208. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comment_in_string.obfuscated +0 -2
  209. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comment_in_string.sql +0 -2
  210. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_cstyle.obfuscated +0 -1
  211. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_cstyle.sql +0 -1
  212. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_doubledash.obfuscated +0 -2
  213. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_doubledash.sql +0 -2
  214. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_hash.obfuscated +0 -1
  215. data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_hash.sql +0 -1
  216. data/test/fixtures/cross_agent_tests/sql_obfuscation/escape_string_constants.postgres.obfuscated +0 -1
  217. data/test/fixtures/cross_agent_tests/sql_obfuscation/escape_string_constants.postgres.sql +0 -4
  218. data/test/fixtures/cross_agent_tests/sql_obfuscation/malformed/unterminated_double_quoted_string.mysql.sql +0 -1
  219. data/test/fixtures/cross_agent_tests/sql_obfuscation/malformed/unterminated_single_quoted_string.sql +0 -1
  220. data/test/fixtures/cross_agent_tests/sql_obfuscation/multiple_literal_types.mysql.obfuscated +0 -1
  221. data/test/fixtures/cross_agent_tests/sql_obfuscation/multiple_literal_types.mysql.sql +0 -1
  222. data/test/fixtures/cross_agent_tests/sql_obfuscation/numbers_in_identifiers.obfuscated +0 -1
  223. data/test/fixtures/cross_agent_tests/sql_obfuscation/numbers_in_identifiers.sql +0 -1
  224. data/test/fixtures/cross_agent_tests/sql_obfuscation/numeric_literals.obfuscated +0 -1
  225. data/test/fixtures/cross_agent_tests/sql_obfuscation/numeric_literals.sql +0 -1
  226. data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/README.md +0 -4
  227. data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/end_of_line_comments_with_quotes.obfuscated +0 -1
  228. data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/end_of_line_comments_with_quotes.sql +0 -2
  229. data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/mixed_comments_and_quotes.obfuscated +0 -1
  230. data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/mixed_comments_and_quotes.sql +0 -2
  231. data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/mixed_quotes_comments_and_newlines.obfuscated +0 -1
  232. data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/mixed_quotes_comments_and_newlines.sql +0 -4
  233. data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/mixed_quotes_end_of_line_comments.obfuscated +0 -1
  234. data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/mixed_quotes_end_of_line_comments.sql +0 -3
  235. data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/quote_delimiters_in_comments.obfuscated +0 -1
  236. data/test/fixtures/cross_agent_tests/sql_obfuscation/pathological/quote_delimiters_in_comments.sql +0 -1
  237. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_double_quoted.mysql.obfuscated +0 -1
  238. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_double_quoted.mysql.sql +0 -1
  239. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_single_quoted.obfuscated +0 -1
  240. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_single_quoted.sql +0 -1
  241. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_backslash_and_twin_single_quotes.obfuscated +0 -1
  242. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_backslash_and_twin_single_quotes.sql +0 -4
  243. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_double_quote.obfuscated +0 -1
  244. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_double_quote.sql +0 -1
  245. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_newline.obfuscated +0 -1
  246. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_newline.sql +0 -2
  247. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_single_quote.mysql.obfuscated +0 -1
  248. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_single_quote.mysql.sql +0 -1
  249. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_escaped_quotes.mysql.obfuscated +0 -1
  250. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_escaped_quotes.mysql.sql +0 -1
  251. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_backslash.obfuscated +0 -1
  252. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_backslash.sql +0 -4
  253. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash.mysql.obfuscated +0 -1
  254. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash.mysql.sql +0 -1
  255. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash_single_quoted.obfuscated +0 -1
  256. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash_single_quoted.sql +0 -1
  257. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_quote.obfuscated +0 -1
  258. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_quote.sql +0 -1
  259. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_twin_single_quotes.obfuscated +0 -1
  260. data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_twin_single_quotes.sql +0 -1
  261. data/test/new_relic/agent/error_collector/notice_error_test.rb +0 -261
  262. data/test/new_relic/agent/transaction/force_persist_sample_buffer_test.rb +0 -52
  263. data/test/new_relic/transaction_analysis_test.rb +0 -125
  264. data/test/new_relic/transaction_sample/composite_segment_test.rb +0 -38
  265. data/test/new_relic/transaction_sample/fake_segment_test.rb +0 -18
  266. data/test/new_relic/transaction_sample/segment_test.rb +0 -361
  267. data/test/new_relic/transaction_sample/summary_segment_test.rb +0 -34
  268. data/test/new_relic/transaction_sample_subtest_test.rb +0 -41
  269. data/test/new_relic/transaction_sample_test.rb +0 -361
@@ -32,6 +32,13 @@ module NewRelic
32
32
  memo
33
33
  end
34
34
  end
35
+
36
+ def filter_rails_request_parameters(params)
37
+ result = params.dup
38
+ result.delete("controller")
39
+ result.delete("action")
40
+ result
41
+ end
35
42
  end
36
43
  end
37
- end
44
+ end
@@ -80,12 +80,12 @@ module NewRelic
80
80
 
81
81
  QUEUE_QUERY_CONDITION = 'run_at <= ? and failed_at is NULL'.freeze
82
82
 
83
- def record_counts_by(column_name, metric_segment = column_name)
83
+ def record_counts_by(column_name, metric_node = column_name)
84
84
  all_count = 0
85
85
  queue_counts(column_name).each do |column_val, count|
86
86
  all_count += count
87
87
  column_val = "default" if column_val.nil? || column_val == ""
88
- metric = "Workers/DelayedJob/queue_length/#{metric_segment}/#{column_val}"
88
+ metric = "Workers/DelayedJob/queue_length/#{metric_node}/#{column_val}"
89
89
  NewRelic::Agent.record_metric(metric, count)
90
90
  end
91
91
  all_count
@@ -148,6 +148,7 @@ module NewRelic
148
148
  # not pass this parameter.
149
149
  #
150
150
  # @api public
151
+ # @deprecated Use {Datastores.notice_sql} instead.
151
152
  #
152
153
  def notice_sql(sql, metric_name, config, duration, state=nil, &explainer) #THREAD_LOCAL_ACCESS sometimes
153
154
  state ||= TransactionState.tl_get
@@ -95,10 +95,6 @@ module NewRelic
95
95
  @call_count += value
96
96
  end
97
97
 
98
- def inspect
99
- "#<NewRelic::Agent::Stats #{to_s} >"
100
- end
101
-
102
98
  # Concerned about implicit usage of inspect relying on stats format, so
103
99
  # putting back a version to get full inspection as separate method
104
100
  def inspect_full
@@ -6,8 +6,10 @@ require 'new_relic/language_support'
6
6
 
7
7
  module NewRelic
8
8
  module Agent
9
+ # @api public
9
10
  class StatsEngine
10
11
  # Handles methods related to actual Metric collection
12
+ # @api public
11
13
  module MetricStats
12
14
  SCOPE_PLACEHOLDER = '__SCOPE__'.freeze
13
15
 
@@ -108,13 +110,13 @@ module NewRelic
108
110
  end
109
111
 
110
112
  # This method is deprecated and not thread safe, and should not be used
111
- # by any new client code. Use NewRelic::Agent.record_metric instead.
113
+ # by any new client code.
112
114
  #
113
115
  # Lookup the Stats object for a given unscoped metric, returning a new
114
116
  # Stats object if one did not exist previously.
115
117
  #
116
118
  # @api public
117
- # @deprecated
119
+ # @deprecated Use {::NewRelic::Agent.record_metric} instead.
118
120
  #
119
121
  def get_stats_no_scope(metric_name)
120
122
  get_stats(metric_name, false)
@@ -128,7 +130,7 @@ module NewRelic
128
130
  # Leaving second, unused parameter for compatibility
129
131
  #
130
132
  # @api public
131
- # @deprecated
133
+ # @deprecated Use {::NewRelic::Agent.record_metric} instead.
132
134
  #
133
135
  def get_stats(metric_name, _ = true, scoped_metric_only = false, scope = nil)
134
136
  stats = nil
@@ -44,6 +44,10 @@ module NewRelic
44
44
  Hash[self] == Hash[other]
45
45
  end
46
46
 
47
+ def to_h
48
+ Hash[self]
49
+ end
50
+
47
51
  class StatsHashLookupError < NewRelic::Agent::InternalAgentError
48
52
  def initialize(original_error, hash, metric_spec)
49
53
  super("Lookup error in StatsHash: #{original_error.class}: #{original_error.message}. Falling back adding #{metric_spec.inspect}")
@@ -125,7 +125,7 @@ module NewRelic
125
125
  :activerecord =>
126
126
  {
127
127
  :type => :database,
128
- :supported => ["~>2.1.0", "~>2.2.0", "~>2.3.0", "~3.0.0", "~>3.1.0", "~>3.2.0", "~>4.0.0"],
128
+ :supported => ["~>2.1.0", "~>2.2.0", "~>2.3.0", "~>3.0.0", "~>3.1.0", "~>3.2.0", "~>4.0.0", "~>4.1.0", "~>4.2.0"],
129
129
  :deprecated => ["~>2.0.0"],
130
130
  :url => "https://rubygems.org/gems/activerecord",
131
131
  :feed => "https://rubygems.org/gems/activerecord/versions.atom",
@@ -148,7 +148,7 @@ module NewRelic
148
148
  :mongo =>
149
149
  {
150
150
  :type => :database,
151
- :supported => ["~>1.8.0", "~>1.9.0", "~>1.10.0"],
151
+ :supported => [">= 1.8.0", "< 2.0.0"],
152
152
  :url => "https://rubygems.org/gems/mongo",
153
153
  :feed => "https://rubygems.org/gems/mongo/versions.atom"
154
154
  },
@@ -24,9 +24,9 @@ module NewRelic
24
24
  end
25
25
 
26
26
  # Pushes a frame onto the transaction stack - this generates a
27
- # TransactionSample::Segment at the end of transaction execution.
27
+ # Agent::Transaction::TraceNode at the end of transaction execution.
28
28
  #
29
- # The generated segment won't be named until pop_frame is called.
29
+ # The generated node won't be named until pop_frame is called.
30
30
  #
31
31
  # +tag+ should be a Symbol, and is only for debugging purposes to
32
32
  # identify this frame if the stack gets corrupted.
@@ -43,7 +43,7 @@ module NewRelic
43
43
  # +expected_frame+ should be TracedMethodFrame from the corresponding
44
44
  # push_frame call.
45
45
  #
46
- # +name+ will be applied to the generated transaction trace segment.
46
+ # +name+ will be applied to the generated transaction trace node.
47
47
  def pop_frame(state, expected_frame, name, time, deduct_call_time_from_parent=true)
48
48
  frame = fetch_matching_frame(expected_frame)
49
49
 
@@ -6,6 +6,7 @@ require 'new_relic/agent/transaction_timings'
6
6
  require 'new_relic/agent/instrumentation/queue_time'
7
7
  require 'new_relic/agent/transaction_metrics'
8
8
  require 'new_relic/agent/method_tracer_helpers'
9
+ require 'new_relic/agent/transaction/attributes'
9
10
 
10
11
  module NewRelic
11
12
  module Agent
@@ -51,17 +52,15 @@ module NewRelic
51
52
  :process_cpu_start,
52
53
  :http_response_code
53
54
 
54
- # Give the current transaction a request context. Use this to
55
- # get the URI and referer. The request is interpreted loosely
56
- # as a Rack::Request or an ActionController::AbstractRequest.
57
- attr_accessor :request
58
-
59
55
  attr_reader :guid,
60
56
  :metrics,
61
57
  :gc_start_snapshot,
62
58
  :category,
63
59
  :frame_stack,
64
- :cat_path_hashes
60
+ :cat_path_hashes,
61
+ :attributes,
62
+ :request_path,
63
+ :referer
65
64
 
66
65
  # Populated with the trace sample once this transaction is completed.
67
66
  attr_reader :transaction_trace
@@ -74,10 +73,10 @@ module NewRelic
74
73
  TransactionState.tl_get.current_transaction
75
74
  end
76
75
 
77
- def self.set_default_transaction_name(name, category = nil, segment_name = nil) #THREAD_LOCAL_ACCESS
76
+ def self.set_default_transaction_name(name, category = nil, node_name = nil) #THREAD_LOCAL_ACCESS
78
77
  txn = tl_current
79
78
  name = txn.make_transaction_name(name, category)
80
- txn.name_last_frame(segment_name || name)
79
+ txn.name_last_frame(node_name || name)
81
80
  txn.set_default_transaction_name(name, category)
82
81
  end
83
82
 
@@ -186,18 +185,8 @@ module NewRelic
186
185
  txn.abort_transaction!(state) if txn
187
186
  end
188
187
 
189
- # If we have an active transaction, notice the error and increment the error metric.
190
- # Options:
191
- # * <tt>:request</tt> => Request object to get the uri and referer
192
- # * <tt>:uri</tt> => The request path, minus any request params or query string.
193
- # * <tt>:referer</tt> => The URI of the referer
194
- # * <tt>:metric</tt> => The metric name associated with the transaction
195
- # * <tt>:request_params</tt> => Request parameters, already filtered if necessary
196
- # * <tt>:custom_params</tt> => Custom parameters
197
- # Anything left over is treated as custom params
198
-
188
+ # See NewRelic::Agent.notice_error for options and commentary
199
189
  def self.notice_error(e, options={}) #THREAD_LOCAL_ACCESS
200
- options = extract_request_options(options)
201
190
  state = NewRelic::Agent::TransactionState.tl_get
202
191
  txn = state.current_transaction
203
192
  if txn
@@ -207,15 +196,6 @@ module NewRelic
207
196
  end
208
197
  end
209
198
 
210
- def self.extract_request_options(options)
211
- req = options.delete(:request)
212
- if req
213
- options[:uri] = uri_from_request(req)
214
- options[:referer] = referer_from_request(req)
215
- end
216
- options
217
- end
218
-
219
199
  # Returns truthy if the current in-progress transaction is considered a
220
200
  # a web transaction (as opposed to, e.g., a background transaction).
221
201
  #
@@ -226,27 +206,6 @@ module NewRelic
226
206
  txn && txn.recording_web_transaction?
227
207
  end
228
208
 
229
- # Make a safe attempt to get the referer from a request object, generally successful when
230
- # it's a Rack request.
231
- def self.referer_from_request(req)
232
- if req && req.respond_to?(:referer)
233
- req.referer.to_s.split('?').first
234
- end
235
- end
236
-
237
- # Make a safe attempt to get the URI, without the host and query string.
238
- def self.uri_from_request(req)
239
- approximate_uri = case
240
- when req.respond_to?(:fullpath ) then req.fullpath
241
- when req.respond_to?(:path ) then req.path
242
- when req.respond_to?(:request_uri) then req.request_uri
243
- when req.respond_to?(:uri ) then req.uri
244
- when req.respond_to?(:url ) then req.url
245
- end
246
- return approximate_uri[%r{^(https?://.*?)?(/[^?]*)}, 2] || '/' if approximate_uri
247
- end
248
-
249
-
250
209
  def self.apdex_bucket(duration, failed, apdex_t)
251
210
  case
252
211
  when failed
@@ -260,6 +219,30 @@ module NewRelic
260
219
  end
261
220
  end
262
221
 
222
+ def self.add_agent_attribute(key, value, default_destinations)
223
+ if txn = tl_current
224
+ txn.add_agent_attribute(key, value, default_destinations)
225
+ else
226
+ NewRelic::Agent.logger.debug "Attempted to add agent attribute: #{key} without transaction"
227
+ end
228
+ end
229
+
230
+ def add_agent_attribute(key, value, default_destinations)
231
+ @attributes.add_agent_attribute(key, value, default_destinations)
232
+ end
233
+
234
+ def self.merge_untrusted_agent_attributes(attributes, prefix, default_destinations)
235
+ if txn = tl_current
236
+ txn.merge_untrusted_agent_attributes(attributes, prefix, default_destinations)
237
+ else
238
+ NewRelic::Agent.logger.debug "Attempted to merge untrusted attributes without transaction"
239
+ end
240
+ end
241
+
242
+ def merge_untrusted_agent_attributes(attributes, prefix, default_destinations)
243
+ @attributes.merge_untrusted_agent_attributes(attributes, prefix, default_destinations)
244
+ end
245
+
263
246
  @@java_classes_loaded = false
264
247
 
265
248
  if defined? JRuby
@@ -287,7 +270,7 @@ module NewRelic
287
270
  @process_cpu_start = process_cpu
288
271
  @gc_start_snapshot = NewRelic::Agent::StatsEngine::GCProfiler.take_snapshot
289
272
  @filtered_params = options[:filtered_params] || {}
290
- @request = options[:request]
273
+
291
274
  @exceptions = {}
292
275
  @metrics = TransactionMetrics.new
293
276
  @guid = generate_guid
@@ -296,6 +279,15 @@ module NewRelic
296
279
  @ignore_this_transaction = false
297
280
  @ignore_apdex = false
298
281
  @ignore_enduser = false
282
+
283
+ @attributes = Attributes.new(NewRelic::Agent.instance.attribute_filter)
284
+
285
+ merge_request_parameters(@filtered_params)
286
+
287
+ if request = options[:request]
288
+ @request_path = path_from_request(request)
289
+ @referer = referer_from_request(request)
290
+ end
299
291
  end
300
292
 
301
293
  # This transaction-local hash may be used as temprory storage by
@@ -332,6 +324,7 @@ module NewRelic
332
324
  @has_children = true
333
325
  if options[:filtered_params] && !options[:filtered_params].empty?
334
326
  @filtered_params = options[:filtered_params]
327
+ merge_request_parameters(options[:filtered_params])
335
328
  end
336
329
 
337
330
  frame_stack.push NewRelic::Agent::MethodTracerHelpers.trace_execution_scoped_header(state, Time.now.to_f)
@@ -340,6 +333,10 @@ module NewRelic
340
333
  set_default_transaction_name(options[:transaction_name], category)
341
334
  end
342
335
 
336
+ def merge_request_parameters(params)
337
+ merge_untrusted_agent_attributes(params, :'request.parameters', AttributeFilter::DST_NONE)
338
+ end
339
+
343
340
  def make_transaction_name(name, category=nil)
344
341
  namer = Instrumentation::ControllerInstrumentation::TransactionNamer
345
342
  "#{namer.prefix_for_category(self, category)}#{name}"
@@ -417,8 +414,8 @@ module NewRelic
417
414
  def start(state)
418
415
  return if !state.is_execution_traced?
419
416
 
420
- transaction_sampler.on_start_transaction(state, start_time, uri)
421
- sql_sampler.on_start_transaction(state, start_time, uri)
417
+ transaction_sampler.on_start_transaction(state, start_time)
418
+ sql_sampler.on_start_transaction(state, start_time, request_path)
422
419
  NewRelic::Agent.instance.events.notify(:start_transaction)
423
420
  NewRelic::Agent::BusyCalculator.dispatcher_start(start_time)
424
421
 
@@ -426,19 +423,10 @@ module NewRelic
426
423
  name_last_frame @default_name
427
424
  end
428
425
 
429
- # For the current web transaction, return the path of the URI minus the host part and query string, or nil.
430
- def uri
431
- @uri ||= self.class.uri_from_request(@request) unless @request.nil?
432
- end
433
-
434
- # For the current web transaction, return the full referer, minus the host string, or nil.
435
- def referer
436
- @referer ||= self.class.referer_from_request(@request)
437
- end
438
-
439
- # Call this to ensure that the current transaction is not saved
426
+ # Call this to ensure that the current transaction trace is not saved
427
+ # To fully ignore all metrics and errors, use ignore! instead.
440
428
  def abort_transaction!(state)
441
- transaction_sampler.ignore_transaction(state)
429
+ @ignore_trace = true
442
430
  end
443
431
 
444
432
  WEB_SUMMARY_METRIC = 'HttpDispatcher'.freeze
@@ -502,29 +490,22 @@ module NewRelic
502
490
  end
503
491
 
504
492
  def user_defined_rules_ignore?
505
- return unless uri
493
+ return unless request_path
506
494
  return if (rules = NewRelic::Agent.config[:"rules.ignore_url_regexes"]).empty?
507
495
 
508
- parsed = NewRelic::Agent::HTTPClients::URIUtil.parse_url(uri)
509
- filtered_uri = NewRelic::Agent::HTTPClients::URIUtil.filter_uri(parsed)
510
-
511
496
  rules.any? do |rule|
512
- filtered_uri.match(rule)
497
+ request_path.match(rule)
513
498
  end
514
- rescue URI::InvalidURIError => e
515
- NewRelic::Agent.logger.debug("Error parsing URI: #{uri}", e)
516
- false
517
499
  end
518
500
 
519
- def commit!(state, end_time, outermost_segment_name)
520
- record_transaction_cpu(state)
521
- gc_stop_snapshot = NewRelic::Agent::StatsEngine::GCProfiler.take_snapshot
522
- gc_delta = NewRelic::Agent::StatsEngine::GCProfiler.record_delta(
523
- gc_start_snapshot, gc_stop_snapshot)
524
- @transaction_trace = transaction_sampler.on_finishing_transaction(state, self, end_time, gc_delta)
501
+ def commit!(state, end_time, outermost_node_name)
502
+ assign_agent_attributes
503
+ assign_intrinsics(state)
504
+
505
+ @transaction_trace = transaction_sampler.on_finishing_transaction(state, self, end_time)
525
506
  sql_sampler.on_finishing_transaction(state, @frozen_name)
526
507
 
527
- record_summary_metrics(outermost_segment_name, end_time)
508
+ record_summary_metrics(outermost_node_name, end_time)
528
509
  record_apdex(state, end_time) unless ignore_apdex?
529
510
  record_queue_time
530
511
 
@@ -534,11 +515,51 @@ module NewRelic
534
515
  send_transaction_finished_event(state, start_time, end_time)
535
516
  end
536
517
 
518
+ def assign_agent_attributes
519
+ if referer
520
+ add_agent_attribute(:'request.headers.referer', referer,
521
+ NewRelic::Agent::AttributeFilter::DST_ERROR_COLLECTOR)
522
+ end
523
+
524
+ if http_response_code
525
+ add_agent_attribute(:httpResponseCode, http_response_code,
526
+ NewRelic::Agent::AttributeFilter::DST_TRANSACTION_TRACER|
527
+ NewRelic::Agent::AttributeFilter::DST_TRANSACTION_EVENTS|
528
+ NewRelic::Agent::AttributeFilter::DST_ERROR_COLLECTOR)
529
+ end
530
+ end
531
+
532
+ def assign_intrinsics(state)
533
+ if gc_time = calculate_gc_time
534
+ attributes.add_intrinsic_attribute(:gc_time, gc_time)
535
+ end
536
+
537
+ if burn = cpu_burn
538
+ attributes.add_intrinsic_attribute(:cpu_time, burn)
539
+ end
540
+
541
+ if is_synthetics_request?
542
+ attributes.add_intrinsic_attribute(:synthetics_resource_id, synthetics_resource_id)
543
+ attributes.add_intrinsic_attribute(:synthetics_job_id, synthetics_job_id)
544
+ attributes.add_intrinsic_attribute(:synthetics_monitor_id, synthetics_monitor_id)
545
+ end
546
+
547
+ if state.is_cross_app?
548
+ attributes.add_intrinsic_attribute(:trip_id, cat_trip_id(state))
549
+ attributes.add_intrinsic_attribute(:path_hash, cat_path_hash(state))
550
+ end
551
+ end
552
+
553
+ def calculate_gc_time
554
+ gc_stop_snapshot = NewRelic::Agent::StatsEngine::GCProfiler.take_snapshot
555
+ NewRelic::Agent::StatsEngine::GCProfiler.record_delta(gc_start_snapshot, gc_stop_snapshot)
556
+ end
557
+
537
558
  # The summary metrics recorded by this method all end up with a duration
538
559
  # equal to the transaction itself, and an exclusive time of zero.
539
- def record_summary_metrics(outermost_segment_name, end_time)
560
+ def record_summary_metrics(outermost_node_name, end_time)
540
561
  metrics = summary_metrics
541
- metrics << @frozen_name unless @frozen_name == outermost_segment_name
562
+ metrics << @frozen_name unless @frozen_name == outermost_node_name
542
563
  @metrics.record_unscoped(metrics, end_time.to_f - start_time.to_f, 0)
543
564
  end
544
565
 
@@ -547,12 +568,12 @@ module NewRelic
547
568
  def send_transaction_finished_event(state, start_time, end_time)
548
569
  duration = end_time.to_f - start_time.to_f
549
570
  payload = {
550
- :name => @frozen_name,
551
- :bucket => recording_web_transaction? ? :request : :background,
552
- :start_timestamp => start_time.to_f,
553
- :duration => duration,
554
- :metrics => @metrics,
555
- :custom_params => custom_parameters
571
+ :name => @frozen_name,
572
+ :bucket => recording_web_transaction? ? :request : :background,
573
+ :start_timestamp => start_time.to_f,
574
+ :duration => duration,
575
+ :metrics => @metrics,
576
+ :attributes => @attributes,
556
577
  }
557
578
  append_cat_info(state, duration, payload)
558
579
  append_apdex_perf_zone(duration, payload)
@@ -688,22 +709,16 @@ module NewRelic
688
709
 
689
710
  def record_exceptions
690
711
  @exceptions.each do |exception, options|
691
- options[:metric] = best_name
712
+ options[:uri] ||= request_path if request_path
713
+ options[:metric] = best_name
714
+ options[:attributes] = @attributes
715
+
692
716
  agent.error_collector.notice_error(exception, options)
693
717
  end
694
718
  end
695
719
 
696
720
  # Do not call this. Invoke the class method instead.
697
721
  def notice_error(error, options={}) # :nodoc:
698
- options[:uri] ||= uri if uri
699
- options[:referer] ||= referer if referer
700
-
701
- if filtered_params && !filtered_params.empty?
702
- options[:request_params] = filtered_params
703
- end
704
-
705
- options.merge!(custom_parameters)
706
-
707
722
  if @exceptions[error]
708
723
  @exceptions[error].merge! options
709
724
  else
@@ -772,7 +787,7 @@ module NewRelic
772
787
 
773
788
  @metrics.record_unscoped(rollup_metric, apdex_bucket_global, current_apdex_t)
774
789
  @metrics.record_unscoped(APDEX_ALL_METRIC, apdex_bucket_global, current_apdex_t)
775
- txn_apdex_metric = @frozen_name.gsub(/^[^\/]+\//, transaction_prefix)
790
+ txn_apdex_metric = @frozen_name.sub(/^[^\/]+\//, transaction_prefix)
776
791
  @metrics.record_unscoped(txn_apdex_metric, apdex_bucket_txn, current_apdex_t)
777
792
  end
778
793
 
@@ -801,21 +816,12 @@ module NewRelic
801
816
  self.instrumentation_state[:datastore_override] = previous
802
817
  end
803
818
 
804
- def custom_parameters
805
- @custom_parameters ||= {}
806
- end
807
-
808
- def add_custom_parameters(p)
809
- if NewRelic::Agent.config[:high_security]
810
- NewRelic::Agent.logger.debug("Unable to add custom attributes #{p.keys.inspect} while in high security mode.")
811
- return
812
- end
813
-
814
- custom_parameters.merge!(p)
819
+ def add_custom_attributes(p)
820
+ attributes.merge_custom_attributes(p)
815
821
  end
816
822
 
817
- alias_method :user_attributes, :custom_parameters
818
- alias_method :set_user_attributes, :add_custom_parameters
823
+ alias_method :set_user_attributes, :add_custom_attributes
824
+ alias_method :add_custom_parameters, :add_custom_attributes
819
825
 
820
826
  def recording_web_transaction?
821
827
  web_category?(@category)
@@ -843,13 +849,6 @@ module NewRelic
843
849
  jruby_cpu_time - @jruby_cpu_start
844
850
  end
845
851
 
846
- def record_transaction_cpu(state)
847
- burn = cpu_burn
848
- if burn
849
- transaction_sampler.notice_transaction_cpu_time(state, burn)
850
- end
851
- end
852
-
853
852
  def ignore!
854
853
  @ignore_this_transaction = true
855
854
  end
@@ -874,6 +873,10 @@ module NewRelic
874
873
  @ignore_enduser
875
874
  end
876
875
 
876
+ def ignore_trace?
877
+ @ignore_trace
878
+ end
879
+
877
880
  private
878
881
 
879
882
  def process_cpu
@@ -921,6 +924,26 @@ module NewRelic
921
924
  guid
922
925
  end
923
926
 
927
+ # Make a safe attempt to get the referer from a request object, generally successful when
928
+ # it's a Rack request.
929
+ def referer_from_request(req)
930
+ if req && req.respond_to?(:referer) && req.referer
931
+ HTTPClients::URIUtil.strip_query_string(req.referer.to_s)
932
+ end
933
+ end
934
+
935
+ # In practice we expect req to be a Rack::Request or ActionController::AbstractRequest
936
+ # (for older Rails versions). But anything that responds to path can be passed to
937
+ # perform_action_with_newrelic_trace.
938
+ #
939
+ # We don't expect the path to include a query string, however older test helpers for
940
+ # rails construct the PATH_INFO enviroment variable improperly and we're generally
941
+ # being defensive.
942
+ def path_from_request(req)
943
+ path = req.path
944
+ path = HTTPClients::URIUtil.strip_query_string(path)
945
+ path.empty? ? "/" : path
946
+ end
924
947
  end
925
948
  end
926
949
  end