newrelic_rpm 3.13.2.302 → 3.14.0.305

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +20 -0
  3. data/README.md +1 -13
  4. data/lib/new_relic/agent/agent.rb +40 -15
  5. data/lib/new_relic/agent/agent_logger.rb +1 -1
  6. data/lib/new_relic/agent/configuration/default_source.rb +16 -6
  7. data/lib/new_relic/agent/configuration/server_source.rb +2 -1
  8. data/lib/new_relic/agent/error_collector.rb +13 -21
  9. data/lib/new_relic/agent/error_event_aggregator.rb +124 -0
  10. data/lib/new_relic/agent/error_trace_aggregator.rb +15 -5
  11. data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +16 -2
  12. data/lib/new_relic/agent/new_relic_service.rb +11 -10
  13. data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +1 -1
  14. data/lib/new_relic/agent/payload_metric_mapping.rb +58 -0
  15. data/lib/new_relic/agent/sampled_buffer.rb +15 -1
  16. data/lib/new_relic/agent/supported_versions.rb +4 -4
  17. data/lib/new_relic/agent/transaction.rb +52 -44
  18. data/lib/new_relic/agent/transaction/request_attributes.rb +110 -0
  19. data/lib/new_relic/agent/transaction_event_aggregator.rb +4 -41
  20. data/lib/new_relic/noticed_error.rb +25 -9
  21. data/lib/new_relic/rack/agent_middleware.rb +5 -0
  22. data/lib/new_relic/version.rb +2 -2
  23. data/newrelic_rpm.gemspec +6 -0
  24. data/test/agent_helper.rb +16 -7
  25. data/test/environments/norails/Gemfile +1 -0
  26. data/test/multiverse/lib/multiverse/runner.rb +1 -1
  27. data/test/multiverse/lib/multiverse/suite.rb +6 -3
  28. data/test/multiverse/suites/agent_only/agent_attributes_test.rb +57 -0
  29. data/test/multiverse/suites/agent_only/audit_log_test.rb +1 -2
  30. data/test/multiverse/suites/agent_only/error_events_test.rb +82 -0
  31. data/test/multiverse/suites/agent_only/harvest_timestamps_test.rb +31 -6
  32. data/test/multiverse/suites/agent_only/logging_test.rb +2 -2
  33. data/test/multiverse/suites/agent_only/marshaling_test.rb +6 -0
  34. data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +2 -2
  35. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +0 -20
  36. data/test/multiverse/suites/grape/grape_test.rb +16 -1
  37. data/test/multiverse/suites/no_json/Envfile +12 -0
  38. data/test/multiverse/suites/no_json/config/newrelic.yml +27 -0
  39. data/test/multiverse/suites/no_json/marshal_config_test.rb +22 -0
  40. data/test/multiverse/suites/rack/example_app.rb +19 -0
  41. data/test/multiverse/suites/rack/response_content_type_test.rb +50 -0
  42. data/test/multiverse/suites/rails/error_tracing_test.rb +12 -7
  43. data/test/multiverse/suites/rails/parameter_capture_test.rb +21 -1
  44. data/test/multiverse/suites/sinatra/sinatra_error_tracing_test.rb +5 -2
  45. data/test/multiverse/suites/sinatra/sinatra_parameter_capture_test.rb +16 -1
  46. data/test/multiverse/suites/sinatra/sinatra_test_cases.rb +4 -2
  47. data/test/new_relic/agent/agent_logger_test.rb +9 -0
  48. data/test/new_relic/agent/agent_test.rb +6 -4
  49. data/test/new_relic/agent/audit_logger_test.rb +0 -7
  50. data/test/new_relic/agent/error_collector_test.rb +20 -250
  51. data/test/new_relic/agent/error_event_aggregator_test.rb +294 -0
  52. data/test/new_relic/agent/error_trace_aggregator_test.rb +273 -5
  53. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +2 -2
  54. data/test/new_relic/agent/new_relic_service_test.rb +8 -32
  55. data/test/new_relic/agent/payload_metric_mapping_test.rb +74 -0
  56. data/test/new_relic/agent/pipe_channel_manager_test.rb +6 -5
  57. data/test/new_relic/agent/sampled_buffer_test.rb +36 -0
  58. data/test/new_relic/agent/sql_sampler_test.rb +4 -14
  59. data/test/new_relic/agent/stats_engine/stats_hash_test.rb +5 -4
  60. data/test/new_relic/agent/threading/thread_profile_test.rb +1 -2
  61. data/test/new_relic/agent/transaction/request_attributes_test.rb +76 -0
  62. data/test/new_relic/agent/transaction_event_aggregator_test.rb +12 -1
  63. data/test/new_relic/agent/transaction_test.rb +60 -11
  64. data/test/new_relic/data_container_tests.rb +17 -6
  65. data/test/new_relic/fake_collector.rb +16 -21
  66. data/test/new_relic/marshalling_test_cases.rb +1 -0
  67. data/test/new_relic/noticed_error_test.rb +59 -0
  68. data/test/new_relic/rack/agent_hooks_test.rb +1 -1
  69. data/test/new_relic/rack/error_collector_test.rb +7 -5
  70. data/test/performance/suites/error_collector.rb +28 -0
  71. data/test/performance/suites/marshalling.rb +0 -8
  72. metadata +14 -3
  73. data/lib/new_relic/agent/new_relic_service/pruby_marshaller.rb +0 -56
