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,34 @@
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 'base64'
6
+ require 'zlib'
7
+
8
+ module NewRelic
9
+ module Agent
10
+ class NewRelicService
11
+ module Encoders
12
+ module Identity
13
+ def self.encode(data)
14
+ data
15
+ end
16
+ end
17
+
18
+ module Compressed
19
+ def self.encode(data)
20
+ Zlib::Deflate.deflate(data, Zlib::DEFAULT_COMPRESSION)
21
+ end
22
+ end
23
+
24
+ module Base64CompressedJSON
25
+ def self.encode(data)
26
+ json = ::NewRelic::JSONWrapper.dump(data,
27
+ :normalize => Agent.config[:normalize_json_string_encodings])
28
+ Base64.encode64(Compressed.encode(json))
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,50 @@
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 'new_relic/agent/new_relic_service/marshaller'
6
+
7
+ module NewRelic
8
+ module Agent
9
+ class NewRelicService
10
+ # Marshal collector protocol with JSON when available
11
+ class JsonMarshaller < Marshaller
12
+ def initialize
13
+ ::NewRelic::Agent.logger.debug "Using JSON marshaller (#{NewRelic::JSONWrapper.backend_name})"
14
+ unless self.class.is_supported?
15
+ ::NewRelic::Agent.logger.warn "The JSON marshaller in use (#{NewRelic::JSONWrapper.backend_name}) is not recommended. Ensure the 'json' gem is available in your application for better performance."
16
+ end
17
+ end
18
+
19
+ def dump(ruby, opts={})
20
+ prepared = prepare(ruby, opts)
21
+ NewRelic::JSONWrapper.dump(prepared,
22
+ :normalize => Agent.config[:normalize_json_string_encodings])
23
+ end
24
+
25
+ def load(data)
26
+ return_value(NewRelic::JSONWrapper.load(data)) if data && data != ''
27
+ rescue => e
28
+ ::NewRelic::Agent.logger.debug "#{e.class.name} : #{e.message} encountered loading collector response: #{data}"
29
+ raise
30
+ end
31
+
32
+ def default_encoder
33
+ Encoders::Base64CompressedJSON
34
+ end
35
+
36
+ def format
37
+ 'json'
38
+ end
39
+
40
+ def self.is_supported?
41
+ NewRelic::JSONWrapper.usable_for_collector_serialization?
42
+ end
43
+
44
+ def self.human_readable?
45
+ true # for some definitions of 'human'
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,52 @@
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 NewRelic
6
+ module Agent
7
+ class NewRelicService
8
+ class Marshaller
9
+ def parsed_error(error)
10
+ error_class = error['error_type'].split('::') \
11
+ .inject(Module) {|mod,const| mod.const_get(const) }
12
+ error_class.new(error['message'])
13
+ rescue NameError
14
+ CollectorError.new("#{error['error_type']}: #{error['message']}")
15
+ end
16
+
17
+ def prepare(data, options={})
18
+ encoder = options[:encoder] || default_encoder
19
+ if data.respond_to?(:to_collector_array)
20
+ data.to_collector_array(encoder)
21
+ elsif data.kind_of?(Array)
22
+ data.map { |element| prepare(element, options) }
23
+ else
24
+ data
25
+ end
26
+ end
27
+
28
+ def default_encoder
29
+ Encoders::Identity
30
+ end
31
+
32
+ def self.human_readable?
33
+ false
34
+ end
35
+
36
+ protected
37
+
38
+ def return_value(data)
39
+ if data.respond_to?(:has_key?)
40
+ if data.has_key?('exception')
41
+ raise parsed_error(data['exception'])
42
+ elsif data.has_key?('return_value')
43
+ return data['return_value']
44
+ end
45
+ end
46
+ ::NewRelic::Agent.logger.debug("Unexpected response from collector: #{data}")
47
+ nil
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,52 @@
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 'new_relic/agent/new_relic_service/marshaller'
6
+
7
+ module NewRelic
8
+ module Agent
9
+ class NewRelicService
10
+ # Primitive Ruby Object Notation which complies JSON format data strutures
11
+ class PrubyMarshaller < Marshaller
12
+ def initialize
13
+ ::NewRelic::Agent.logger.debug 'Using Pruby marshaller'
14
+ warn_for_pruby_deprecation
15
+ end
16
+
17
+ def warn_for_pruby_deprecation
18
+ if RUBY_VERSION < "1.9" && !defined?(::JSON)
19
+ NewRelic::Agent.logger.warn("Upcoming versions of the Ruby agent running on Ruby 1.8.7 will require the 'json' gem. To avoid interuption in reporting, please update your Gemfile. See http://docs.newrelic.com/docs/ruby/ruby-1.8.7-support for more information.")
20
+ end
21
+ end
22
+
23
+ def dump(ruby, opts={})
24
+ NewRelic::LanguageSupport.with_cautious_gc do
25
+ Marshal.dump(prepare(ruby, opts))
26
+ end
27
+ rescue => e
28
+ ::NewRelic::Agent.logger.debug("#{e.class.name} : #{e.message} when marshalling #{ruby.inspect}")
29
+ raise
30
+ end
31
+
32
+ def load(data)
33
+ return unless data && data != ''
34
+ NewRelic::LanguageSupport.with_cautious_gc do
35
+ return_value(Marshal.load(data))
36
+ end
37
+ rescue
38
+ ::NewRelic::Agent.logger.debug "Error encountered loading collector response: #{data}"
39
+ raise
40
+ end
41
+
42
+ def format
43
+ 'pruby'
44
+ end
45
+
46
+ def self.is_supported?
47
+ true
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -105,7 +105,7 @@ module NewRelic
105
105
  end
