wd_newrelic_rpm 3.5.5 → 3.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. data/.gitignore +2 -0
  2. data/CHANGELOG +60 -0
  3. data/Rakefile +14 -18
  4. data/gem-public_cert.pem +20 -0
  5. data/lib/new_relic/agent.rb +3 -0
  6. data/lib/new_relic/agent/agent.rb +86 -97
  7. data/lib/new_relic/agent/agent_logger.rb +9 -1
  8. data/lib/new_relic/agent/busy_calculator.rb +5 -0
  9. data/lib/new_relic/agent/configuration/defaults.rb +3 -3
  10. data/lib/new_relic/agent/configuration/manager.rb +12 -0
  11. data/lib/new_relic/agent/configuration/mask_defaults.rb +1 -0
  12. data/lib/new_relic/agent/configuration/yaml_source.rb +5 -1
  13. data/lib/new_relic/agent/cross_process_monitoring.rb +164 -20
  14. data/lib/new_relic/agent/error_collector.rb +13 -2
  15. data/lib/new_relic/agent/event_listener.rb +39 -0
  16. data/lib/new_relic/agent/instrumentation/browser_monitoring_timings.rb +18 -8
  17. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +1 -1
  18. data/lib/new_relic/agent/instrumentation/sinatra.rb +8 -1
  19. data/lib/new_relic/agent/new_relic_service.rb +90 -10
  20. data/lib/new_relic/agent/pipe_service.rb +9 -0
  21. data/lib/new_relic/agent/sql_sampler.rb +10 -3
  22. data/lib/new_relic/agent/stats_engine/transactions.rb +1 -0
  23. data/lib/new_relic/agent/thread_profiler.rb +20 -7
  24. data/lib/new_relic/agent/worker_loop.rb +2 -1
  25. data/lib/new_relic/coerce.rb +37 -0
  26. data/lib/new_relic/commands/deployments.rb +1 -1
  27. data/lib/new_relic/control/frameworks/rails.rb +29 -5
  28. data/lib/new_relic/control/frameworks/rails3.rb +2 -11
  29. data/lib/new_relic/control/instance_methods.rb +11 -7
  30. data/lib/new_relic/control/server_methods.rb +5 -37
  31. data/lib/new_relic/latest_changes.rb +31 -0
  32. data/lib/new_relic/local_environment.rb +1 -1
  33. data/lib/new_relic/metric_data.rb +13 -2
  34. data/lib/new_relic/noticed_error.rb +8 -1
  35. data/lib/new_relic/rack/agent_hooks.rb +20 -0
  36. data/lib/new_relic/rack/error_collector.rb +11 -1
  37. data/lib/new_relic/recipes.rb +32 -10
  38. data/lib/new_relic/transaction_sample.rb +12 -3
  39. data/lib/new_relic/transaction_sample/segment.rb +6 -3
  40. data/lib/new_relic/version.rb +10 -15
  41. data/newrelic.yml +12 -19
  42. data/newrelic_rpm.gemspec +22 -464
  43. data/test/multiverse/.gitignore +1 -0
  44. data/test/multiverse/lib/multiverse/environment.rb +1 -1
  45. data/test/multiverse/lib/multiverse/suite.rb +2 -0
  46. data/test/multiverse/suites/active_record/Envfile +3 -3
  47. data/test/multiverse/suites/active_record/ar_method_aliasing.rb +1 -1
  48. data/test/multiverse/suites/active_record/config/newrelic.yml +2 -2
  49. data/test/multiverse/suites/agent_only/Envfile +2 -1
  50. data/test/multiverse/suites/agent_only/config/newrelic.yml +3 -1
  51. data/test/multiverse/suites/agent_only/cross_process_test.rb +56 -0
  52. data/test/multiverse/suites/{logging → agent_only}/logging_test.rb +42 -22
  53. data/test/multiverse/suites/agent_only/no_dns_resolv.rb +17 -0
  54. data/test/multiverse/suites/{rum_auto_instrumentation/sanity_test.rb → agent_only/rum_instrumentation_test.rb} +25 -46
  55. data/test/multiverse/suites/agent_only/service_timeout_test.rb +6 -3
  56. data/test/multiverse/suites/agent_only/ssl_test.rb +22 -0
  57. data/test/multiverse/suites/{no_load → agent_only}/start_up_test.rb +9 -2
  58. data/test/multiverse/suites/agent_only/testing_app.rb +17 -0
  59. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +6 -5
  60. data/test/multiverse/suites/datamapper/config/newrelic.yml +1 -1
  61. data/test/multiverse/suites/{rails_3_queue_time → rails}/Envfile +3 -0
  62. data/test/multiverse/suites/rails/app.rb +49 -0
  63. data/test/multiverse/suites/{rails_3_views → rails}/app/views/foos/_foo.html.haml +0 -0
  64. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/_a_partial.html.erb +0 -0
  65. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/_mid_partial.html.erb +0 -0
  66. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/_top_partial.html.erb +0 -0
  67. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/deep_partial.html.erb +0 -0
  68. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/haml_view.html.haml +0 -0
  69. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/index.html.erb +0 -0
  70. data/test/multiverse/suites/rails/config/newrelic.yml +32 -0
  71. data/test/multiverse/suites/{rails_3_error_tracing → rails}/error_tracing_test.rb +51 -88
  72. data/test/multiverse/suites/rails/gc_instrumentation_test.rb +79 -0
  73. data/test/multiverse/suites/{rails_3_queue_time → rails}/queue_time_test.rb +3 -23
  74. data/test/multiverse/suites/{rails_3_views → rails}/view_instrumentation_test.rb +21 -61
  75. data/test/multiverse/suites/resque/Envfile +7 -4
  76. data/test/multiverse/suites/resque/Rakefile +8 -0
  77. data/test/multiverse/suites/resque/config/newrelic.yml +1 -1
  78. data/test/multiverse/suites/resque/instrumentation_test.rb +118 -41
  79. data/test/multiverse/suites/resque/resque_setup.rb +15 -0
  80. data/test/multiverse/suites/sinatra/config/newrelic.yml +1 -2
  81. data/test/multiverse/suites/sinatra/sinatra_error_tracing_test.rb +38 -0
  82. data/test/multiverse/suites/sinatra/sinatra_test.rb +17 -0
  83. data/test/multiverse/test/suite_examples/one/a/config/newrelic.yml +1 -1
  84. data/test/multiverse/test/suite_examples/one/b/config/newrelic.yml +1 -1
  85. data/test/new_relic/agent/agent/connect_test.rb +24 -100
  86. data/test/new_relic/agent/agent/start_worker_thread_test.rb +3 -3
  87. data/test/new_relic/agent/agent_test.rb +126 -31
  88. data/test/new_relic/agent/browser_monitoring_test.rb +1 -1
  89. data/test/new_relic/agent/busy_calculator_test.rb +8 -0
  90. data/test/new_relic/agent/configuration/manager_test.rb +28 -0
  91. data/test/new_relic/agent/configuration/yaml_source_test.rb +12 -2
  92. data/test/new_relic/agent/cross_process_monitoring_test.rb +144 -31
  93. data/test/new_relic/agent/error_collector_test.rb +16 -0
  94. data/test/new_relic/agent/event_listener_test.rb +46 -0
  95. data/test/new_relic/agent/instrumentation/browser_monitoring_timings_test.rb +57 -30
  96. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +1 -0
  97. data/test/new_relic/agent/new_relic_service_test.rb +95 -2
  98. data/test/new_relic/agent/pipe_channel_manager_test.rb +3 -3
  99. data/test/new_relic/agent/pipe_service_test.rb +21 -1
  100. data/test/new_relic/agent/rpm_agent_test.rb +1 -1
  101. data/test/new_relic/agent/sql_sampler_test.rb +20 -0
  102. data/test/new_relic/agent/thread_profiler_test.rb +53 -8
  103. data/test/new_relic/agent/worker_loop_test.rb +19 -16
  104. data/test/new_relic/agent_test.rb +1 -2
  105. data/test/new_relic/coerce_test.rb +65 -0
  106. data/test/new_relic/command/deployments_test.rb +1 -1
  107. data/test/new_relic/control_test.rb +23 -44
  108. data/test/new_relic/fake_collector.rb +34 -6
  109. data/test/new_relic/local_environment_test.rb +1 -1
  110. data/test/new_relic/metric_data_test.rb +29 -0
  111. data/test/new_relic/noticed_error_test.rb +8 -0
  112. data/test/new_relic/rack/agent_hooks_test.rb +30 -0
  113. data/test/new_relic/rack/error_collector_test.rb +16 -0
  114. data/test/new_relic/transaction_sample/segment_test.rb +7 -0
  115. data/test/new_relic/transaction_sample_test.rb +36 -8
  116. data/test/new_relic/version_number_test.rb +6 -30
  117. data/test/script/ci.sh +6 -5
  118. data/test/test_contexts.rb +2 -1
  119. data/test/test_helper.rb +23 -6
  120. data/ui/helpers/google_pie_chart.rb +1 -0
  121. metadata +68 -67
  122. data/newrelic_rpm.gemspec.erb +0 -54
  123. data/test/fixtures/gemspec_no_build.rb +0 -442
  124. data/test/fixtures/gemspec_with_build.rb +0 -442
  125. data/test/fixtures/gemspec_with_build_and_stage.rb +0 -442
  126. data/test/multiverse/suites/logging/Envfile +0 -4
  127. data/test/multiverse/suites/logging/config/newrelic.yml +0 -22
  128. data/test/multiverse/suites/monitor_mode_false/Envfile +0 -2
  129. data/test/multiverse/suites/monitor_mode_false/config/newrelic.yml +0 -25
  130. data/test/multiverse/suites/monitor_mode_false/no_dns_resolv.rb +0 -29
  131. data/test/multiverse/suites/no_load/Envfile +0 -2
  132. data/test/multiverse/suites/no_load/config/newrelic.yml +0 -22
  133. data/test/multiverse/suites/rails_3_error_tracing/Envfile +0 -15
  134. data/test/multiverse/suites/rails_3_error_tracing/config/newrelic.yml +0 -165
  135. data/test/multiverse/suites/rails_3_gc/Envfile +0 -8
  136. data/test/multiverse/suites/rails_3_gc/config/newrelic.yml +0 -167
  137. data/test/multiverse/suites/rails_3_gc/instrumentation_test.rb +0 -92
  138. data/test/multiverse/suites/rails_3_queue_time/config/newrelic.yml +0 -165
  139. data/test/multiverse/suites/rails_3_views/.gitignore +0 -3
  140. data/test/multiverse/suites/rails_3_views/Envfile +0 -16
  141. data/test/multiverse/suites/rails_3_views/config/newrelic.yml +0 -164
  142. data/test/multiverse/suites/resque/dump.rdb +0 -0
  143. data/test/multiverse/suites/rum_auto_instrumentation/Envfile +0 -4
  144. data/test/multiverse/suites/rum_auto_instrumentation/config/newrelic.yml +0 -24
  145. data/test/multiverse/suites/rum_auto_instrumentation/responses/worst_case_small.html +0 -5000
  146. data/test/new_relic/fake_service.rb +0 -53