@@ -7,6 +7,7 @@ require 'monitor'
7
7
 
8
8
  require 'newrelic_rpm' unless defined?( NewRelic )
9
9
  require 'new_relic/agent' unless defined?( NewRelic::Agent )
10
+ require 'new_relic/agent/payload_metric_mapping'
10
11
 
11
12
  class NewRelic::Agent::TransactionEventAggregator
12
13
  include NewRelic::Coerce,
@@ -20,6 +21,7 @@ class NewRelic::Agent::TransactionEventAggregator
20
21
  TIMESTAMP_KEY = 'timestamp'.freeze
21
22
  NAME_KEY = 'name'.freeze
22
23
  DURATION_KEY = 'duration'.freeze
24
+ ERROR_KEY = 'error'.freeze
23
25
  GUID_KEY = 'nr.guid'.freeze
24
26
  REFERRING_TRANSACTION_GUID_KEY = 'nr.referringTransactionGuid'.freeze
25
27
  CAT_TRIP_ID_KEY = 'nr.tripId'.freeze
@@ -170,54 +172,15 @@ class NewRelic::Agent::TransactionEventAggregator
170
172
  end
171
173
  end
172
174
 
173
- def self.map_metric(metric_name, to_add={})
174
- to_add.values.each(&:freeze)
175
-
176
- mappings = OVERVIEW_SPECS.fetch(metric_name, {})
177
- mappings.merge!(to_add)
178
-
179
- OVERVIEW_SPECS[metric_name] = mappings
180
- end
181
-
182
- OVERVIEW_SPECS = {}
183
-
184
- # All Transactions
185
- # Don't need to use the transaction-type specific metrics since this is
186
- # scoped to just one transaction, so Datastore/all has what we want.
187
- map_metric('Datastore/all', :total_call_time => "databaseDuration")
188
- map_metric('Datastore/all', :call_count => "databaseCallCount")
189
- map_metric('GC/Transaction/all', :total_call_time => "gcCumulative")
190
-
191
- # Web Metrics
192
- map_metric('WebFrontend/QueueTime', :total_call_time => "queueDuration")
193
- map_metric('External/allWeb', :total_call_time => "externalDuration")
194
- map_metric('External/allWeb', :call_count => "externalCallCount")
195
-
196
- # Background Metrics
197
- map_metric('External/allOther', :total_call_time => "externalDuration")
198
- map_metric('External/allOther', :call_count => "externalCallCount")
199
-
200
- def append_metrics(txn_metrics, sample)
201
- if txn_metrics
202
- OVERVIEW_SPECS.each do |(name, extracted_values)|
203
- if txn_metrics.has_key?(name)
204
- stat = txn_metrics[name]
205
- extracted_values.each do |value_name, key_name|
206
- sample[key_name] = stat.send(value_name)
207
- end
208
- end
209
- end
210
- end
211
- end
212
-
213
175
  def create_main_event(payload)
