newrelic_rpm 3.5.4.35.beta → 3.5.5.38

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/CHANGELOG +42 -0
  2. data/GUIDELINES_FOR_CONTRIBUTING.md +3 -0
  3. data/Rakefile +8 -0
  4. data/bin/mongrel_rpm +1 -1
  5. data/init.rb +1 -8
  6. data/lib/new_relic/agent.rb +11 -13
  7. data/lib/new_relic/agent/agent.rb +89 -110
  8. data/lib/new_relic/agent/agent_logger.rb +165 -0
  9. data/lib/new_relic/agent/audit_logger.rb +72 -0
  10. data/lib/new_relic/agent/beacon_configuration.rb +4 -4
  11. data/lib/new_relic/agent/browser_monitoring.rb +13 -7
  12. data/lib/new_relic/agent/busy_calculator.rb +2 -2
  13. data/lib/new_relic/agent/configuration.rb +25 -0
  14. data/lib/new_relic/agent/configuration/defaults.rb +45 -8
  15. data/lib/new_relic/agent/configuration/environment_source.rb +8 -15
  16. data/lib/new_relic/agent/configuration/manager.rb +22 -2
  17. data/lib/new_relic/agent/configuration/mask_defaults.rb +10 -0
  18. data/lib/new_relic/agent/configuration/yaml_source.rb +4 -2
  19. data/lib/new_relic/agent/cross_process_monitoring.rb +43 -0
  20. data/lib/new_relic/agent/database.rb +2 -4
  21. data/lib/new_relic/agent/error_collector.rb +4 -9
  22. data/lib/new_relic/agent/instrumentation/active_merchant.rb +1 -1
  23. data/lib/new_relic/agent/instrumentation/active_record.rb +1 -1
  24. data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +1 -1
  25. data/lib/new_relic/agent/instrumentation/authlogic.rb +1 -1
  26. data/lib/new_relic/agent/instrumentation/browser_monitoring_timings.rb +41 -0
  27. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +7 -7
  28. data/lib/new_relic/agent/instrumentation/data_mapper.rb +1 -1
  29. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +1 -1
  30. data/lib/new_relic/agent/instrumentation/memcache.rb +4 -4
  31. data/lib/new_relic/agent/instrumentation/merb/controller.rb +1 -1
  32. data/lib/new_relic/agent/instrumentation/merb/errors.rb +1 -1
  33. data/lib/new_relic/agent/instrumentation/metric_frame/pop.rb +1 -1
  34. data/lib/new_relic/agent/instrumentation/net.rb +1 -1
  35. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +2 -2
  36. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +4 -4
  37. data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +1 -1
  38. data/lib/new_relic/agent/instrumentation/rails/errors.rb +1 -1
  39. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +3 -3
  40. data/lib/new_relic/agent/instrumentation/rails3/errors.rb +1 -1
  41. data/lib/new_relic/agent/instrumentation/resque.rb +3 -2
  42. data/lib/new_relic/agent/instrumentation/sinatra.rb +1 -1
  43. data/lib/new_relic/agent/instrumentation/sunspot.rb +1 -1
  44. data/lib/new_relic/agent/instrumentation/unicorn_instrumentation.rb +2 -2
  45. data/lib/new_relic/agent/method_tracer.rb +6 -8
  46. data/lib/new_relic/agent/new_relic_service.rb +94 -106
  47. data/lib/new_relic/agent/pipe_channel_manager.rb +1 -1
  48. data/lib/new_relic/agent/samplers/memory_sampler.rb +4 -6
  49. data/lib/new_relic/agent/sql_sampler.rb +3 -18
  50. data/lib/new_relic/agent/stats_engine.rb +0 -5
  51. data/lib/new_relic/agent/stats_engine/metric_stats.rb +3 -3
  52. data/lib/new_relic/agent/stats_engine/samplers.rb +2 -4
  53. data/lib/new_relic/agent/thread.rb +8 -3
  54. data/lib/new_relic/agent/thread_profiler.rb +38 -27
  55. data/lib/new_relic/agent/transaction_info.rb +1 -1
  56. data/lib/new_relic/agent/transaction_sample_builder.rb +2 -3
  57. data/lib/new_relic/agent/transaction_sampler.rb +3 -7
  58. data/lib/new_relic/agent/worker_loop.rb +3 -11
  59. data/lib/new_relic/control.rb +0 -2
  60. data/lib/new_relic/control/class_methods.rb +8 -2
  61. data/lib/new_relic/control/frameworks/merb.rb +0 -6
  62. data/lib/new_relic/control/frameworks/rails.rb +8 -29
  63. data/lib/new_relic/control/frameworks/rails3.rb +8 -20
  64. data/lib/new_relic/control/frameworks/rails4.rb +23 -0
  65. data/lib/new_relic/control/frameworks/ruby.rb +1 -22
  66. data/lib/new_relic/control/instance_methods.rb +12 -34
  67. data/lib/new_relic/control/instrumentation.rb +7 -12
  68. data/lib/new_relic/control/server_methods.rb +5 -8
  69. data/lib/new_relic/delayed_job_injection.rb +1 -1
  70. data/lib/new_relic/local_environment.rb +30 -64
  71. data/lib/new_relic/metric_data.rb +1 -1
  72. data/lib/new_relic/metric_spec.rb +1 -1
  73. data/lib/new_relic/noticed_error.rb +1 -1
  74. data/lib/new_relic/rack/browser_monitoring.rb +5 -5
  75. data/lib/new_relic/stats.rb +9 -7
  76. data/lib/new_relic/transaction_sample.rb +2 -7
  77. data/lib/new_relic/version.rb +1 -1
  78. data/lib/newrelic_rpm.rb +1 -1
  79. data/newrelic_rpm.gemspec.erb +15 -17
  80. data/test/config/newrelic.yml +1 -1
  81. data/test/config/test_control.rb +18 -18
  82. data/test/fixtures/gemspec_no_build.rb +0 -2
  83. data/test/fixtures/gemspec_with_build.rb +0 -2
  84. data/test/fixtures/gemspec_with_build_and_stage.rb +0 -2
  85. data/test/multiverse/README.md +3 -8
  86. data/test/multiverse/suites/agent_only/Envfile +1 -0
  87. data/test/multiverse/suites/agent_only/audit_log_test.rb +99 -0
  88. data/test/multiverse/suites/agent_only/marshaling_test.rb +1 -1
  89. data/test/multiverse/suites/config_file_loading/Envfile +7 -0
  90. data/test/multiverse/suites/config_file_loading/config_file_loading_test.rb +106 -0
  91. data/test/multiverse/suites/logging/Envfile +4 -0
  92. data/test/multiverse/suites/logging/config/newrelic.yml +22 -0
  93. data/test/multiverse/suites/logging/logging_test.rb +143 -0
  94. data/test/multiverse/suites/no_load/config/newrelic.yml +1 -2
  95. data/test/multiverse/suites/rum_auto_instrumentation/sanity_test.rb +0 -13
  96. data/test/new_relic/agent/agent/connect_test.rb +30 -92
  97. data/test/new_relic/agent/agent/start_test.rb +4 -84
  98. data/test/new_relic/agent/agent/start_worker_thread_test.rb +8 -43
  99. data/test/new_relic/agent/agent_logger_test.rb +153 -0
  100. data/test/new_relic/agent/agent_test.rb +10 -9
  101. data/test/new_relic/agent/audit_logger_test.rb +105 -0
  102. data/test/new_relic/agent/browser_monitoring_test.rb +2 -1
  103. data/test/new_relic/agent/busy_calculator_test.rb +7 -0
  104. data/test/new_relic/agent/configuration/environment_source_test.rb +25 -20
  105. data/test/new_relic/agent/configuration/manager_test.rb +59 -4
  106. data/test/new_relic/agent/configuration/yaml_source_test.rb +20 -1
  107. data/test/new_relic/agent/cross_process_monitoring_test.rb +77 -0
  108. data/test/new_relic/agent/database_test.rb +0 -11
  109. data/test/new_relic/agent/error_collector/notice_error_test.rb +1 -3
  110. data/test/new_relic/agent/error_collector_test.rb +11 -7
  111. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +39 -19
  112. data/test/new_relic/agent/instrumentation/browser_monitoring_timings_test.rb +39 -0
  113. data/test/new_relic/agent/instrumentation/metric_frame/pop_test.rb +1 -1
  114. data/test/new_relic/agent/method_tracer/class_methods/add_method_tracer_test.rb +0 -6
  115. data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +3 -15
  116. data/test/new_relic/agent/new_relic_service_test.rb +48 -8
  117. data/test/new_relic/agent/pipe_channel_manager_test.rb +1 -1
  118. data/test/new_relic/agent/sql_sampler_test.rb +1 -1
  119. data/test/new_relic/agent/thread_profiler_test.rb +46 -45
  120. data/test/new_relic/agent/thread_test.rb +13 -0
  121. data/test/new_relic/agent/transaction_sample_builder_test.rb +1 -1
  122. data/test/new_relic/agent/worker_loop_test.rb +4 -9
  123. data/test/new_relic/agent_test.rb +6 -9
  124. data/test/new_relic/control/class_methods_test.rb +0 -18
  125. data/test/new_relic/control_test.rb +6 -9
  126. data/test/new_relic/dispatcher_test.rb +54 -0
  127. data/test/new_relic/fake_collector.rb +15 -14
  128. data/test/new_relic/fake_service.rb +4 -1
  129. data/test/new_relic/fakes_sending_data.rb +30 -0
  130. data/test/new_relic/framework_test.rb +53 -0
  131. data/test/new_relic/local_environment_test.rb +5 -2
  132. data/test/new_relic/rack/browser_monitoring_test.rb +2 -1
  133. data/test/new_relic/rack/developer_mode_test.rb +1 -1
  134. data/test/new_relic/stats_test.rb +10 -0
  135. data/test/new_relic/transaction_sample_test.rb +2 -2
  136. data/test/script/ci.sh +1 -1
  137. data/test/test_helper.rb +23 -0
  138. data/ui/views/newrelic/file/images/arrow-close.png +0 -0
  139. data/ui/views/newrelic/file/images/arrow-open.png +0 -0
  140. data/ui/views/newrelic/file/images/blue_bar.gif +0 -0
  141. data/ui/views/newrelic/file/images/file_icon.png +0 -0
  142. data/ui/views/newrelic/file/images/gray_bar.gif +0 -0
  143. metadata +47 -41
  144. data/InstallationNotes.md +0 -15
  145. data/lib/new_relic/control/logging_methods.rb +0 -125
  146. data/test/multiverse/Rakefile +0 -17
  147. data/test/multiverse/suites/rum_auto_instrumentation/problem_response.html +0 -422
  148. data/test/new_relic/control/logging_methods_test.rb +0 -211
