newrelic_rpm 3.7.1.188 → 3.7.2.190.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (209) hide show
  1. data.tar.gz.sig +3 -2
  2. data/CHANGELOG +1 -1
  3. data/Guardfile +3 -3
  4. data/README.md +1 -1
  5. data/Rakefile +0 -2
  6. data/init.rb +2 -5
  7. data/lib/new_relic/agent.rb +3 -0
  8. data/lib/new_relic/agent/agent.rb +2 -0
  9. data/lib/new_relic/agent/configuration/default_source.rb +32 -14
  10. data/lib/new_relic/agent/configuration/environment_source.rb +1 -0
  11. data/lib/new_relic/agent/cross_app_monitor.rb +2 -2
  12. data/lib/new_relic/agent/cross_app_tracing.rb +2 -2
  13. data/lib/new_relic/agent/error_collector.rb +1 -1
  14. data/lib/new_relic/agent/http_clients/typhoeus_wrappers.rb +4 -1
  15. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +10 -8
  16. data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +11 -6
  17. data/lib/new_relic/agent/javascript_instrumentor.rb +27 -36
  18. data/lib/new_relic/agent/method_tracer.rb +20 -2
  19. data/lib/new_relic/agent/new_relic_service.rb +35 -27
  20. data/lib/new_relic/agent/request_sampler.rb +20 -13
  21. data/lib/new_relic/agent/sampler_collection.rb +4 -0
  22. data/lib/new_relic/agent/stats_engine/stats_hash.rb +4 -4
  23. data/lib/new_relic/agent/system_info.rb +25 -15
  24. data/lib/new_relic/agent/transaction.rb +23 -4
  25. data/lib/new_relic/agent/transaction_sampler.rb +1 -1
  26. data/lib/new_relic/cli/install.rb +1 -1
  27. data/lib/new_relic/control.rb +1 -0
  28. data/lib/new_relic/helper.rb +1 -29
  29. data/lib/new_relic/json_wrapper.rb +92 -0
  30. data/lib/new_relic/language_support.rb +4 -0
  31. data/lib/new_relic/rack/agent_hooks.rb +4 -0
  32. data/lib/new_relic/rack/browser_monitoring.rb +4 -0
  33. data/lib/new_relic/rack/developer_mode.rb +4 -1
  34. data/lib/new_relic/rack/error_collector.rb +5 -0
  35. data/lib/new_relic/rack/transaction_reset.rb +20 -0
  36. data/lib/new_relic/version.rb +1 -1
  37. data/lib/tasks/install.rake +0 -1
  38. data/newrelic_rpm.gemspec +1 -1
  39. data/test/agent_helper.rb +7 -8
  40. data/test/environments/norails/Gemfile +2 -1
  41. data/test/environments/rails21/Gemfile +2 -2
  42. data/test/environments/rails21/config/environment.rb +1 -3
  43. data/test/environments/rails21/config/environments/development.rb +0 -6
  44. data/test/environments/rails22/Gemfile +2 -2
  45. data/test/environments/rails22/config/environment.rb +0 -2
  46. data/test/environments/rails22/config/environments/development.rb +0 -6
  47. data/test/environments/rails23/Gemfile +2 -3
  48. data/test/environments/rails23/config/environment.rb +0 -9
  49. data/test/environments/rails23/config/environments/development.rb +0 -5
  50. data/test/environments/rails30/Gemfile +2 -2
  51. data/test/environments/rails31/Gemfile +2 -2
  52. data/test/environments/rails32/Gemfile +2 -1
  53. data/test/environments/rails40/Gemfile +2 -1
  54. data/test/intentional_fail.rb +1 -2
  55. data/test/multiverse/lib/multiverse/envfile.rb +1 -5
  56. data/test/multiverse/lib/multiverse/suite.rb +10 -27
  57. data/test/multiverse/suites/active_record/ar_method_aliasing.rb +49 -67
  58. data/test/multiverse/suites/agent_only/encoding_handling_test.rb +128 -0
  59. data/test/multiverse/suites/agent_only/marshaling_test.rb +7 -9
  60. data/test/multiverse/suites/agent_only/script/loading.rb +20 -0
  61. data/test/multiverse/suites/agent_only/start_up_test.rb +7 -0
  62. data/test/multiverse/suites/bare/Envfile +3 -0
  63. data/test/multiverse/suites/bare/standalone_instrumentation_test.rb +43 -0
  64. data/test/multiverse/suites/rails/Envfile +0 -2
  65. data/test/multiverse/suites/rails/app/views/views/_a_partial.html.erb +1 -0
  66. data/test/multiverse/suites/rails/app/views/views/index.html.erb +1 -1
  67. data/test/multiverse/suites/rails/error_tracing_test.rb +1 -1
  68. data/test/multiverse/suites/rails/request_statistics_test.rb +9 -4
  69. data/test/multiverse/suites/rails/view_instrumentation_test.rb +111 -106
  70. data/test/multiverse/suites/typhoeus/Envfile +1 -1
  71. data/test/multiverse/suites/typhoeus/typhoeus_test.rb +16 -2
  72. data/test/multiverse/test/multiverse_test.rb +2 -2
  73. data/test/new_relic/agent/agent/connect_test.rb +1 -1
  74. data/test/new_relic/agent/agent/start_test.rb +1 -1
  75. data/test/new_relic/agent/agent/start_worker_thread_test.rb +1 -1
  76. data/test/new_relic/agent/agent_logger_test.rb +3 -7
  77. data/test/new_relic/agent/agent_test.rb +33 -57
  78. data/test/new_relic/agent/apdex_from_server_test.rb +1 -1
  79. data/test/new_relic/agent/audit_logger_test.rb +5 -8
  80. data/test/new_relic/agent/autostart_test.rb +1 -1
  81. data/test/new_relic/agent/browser_token_test.rb +1 -1
  82. data/test/new_relic/agent/busy_calculator_test.rb +2 -4
  83. data/test/new_relic/agent/commands/agent_command_router_test.rb +5 -5
  84. data/test/new_relic/agent/commands/agent_command_test.rb +1 -1
  85. data/test/new_relic/agent/commands/thread_profiler_session_test.rb +6 -6
  86. data/test/new_relic/agent/commands/xray_session_collection_test.rb +10 -10
  87. data/test/new_relic/agent/commands/xray_session_test.rb +1 -1
  88. data/test/new_relic/agent/configuration/default_source_test.rb +4 -4
  89. data/test/new_relic/agent/configuration/environment_source_test.rb +14 -2
  90. data/test/new_relic/agent/configuration/manager_test.rb +3 -3
  91. data/test/new_relic/agent/configuration/orphan_configuration_test.rb +1 -1
  92. data/test/new_relic/agent/configuration/server_source_test.rb +1 -1
  93. data/test/new_relic/agent/configuration/yaml_source_test.rb +2 -2
  94. data/test/new_relic/agent/cpu_sampler_test.rb +1 -1
  95. data/test/new_relic/agent/cross_app_monitor_test.rb +3 -3
  96. data/test/new_relic/agent/cross_app_tracing_test.rb +5 -4
  97. data/test/new_relic/agent/database_test.rb +1 -1
  98. data/test/new_relic/agent/datastores/mongo/metric_generator_test.rb +1 -1
  99. data/test/new_relic/agent/datastores/mongo/metric_translator_test.rb +1 -1
  100. data/test/new_relic/agent/datastores/mongo/obfuscator_test.rb +1 -1
  101. data/test/new_relic/agent/datastores/mongo/statement_formatter_test.rb +2 -2
  102. data/test/new_relic/agent/error_collector/notice_error_test.rb +1 -1
  103. data/test/new_relic/agent/error_collector_test.rb +5 -3
  104. data/test/new_relic/agent/event_listener_test.rb +1 -1
  105. data/test/new_relic/agent/harvester_test.rb +1 -1
  106. data/test/new_relic/agent/http_clients/uri_util_test.rb +1 -1
  107. data/test/new_relic/agent/instrumentation/action_controller_subscriber_test.rb +1 -1
  108. data/test/new_relic/agent/instrumentation/action_view_subscriber_test.rb +1 -1
  109. data/test/new_relic/agent/instrumentation/active_record_helper_test.rb +1 -1
  110. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +495 -495
  111. data/test/new_relic/agent/instrumentation/active_record_subscriber_test.rb +2 -2
  112. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +1 -1
  113. data/test/new_relic/agent/instrumentation/instrumentation_test.rb +1 -1
  114. data/test/new_relic/agent/instrumentation/metric_frame_test.rb +1 -1
  115. data/test/new_relic/agent/instrumentation/net_instrumentation_test.rb +4 -6
  116. data/test/new_relic/agent/instrumentation/queue_time_test.rb +1 -1
  117. data/test/new_relic/agent/instrumentation/rack_test.rb +1 -1
  118. data/test/new_relic/agent/instrumentation/sinatra/transaction_namer_test.rb +1 -1
  119. data/test/new_relic/agent/instrumentation/sinatra_test.rb +1 -1
  120. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +7 -7
  121. data/test/new_relic/agent/javascript_instrumentor_test.rb +47 -55
  122. data/test/new_relic/agent/memcache_instrumentation_test.rb +1 -1
  123. data/test/new_relic/agent/memory_logger_test.rb +1 -1
  124. data/test/new_relic/agent/method_interrobang_test.rb +2 -3
  125. data/test/new_relic/agent/method_tracer/class_methods/add_method_tracer_test.rb +4 -4
  126. data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +1 -1
  127. data/test/new_relic/agent/method_tracer_test.rb +6 -7
  128. data/test/new_relic/agent/method_visibility_test.rb +1 -1
  129. data/test/new_relic/agent/new_relic_service_test.rb +129 -19
  130. data/test/new_relic/agent/obfuscator_test.rb +1 -1
  131. data/test/new_relic/agent/pipe_channel_manager_test.rb +143 -145
  132. data/test/new_relic/agent/pipe_service_test.rb +2 -4
  133. data/test/new_relic/agent/request_sampler_test.rb +23 -19
  134. data/test/new_relic/agent/rpm_agent_test.rb +3 -3
  135. data/test/new_relic/agent/rules_engine_test.rb +1 -1
  136. data/test/new_relic/agent/sampled_buffer_test.rb +1 -1
  137. data/test/new_relic/agent/sampler_collection_test.rb +3 -3
  138. data/test/new_relic/agent/sampler_test.rb +1 -1
  139. data/test/new_relic/agent/shim_agent_test.rb +1 -1
  140. data/test/new_relic/agent/sql_sampler_test.rb +4 -6
  141. data/test/new_relic/agent/stats_engine/gc_profiler_test.rb +1 -1
  142. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +5 -5
  143. data/test/new_relic/agent/stats_engine/samplers_test.rb +2 -2
  144. data/test/new_relic/agent/stats_engine_test.rb +3 -3
  145. data/test/new_relic/agent/stats_hash_test.rb +2 -2
  146. data/test/new_relic/agent/stats_test.rb +1 -1
  147. data/test/new_relic/agent/threading/agent_thread_test.rb +2 -4
  148. data/test/new_relic/agent/threading/backtrace_node_test.rb +1 -1
  149. data/test/new_relic/agent/threading/backtrace_service_test.rb +5 -5
  150. data/test/new_relic/agent/threading/thread_profile_test.rb +1 -1
  151. data/test/new_relic/agent/transaction/developer_mode_sample_buffer_test.rb +1 -1
  152. data/test/new_relic/agent/transaction/force_persist_sample_buffer_test.rb +1 -1
  153. data/test/new_relic/agent/transaction/pop_test.rb +1 -1
  154. data/test/new_relic/agent/transaction/slowest_sample_buffer_test.rb +1 -1
  155. data/test/new_relic/agent/transaction/xray_sample_buffer_test.rb +1 -1
  156. data/test/new_relic/agent/transaction_interrobang_test.rb +2 -3
  157. data/test/new_relic/agent/transaction_sample_builder_test.rb +16 -14
  158. data/test/new_relic/agent/transaction_sampler_test.rb +16 -21
  159. data/test/new_relic/agent/transaction_state_test.rb +1 -1
  160. data/test/new_relic/agent/transaction_test.rb +61 -1
  161. data/test/new_relic/agent/transaction_timings_test.rb +1 -1
  162. data/test/new_relic/agent/worker_loop_test.rb +1 -1
  163. data/test/new_relic/agent_test.rb +2 -3
  164. data/test/new_relic/cli/deployments_test.rb +3 -3
  165. data/test/new_relic/coerce_test.rb +1 -1
  166. data/test/new_relic/collection_helper_test.rb +1 -1
  167. data/test/new_relic/control/class_methods_test.rb +2 -2
  168. data/test/new_relic/control/frameworks/rails_test.rb +1 -1
  169. data/test/new_relic/control_test.rb +9 -4
  170. data/test/new_relic/dependency_detection_test.rb +1 -1
  171. data/test/new_relic/dispatcher_test.rb +1 -1
  172. data/test/new_relic/environment_report_test.rb +4 -6
  173. data/test/new_relic/fake_collector.rb +1 -158
  174. data/test/new_relic/framework_test.rb +2 -1
  175. data/test/new_relic/http_client_test_cases.rb +2 -3
  176. data/test/new_relic/json_wrapper_test.rb +77 -0
  177. data/test/new_relic/language_support_test.rb +1 -1
  178. data/test/new_relic/license_test.rb +2 -2
  179. data/test/new_relic/load_test.rb +2 -8
  180. data/test/new_relic/local_environment_test.rb +1 -1
  181. data/test/new_relic/metric_data_test.rb +1 -1
  182. data/test/new_relic/metric_parser/metric_parser_test.rb +1 -1
  183. data/test/new_relic/metric_spec_test.rb +1 -1
  184. data/test/new_relic/multiverse_helpers.rb +26 -30
  185. data/test/new_relic/noticed_error_test.rb +1 -1
  186. data/test/new_relic/rack/agent_hooks_test.rb +1 -1
  187. data/test/new_relic/rack/all_test.rb +1 -1
  188. data/test/new_relic/rack/browser_monitoring_test.rb +4 -2
  189. data/test/new_relic/rack/deferred_instrumentation_test.rb +3 -5
  190. data/test/new_relic/rack/developer_mode_helper_test.rb +1 -1
  191. data/test/new_relic/rack/developer_mode_test.rb +1 -1
  192. data/test/new_relic/rack/error_collector_test.rb +8 -8
  193. data/test/new_relic/rack/transaction_reset_test.rb +35 -0
  194. data/test/new_relic/transaction_analysis/segment_summary_test.rb +2 -2
  195. data/test/new_relic/transaction_analysis_test.rb +1 -1
  196. data/test/new_relic/transaction_sample/composite_segment_test.rb +1 -1
  197. data/test/new_relic/transaction_sample/fake_segment_test.rb +2 -4
  198. data/test/new_relic/transaction_sample/segment_test.rb +3 -7
  199. data/test/new_relic/transaction_sample/summary_segment_test.rb +1 -1
  200. data/test/new_relic/transaction_sample_subtest_test.rb +1 -1
  201. data/test/new_relic/transaction_sample_test.rb +4 -6
  202. data/test/new_relic/version_number_test.rb +1 -1
  203. data/test/performance/lib/performance/instrumentation/gc_stats.rb +1 -1
  204. data/test/performance/lib/performance/json_reporter.rb +1 -1
  205. data/test/performance/suites/marshalling.rb +76 -0
  206. data/test/test_helper.rb +6 -39
  207. metadata +19 -12
  208. metadata.gz.sig +0 -0
  209. data/test/new_relic/helper_test.rb +0 -32