214
176
  sample = {
215
177
  TIMESTAMP_KEY => float(payload[:start_timestamp]),
216
178
  NAME_KEY => string(payload[:name]),
217
179
  DURATION_KEY => float(payload[:duration]),
218
180
  TYPE_KEY => SAMPLE_TYPE,
181
+ ERROR_KEY => payload[:error]
219
182
  }
220
- append_metrics(payload[:metrics], sample)
183
+ NewRelic::Agent::PayloadMetricMapping.append_mapped_metrics(payload[:metrics], sample)
221
184
  optionally_append(GUID_KEY, :guid, sample, payload)
222
185
  optionally_append(REFERRING_TRANSACTION_GUID_KEY, :referring_transaction_guid, sample, payload)
223
186
  optionally_append(CAT_TRIP_ID_KEY, :cat_trip_id, sample, payload)
@@ -10,8 +10,8 @@ class NewRelic::NoticedError
10
10
  extend NewRelic::CollectionHelper
11
11
 
12
12
  attr_accessor :path, :timestamp, :message, :exception_class_name,
13
- :request_uri, :file_name, :line_number, :stack_trace,
14
- :attributes_from_notice_error, :attributes
13
+ :request_uri, :request_port, :file_name, :line_number,
14
+ :stack_trace, :attributes_from_notice_error, :attributes
15
15
 
16
16
  attr_reader :exception_id, :is_internal
17
17
 
@@ -86,7 +86,7 @@ class NewRelic::NoticedError
86
86
  string(path),
87
87
  string(message),
88
88
  string(exception_class_name),
89
- build_params ]
89
+ processed_attributes ]
90
90
  end
91
91
 
92
92
  USER_ATTRIBUTES = "userAttributes".freeze
@@ -97,12 +97,17 @@ class NewRelic::NoticedError
97
97
 
98
98
  DESTINATION = NewRelic::Agent::AttributeFilter::DST_ERROR_COLLECTOR
99
99
 
100
- def build_params
101
- params = base_parameters
102
- append_attributes(params, USER_ATTRIBUTES, merged_custom_attributes)
103
- append_attributes(params, AGENT_ATTRIBUTES, build_agent_attributes)
104
- append_attributes(params, INTRINSIC_ATTRIBUTES, build_intrinsic_attributes)
105
- params
100
+ # Note that we process attributes lazily and store the result. This is because
101
+ # there is a possibility that a noticed error will be discarded and not sent back
102
+ # as a traced error or TransactionError.
103
+ def processed_attributes
104
+ @processed_attributes ||= begin
105
+ attributes = base_parameters
106
+ append_attributes(attributes, USER_ATTRIBUTES, merged_custom_attributes)
107
+ append_attributes(attributes, AGENT_ATTRIBUTES, build_agent_attributes)
108
+ append_attributes(attributes, INTRINSIC_ATTRIBUTES, build_intrinsic_attributes)
109
+ attributes
110
+ end
106
111
  end
107
112
 
108
113
  def base_parameters
@@ -161,4 +166,15 @@ class NewRelic::NoticedError
161
166
  outgoing_params[outgoing_key] = source_attributes || {}
162
167
  end
163
168
 
169
+ def agent_attributes
170
+ processed_attributes[AGENT_ATTRIBUTES]
171
+ end
172
+
173
+ def custom_attributes
174
+ processed_attributes[USER_ATTRIBUTES]
175
+ end
176
+
177
+ def intrinsic_attributes
178
+ processed_attributes[INTRINSIC_ATTRIBUTES]
179
+ end
164
180
  end
@@ -35,6 +35,11 @@ module NewRelic
35
35
  return if NewRelic::Agent.config[:disable_middleware_instrumentation]
36
36
  super
37
37
  end
38
+
39
+ def capture_response_content_type(state, result)
40
+ return if NewRelic::Agent.config[:disable_middleware_instrumentation]
41
+ super
42
+ end
38
43
  end
39
44
  end
40
45
  end
@@ -11,8 +11,8 @@ module NewRelic
11
11
  end