@@ -14,7 +14,7 @@ module NewRelic
14
14
  end
15
15
 
16
16
  def log_underflow
17
- NewRelic::Agent.logger.error "Underflow in metric frames: #{caller.join("\n ")}"
17
+ ::NewRelic::Agent.logger.error "Underflow in metric frames: #{caller.join("\n ")}"
18
18
  end
19
19
 
20
20
  def notice_scope_empty
@@ -6,7 +6,7 @@ DependencyDetection.defer do
6
6
  end
7
7
 
8
8
  executes do
9
- NewRelic::Agent.logger.debug 'Installing Net instrumentation'
9
+ ::NewRelic::Agent.logger.info 'Installing Net instrumentation'
10
10
  end
11
11
 
12
12
  executes do
@@ -6,10 +6,10 @@ DependencyDetection.defer do
6
6
  end
7
7
 
8
8
  executes do
9
- NewRelic::Agent.logger.debug "Installing Passenger event hooks."
9
+ ::NewRelic::Agent.logger.debug "Installing Passenger event hooks."
10
10
 
11
11
  ::PhusionPassenger.on_event(:stopping_worker_process) do
12
- NewRelic::Agent.logger.debug "Passenger stopping this process, shutdown the agent."
12
+ ::NewRelic::Agent.logger.debug "Passenger stopping this process, shutdown the agent."
13
13
  NewRelic::Agent.instance.shutdown