106
106
 
107
107
  def dump_string(indent=0)
108
- file, method, line = parse_backtrace_frame(@raw_line)
108
+ @file, @method, @line_no = parse_backtrace_frame(@raw_line)
109
109
  result = "#{" " * indent}#<BacktraceNode:#{object_id} [#{@runnable_count}] #{@file}:#{@line_no} in #{@method}>"
110
110
  child_results = @children.map { |c| c.dump_string(indent+2) }.join("\n")
111
111
  result << "\n" unless child_results.empty?
@@ -45,8 +45,7 @@ module NewRelic
45
45
  #
46
46
  # +name+ will be applied to the generated transaction trace segment.
47
47
  def pop_frame(state, expected_frame, name, time, deduct_call_time_from_parent=true)
48
- frame = @stack.pop
49
- fail "unbalanced pop from blame stack, got #{frame ? frame.tag : 'nil'}, expected #{expected_frame ? expected_frame.tag : 'nil'}" if frame != expected_frame
48
+ frame = fetch_matching_frame(expected_frame)
50
49
 
51
50
  note_children_time(frame, time, deduct_call_time_from_parent)
52
51
 
@@ -55,6 +54,21 @@ module NewRelic
55
54
  frame
56
55
  end
57
56
 
57
+ def fetch_matching_frame(expected_frame)
58
+ while frame = @stack.pop
59
+ if frame == expected_frame
60
+ return frame
61
+ else
62
+ NewRelic::Agent.logger.info("Unexpected frame in traced method stack: #{frame.inspect} expected to be #{expected_frame.inspect}")
63
+ NewRelic::Agent.logger.debug do
64
+ ["Backtrace for unexpected frame: ", caller.join("\n")]
65
+ end
66
+ end
67
+ end
68
+
69
+ raise "Frame not found in blame stack: #{expected_frame.inspect}"
70
+ end
71
+
58
72
  def note_children_time(frame, time, deduct_call_time_from_parent)
59
73
  if !@stack.empty?
60
74
  if deduct_call_time_from_parent
@@ -317,10 +317,6 @@ module NewRelic
317
317
  @frozen_name ? true : false
318
318
  end
319
319
 
320
- def ignored?
321
- @ignore_this_transaction
322
- end
323
-
324
320
  # Indicate that we are entering a measured controller action or task.
325
321
  # Make sure you unwind every push with a pop call.
326
322
  def start(state)
@@ -40,7 +40,7 @@ module NewRelic
40
40
  if backtrace && !Agent.config[:disable_backtrace_cleanup]
41
41
  # this is for 1.9.1, where strings no longer have Enumerable