12
12
 
13
13
  MAJOR = 3
14
- MINOR = 13
15
- TINY = 2
14
+ MINOR = 14
15
+ TINY = 0
16
16
 
17
17
  begin
18
18
  require File.join(File.dirname(__FILE__), 'build')
@@ -56,6 +56,12 @@ EOS
56
56
  s.add_development_dependency 'rb-fsevent'
57
57
  end
58
58
 
59
+ # rack-cache ~> 1.2 is specified by actionpack 3.2, but rack-cache 1.3.1 only works on Ruby 1.9.3 & newer. :(
60
+ # https://github.com/rtomayko/rack-cache/issues/124
61
+ if RUBY_VERSION < "1.9.3"
62
+ s.add_development_dependency "rack-cache", "~> 1.2.0"
63
+ end
64
+
59
65
  # version lock down for i18n that is compatible with Ruby 1.8.7
60
66
  s.add_development_dependency 'i18n', '0.6.11'
61
67
 
@@ -26,12 +26,25 @@ def assert_in_delta(expected, actual, delta)
26
26
  assert_between((expected - delta), (expected + delta), actual)
27
27
  end
28
28
 
29
- def assert_has_error(error_class)
29
+ def harvest_error_traces!
30
+ NewRelic::Agent.instance.error_collector.error_trace_aggregator.harvest!
31
+ end
32
+
33
+ def reset_error_traces!
34
+ NewRelic::Agent.instance.error_collector.error_trace_aggregator.reset!
35
+ end
36
+
37
+ def assert_has_traced_error(error_class)
38
+ errors = harvest_error_traces!
30
39
  assert \
31
- NewRelic::Agent.instance.error_collector.errors.find {|e| e.exception_class_name == error_class.name} != nil, \
40
+ errors.find {|e| e.exception_class_name == error_class.name} != nil, \
32
41
  "Didn't find error of class #{error_class}"
33
42
  end
34
43
 
44
+ def last_traced_error
45
+ harvest_error_traces!.last
46
+ end
47
+
35
48
  unless defined?( assert_block )
36
49
  def assert_block(*msgs)
37
50
  assert yield, *msgs
@@ -81,7 +94,7 @@ end
81
94
  # orderings of the key/value pairs in Hashes that were embedded in the request
82
95
  # body). So, this method traverses an object graph and only makes assertions
83
96
  # about the terminal (non-Array-or-Hash) nodes therein.
84
- def assert_audit_log_contains_object(audit_log_contents, o, format)
97
+ def assert_audit_log_contains_object(audit_log_contents, o, format = :json)
85
98
  case o
86
99
  when Hash
87
100
  o.each do |k,v|
@@ -321,10 +334,6 @@ def refute_contains_request_params(attributes)
321
334
  end
322
335
  end
323
336
 
324
- def last_traced_error
325
- NewRelic::Agent.agent.error_collector.errors.last
326
- end
327
-
328
337
  def last_transaction_trace
329
338
  NewRelic::Agent.agent.transaction_sampler.last_sample
330
339
  end
@@ -6,6 +6,7 @@ gem 'minitest', '~>4.7.5'
6
6
  gem 'mocha', :require => false
7
7
  gem 'rack'
8
8
  gem 'rack-test'
9
+ gem 'json' if RUBY_VERSION == "1.8.7"
9
10
 
10
11
  platforms :rbx do
11
12
  gem "rubysl"
@@ -83,7 +83,7 @@ module Multiverse
83
83
 
84
84
  GROUPS = {
85
85
  "agent" => ["agent_only", "bare", "config_file_loading",
86
- "deferred_instrumentation", "high_security"],
86
+ "deferred_instrumentation", "high_security", "no_json"],
87
87
  "api" => ["grape"],
88
88
  "background" => ["delayed_job", "rake", "resque", "sidekiq"],
89
89
  "database" => ["datamapper", "mongo", "redis", "sequel"],
@@ -174,18 +174,21 @@ module Multiverse
174
174
  f.puts newrelic_gemfile_line unless gemfile_text =~ /^\s*gem .newrelic_rpm./