@@ -159,7 +159,6 @@ module NewRelic
159
159
 
160
160
  # Send fine-grained analytic data to the collector.
161
161
  def analytic_event_data(data)
162
- data = data.map { |hash| [hash] }
163
162
  invoke_remote(:analytic_event_data, @agent_id, data)
164
163
  end
165
164
 
@@ -279,15 +278,15 @@ module NewRelic
279
278
  # enough to be worth compressing, and handles any errors the
280
279
  # server may return
281
280
  def invoke_remote(method, *args)
282
- now = Time.now
281
+ start_ts = Time.now
283
282
 
284
- data, size = nil
283
+ data, size, serialize_finish_ts = nil
285
284
  begin
286
285
  data = @marshaller.dump(args)
287
- rescue JsonError
288
- @marshaller = PrubyMarshaller.new
289
- retry
286
+ rescue => e
287
+ handle_serialization_error(method, e)
290
288
  end
289
+ serialize_finish_ts = Time.now
291
290
 
292
291
  data, encoding = compress_request_if_needed(data)
293
292
  size = data.size
@@ -301,20 +300,31 @@ module NewRelic
301
300
  :encoding => encoding,
302
301
  :collector => @collector)
303
302
  @marshaller.load(decompress_response(response))
304
- rescue NewRelic::Agent::ForceRestartException => e
305
- ::NewRelic::Agent.logger.debug e.message
306
- raise
307
303
  ensure