@@ -149,7 +149,7 @@ DependencyDetection.defer do
149
149
 
150
150
  def render_with_newrelic(context, options)
151
151
  # This is needed for rails 3.2 compatibility
152
- @details = extract_details(options) if respond_to? :extract_details
152
+ @details = extract_details(options) if respond_to? :extract_details, true
153
153
  identifier = determine_template(options) ? determine_template(options).identifier : nil
154
154
  str = "View/#{NewRelic::Agent::Instrumentation::Rails3::ActionView::NewRelic.template_metric(identifier, options)}/Rendering"
155
155
  trace_execution_scoped str do
@@ -45,7 +45,14 @@ module NewRelic
45
45
  perform_action_with_newrelic_trace(:category => :sinatra,
46
46
  :name => txn_name,
47
47
  :params => @request.params) do
48
- dispatch_without_newrelic
48
+ result = dispatch_without_newrelic
49
+
50
+ # Will only see an error raised if :show_exceptions is true, but
51
+ # will always see them in the env hash if they occur
52
+ had_error = env.has_key?('sinatra.error')
53
+ ::NewRelic::Agent.notice_error(env['sinatra.error']) if had_error
54
+
55
+ result
49
56
  end
50
57
  end
51
58
 
@@ -29,7 +29,16 @@ module NewRelic
29
29
  Agent.config.register_callback(:'audit_log.enabled') do |enabled|