175
175
  f.puts jruby_openssl_line unless gemfile_text =~ /^\s*gem .jruby-openssl./ || (defined?(JRUBY_VERSION) && JRUBY_VERSION > '1.7')
176
176
  f.puts minitest_line unless gemfile_text =~ /^\s*gem .minitest[^_]./
177
+ if RUBY_VERSION == "1.8.7"
178
+ f.puts "gem 'json'" unless gemfile_text =~ /^\s.*gem .json./
179
+ end
177
180
 
178
181
  rbx_gemfile_lines(f, gemfile_text)
179
182
 
180
183
  f.puts " gem 'mocha', '0.14.0', :require => false"
181
184
 
182
185
  if debug
183
- pry_version = RUBY_VERSION >= '1.8.7' ? '0.10.0' : '0.9.12'
186
+ pry_version = RUBY_VERSION > '1.8.7' ? '0.10.0' : '0.9.12'
184
187
 
185
188
  # Pry 0.10.0 breaks compatibility with Ruby 1.8.7 :(
186
189
  f.puts " gem 'pry', '~> #{pry_version}'"
187
- f.puts " gem 'pry-byebug'" if RUBY_VERSION >= "2.0.0" && RUBY_ENGINE == "ruby"
188
- f.puts " gem 'pry-stack_explorer'" if RUBY_ENGINE == "ruby"
190
+ f.puts " gem 'pry-byebug'" if defined?(RUBY_ENGINE) && RUBY_VERSION >= "2.0.0" && RUBY_ENGINE == "ruby"
191
+ f.puts " gem 'pry-stack_explorer'" if defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby"
189
192
  end
190
193
  end
191
194
  puts yellow("Gemfile.#{env_index} set to:") if verbose?
@@ -20,6 +20,18 @@ class AgentAttributesTest < Minitest::Test
20
20
  refute_browser_monitoring_has_agent_attribute("httpResponseCode")
21
21
  end
22
22
 
23
+ def test_response_content_type_default_destinations
24
+ run_transaction do |txn|
25
+ txn.response_content_type = 'application/json'
26
+ end
27
+
28
+ assert_transaction_trace_has_agent_attribute("response.headers.contentType", "application/json")
29
+ assert_event_has_agent_attribute("response.headers.contentType", "application/json")
30
+ assert_error_has_agent_attribute("response.headers.contentType", "application/json")
31
+
32
+ refute_browser_monitoring_has_agent_attribute("response.headers.contentType")
33
+ end
34
+
23
35
  def test_request_headers_referer_default_destinations
24
36
  txn_options = {:request => stub(:referer => "referrer", :path => "/")}
25
37
  run_transaction({}, txn_options) do |txn|
@@ -55,6 +67,51 @@ class AgentAttributesTest < Minitest::Test
55
67
  refute_browser_monitoring_has_agent_attribute("request.parameters.duly")
56
68
  end
57
69
 