308
- record_supportability_metrics(method, now, size)
304
+ record_supportability_metrics(method, start_ts, serialize_finish_ts, size)
305
+ end
306
+
307
+ def handle_serialization_error(method, e)
308
+ NewRelic::Agent.increment_metric("Supportability/serialization_failure")
309
+ NewRelic::Agent.increment_metric("Supportability/serialization_failure/#{method}")
310
+ msg = "Failed to serialize #{method} data using #{@marshaller.class.to_s}: #{e.inspect}"
311
+ error = SerializationError.new(msg)
312
+ error.set_backtrace(e.backtrace)
313
+ raise error
309
314
  end
310
315
 
311
- def record_supportability_metrics(method, now, size)
312
- duration = (Time.now - now).to_f
313
- NewRelic::Agent.record_metric('Supportability/invoke_remote', duration)
314
- NewRelic::Agent.record_metric('Supportability/invoke_remote/' + method.to_s, duration)
316
+ def record_supportability_metrics(method, start_ts, serialize_finish_ts, size)
317
+ serialize_time = serialize_finish_ts && (serialize_finish_ts - start_ts)
318
+ duration = (Time.now - start_ts).to_f
319
+ NewRelic::Agent.record_metric("Supportability/invoke_remote", duration)
320
+ NewRelic::Agent.record_metric("Supportability/invoke_remote/#{method.to_s}", duration)
321
+ if serialize_time
322
+ NewRelic::Agent.record_metric("Supportability/invoke_remote_serialize", serialize_time)
323
+ NewRelic::Agent.record_metric("Supportability/invoke_remote_serialize/#{method.to_s}", serialize_time)
324
+ end
315
325
  if size