30
30
  @audit_logger.enabled = enabled
31
31
  end
32
-
32
+ Agent.config.register_callback(:ssl) do |ssl|
33
+ if !ssl
34
+ ::NewRelic::Agent.logger.warn("Agent is configured not to use SSL when communicating with New Relic's servers")
35
+ elsif !Agent.config[:verify_certificate]
36
+ ::NewRelic::Agent.logger.warn("Agent is configured to use SSL but to skip certificate validation when communicating with New Relic's servers")
37
+ else
38
+ ::NewRelic::Agent.logger.debug("Agent is configured to use SSL")
39
+ end
40
+ end
41
+
33
42
  Agent.config.register_callback(:marshaller) do |marshaller|
34
43
  begin
35
44
  if marshaller == 'json'
@@ -106,6 +115,73 @@ module NewRelic
106
115
  [data, encoding]
107
116
  end
108
117
 
118
+ # One session with the service's endpoint. In this case the session
119
+ # represents 1 tcp connection which may transmit multiple HTTP requests
120
+ # via keep-alive.
121
+ def session(&block)
122
+ raise ArgumentError, "#{self.class}#shared_connection must be passed a block" unless block_given?
123
+
124
+ http = create_http_connection
125
+
126
+ # Immediately open a TCP connection to the server and leave it open for
127
+ # multiple requests.
128
+ ::NewRelic::Agent.logger.debug("Opening TCP connection to #{http.address}:#{http.port}")
129
+ http.start
130
+ begin
131
+ @shared_tcp_connection = http
132
+ block.call
133
+ ensure
134
+ @shared_tcp_connection = nil
135
+ # Close the TCP socket
136
+ ::NewRelic::Agent.logger.debug("Closing TCP connection to #{http.address}:#{http.port}")
137
+ http.finish
138
+ end
139
+ end
140
+
141
+ # Return a Net::HTTP connection object to make a call to the collector.
142
+ # We'll reuse the same handle for cases where we're using keep-alive, or
143
+ # otherwise create a new one.
144
+ def http_connection
145
+ @shared_tcp_connection || create_http_connection
146
+ end
147
+
148
+ # Return the Net::HTTP with proxy configuration given the NewRelic::Control::Server object.
149
+ def create_http_connection
150
+ proxy_server = control.proxy_server
151
+ # Proxy returns regular HTTP if @proxy_host is nil (the default)
152
+ http_class = Net::HTTP::Proxy(proxy_server.name, proxy_server.port,
153
+ proxy_server.user, proxy_server.password)
154
+
155
+ http = http_class.new((@collector.ip || @collector.name), @collector.port)
156
+ if Agent.config[:ssl]
157
+ begin
158
+ # Jruby 1.6.8 requires a gem for full ssl support and will throw
159
+ # an error when use_ssl=(true) is called and jruby-openssl isn't
160
+ # installed
161
+ http.use_ssl = true
162
+ if Agent.config[:verify_certificate]
163
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
164
+ http.ca_file = cert_file_path
165
+ else
166
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
167
+ end
168
+ rescue StandardError, LoadError
169
+ msg = "Agent is configured to use SSL, but SSL is not available in the environment. "
170
+ msg << "Either disable SSL in the agent configuration, or install SSL support."
171
+ raise UnrecoverableAgentException.new(msg)
172
+ end
173
+ end
174
+ ::NewRelic::Agent.logger.debug("Created net/http handle to #{http.address}:#{http.port}")
175
+ http
176
+ end
177
+
178
+
179
+ # The path to the certificate file used to verify the SSL
180
+ # connection if verify_peer is enabled
181
+ def cert_file_path
182
+ File.expand_path(File.join(control.newrelic_root, 'cert', 'cacert.pem'))
183
+ end
184
+
109
185
  private