14
14
  end
15
15
 
@@ -8,7 +8,7 @@ DependencyDetection.defer do
8
8
  end
9
9
 
10
10
  executes do
11
- NewRelic::Agent.logger.debug 'Installing Rails 2.1 View instrumentation'
11
+ ::NewRelic::Agent.logger.info 'Installing Rails 2.1 View instrumentation'
12
12
  end
13
13
 
14
14
  executes do
@@ -32,7 +32,7 @@ DependencyDetection.defer do
32
32
  end
33
33
 
34
34
  executes do
35
- NewRelic::Agent.logger.debug 'Installing Rails 1.* - 2.0 View instrumentation'
35
+ ::NewRelic::Agent.logger.info 'Installing Rails 1.* - 2.0 View instrumentation'
36
36
  end
37
37
 
38
38
  executes do
@@ -53,7 +53,7 @@ DependencyDetection.defer do
53
53
  end
54
54
 
55
55
  executes do
56
- NewRelic::Agent.logger.debug 'Installing Rails 2.2 - 2.3 View instrumentation'
56
+ ::NewRelic::Agent.logger.info 'Installing Rails 2.2 - 2.3 View instrumentation'
57
57
  end
58
58
 
59
59
  executes do
@@ -78,7 +78,7 @@ DependencyDetection.defer do
78
78
  end
79
79
 
80
80
  executes do
