wd_newrelic_rpm 3.5.5 → 3.5.6

Sign up to get free protection for your applications and to get access to all the features.
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