110
186
 
111
187
  # A shorthand for NewRelic::Control.instance
@@ -183,31 +259,33 @@ module NewRelic
183
259
  request.content_type = "application/octet-stream"
184
260
  request.body = opts[:data]
185
261
 
186
- ::NewRelic::Agent.logger.debug "Connect to #{opts[:collector]}#{opts[:uri]}"
187
-
188
262
  response = nil
189
- http = control.http_connection(@collector)
263
+ http = http_connection
190
264
  http.read_timeout = nil
191
265
  begin
192
266
  NewRelic::TimerLib.timeout(@request_timeout) do
267
+ ::NewRelic::Agent.logger.debug "Sending request to #{opts[:collector]}#{opts[:uri]}"
193
268
  response = http.request(request)
194
269
  end
195
270
  rescue Timeout::Error
196
271
  ::NewRelic::Agent.logger.warn "Timed out trying to post data to New Relic (timeout = #{@request_timeout} seconds)" unless @request_timeout < 30
197
272
  raise
198
273
  end
199
- if response.is_a? Net::HTTPUnauthorized
274
+ case response
275
+ when Net::HTTPSuccess
276
+ true # fall through
277
+ when Net::HTTPUnauthorized
200
278
  raise LicenseException, 'Invalid license key, please contact support@newrelic.com'