81
- NewRelic::Agent.logger.debug 'Installing Rails 2 Controller instrumentation'
81
+ ::NewRelic::Agent.logger.info 'Installing Rails 2 Controller instrumentation'
82
82
  end
83
83
 
84
84
  executes do
@@ -6,7 +6,7 @@ DependencyDetection.defer do
6
6
  end
7
7
 
8
8
  executes do
9
- NewRelic::Agent.logger.debug 'Installing Rails ActionWebService instrumentation'
9
+ ::NewRelic::Agent.logger.info 'Installing Rails ActionWebService instrumentation'
10
10
  end
11
11
 
12
12
  executes do
@@ -10,7 +10,7 @@ DependencyDetection.defer do
10
10
  end
11
11
 
12
12
  executes do
13
- NewRelic::Agent.logger.debug 'Installing Rails 2 Error instrumentation'
13
+ ::NewRelic::Agent.logger.info 'Installing Rails 2 Error instrumentation'
14
14
  end
15
15
 
16
16
  executes do
@@ -78,7 +78,7 @@ DependencyDetection.defer do
78
78
  end
79
79
 
80
80
  executes do
81
- NewRelic::Agent.logger.debug 'Installing Rails 3 Controller instrumentation'
81
+ ::NewRelic::Agent.logger.info 'Installing Rails 3 Controller instrumentation'
82
82
  end
83
83
 
84
84
  executes do
@@ -100,7 +100,7 @@ DependencyDetection.defer do
100
100
  end
101
101
 
102
102
  executes do
103
- NewRelic::Agent.logger.debug 'Installing Rails 3.0 view instrumentation'
103
+ ::NewRelic::Agent.logger.info 'Installing Rails 3.0 view instrumentation'
104
104
  end
105
105
 
106
106
  executes do
@@ -139,7 +139,7 @@ DependencyDetection.defer do
139
139
  end
140
140
 
141
141
  executes do
142
- NewRelic::Agent.logger.debug 'Installing Rails 3.1/3.2 view instrumentation'
142
+ ::NewRelic::Agent.logger.info 'Installing Rails 3.1/3.2 view instrumentation'
143
143
  end
144
144
 
145
145
  executes do
@@ -30,7 +30,7 @@ DependencyDetection.defer do
30
30
  end
31
31
 
32
32
  executes do
33
- NewRelic::Agent.logger.debug 'Installing Rails3 Error instrumentation'
33
+ ::NewRelic::Agent.logger.info 'Installing Rails3 Error instrumentation'
34
34
  end
35
35
 
36
36
  executes do
@@ -7,7 +7,7 @@ DependencyDetection.defer do
7
7
  end
8
8
 
9
9
  executes do
10
- NewRelic::Agent.logger.debug 'Installing Resque instrumentation'
10
+ ::NewRelic::Agent.logger.info 'Installing Resque instrumentation'
11
11
  end
12
12
 
13
13
  executes do
@@ -62,7 +62,8 @@ DependencyDetection.defer do
62
62
  ::Resque.before_first_fork do
63
63
  NewRelic::Agent.manual_start(:dispatcher => :resque,
64
64
  :sync_startup => true,
65
- :start_channel_listener => true)
65
+ :start_channel_listener => true,
66
+ :report_instance_busy => false)
66
67
  end
67
68
 
68
69
  ::Resque.before_fork do |job|
@@ -9,7 +9,7 @@ DependencyDetection.defer do
9
9
  end
10
10
 
11
11
  executes do
12
- NewRelic::Agent.logger.debug 'Installing Sinatra instrumentation'
12
+ ::NewRelic::Agent.logger.info 'Installing Sinatra instrumentation'
13
13
  end
14
14
 
15
15
  executes do
@@ -6,7 +6,7 @@ DependencyDetection.defer do
6
6
  end
7
7
 
8
8
  executes do
9
- NewRelic::Agent.logger.debug 'Installing Rails Sunspot instrumentation'
9
+ ::NewRelic::Agent.logger.info 'Installing Rails Sunspot instrumentation'
10
10
  end
11
11
 
12
12
  executes do
@@ -6,8 +6,8 @@ DependencyDetection.defer do
6
6
  end
7
7
 
8
8
  executes do
9
- NewRelic::Agent.logger.debug 'Installing Unicorn instrumentation'
10
- NewRelic::Agent.logger.info 'Detected Unicorn, please see additional documentation: https://newrelic.com/docs/troubleshooting/im-using-unicorn-and-i-dont-see-any-data'
9
+ ::NewRelic::Agent.logger.info 'Installing Unicorn instrumentation'
10
+ ::NewRelic::Agent.logger.info 'Detected Unicorn, please see additional documentation: https://newrelic.com/docs/troubleshooting/im-using-unicorn-and-i-dont-see-any-data'
11
11
  end