316
- NewRelic::Agent.record_metric('Supportability/invoke_remote_size', size)
317
- NewRelic::Agent.record_metric('Supportability/invoke_remote_size/' + method.to_s, size)
326
+ NewRelic::Agent.record_metric("Supportability/invoke_remote_size", size)
327
+ NewRelic::Agent.record_metric("Supportability/invoke_remote_size/#{method.to_s}", size)
318
328
  end
319
329
  end
320
330
 
@@ -353,7 +363,7 @@ module NewRelic
353
363
  when Net::HTTPSuccess
354
364
  true # fall through
355
365
  when Net::HTTPUnauthorized
356
- raise LicenseException, 'Invalid license key, please contact support@newrelic.com'
366
+ raise LicenseException, 'Invalid license key, please visit support.newrelic.com'
357
367
  when Net::HTTPServiceUnavailable
358
368
  raise ServerConnectionException, "Service unavailable (#{response.code}): #{response.message}"
359
369
  when Net::HTTPGatewayTimeOut
@@ -416,7 +426,9 @@ module NewRelic
416
426
 
417
427
  module Base64CompressedJSON
418
428
  def self.encode(data)
419
- Base64.encode64(Compressed.encode(JSON.dump(data)))
429
+ json = ::NewRelic::JSONWrapper.dump(data,
430
+ :normalize => Agent.config[:normalize_json_string_encodings])
431
+ Base64.encode64(Compressed.encode(json))
420
432
  end