201
- elsif response.is_a? Net::HTTPServiceUnavailable
279
+ when Net::HTTPServiceUnavailable
202
280
  raise ServerConnectionException, "Service unavailable (#{response.code}): #{response.message}"
203
- elsif response.is_a? Net::HTTPGatewayTimeOut
281
+ when Net::HTTPGatewayTimeOut
204
282
  ::NewRelic::Agent.logger.warn("Timed out getting response: #{response.message}")
205
283
  raise Timeout::Error, response.message
206
- elsif response.is_a? Net::HTTPRequestEntityTooLarge
284
+ when Net::HTTPRequestEntityTooLarge
207
285
  raise UnrecoverableServerException, '413 Request Entity Too Large'
208
- elsif response.is_a? Net::HTTPUnsupportedMediaType
286
+ when Net::HTTPUnsupportedMediaType
209
287
  raise UnrecoverableServerException, '415 Unsupported Media Type'
210
- elsif !(response.is_a? Net::HTTPSuccess)
288
+ else
211
289
  raise ServerConnectionException, "Unexpected response from server (#{response.code}): #{response.message}"
212
290
  end
213
291
  response
@@ -216,6 +294,8 @@ module NewRelic
216
294
  raise NewRelic::Agent::ServerConnectionException, "Recoverable error connecting to the server: #{e}"
217
295
  end
218
296
 
297
+
298
+
219
299
  # Decompresses the response from the server, if it is gzip
220
300
  # encoded, otherwise returns it verbatim
221
301
  def decompress_response(response)
@@ -39,6 +39,13 @@ module NewRelic
39
39
  write_to_pipe('EOF')
40
40
  NewRelic::Agent::PipeChannelManager.channels[@channel_id].close
41
41
  end
42
+
43
+ # Invokes the block it is passed. This is used to implement HTTP
44
+ # keep-alive in the NewRelicService, and is a required interface for any
45
+ # Service class.
46
+ def session
47
+ yield
48
+ end
42
49
 
43
50
  private
44
51
 
@@ -52,6 +59,8 @@ module NewRelic
52
59
 
53
60
  def write_to_pipe(data)