12
12
 
13
13
  executes do
@@ -175,13 +175,11 @@ module NewRelic
175
175
  end
176
176
 
177
177
  # helper for logging errors to the newrelic_agent.log
178
- # properly. Logs the error at error level, and includes a
179
- # backtrace if we're running at debug level
178
+ # properly. Logs the error at error level
180
179
  def log_errors(code_area, metric)
181
180
  yield
182
181
  rescue => e
183
- NewRelic::Control.instance.log.error("Caught exception in #{code_area}. Metric name = #{metric}, exception = #{e}")
184
- NewRelic::Control.instance.log.error(e.backtrace.join("\n"))
182
+ ::NewRelic::Agent.logger.error("Caught exception in #{code_area}. Metric name = #{metric}", e)
185
183
  end
186
184
 
187
185
  # provides the header for our traced execution scoped
@@ -327,7 +325,7 @@ module NewRelic
327
325
  # anything if the method doesn't exist.
328
326
  def newrelic_method_exists?(method_name)
329
327
  exists = method_defined?(method_name) || private_method_defined?(method_name)
330
- NewRelic::Control.instance.log.warn("Did not trace #{self.name}##{method_name} because that method does not exist") unless exists
328
+ ::NewRelic::Agent.logger.error("Did not trace #{self.name}##{method_name} because that method does not exist") unless exists
331
329
  exists
332
330
  end
333
331
 
@@ -337,7 +335,7 @@ module NewRelic
337
335
  # to help with debugging custom instrumentation.
338
336
  def traced_method_exists?(method_name, metric_name_code)
339
337
  exists = method_defined?(_traced_method_name(method_name, metric_name_code))
340
- NewRelic::Control.instance.log.warn("Attempt to trace a method twice with the same metric: Method = #{method_name}, Metric Name = #{metric_name_code}") if exists
338
+ ::NewRelic::Agent.logger.error("Attempt to trace a method twice with the same metric: Method = #{method_name}, Metric Name = #{metric_name_code}") if exists
341
339
  exists
342
340
  end
343
341
 
@@ -488,7 +486,7 @@ module NewRelic
488
486
  alias_method method_name, _traced_method_name(method_name, metric_name_code)
489
487
  send visibility, method_name
490
488
  send visibility, _traced_method_name(method_name, metric_name_code)