42
42
  backtrace = backtrace.split("\n") if String === backtrace
43
- backtrace = backtrace.map &:to_s
43
+ backtrace = backtrace.map(&:to_s)
44
44
  backtrace = backtrace.reject do |line|
45
45
  line.include?(NewRelic::Control.newrelic_root) or
46
46
  line =~ /^newrelic_rpm\s/
@@ -55,7 +55,7 @@ module NewRelic
55
55
 
56
56
  # Convert any kind of object to a short string.
57
57
  def flatten(object)
58
- s = case object
58
+ case object
59
59
  when nil then ''
60
60
  when object.instance_of?(String) then object
61
61
  when String then String.new(object) # convert string subclasses to strings
@@ -98,6 +98,9 @@ module NewRelic
98
98
  require 'new_relic/rack/developer_mode'
99
99
  rails_config.middleware.use NewRelic::Rack::DeveloperMode
100
100
  ::NewRelic::Agent.logger.info("New Relic Agent Developer Mode enabled.")
101
+ if env == "production"
102
+ ::NewRelic::Agent.logger.warn("***New Relic Developer Mode is not intended to be enabled in production environments! We highly recommend setting developer_mode: false for the production environment in your newrelic.yml.")
103
+ end
101
104
  rescue => e
102
105
  ::NewRelic::Agent.logger.warn("Error installing New Relic Developer Mode", e)
103
106
  end
@@ -27,8 +27,12 @@ module NewRelic
27
27
  # if the agent is not running.
28
28
  def install_shim
29
29
  # Once we install instrumentation, you can't undo that by installing the shim.
30
- raise "Cannot install the Agent shim after instrumentation has already been installed!" if @instrumented
31
- NewRelic::Agent.agent = NewRelic::Agent::ShimAgent.instance
30
+ if @instrumented
31
+ NewRelic::Agent.logger.error "Cannot install the Agent shim after instrumentation has already been installed!"
32
+ NewRelic::Agent.logger.error caller.join("\n")
33
+ else
34
+ NewRelic::Agent.agent = NewRelic::Agent::ShimAgent.instance
35
+ end
32
36
  end
33
37
 
34
38
  # Add instrumentation. Don't call this directly. Use NewRelic::Agent#add_instrumentation.
@@ -4,16 +4,14 @@
4
4
 
5
5
  module NewRelic
6
6
  class JSONWrapper
7
- def self.load_stdlib_json
8
- return false unless NewRelic::LanguageSupport.stdlib_json_usable?
9
-
7
+ def self.load_native_json
10
8
  begin
11
- require 'json'
9
+ require 'json' unless defined?(::JSON)
12
10
  @load_method = ::JSON.method(:load)
13
11
  @dump_method = ::JSON.method(:dump)
14
12
  @backend_name = :json
15
13
  return true
16
- rescue
14
+ rescue StandardError, ScriptError
17
15
  NewRelic::Agent.logger.debug "%p while loading JSON library: %s" % [ err, err.message ] if
18
16
  defined?( NewRelic::Agent ) && NewRelic::Agent.respond_to?( :logger )
19
17
  end
@@ -26,38 +24,62 @@ module NewRelic
26
24
  @backend_name = :okjson
27
25
  end
28
26
 
29
- load_stdlib_json or load_okjson
27
+ load_native_json or load_okjson
30
28
 
31
29
  def self.usable_for_collector_serialization?
32
30
  @backend_name == :json
33
31
  end
34
32
 
33
+ def self.backend_name
34
+ @backend_name
35
+ end
36
+
35
37
  def self.normalize_string(s)
36
- # Early return if called on 1.8.x. In normal circumstances 1.8.x
37
- # shouldn't call this--it does nothing for Ruby-marshalled formats-- but
38
- # we use it in multiverse to make comparing data more consistent.
39
- return s unless supports_normalization?
38
+ choose_normalizer unless @normalizer
39
+ @normalizer.normalize(s)
40
+ end
40
41
 
41
- encoding = s.encoding
42
- if (encoding == Encoding::UTF_8 || encoding == Encoding::ISO_8859_1) && s.valid_encoding?
43
- return s
42
+ def self.choose_normalizer
43
+ if NewRelic::LanguageSupport.supports_string_encodings?
44
+ @normalizer = EncodingNormalizer
45
+ else
46
+ @normalizer = IconvNormalizer
44
47
  end