54
61
  NewRelic::Agent::PipeChannelManager.channels[@channel_id].write(data)
62
+ rescue => e
63
+ NewRelic::Agent.logger.error("#{e.message}: Unable to send data to parent process, please see https://newrelic.com/docs/ruby/resque-instrumentation for more information.")
55
64
  end
56
65
  end
57
66
  end
@@ -189,7 +189,7 @@ module NewRelic
189
189
  @params = {} #FIXME
190
190
  @sql_id = consistent_hash(normalized_query)
191
191
  set_primary slow_sql, path, uri
192
- record_data_point slow_sql.duration
192
+ record_data_point(float(slow_sql.duration))
193
193
  end
194
194
 
195
195
  def set_primary(slow_sql, path, uri)
@@ -207,7 +207,7 @@ module NewRelic
207
207
  set_primary slow_sql, path, uri
208
208
  end
209
209
 
210
- record_data_point slow_sql.duration
210
+ record_data_point(float(slow_sql.duration))
211
211
  end
212
212
 
213
213
  def prepare_to_send
@@ -223,8 +223,15 @@ module NewRelic
223
223
  Agent.config[:'slow_sql.explain_enabled']
224
224
  end
225
225
 
226
+ include NewRelic::Coerce
227
+
226
228
  def to_collector_array(encoder)