421
433
  end
422
434
  end
@@ -424,9 +436,6 @@ module NewRelic
424
436
  # Used to wrap errors reported to agent by the collector
425
437
  class CollectorError < StandardError; end
426
438
 
427
- # Used to wrap any problem with the JSON marshaller
428
- class JsonError < StandardError; end
429
-
430
439
  class Marshaller
431
440
  def parsed_error(error)
432
441
  error_class = error['error_type'].split('::') \
@@ -511,14 +520,13 @@ module NewRelic
511
520
  end
512
521
 
513
522
  def dump(ruby, opts={})
514
- JSON.dump(prepare(ruby, opts))
515
- rescue => e
516
- ::NewRelic::Agent.logger.debug "#{e.class.name} : #{e.message} encountered dumping agent data: #{ruby}"
517
- raise JsonError.new(e)
523
+ prepared = prepare(ruby, opts)
524
+ NewRelic::JSONWrapper.dump(prepared,
525
+ :normalize => Agent.config[:normalize_json_string_encodings])
518
526
  end
519
527
 
520
528
  def load(data)
521
- return_value(JSON.load(data)) if data && data != ''
529
+ return_value(NewRelic::JSONWrapper.load(data)) if data && data != ''
522
530
  rescue => e
523
531
  ::NewRelic::Agent.logger.debug "#{e.class.name} : #{e.message} encountered loading collector response: #{data}"
524
532
  raise
@@ -533,7 +541,7 @@ module NewRelic
533
541
  end
534
542
 
535
543
  def self.is_supported?
536
- NewRelic::LanguageSupport.stdlib_json_usable?
544
+ NewRelic::JSONWrapper.usable_for_collector_serialization?
537
545
  end
538
546
 
539
547
  def self.human_readable?
@@ -12,9 +12,6 @@ class NewRelic::Agent::RequestSampler
12
12
  include NewRelic::Coerce,
13
13
  MonitorMixin
14
14
 