491
- NewRelic::Control.instance.log.debug("Traced method: class = #{self.name},"+
489
+ ::NewRelic::Agent.logger.debug("Traced method: class = #{self.name},"+
492
490
  "method = #{method_name}, "+
493
491
  "metric = '#{metric_name_code}'")
494
492
  end
@@ -501,7 +499,7 @@ module NewRelic
501
499
  if method_defined? "#{_traced_method_name(method_name, metric_name_code)}"
502
500
  alias_method method_name, "#{_untraced_method_name(method_name, metric_name_code)}"
503
501
  undef_method "#{_traced_method_name(method_name, metric_name_code)}"
504
- NewRelic::Control.instance.log.debug("removed method tracer #{method_name} #{metric_name_code}\n")
502
+ ::NewRelic::Agent.logger.debug("removed method tracer #{method_name} #{metric_name_code}\n")
505
503
  else
506
504
  raise "No tracer for '#{metric_name_code}' on method '#{method_name}'"
507
505
  end
@@ -1,4 +1,5 @@
1
1
  require 'zlib'
2
+ require 'new_relic/agent/audit_logger'
2
3
 
3
4
  module NewRelic
4
5
  module Agent
@@ -23,18 +24,24 @@ module NewRelic
23
24
  @license_key = license_key || Agent.config[:license_key]
24
25
  @collector = collector
25
26
  @request_timeout = Agent.config[:timeout]
26
- load_marshaller
27
- end
28
27
 
29
- def load_marshaller
30
- if Agent.config[:marshaller] == :json
31
- require 'json'
32
- @marshaller = JsonMarshaller.new
33
- else
34
- @marshaller = PrubyMarshaller.new
28
+ @audit_logger = ::NewRelic::Agent::AuditLogger.new(Agent.config)
29
+ Agent.config.register_callback(:'audit_log.enabled') do |enabled|
30
+ @audit_logger.enabled = enabled
31
+ end
32
+
33
+ Agent.config.register_callback(:marshaller) do |marshaller|
34
+ begin
35
+ if marshaller == 'json'
36
+ require 'json'
37
+ @marshaller = JsonMarshaller.new
38
+ else
39
+ @marshaller = PrubyMarshaller.new
40
+ end
41
+ rescue LoadError
42
+ @marshaller = PrubyMarshaller.new
43
+ end
35
44
  end
36
- rescue LoadError
37
- @marshaller = PrubyMarshaller.new
38
45
  end
39
46
 
40
47
  def connect(settings={})
@@ -72,7 +79,7 @@ module NewRelic
72
79
  end
73
80
 
74
81
  def profile_data(profile)
75
- invoke_remote(:profile_data, @agent_id, profile.to_compressed_array) || ''
82
+ invoke_remote(:profile_data, @agent_id, profile) || ''
76
83
  end
77
84
 
78
85
  def get_agent_commands
@@ -86,6 +93,19 @@ module NewRelic
86
93
  invoke_remote(:agent_command_results, @agent_id, { command_id.to_s => results })
87
94
  end
88
95
 
96
+ # We do not compress if content is smaller than 64kb. There are
97
+ # problems with bugs in Ruby in some versions that expose us
98
+ # to a risk of segfaults if we compress aggressively.
99
+ def compress_request_if_needed(data)
100
+ encoding = 'identity'
101
+ if data.size > 64 * 1024
102
+ data = Encoders::Compressed.encode(data)
103
+ encoding = 'deflate'
104
+ end
105
+ check_post_size(data)
106
+ [data, encoding]
107
+ end
108
+
89
109
  private
90
110
 
91
111
  # A shorthand for NewRelic::Control.instance
@@ -93,11 +113,6 @@ module NewRelic
93
113
  NewRelic::Control.instance
94
114
  end
95
115
 
96
- # Shorthand to the NewRelic::Agent.logger method
97
- def log
98
- NewRelic::Agent.logger
99
- end
100
-
101
116
  # The path on the server that we should post our data to
102
117
  def remote_method_uri(method, format='ruby')
103
118
  params = {'run_id' => @agent_id, 'marshal_format' => format}
@@ -117,15 +132,19 @@ module NewRelic
117
132
  now = Time.now
118
133
 
119
134
  data = @marshaller.dump(args)
120
- check_post_size(data)
135
+ data, encoding = compress_request_if_needed(data)
136
+
137
+ uri = remote_method_uri(method, @marshaller.format)
138
+ full_uri = "#{@collector}#{uri}"
139
+
140
+ @audit_logger.log_request(full_uri, args, @marshaller)
121
141
  response = send_request(:data => data,
122
- :uri => remote_method_uri(method,
123
- @marshaller.format),
124
- :encoding => @marshaller.encoding,
142
+ :uri => uri,
143
+ :encoding => encoding,
125
144
  :collector => @collector)
126
145
  @marshaller.load(decompress_response(response))
127
146
  rescue NewRelic::Agent::ForceRestartException => e
128
- log.info e.message
147
+ ::NewRelic::Agent.logger.debug e.message
129
148
  raise
130
149
  ensure
131
150
  record_supportability_metrics(method, now)
@@ -140,48 +159,11 @@ module NewRelic
140
159
  record_data_point((Time.now - now).to_f)
141
160
  end
142
161
 
143
- # This method handles the compression of the request body that
144
- # we are going to send to the server
145
- #
146
- # We currently optimize for CPU here since we get roughly a 10x
147
- # reduction in message size with this, and CPU overhead is at a
148
- # premium. For extra-large posts, we use the higher compression
149
- # since otherwise it actually errors out.
150
- #
151
- # We do not compress if content is smaller than 64kb. There are
152
- # problems with bugs in Ruby in some versions that expose us
153
- # to a risk of segfaults if we compress aggressively.
154
- #
155
- # medium payloads get fast compression, to save CPU
156
- # big payloads get all the compression possible, to stay under
157
- # the 2,000,000 byte post threshold
158
- def compress_data(object)
159
- dump = marshal_data(object)
160
-
161
- return [dump, 'identity'] if dump.size < (64*1024)
162
-
163
- compressed_dump = Zlib::Deflate.deflate(dump, Zlib::DEFAULT_COMPRESSION)
164
-
165
- # this checks to make sure mongrel won't choke on big uploads
166
- check_post_size(compressed_dump)
167
-
168
- [compressed_dump, 'deflate']
169
- end
170
-
171
- def marshal_data(data)
172
- NewRelic::LanguageSupport.with_cautious_gc do
173
- Marshal.dump(data)
174
- end
175
- rescue => e
176
- log.debug("#{e.class.name} : #{e.message} when marshalling #{object}")
177
- raise
178
- end
179
-
180
162
  # Raises an UnrecoverableServerException if the post_string is longer
181
163
  # than the limit configured in the control object
182
164
  def check_post_size(post_string)
183
165
  return if post_string.size < Agent.config[:post_size_limit]
184
- log.debug "Tried to send too much data: #{post_string.size} bytes"
166
+ ::NewRelic::Agent.logger.debug "Tried to send too much data: #{post_string.size} bytes"
185
167
  raise UnrecoverableServerException.new('413 Request Entity Too Large')
186
168
  end
187
169
 
@@ -201,7 +183,7 @@ module NewRelic
201
183
  request.content_type = "application/octet-stream"
202
184
  request.body = opts[:data]
203
185
 
204
- log.debug "Connect to #{opts[:collector]}#{opts[:uri]}"
186
+ ::NewRelic::Agent.logger.debug "Connect to #{opts[:collector]}#{opts[:uri]}"
205
187
 
206
188
  response = nil
207
189
  http = control.http_connection(@collector)
@@ -211,7 +193,7 @@ module NewRelic
211
193
  response = http.request(request)
212
194
  end
213
195
  rescue Timeout::Error
214
- log.warn "Timed out trying to post data to New Relic (timeout = #{@request_timeout} seconds)" unless @request_timeout < 30
196
+ ::NewRelic::Agent.logger.warn "Timed out trying to post data to New Relic (timeout = #{@request_timeout} seconds)" unless @request_timeout < 30
215
197
  raise
216
198
  end
217
199
  if response.is_a? Net::HTTPUnauthorized
@@ -219,7 +201,7 @@ module NewRelic
219
201
  elsif response.is_a? Net::HTTPServiceUnavailable
220
202
  raise ServerConnectionException, "Service unavailable (#{response.code}): #{response.message}"
221
203
  elsif response.is_a? Net::HTTPGatewayTimeOut
222
- log.debug("Timed out getting response: #{response.message}")
204
+ ::NewRelic::Agent.logger.warn("Timed out getting response: #{response.message}")
223
205
  raise Timeout::Error, response.message
224
206
  elsif response.is_a? Net::HTTPRequestEntityTooLarge
225
207
  raise UnrecoverableServerException, '413 Request Entity Too Large'
@@ -238,10 +220,10 @@ module NewRelic
238
220
  # encoded, otherwise returns it verbatim
239
221
  def decompress_response(response)
240
222
  if response['content-encoding'] != 'gzip'
241
- log.debug "Uncompressed content returned"
223
+ ::NewRelic::Agent.logger.debug "Uncompressed content returned"
242
224
  return response.body
243
225
  end
244
- log.debug "Decompressing return value"
226
+ ::NewRelic::Agent.logger.debug "Decompressing return value"
245
227
  i = Zlib::GzipReader.new(StringIO.new(response.body))
246
228
  i.read
247
229
  end
@@ -259,34 +241,27 @@ module NewRelic
259
241
  "NewRelic-RubyAgent/#{NewRelic::VERSION::STRING} #{ruby_description}#{zlib_version}"
260
242
  end
261
243
 
262
- class Marshaller
263
- attr_reader :encoding
264
-
265
- # This method handles the compression of the request body that
266
- # we are going to send to the server
267
- #
268
- # We currently optimize for CPU here since we get roughly a 10x
269
- # reduction in message size with this, and CPU overhead is at a
270
- # premium. For extra-large posts, we use the higher compression
271
- # since otherwise it actually errors out.
272
- #
273
- # We do not compress if content is smaller than 64kb. There are
274
- # problems with bugs in Ruby in some versions that expose us
275
- # to a risk of segfaults if we compress aggressively.
276
- #
277
- # medium payloads get fast compression, to save CPU
278
- # big payloads get all the compression possible, to stay under
279
- # the 2,000,000 byte post threshold
280
- def compress(data, opts={})
281
- if opts[:force] || data.size > 64 * 1024
282
- data = Zlib::Deflate.deflate(data, Zlib::DEFAULT_COMPRESSION)
283
- @encoding = 'deflate'
284
- else
285
- @encoding = 'identity'
244
+ module Encoders
245
+ module Identity
246
+ def self.encode(data)
247
+ data
248
+ end
249
+ end
250
+
251
+ module Compressed
252
+ def self.encode(data)
253
+ Zlib::Deflate.deflate(data, Zlib::DEFAULT_COMPRESSION)
254
+ end
255
+ end
256
+
257
+ module Base64CompressedJSON
258
+ def self.encode(data)
259
+ Base64.encode64(Compressed.encode(JSON.dump(data)))
286
260
  end
287
- data
288
261
  end
262
+ end
289
263
 
264
+ class Marshaller
290
265
  def parsed_error(error)
291
266
  error_class = error['error_type'].split('::') \
292
267
  .inject(Module) {|mod,const| mod.const_get(const) }
@@ -295,18 +270,27 @@ module NewRelic
295
270
  CollectorError.new("#{error['error_type']}: #{error['message']}")
296
271
  end
297
272
 
298
- protected
299
-
300
- def prepare(data)
273
+ def prepare(data, options={})
274
+ encoder = options[:encoder] || default_encoder
301
275
  if data.respond_to?(:to_collector_array)
302
- data.to_collector_array(self)
276
+ data.to_collector_array(encoder)
303
277
  elsif data.kind_of?(Array)
304
- data.map {|element| prepare(element) }
278
+ data.map { |element| prepare(element, options) }
305
279
  else
306
280
  data
307
281
  end
308
282
  end
309
283
 
284
+ def default_encoder
285
+ Encoders::Identity
286
+ end
287
+
288
+ def self.human_readable?
289
+ false
290
+ end
291
+
292
+ protected
293
+
310
294
  def return_value(data)
311
295
  if data.respond_to?(:has_key?)
312
296
  if data.has_key?('exception')
@@ -315,7 +299,7 @@ module NewRelic
315
299
  return data['return_value']
316
300
  end
317
301
  end
318
- NewRelic::Agent.logger.debug("Unexpected response from collector: #{data}")
302
+ ::NewRelic::Agent.logger.debug("Unexpected response from collector: #{data}")
319
303
  nil
320
304
  end
321
305
  end
@@ -323,15 +307,15 @@ module NewRelic
323
307
  # Primitive Ruby Object Notation which complies JSON format data strutures
324
308
  class PrubyMarshaller < Marshaller
325
309
  def initialize
326
- NewRelic::Agent.logger.debug 'Using Pruby marshaller'
310
+ ::NewRelic::Agent.logger.debug 'Using Pruby marshaller'
327
311
  end
328
312
 
329
- def dump(ruby)
313
+ def dump(ruby, opts={})
330
314
  NewRelic::LanguageSupport.with_cautious_gc do
331
- compress(Marshal.dump(prepare(ruby)))
315
+ Marshal.dump(prepare(ruby, opts))
332
316
  end
333
317
  rescue => e
334
- NewRelic::Agent.logger.debug("#{e.class.name} : #{e.message} when marshalling #{ruby.inspect}")
318
+ ::NewRelic::Agent.logger.debug("#{e.class.name} : #{e.message} when marshalling #{ruby.inspect}")
335
319
  raise
336
320
  end
337
321
 
@@ -341,7 +325,7 @@ module NewRelic
341
325
  return_value(Marshal.load(data))
342
326
  end
343
327
  rescue
344
- NewRelic::Agent.logger.debug "Error encountered loading collector response: #{data}"
328
+ ::NewRelic::Agent.logger.debug "Error encountered loading collector response: #{data}"
345
329
  raise
346
330
  end
347
331
 
@@ -357,23 +341,23 @@ module NewRelic
357
341
  # Marshal collector protocol with JSON when available
358
342
  class JsonMarshaller < Marshaller
359
343
  def initialize
360
- NewRelic::Agent.logger.debug 'Using JSON marshaller'
344
+ ::NewRelic::Agent.logger.debug 'Using JSON marshaller'
361
345
  end
362
346
 
363
- def dump(ruby)
364
- compress(JSON.dump(prepare(ruby)))
347
+ def dump(ruby, opts={})
348
+ JSON.dump(prepare(ruby, opts))
365
349
  end
366
350
 
367
351
  def load(data)
368
352
  return unless data && data != ''
369
353
  return_value(JSON.load(data))
370
354
  rescue
371
- NewRelic::Agent.logger.debug "Error encountered loading collector response: #{data}"
355
+ ::NewRelic::Agent.logger.debug "Error encountered loading collector response: #{data}"
372
356
  raise
373
357
  end
374
358
 
375
- def encode_compress(data)
376
- Base64.encode64(compress(JSON.dump(data), :force => true))
359
+ def default_encoder
360
+ Encoders::Base64CompressedJSON
377
361
  end
378
362
 
379
363
  def format
@@ -383,6 +367,10 @@ module NewRelic
383
367
  def self.is_supported?
384
368
  RUBY_VERSION >= '1.9.2'
385
369
  end
370
+
371
+ def self.human_readable?
372
+ true # for some definitions of 'human'
373
+ end
386
374
  end
387
375
 
388
376
  class CollectorError < StandardError; end