48
+ end
45
49
 
46
- # If the encoding is not valid, or it's ASCII-8BIT, we know conversion to
47
- # UTF-8 is likely to fail, so treat it as ISO-8859-1 (byte-preserving).
48
- normalized = s.dup
49
- if encoding == Encoding::ASCII_8BIT || !s.valid_encoding?
50
- normalized.force_encoding(Encoding::ISO_8859_1)
51
- else
52
- # Encoding is valid and non-binary, so it might be cleanly convertible
53
- # to UTF-8. Give it a try and fall back to ISO-8859-1 if it fails.
54
- begin
55
- normalized.encode!(Encoding::UTF_8)
56
- rescue
50
+ class EncodingNormalizer
51
+ def self.normalize(s)
52
+ encoding = s.encoding
53
+ if (encoding == Encoding::UTF_8 || encoding == Encoding::ISO_8859_1) && s.valid_encoding?
54
+ return s
55
+ end
56
+
57
+ # If the encoding is not valid, or it's ASCII-8BIT, we know conversion to
58
+ # UTF-8 is likely to fail, so treat it as ISO-8859-1 (byte-preserving).
59
+ normalized = s.dup
60
+ if encoding == Encoding::ASCII_8BIT || !s.valid_encoding?
57
61
  normalized.force_encoding(Encoding::ISO_8859_1)
62
+ else
63
+ # Encoding is valid and non-binary, so it might be cleanly convertible
64
+ # to UTF-8. Give it a try and fall back to ISO-8859-1 if it fails.
65
+ begin
66
+ normalized.encode!(Encoding::UTF_8)
67
+ rescue
68
+ normalized.force_encoding(Encoding::ISO_8859_1)
69
+ end
70
+ end
71
+ normalized
72
+ end
73
+ end
74
+
75
+ class IconvNormalizer
76
+ def self.normalize(s)
77
+ if @iconv.nil?
78
+ require 'iconv'
79
+ @iconv = Iconv.new('utf-8', 'iso-8859-1')
58
80
  end
81
+ @iconv.iconv(s)
59
82
  end
60
- normalized
61
83
  end
62
84
 
63
85
  def self.normalize(object)
@@ -107,10 +107,6 @@ module NewRelic::LanguageSupport
107
107
  numbers == ::RUBY_VERSION.split('.')[0, numbers.size]
108
108
  end
109
109
 
110
- def stdlib_json_usable?
111
- RUBY_VERSION >= '1.9.2'
112
- end
113
-
114
110
  def supports_string_encodings?
115
111
  RUBY_VERSION >= '1.9.0'
116
112
  end
@@ -30,8 +30,8 @@ EOS
30
30
 
31
31
  current_item = nil
32
32
  latest.each do |line|
33
- if line.match /^\s*\*.*/
34
- if line.match /\(#{patch_level}\)/
33
+ if line.match(/^\s*\*.*/)
34
+ if line.match(/\(#{patch_level}\)/)
35
35
  # Found a patch level item, so start tracking the lines!
36
36
  current_item = line
37
37
  else
@@ -105,7 +105,7 @@ module NewRelic
105
105
  @obfuscated_sql = @segment.obfuscated_sql
106
106
  end
107
107
 
108
- headers, explanations = @segment.explain_sql
108
+ _headers, explanations = @segment.explain_sql
109
109
  if explanations
110
110
  @explanation = explanations
111
111
  if !@explanation.blank?
@@ -138,12 +138,13 @@ module NewRelic
138
138
  if view.is_a? Hash
139
139
  layout = false
140
140
  if view[:object]
141
+ # object *is* used here, as it is capture in the binding below
141
142
  object = view[:object]
142
143
  end
143
144
 
144
145
  if view[:collection]
145
- return view[:collection].map do |object|
146
- render({:partial => view[:partial], :object => object})
146
+ return view[:collection].map do |obj|
147
+ render({:partial => view[:partial], :object => obj})
147
148
  end.join(' ')
148
149
  end
149
150