15
- # The namespace and keys of config values
16
- ENABLED_KEY = :'analytics_events.enabled'
17
-
18
15
  # The type field of the sample
19
16
  SAMPLE_TYPE = 'Transaction'
20
17
 
@@ -102,7 +99,7 @@ class NewRelic::Agent::RequestSampler
102
99
  self.reset!
103
100
  end
104
101
 
105
- NewRelic::Agent.config.register_callback(ENABLED_KEY) do |enabled|
102
+ NewRelic::Agent.config.register_callback(:'analytics_events.enabled') do |enabled|
106
103
  NewRelic::Agent.logger.info "%sabling the Request Sampler." % [ enabled ? 'En' : 'Dis' ]
107
104
  @enabled = enabled
108
105
  end
@@ -117,20 +114,30 @@ class NewRelic::Agent::RequestSampler
117
114
  def on_transaction_finished(payload)
118
115
  return unless @enabled
119
116
  return unless NewRelic::Agent::Transaction.transaction_type_is_web?(payload[:type])
120
- # The order in which these are merged is important. We want to ensure that
121
- # custom parameters can't override required fields (e.g. type)
122
- sample = {}
123
- if ::NewRelic::Agent.config[:'capture_attributes.transaction_events']
124
- sample.merge!(event_params(payload[:custom_params] || {}))
125
- end
126
- sample.merge!(payload[:overview_metrics] || {})
117
+
118
+ main_event = create_main_event(payload)
119
+ custom_params = create_custom_parameters(payload)
120
+
121
+ is_full = self.synchronize { @samples.append([main_event, custom_params]) }
122
+ notify_full if is_full && !@notified_full
123
+ end
124
+
125
+ def create_main_event(payload)
126
+ sample = payload[:overview_metrics] || {}
127
127
  sample.merge!({
128
128
  TIMESTAMP_KEY => float(payload[:start_timestamp]),
129
129
  NAME_KEY => string(payload[:name]),
130
130
  DURATION_KEY => float(payload[:duration]),
131
131
  TYPE_KEY => SAMPLE_TYPE,
132
132
  })
133
- is_full = self.synchronize { @samples.append(sample) }
134
- notify_full if is_full && !@notified_full
135
133
  end
134
+
135
+ def create_custom_parameters(payload)
136
+ custom_params = {}
137
+ if ::NewRelic::Agent.config[:'analytics_events.capture_attributes']
138
+ custom_params.merge!(event_params(payload[:custom_params] || {}))
139
+ end
140
+ custom_params
141
+ end
142
+
136
143
  end
@@ -16,6 +16,10 @@ module NewRelic
16
16
  @samplers.each(&blk)
17
17
  end
18
18
 
19
+ def clear()
20
+ @samplers.clear
21
+ end
22
+
19
23
  def sampler_class_registered?(sampler_class)
20
24
  self.any? { |s| s.class == sampler_class }
21
25
  end
@@ -38,9 +38,9 @@ module NewRelic
38
38
  Hash[self] == Hash[other]
39
39
  end
40
40
 
41
- class CorruptedDefaultProcError < NewRelic::Agent::InternalAgentError
42
- def initialize(hash, metric_spec)
43
- super("Corrupted default proc for StatsHash. Falling back adding #{metric_spec.inspect}")
41
+ class StatsHashLookupError < NewRelic::Agent::InternalAgentError
42
+ def initialize(original_error, hash, metric_spec)
43
+ super("Lookup error in StatsHash: #{original_error.class}: #{original_error.message}. Falling back adding #{metric_spec.inspect}")
44
44
  end
45
45
  end
46
46
 
@@ -53,7 +53,7 @@ module NewRelic
53
53
  # This only happen in the case of a corrupted default_proc
54
54
  # Side-step it manually, notice the issue, and carry on....
55
55
  NewRelic::Agent.instance.error_collector. \
56
- notice_agent_error(CorruptedDefaultProcError.new(self, metric_spec))
56
+ notice_agent_error(StatsHashLookupError.new(e, self, metric_spec))
57
57
 
58
58
  stats = NewRelic::Agent::Stats.new
59
59
  self[metric_spec] = stats
@@ -21,20 +21,8 @@ module NewRelic
21
21
  when /darwin/, /freebsd/
22
22
  `sysctl -n hw.ncpu`.to_i
23
23
  when /linux/