70
+ def test_agent_attributes_assigned_from_request
71
+ request = stub(
72
+ :path => "/",
73
+ :referer => "http://docs.newrelic.com",
74
+ :env => {"HTTP_ACCEPT" => "application/json"},
75
+ :content_length => 103,
76
+ :host => 'chippy',
77
+ :user_agent => 'Use This!',
78
+ :request_method => "GET"
79
+ )
80
+
81
+ run_transaction({}, {:request => request}) do |txn|
82
+ end
83
+
84
+ assert_error_has_agent_attribute "request.headers.referer", "http://docs.newrelic.com"
85
+ refute_transaction_trace_has_agent_attribute "request.headers.referer"
86
+ refute_event_has_agent_attribute "request.headers.referer"
87
+ refute_browser_monitoring_has_agent_attribute "request.headers.referer"
88
+
89
+ assert_transaction_trace_has_agent_attribute "request.headers.accept", "application/json"
90
+ assert_event_has_agent_attribute "request.headers.accept", "application/json"
91
+ assert_error_has_agent_attribute "request.headers.accept", "application/json"
92
+ refute_browser_monitoring_has_agent_attribute "request.headers.accept"
93
+
94
+ assert_transaction_trace_has_agent_attribute "request.headers.contentLength", 103
95
+ assert_event_has_agent_attribute "request.headers.contentLength", 103
96
+ assert_error_has_agent_attribute "request.headers.contentLength", 103
97
+ refute_browser_monitoring_has_agent_attribute "request.headers.contentLength"
98
+
99
+ assert_transaction_trace_has_agent_attribute "request.headers.host", "chippy"
100
+ assert_event_has_agent_attribute "request.headers.host", "chippy"
101
+ assert_error_has_agent_attribute "request.headers.host", "chippy"
102
+ refute_browser_monitoring_has_agent_attribute "request.headers.host"
103
+
104
+ assert_transaction_trace_has_agent_attribute "request.headers.userAgent", "Use This!"
105
+ assert_event_has_agent_attribute "request.headers.userAgent", "Use This!"
106
+ assert_error_has_agent_attribute "request.headers.userAgent", "Use This!"
107
+ refute_browser_monitoring_has_agent_attribute "request.headers.userAgent"
108
+
109
+ assert_transaction_trace_has_agent_attribute "request.method", "GET"
110
+ assert_event_has_agent_attribute "request.method", "GET"
111
+ assert_error_has_agent_attribute "request.method", "GET"
112
+ refute_browser_monitoring_has_agent_attribute "request.method"
113
+ end
114
+
58
115
  def test_custom_attributes_included
59
116
  run_transaction do
60
117
  NewRelic::Agent.add_custom_attributes(:foo => 'bar')
@@ -39,9 +39,8 @@ class AuditLogTest < Minitest::Test
39
39
  def test_logs_request_bodies_human_readably_ish
40
40
  run_agent(:'audit_log.enabled' => true) do
41
41
  perform_actions
42
- format = NewRelic::Agent::NewRelicService::JsonMarshaller.is_supported? ? :json : :pruby
43
42
  $collector.agent_data.each do |req|
44
- assert_audit_log_contains_object(audit_log_contents, req.body, format)
43
+ assert_audit_log_contains_object(audit_log_contents, req.body)
45
44
  end
46
45
  end
47
46
  end
@@ -0,0 +1,82 @@
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
+ class ErrorEventsTest < Minitest::Test
6
+ include MultiverseHelpers
7
+
8
+ setup_and_teardown_agent
9
+
10
+ def test_error_events_are_submitted
11
+ txn = generate_errors
12
+
13
+ NewRelic::Agent.agent.send(:harvest_and_send_error_event_data)
14
+
15
+ intrinsics, _, _ = last_error_event
16
+
17
+ assert_equal txn.best_name, intrinsics["transactionName"]
18
+ assert_equal "RuntimeError", intrinsics["error.class"]
19
+ assert_equal "Big Controller", intrinsics["error.message"]
20
+ assert_equal "TransactionError", intrinsics["type"]
21
+ if RUBY_VERSION == '1.8.7'
22
+ # 1.8 + JSON is finicky about comparing floats.
23
+ # If the timestamps are within 0.001 seconds, it's Good Enough.
24
+ assert_in_delta(txn.payload[:duration], intrinsics["duration"], 0.001)
25
+ else
26
+ assert_equal txn.payload[:duration], intrinsics["duration"]
27
+ end
28
+ end
29
+
30
+ def test_records_supportability_metrics
31
+ with_config :'error_collector.max_event_samples_stored' => 10 do
32
+ generate_errors 15
33
+
34
+ NewRelic::Agent.agent.send(:harvest_and_send_error_event_data)
35
+
36
+ assert_metrics_recorded({
37
+ "Supportability/Events/TransactionError/Sent" => {:call_count => 10},
38
+ "Supportability/Events/TransactionError/Seen" => {:call_count => 15}
39
+ })
40
+ end
41
+ end
42
+
43
+ def test_does_not_record_error_events_when_disabled
44
+ with_config :'error_collector.capture_events' => false do
45
+ generate_errors 5
46
+
47
+ NewRelic::Agent.agent.send(:harvest_and_send_error_event_data)
48
+ assert_equal(0, $collector.calls_for(:error_event_data).size)
49
+ end
50
+ end
51
+
52
+ def test_does_not_record_error_events_when_disabled_by_feature_gate
53
+ connect_response = {
54
+ 'agent_run_id' => 1,
55
+ 'collect_error_events' => false
56
+ }
57
+
58
+ $collector.stub('connect', connect_response)
59
+ trigger_agent_reconnect
60
+
61
+ generate_errors 5
62
+
63
+ NewRelic::Agent.agent.send(:harvest_and_send_error_event_data)
64
+ assert_equal(0, $collector.calls_for(:error_event_data).size)
65
+ end
66
+
67
+ def generate_errors num_errors = 1
68
+ in_transaction :transaction_name => "Controller/blogs/index" do |t|
69
+ num_errors.times { t.notice_error RuntimeError.new "Big Controller" }
70
+ end
71
+ end
72
+
73
+ def last_error_event
74
+ post = last_error_event_post
75
+ assert_equal(1, post.error_events.size)
76
+ post.error_events.last
77
+ end
78
+
79
+ def last_error_event_post
80
+ $collector.calls_for(:error_event_data).first
81
+ end
82
+ end
@@ -23,8 +23,15 @@ class HarvestTimestampsTest < Minitest::Test
23
23
  metric_data_post = $collector.calls_for('metric_data').first