227
- [ @path, @url, @sql_id, @sql, @database_metric_name, @call_count,
229
+ [ string(@path),
230
+ string(@url),
231
+ int(@sql_id),
232
+ string(@sql),
233
+ string(@database_metric_name),
234
+ int(@call_count),
228
235
  Helper.time_to_millis(@total_call_time),
229
236
  Helper.time_to_millis(@min_call_time),
230
237
  Helper.time_to_millis(@max_call_time),
@@ -100,6 +100,7 @@ module Agent
100
100
  def start_transaction(name = nil)
101
101
  Thread::current[:newrelic_scope_stack] ||= []
102
102
  self.scope_name = name if name
103
+ NewRelic::Agent.instance.events.notify(:start_transaction, name)
103
104
  GCProfiler.init
104
105
  end
105
106
 
@@ -202,6 +202,8 @@ EOF
202
202
 
203
203
  THREAD_PROFILER_NODES = 20_000
204
204
 
205
+ include NewRelic::Coerce
206
+
205
207
  def to_collector_array(encoder)
206
208
  prune!(THREAD_PROFILER_NODES)
207
209
 
@@ -212,11 +214,15 @@ EOF
212
214
  "BACKGROUND" => @traces[:background].map{|t| t.to_array }
213
215
  }
214
216
 
215
- [[@profile_id,
216
- @start_time.to_f, @stop_time.to_f,
217
- @poll_count,
218
- encoder.encode(traces),
219
- @sample_count, 0]]
217
+ [[
218
+ int(@profile_id),
219
+ float(@start_time),
220
+ float(@stop_time),
221
+ int(@poll_count),
222
+ string(encoder.encode(traces)),
223
+ int(@sample_count),
224
+ 0
225
+ ]]
220
226
  end
221
227
 
222
228
  def now_in_millis
@@ -280,9 +286,16 @@ EOF
280
286
  [-runnable_count, depth] <=> [-y.runnable_count, y.depth]
281
287
  end
282
288
 
289
+ include NewRelic::Coerce
290
+
283
291
  def to_array
284
- [[@file, @method, @line_no],
285
- @runnable_count, 0,
292
+ [[
293
+ string(@file),
294
+ string(@method),
295
+ int(@line_no)
296
+ ],
297
+ int(@runnable_count),
298
+ 0,
286
299
  @children.map {|c| c.to_array}]
287
300
  end
288
301
 
@@ -12,7 +12,7 @@ module NewRelic
12
12
  @should_run = true
13
13
  @next_invocation_time = Time.now
14
14
  @period = 60.0
15
- @deadline = Time.now + opts[:duration] if opts[:duration]
15
+ @duration = opts[:duration] if opts[:duration]
16
16
  @limit = opts[:limit] if opts[:limit]
17
17
  @iterations = 0
18
18
  end
@@ -26,6 +26,7 @@ module NewRelic
26
26
  # call periods. The caller is responsible for creating the thread
27
27
  # that runs this worker loop. This will run the task immediately.
28
28
  def run(period=nil, &block)
29
+ @deadline = Time.now + @duration if @duration
29
30
  @period = period if period
30
31
  @next_invocation_time = (Time.now + @period)
31
32
  @task = block
@@ -0,0 +1,37 @@
1
+ module NewRelic
2
+ # We really don't want to send bad values to the collector, and it doesn't
3
+ # accept types like Rational that have occasionally slipped into our data.
4
+ #
5
+ # These methods are intended to safely coerce things into the form we want,
6
+ # to provide documentation of expected types on to_collector_array methods,
7
+ # and to log failures if totally invalid data gets into outgoing data
8
+ module Coerce
9
+ def int(value, context=nil)
10
+ Integer(value)
11
+ rescue => error
12
+ log_failure(value, Integer, context, error)
13
+ 0
14
+ end
15
+
16
+ def float(value, context=nil)
17
+ Float(value)
18
+ rescue => error
19
+ log_failure(value, Float, context, error)
20
+ 0.0
21
+ end
22
+
23
+ def string(value, context=nil)
24
+ return value if value.nil?
25
+ String(value)
26
+ rescue => error
27
+ log_failure(value.class, String, context, error)
28
+ ""
29
+ end
30
+
31
+ def log_failure(value, type, context, error)
32
+ msg = "Unable to convert '#{value}' to #{type}"
33
+ msg += " in context '#{context}'" if context
34
+ NewRelic::Agent.logger.warn(msg, error)
35
+ end
36
+ end
37
+ end
@@ -54,7 +54,7 @@ class NewRelic::Command::Deployments < NewRelic::Command
54
54
  }.each do |k, v|
55
55
  create_params["deployment[#{k}]"] = v unless v.nil? || v == ''
56
56
  end
57
- http = control.http_connection(control.api_server)
57
+ http = ::NewRelic::Agent::NewRelicService.new(nil, control.api_server).http_connection
58
58
 
59
59
  uri = "/deployments.xml"
60
60
 
@@ -10,14 +10,24 @@ module NewRelic
10
10
  def env
11
11
  @env ||= RAILS_ENV.dup
12
12
  end
13
+
14
+ # Rails can return an empty string from this method, causing
15
+ # the agent not to start even when it is properly in a rails 3
16
+ # application, so we test the value to make sure it actually
17
+ # has contents, and bail to the parent class if it is empty.
13
18
  def root
14
- if defined?(RAILS_ROOT) && RAILS_ROOT.to_s != ''
15
- RAILS_ROOT.to_s
19
+ root = rails_root.to_s
20
+ if !root.empty?
21
+ root
16
22
  else
17
23
  super
18
24
  end
19
25
  end
20
26
 
27
+ def rails_root
28
+ RAILS_ROOT if defined?(RAILS_ROOT)
29
+ end
30
+
21
31
  def rails_config
22
32
  if defined?(::Rails) && ::Rails.respond_to?(:configuration)
23
33
  ::Rails.configuration
@@ -46,8 +56,22 @@ module NewRelic
46
56
  ::NewRelic::Agent.logger.info("New Relic Agent not running.")
47
57
  else
48
58
  ::NewRelic::Agent.logger.info("Starting the New Relic Agent.")
49
- install_developer_mode rails_config if Agent.config[:developer_mode]
59
+ install_developer_mode(rails_config) if Agent.config[:developer_mode]
50
60
  install_browser_monitoring(rails_config)
61
+ install_agent_hooks(rails_config)
62
+ end
63
+ end
64
+
65
+ def install_agent_hooks(config)
66
+ return if @agent_hooks_installed
67
+ @agent_hooks_installed = true
68
+ return if config.nil? || !config.respond_to?(:middleware)
69
+ begin
70
+ require 'new_relic/rack/agent_hooks'
71
+ config.middleware.use NewRelic::Rack::AgentHooks
72
+ ::NewRelic::Agent.logger.debug("Installed New Relic Agent Hooks middleware")
73
+ rescue => e
74
+ ::NewRelic::Agent.logger.warn("Error installing New Relic Agent Hooks middleware", e)
51
75
  end
52
76
  end
53
77
 
@@ -60,7 +84,7 @@ module NewRelic
60
84
  config.middleware.use NewRelic::Rack::BrowserMonitoring
61
85
  ::NewRelic::Agent.logger.debug("Installed New Relic Browser Monitoring middleware")
62
86
  rescue => e
63
- ::NewRelic::Agent.logger.warn("Error installing New Relic Browser Monitoring middleware: #{e.inspect}")
87
+ ::NewRelic::Agent.logger.warn("Error installing New Relic Browser Monitoring middleware", e)
64
88
  end
65
89
  end
66
90
 
@@ -80,7 +104,7 @@ module NewRelic
80
104
  ::NewRelic::Agent.logger.debug("To view performance information, go to http://localhost#{port}/newrelic")
81
105
  end
82
106
  rescue => e
83
- ::NewRelic::Agent.logger.warn("Error installing New Relic Developer Mode: #{e.inspect}")
107
+ ::NewRelic::Agent.logger.warn("Error installing New Relic Developer Mode", e)
84
108
  end
85
109
  elsif rails_config
86
110
  ::NewRelic::Agent.logger.warn("Developer mode not available for Rails versions prior to 2.2")
@@ -14,17 +14,8 @@ module NewRelic
14
14
  @env ||= ::Rails.env.to_s
15
15
  end
16
16
 
17
- # Rails can return an empty string from this method, causing
18
- # the agent not to start even when it is properly in a rails 3
19
- # application, so we test the value to make sure it actually
20
- # has contents, and bail to the parent class if it is empty.
21
- def root
22
- value = ::Rails.root.to_s
23
- if value.empty?
24
- super
25
- else
26
- value
27
- end
17
+ def rails_root
18
+ ::Rails.root.to_s
28
19
  end
29
20
 
30
21
  def init_config(options={})
@@ -49,7 +49,10 @@ module NewRelic
49
49
 
50
50
  Agent.config.replace_or_add_config(Agent::Configuration::ManualSource.new(options), 1)
51
51
 
52
- ::NewRelic::Agent.logger = NewRelic::Agent::AgentLogger.new(Agent.config, root, options.delete(:log))
52
+ # Be sure to only create once! RUBY-1020
53
+ if ::NewRelic::Agent.logger.is_startup_logger?
54
+ ::NewRelic::Agent.logger = NewRelic::Agent::AgentLogger.new(Agent.config, root, options.delete(:log))
55
+ end
53
56
 
54
57
  # Merge the stringified options into the config as overrides:
55
58
  environment_name = options.delete(:env) and self.env = environment_name
@@ -93,13 +96,19 @@ module NewRelic
93
96
  end
94
97
 
95
98
  def settings
96
- NewRelic::Agent.config.reported_config
99
+ NewRelic::Agent.config.to_collector_hash
97
100
  end
98
101
 
99
102
  def dispatcher
100
103
  NewRelic::Agent.config[:dispatcher]
101
104
  end
102
105
 
106
+ # Delegates to the class method newrelic_root, implemented by
107
+ # each subclass
108
+ def newrelic_root
109
+ self.class.newrelic_root
110
+ end
111
+
103
112
  protected
104
113
 
105
114
  # Append framework specific environment information for uploading to
@@ -130,11 +139,6 @@ module NewRelic
130
139
  '.'
131
140
  end
132
141
 
133
- # Delegates to the class method newrelic_root, implemented by
134
- # each subclass
135
- def newrelic_root
136
- self.class.newrelic_root
137
- end
138
142
  end
139
143
  include InstanceMethods
140
144
  end