24
- cpuinfo = ''
25
- proc_file = '/proc/cpuinfo'
26
- File.open(proc_file) do |f|
27
- loop do
28
- begin
29
- cpuinfo << f.read_nonblock(4096).strip
30
- rescue EOFError
31
- break
32
- rescue Errno::EWOULDBLOCK, Errno::EAGAIN
33
- cpuinfo = ''
34
- break # don't select file handle, just give up
35
- end
36
- end
37
- end
24
+ cpuinfo = proc_try_read('/proc/cpuinfo')
25
+ return unless cpuinfo
38
26
  processors = cpuinfo.split("\n").select {|line| line =~ /^processor\s*:/ }.size
39
27
  processors == 0 ? nil : processors
40
28
  end
@@ -47,7 +35,29 @@ module NewRelic
47
35
  end
48
36
 
49
37
  def self.os_version
50
- `uname -v` rescue nil
38
+ proc_try_read('/proc/version')
39
+ end
40
+
41
+ # A File.read against /(proc|sysfs)/* can hang with some older Linuxes.
42
+ # See https://bugzilla.redhat.com/show_bug.cgi?id=604887, RUBY-736, and
43
+ # https://github.com/opscode/ohai/commit/518d56a6cb7d021b47ed3d691ecf7fba7f74a6a7
44
+ # for details on why we do it this way.
45
+ def self.proc_try_read(path)
46
+ return nil unless File.exist?(path)
47
+ content = ''
48
+ File.open(path) do |f|
49
+ loop do
50
+ begin
51
+ content << f.read_nonblock(4096)
52
+ rescue EOFError
53
+ break
54
+ rescue Errno::EWOULDBLOCK, Errno::EAGAIN
55
+ content = nil
56
+ break # don't select file handle, just give up
57
+ end
58
+ end
59
+ end
60
+ content
51
61
  end
52
62
  end
53
63
  end
@@ -262,16 +262,35 @@ module NewRelic
262
262
  # Anything left over is treated as custom params
263
263
 
264
264
  def self.notice_error(e, options={})
265
+ options = extract_request_options(options)
266
+ if current
267
+ current.notice_error(e, options)
268
+ else
269
+ options = extract_finished_transaction_options(options)
270
+ agent.error_collector.notice_error(e, options)
271
+ end
272
+ end
273
+
274
+ def self.extract_request_options(options)
265
275
  request = options.delete(:request)
266
276
  if request
267
277
  options[:referer] = referer_from_request(request)
268
278
  options[:uri] = uri_from_request(request)
269
279
  end
270
- if current
271
- current.notice_error(e, options)
272
- else
273
- agent.error_collector.notice_error(e, options)
280
+ options
281
+ end
282
+
283
+ # If we aren't currently in a transaction, but found the remains of one
284
+ # just finished in the TransactionState, use those custom params!
285
+ def self.extract_finished_transaction_options(options)
286
+ finished_txn = NewRelic::Agent::TransactionState.get.transaction
287
+ if finished_txn
288
+ custom_params = options.fetch(:custom_params, {})
289
+ custom_params.merge!(finished_txn.custom_parameters)
290
+ options = options.merge(:custom_params => custom_params)
291
+ options[:metric] = finished_txn.name
274
292
  end
293
+ options
275
294
  end
276
295
 
277
296
  # Do not call this. Invoke the class method instead.
@@ -93,7 +93,7 @@ module NewRelic
93
93
  end
94
94
 
95
95
  def custom_parameters_from_transaction(txn)
96
- if Agent.config[:'capture_attributes.traces']
96
+ if Agent.config[:'transaction_tracer.capture_attributes']
97
97
  txn.custom_parameters
98
98
  else
99
99
  {}
@@ -57,7 +57,7 @@ you receive upon registration.
57
57
  EOF
58
58
  puts <<-EOF unless quiet
59
59
 
60
- E-mail support@newrelic.com with any problems or questions.
60
+ Visit support.newrelic.com if you are experiencing installation issues.
61
61
  EOF
62
62
 
63
63
  end
@@ -8,6 +8,7 @@ require 'conditional_vendored_dependency_detection'
8
8
  require 'new_relic/local_environment'
9
9
  require 'new_relic/language_support'
10
10
  require 'new_relic/helper'
11
+ require 'new_relic/json_wrapper'
11
12
 
12
13
  require 'singleton'
13
14
  require 'erb'
@@ -10,7 +10,7 @@ module NewRelic
10
10
 
11
11
  # confirm a string is correctly encoded (in >= 1.9)
12
12
  # If not force the encoding to ASCII-8BIT (binary)
13
- if RUBY_VERSION >= '1.9'
13
+ if NewRelic::LanguageSupport.supports_string_encodings?
14
14
  def correctly_encoded(string)