24
24
  start_ts, end_ts = metric_data_post[1..2]
25
25
 
26
- assert_equal(t1.to_f, start_ts)
27
- assert_equal(t2.to_f, end_ts)
26
+ if RUBY_VERSION == '1.8.7'
27
+ # 1.8 + JSON is finicky about comparing floats.
28
+ # If the timestamps are within 0.001 seconds, it's Good Enough.
29
+ assert_in_delta(t1.to_f, start_ts, 0.001)
30
+ assert_in_delta(t2.to_f, end_ts, 0.001)
31
+ else
32
+ assert_equal(t1.to_f, start_ts)
33
+ assert_equal(t2.to_f, end_ts)
34
+ end
28
35
  end
29
36
 
30
37
  def test_start_timestamp_maintained_on_harvest_failure
@@ -43,8 +50,17 @@ class HarvestTimestampsTest < Minitest::Test
43
50
  trigger_metric_data_post
44
51
  second_post = last_metric_data_post
45
52
 
46
- assert_equal([t0, t1], first_post[1..2])
47
- assert_equal([t0, t2], second_post[1..2])
53
+ if RUBY_VERSION == '1.8.7'
54
+ # 1.8 + JSON is finicky about comparing floats.
55
+ # If the timestamps are within 0.001 seconds, it's Good Enough.
56
+ assert_in_delta(t0, first_post[1], 0.001)
57
+ assert_in_delta(t1, first_post[2], 0.001)
58
+ assert_in_delta(t0, second_post[1], 0.001)
59
+ assert_in_delta(t2, second_post[2], 0.001)
60
+ else
61
+ assert_equal([t0, t1], first_post[1..2])
62
+ assert_equal([t0, t2], second_post[1..2])
63
+ end
48
64
  end
49
65
 
50
66
  def test_timestamps_updated_even_if_filling_metric_id_cache_fails
@@ -65,8 +81,17 @@ class HarvestTimestampsTest < Minitest::Test
65
81
  trigger_metric_data_post
66
82
  second_post = last_metric_data_post
67
83
 
68
- assert_equal([t0, t1], first_post[1..2])
69
- assert_equal([t1, t2], second_post[1..2])
84
+ if RUBY_VERSION == '1.8.7'
85
+ # 1.8 + JSON is finicky about comparing floats.
86
+ # If the timestamps are within 0.001 seconds, it's Good Enough.
87
+ assert_in_delta(t0, first_post[1], 0.001)
88
+ assert_in_delta(t1, first_post[2], 0.001)
89
+ assert_in_delta(t1, second_post[1], 0.001)
90
+ assert_in_delta(t2, second_post[2], 0.001)
91
+ else
92
+ assert_equal([t0, t1], first_post[1..2])
93
+ assert_equal([t1, t2], second_post[1..2])
94
+ end
70
95
  end
71
96
 
72
97
  def trigger_metric_data_post