15
15
  return string unless string.is_a? String
16
16
  # The .dup here is intentional, since force_encoding mutates the target,
@@ -51,32 +51,4 @@ module NewRelic
51
51
  milliseconds / 1000.0
52
52
  end
53
53
  end
54
-
55
- # Load the JSON library from the standard library.
56
- def self::load_stdlib_json
57
- return false unless NewRelic::LanguageSupport.stdlib_json_usable?
58
-
59
- require 'json'
60
- define_method( :json_dump, &::JSON.method(:dump) )
61
- define_method( :json_load, &::JSON.method(:parse) )
62
-
63
- return true
64
- rescue LoadError
65
- NewRelic::Agent.logger.debug "%p while loading JSON library: %s" % [ err, err.message ] if
66
- defined?( NewRelic::Agent ) && NewRelic::Agent.respond_to?( :logger )
67
- return false
68
- end
69
-
70
-
71
- # Load the fallback JSON library
72
- def self::load_okjson
73
- require 'new_relic/okjson'
74
- define_method( :json_dump, &::NewRelic::OkJson.method(:encode) )
75
- define_method( :json_load, &::NewRelic::OkJson.method(:decode) )
76
- end
77
-
78
-
79
- load_stdlib_json or load_okjson
80
- module_function :json_dump, :json_load
81
-
82
54
  end
@@ -0,0 +1,92 @@
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
+ class JSONWrapper
7
+ def self.load_stdlib_json
8
+ return false unless NewRelic::LanguageSupport.stdlib_json_usable?
9
+
10
+ begin
11
+ require 'json'
12
+ @load_method = ::JSON.method(:load)
13
+ @dump_method = ::JSON.method(:dump)
14
+ @backend_name = :json
15
+ return true
16
+ rescue
17
+ NewRelic::Agent.logger.debug "%p while loading JSON library: %s" % [ err, err.message ] if
18
+ defined?( NewRelic::Agent ) && NewRelic::Agent.respond_to?( :logger )
19
+ end
20
+ end
21
+
22
+ def self.load_okjson
23
+ require 'new_relic/okjson'
24
+ @load_method = ::NewRelic::OkJson.method(:decode)
25
+ @dump_method = ::NewRelic::OkJson.method(:encode)
26
+ @backend_name = :okjson
27
+ end
28
+
29
+ load_stdlib_json or load_okjson
30
+
31
+ def self.usable_for_collector_serialization?
32
+ @backend_name == :json
33
+ end
34
+
35
+ def self.normalize_string(s)
36
+ encoding = s.encoding
37
+ if (encoding == Encoding::UTF_8 || encoding == Encoding::ISO_8859_1) && s.valid_encoding?
38
+ return s
39
+ end
40
+
41
+ # If the encoding is not valid, or it's ASCII-8BIT, we know conversion to
42
+ # UTF-8 is likely to fail, so treat it as ISO-8859-1 (byte-preserving).
43
+ normalized = s.dup
44
+ if encoding == Encoding::ASCII_8BIT || !s.valid_encoding?
45
+ normalized.force_encoding(Encoding::ISO_8859_1)
46
+ else
47
+ # Encoding is valid and non-binary, so it might be cleanly convertible
48
+ # to UTF-8. Give it a try and fall back to ISO-8859-1 if it fails.
49
+ begin
50
+ normalized.encode!(Encoding::UTF_8)
51
+ rescue
52
+ normalized.force_encoding(Encoding::ISO_8859_1)
53
+ end
54
+ end
55
+ normalized
56
+ end
57
+
58
+ def self.normalize(object)
59
+ case object
60
+ when String
61
+ normalize_string(object)
62
+ when Array
63
+ return object if object.empty?
64
+ result = object.map { |x| normalize(x) }
65
+ result
66
+ when Hash
67
+ return object if object.empty?
68
+ hash = {}
69
+ object.each_pair do |k, v|
70
+ k = normalize_string(k) if k.is_a?(String)
71
+ hash[k] = normalize(v)
72
+ end
73
+ hash
74
+ else
75
+ object
76
+ end
77
+ end
78
+
79
+ def self.supports_normalization?
80
+ NewRelic::LanguageSupport.supports_string_encodings?
81
+ end
82
+
83
+ def self.dump(object, options={})
84
+ object = normalize(object) if options[:normalize]
85
+ @dump_method.call(object)
86
+ end
87
+
88
+ def self.load(string)
89
+ @load_method.call(string)
90
+ end
91
+ end
92
+ end