newrelic_rpm 6.9.0.363 → 6.10.0.364

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +15 -0
  3. data/CHANGELOG.md +59 -5
  4. data/lib/new_relic/agent.rb +3 -2
  5. data/lib/new_relic/agent/agent.rb +2 -2
  6. data/lib/new_relic/agent/datastores/mongo.rb +1 -1
  7. data/lib/new_relic/agent/distributed_tracing/trace_context_payload.rb +1 -1
  8. data/lib/new_relic/agent/error_collector.rb +30 -11
  9. data/lib/new_relic/agent/error_event_aggregator.rb +4 -4
  10. data/lib/new_relic/agent/hostname.rb +7 -1
  11. data/lib/new_relic/agent/http_clients/abstract.rb +82 -0
  12. data/lib/new_relic/agent/http_clients/curb_wrappers.rb +24 -19
  13. data/lib/new_relic/agent/http_clients/excon_wrappers.rb +28 -13
  14. data/lib/new_relic/agent/http_clients/http_rb_wrappers.rb +17 -21
  15. data/lib/new_relic/agent/http_clients/httpclient_wrappers.rb +10 -11
  16. data/lib/new_relic/agent/http_clients/net_http_wrappers.rb +16 -4
  17. data/lib/new_relic/agent/http_clients/typhoeus_wrappers.rb +4 -6
  18. data/lib/new_relic/agent/http_clients/uri_util.rb +3 -2
  19. data/lib/new_relic/agent/instrumentation/action_cable_subscriber.rb +4 -5
  20. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +4 -0
  21. data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +11 -2
  22. data/lib/new_relic/agent/instrumentation/active_record.rb +4 -2
  23. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +7 -2
  24. data/lib/new_relic/agent/instrumentation/active_storage_subscriber.rb +8 -4
  25. data/lib/new_relic/agent/instrumentation/bunny.rb +44 -27
  26. data/lib/new_relic/agent/instrumentation/curb.rb +58 -17
  27. data/lib/new_relic/agent/instrumentation/data_mapper.rb +3 -1
  28. data/lib/new_relic/agent/instrumentation/excon/connection.rb +6 -3
  29. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +2 -1
  30. data/lib/new_relic/agent/instrumentation/http.rb +5 -2
  31. data/lib/new_relic/agent/instrumentation/httpclient.rb +4 -2
  32. data/lib/new_relic/agent/instrumentation/memcache.rb +3 -1
  33. data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +6 -2
  34. data/lib/new_relic/agent/instrumentation/mongo.rb +9 -3
  35. data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +13 -0
  36. data/lib/new_relic/agent/instrumentation/net.rb +5 -2
  37. data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +25 -1
  38. data/lib/new_relic/agent/instrumentation/redis.rb +9 -3
  39. data/lib/new_relic/agent/instrumentation/sidekiq.rb +0 -1
  40. data/lib/new_relic/agent/instrumentation/typhoeus.rb +22 -5
  41. data/lib/new_relic/agent/logging.rb +1 -1
  42. data/lib/new_relic/agent/method_tracer_helpers.rb +1 -1
  43. data/lib/new_relic/agent/noticible_error.rb +22 -0
  44. data/lib/new_relic/agent/span_event_primitive.rb +43 -32
  45. data/lib/new_relic/agent/tracer.rb +30 -15
  46. data/lib/new_relic/agent/transaction.rb +47 -43
  47. data/lib/new_relic/agent/transaction/abstract_segment.rb +26 -0
  48. data/lib/new_relic/agent/transaction/external_request_segment.rb +25 -9
  49. data/lib/new_relic/agent/transaction_error_primitive.rb +5 -3
  50. data/lib/new_relic/cli/commands/install.rb +3 -2
  51. data/lib/new_relic/noticed_error.rb +28 -9
  52. data/lib/new_relic/rack/browser_monitoring.rb +2 -1
  53. data/lib/new_relic/version.rb +1 -1
  54. data/lib/tasks/multiverse.rb +25 -0
  55. data/lib/tasks/tests.rake +1 -1
  56. data/test/agent_helper.rb +217 -64
  57. metadata +4 -3
  58. data/lib/new_relic/agent/http_clients/abstract_request.rb +0 -31
@@ -74,7 +74,7 @@ module NewRelic
74
74
  end
75
75
 
76
76
  message << COMMA
77
- message << QUOTE << TIMESTAMP_KEY << QUOTE << COLON << time.to_f.to_s
77
+ message << QUOTE << TIMESTAMP_KEY << QUOTE << COLON << (time.to_f * 1000).round.to_s
78
78
  message << CLOSING_BRACE << NEWLINE
79
79
  end
80
80
 
@@ -27,7 +27,7 @@ module NewRelic
27
27
  end
28
28
 
29
29
  begin
30
- yield
30
+ Tracer.capture_segment_error(segment) { yield }
31
31
  ensure
32
32
  segment.finish if segment
33
33
  end
@@ -0,0 +1,22 @@
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
+ # frozen_string_literal: true
5
+
6
+ module NewRelic
7
+ module Agent
8
+
9
+ # This class is used for instrumentations that have exceptions or error classes
10
+ # not derived from Ruby's usual Exception or StandardError or in situations
11
+ # where we do not have such Exception object to work with.
12
+ class NoticibleError
13
+ attr_reader :class_name, :message
14
+
15
+ def initialize class_name, message
16
+ @class_name = class_name
17
+ @message = message
18
+ end
19
+ end
20
+
21
+ end
22
+ end
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
  # This file is distributed under New Relic's license terms.
3
3
  # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+ # frozen_string_literal: true
4
5
 
5
6
  # This module builds the data structures necessary to create a Span
6
7
  # event for a segment.
@@ -15,43 +16,52 @@ module NewRelic
15
16
  extend self
16
17
 
17
18
  # Strings for static keys of the event structure
18
- ELLIPSIS = '...'.freeze
19
- TYPE_KEY = 'type'.freeze
20
- TRACE_ID_KEY = 'traceId'.freeze
21
- GUID_KEY = 'guid'.freeze
22
- PARENT_ID_KEY = 'parentId'.freeze
23
- GRANDPARENT_ID_KEY = 'grandparentId'.freeze
24
- TRANSACTION_ID_KEY = 'transactionId'.freeze
25
- SAMPLED_KEY = 'sampled'.freeze
26
- PRIORITY_KEY = 'priority'.freeze
27
- TIMESTAMP_KEY = 'timestamp'.freeze
28
- DURATION_KEY = 'duration'.freeze
29
- NAME_KEY = 'name'.freeze
30
- CATEGORY_KEY = 'category'.freeze
31
- HTTP_URL_KEY = 'http.url'.freeze
32
- HTTP_METHOD_KEY = 'http.method'.freeze
33
- COMPONENT_KEY = 'component'.freeze
34
- DB_INSTANCE_KEY = 'db.instance'.freeze
35
- DB_STATEMENT_KEY = 'db.statement'.freeze
36
- PEER_ADDRESS_KEY = 'peer.address'.freeze
37
- PEER_HOSTNAME_KEY = 'peer.hostname'.freeze
38
- SPAN_KIND_KEY = 'span.kind'.freeze
39
- ENTRY_POINT_KEY = 'nr.entryPoint'.freeze
40
- TRUSTED_PARENT_KEY = "trustedParentId".freeze
41
- TRACING_VENDORS_KEY = "tracingVendors".freeze
19
+ ELLIPSIS = '...'
20
+ TYPE_KEY = 'type'
21
+ TRACE_ID_KEY = 'traceId'
22
+ GUID_KEY = 'guid'
23
+ PARENT_ID_KEY = 'parentId'
24
+ GRANDPARENT_ID_KEY = 'grandparentId'
25
+ TRANSACTION_ID_KEY = 'transactionId'
26
+ SAMPLED_KEY = 'sampled'
27
+ PRIORITY_KEY = 'priority'
28
+ TIMESTAMP_KEY = 'timestamp'
29
+ DURATION_KEY = 'duration'
30
+ NAME_KEY = 'name'
31
+ CATEGORY_KEY = 'category'
32
+ HTTP_URL_KEY = 'http.url'
33
+ HTTP_METHOD_KEY = 'http.method'
34
+ HTTP_STATUS_CODE_KEY = 'http.statusCode'
35
+ COMPONENT_KEY = 'component'
36
+ DB_INSTANCE_KEY = 'db.instance'
37
+ DB_STATEMENT_KEY = 'db.statement'
38
+ PEER_ADDRESS_KEY = 'peer.address'
39
+ PEER_HOSTNAME_KEY = 'peer.hostname'
40
+ SPAN_KIND_KEY = 'span.kind'
41
+ ENTRY_POINT_KEY = 'nr.entryPoint'
42
+ TRUSTED_PARENT_KEY = "trustedParentId"
43
+ TRACING_VENDORS_KEY = "tracingVendors"
42
44
 
43
45
  # Strings for static values of the event structure
44
- EVENT_TYPE = 'Span'.freeze
45
- GENERIC_CATEGORY = 'generic'.freeze
46
- HTTP_CATEGORY = 'http'.freeze
47
- DATASTORE_CATEGORY = 'datastore'.freeze
48
- CLIENT = 'client'.freeze
46
+ EVENT_TYPE = 'Span'
47
+ GENERIC_CATEGORY = 'generic'
48
+ HTTP_CATEGORY = 'http'
49
+ DATASTORE_CATEGORY = 'datastore'
50
+ CLIENT = 'client'
51
+
52
+ # Builds a Hash of error attributes as well as the Span ID when
53
+ # an error is present. Otherwise, returns nil when no error present.
54
+ def error_attributes segment
55
+ return if Agent.config[:high_security] || !segment.noticed_error
56
+ segment.noticed_error.build_error_attributes
57
+ segment.noticed_error_attributes
58
+ end
49
59
 
50
60
  def for_segment segment
51
61
  intrinsics = intrinsics_for(segment)
52
62
  intrinsics[CATEGORY_KEY] = GENERIC_CATEGORY
53
63
 
54
- [intrinsics, custom_attributes(segment.attributes), NewRelic::EMPTY_HASH]
64
+ [intrinsics, custom_attributes(segment.attributes), error_attributes(segment) || NewRelic::EMPTY_HASH]
55
65
  end
56
66
 
57
67
  def for_external_request_segment segment
@@ -59,10 +69,11 @@ module NewRelic
59
69
 
60
70
  intrinsics[COMPONENT_KEY] = segment.library
61
71
  intrinsics[HTTP_METHOD_KEY] = segment.procedure
72
+ intrinsics[HTTP_STATUS_CODE_KEY] = segment.http_status_code if segment.http_status_code
62
73
  intrinsics[CATEGORY_KEY] = HTTP_CATEGORY
63
74
  intrinsics[SPAN_KIND_KEY] = CLIENT
64
75
 
65
- agent_attributes = {}
76
+ agent_attributes = error_attributes(segment) || {}
66
77
 
67
78
  if allowed?(HTTP_URL_KEY)
68
79
  agent_attributes[HTTP_URL_KEY] = truncate(segment.uri)
@@ -78,7 +89,7 @@ module NewRelic
78
89
  intrinsics[SPAN_KIND_KEY] = CLIENT
79
90
  intrinsics[CATEGORY_KEY] = DATASTORE_CATEGORY
80
91
 
81
- agent_attributes = {}
92
+ agent_attributes = error_attributes(segment) || {}
82
93
 
83
94
  if segment.database_name && allowed?(DB_INSTANCE_KEY)
84
95
  agent_attributes[DB_INSTANCE_KEY] = truncate(segment.database_name)
@@ -102,9 +102,9 @@ module NewRelic
102
102
  # only wrap the yield to be absolutely sure we don't report agent
103
103
  # problems as app errors
104
104
  yield
105
- rescue => e
106
- current_transaction.notice_error(e)
107
- raise e
105
+ rescue => exception
106
+ current_transaction.notice_error(exception)
107
+ raise
108
108
  ensure
109
109
  finishable.finish if finishable
110
110
  end
@@ -157,8 +157,8 @@ module NewRelic
157
157
 
158
158
  rescue ArgumentError
159
159
  raise
160
- rescue => e
161
- log_error('start_transaction_or_segment', e)
160
+ rescue => exception
161
+ log_error('start_transaction_or_segment', exception)
162
162
  end
163
163
 
164
164
  # Takes name or partial_name and a category.
@@ -190,8 +190,8 @@ module NewRelic
190
190
  options)
191
191
  rescue ArgumentError
192
192
  raise
193
- rescue => e
194
- log_error('start_transaction', e)
193
+ rescue => exception
194
+ log_error('start_transaction', exception)
195
195
  end
196
196
 
197
197
  def create_distributed_trace_payload
@@ -251,8 +251,8 @@ module NewRelic
251
251
 
252
252
  rescue ArgumentError
253
253
  raise
254
- rescue => e
255
- log_error('start_segment', e)
254
+ rescue => exception
255
+ log_error('start_segment', exception)
256
256
  end
257
257
 
258
258
  UNKNOWN = "Unknown".freeze
@@ -310,8 +310,8 @@ module NewRelic
310
310
 
311
311
  rescue ArgumentError
312
312
  raise
313
- rescue => e
314
- log_error('start_datastore_segment', e)
313
+ rescue => exception
314
+ log_error('start_datastore_segment', exception)
315
315
  end
316
316
 
317
317
  # Creates and starts an external request segment using the
@@ -357,8 +357,23 @@ module NewRelic
357
357
 
358
358
  rescue ArgumentError
359
359
  raise
360
- rescue => e
361
- log_error('start_external_request_segment', e)
360
+ rescue => exception
361
+ log_error('start_external_request_segment', exception)
362
+ end
363
+
364
+ # Will potentially capture and notice an error at the
365
+ # segment that was executing when error occurred.
366
+ # if passed +segment+ is something that doesn't
367
+ # respond to +notice_segment_error+ then this method
368
+ # is effectively just a yield to the given &block
369
+ def capture_segment_error segment
370
+ return unless block_given?
371
+ yield
372
+ rescue => exception
373
+ if segment && segment.is_a?(Transaction::AbstractSegment)
374
+ segment.notice_error exception
375
+ end
376
+ raise
362
377
  end
363
378
 
364
379
  # For New Relic internal use only.
@@ -390,8 +405,8 @@ module NewRelic
390
405
 
391
406
  rescue ArgumentError
392
407
  raise
393
- rescue => e
394
- log_error('start_datastore_segment', e)
408
+ rescue => exception
409
+ log_error('start_datastore_segment', exception)
395
410
  end
396
411
 
397
412
  # This method should only be used by Tracer for access to the
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
  # This file is distributed under New Relic's license terms.
3
3
  # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+ # frozen_string_literal: true
4
5
 
5
6
  require 'new_relic/agent/instrumentation/queue_time'
6
7
  require 'new_relic/agent/transaction_metrics'
@@ -23,22 +24,36 @@ module NewRelic
23
24
  include Tracing
24
25
 
25
26
  # for nested transactions
26
- SUBTRANSACTION_PREFIX = 'Nested/'.freeze
27
- CONTROLLER_PREFIX = 'Controller/'.freeze
28
- MIDDLEWARE_PREFIX = 'Middleware/Rack/'.freeze
29
- TASK_PREFIX = 'OtherTransaction/Background/'.freeze
30
- RAKE_PREFIX = 'OtherTransaction/Rake/'.freeze
31
- MESSAGE_PREFIX = 'OtherTransaction/Message/'.freeze
32
- RACK_PREFIX = 'Controller/Rack/'.freeze
33
- SINATRA_PREFIX = 'Controller/Sinatra/'.freeze
34
- GRAPE_PREFIX = 'Controller/Grape/'.freeze
35
- ACTION_CABLE_PREFIX = 'Controller/ActionCable/'.freeze
36
- OTHER_TRANSACTION_PREFIX = 'OtherTransaction/'.freeze
27
+ NESTED_TRANSACTION_PREFIX = "Nested/"
28
+ CONTROLLER_PREFIX = "Controller/"
29
+ MIDDLEWARE_PREFIX = "Middleware/Rack/"
30
+ OTHER_TRANSACTION_PREFIX = "OtherTransaction/"
31
+ TASK_PREFIX = "#{OTHER_TRANSACTION_PREFIX}Background/"
32
+ RAKE_PREFIX = "#{OTHER_TRANSACTION_PREFIX}Rake/"
33
+ MESSAGE_PREFIX = "#{OTHER_TRANSACTION_PREFIX}Message/"
34
+ RACK_PREFIX = "#{CONTROLLER_PREFIX}Rack/"
35
+ SINATRA_PREFIX = "#{CONTROLLER_PREFIX}Sinatra/"
36
+ GRAPE_PREFIX = "#{CONTROLLER_PREFIX}Grape/"
37
+ ACTION_CABLE_PREFIX = "#{CONTROLLER_PREFIX}ActionCable/"
37
38
 
38
39
  WEB_TRANSACTION_CATEGORIES = [:web, :controller, :uri, :rack, :sinatra, :grape, :middleware, :action_cable].freeze
39
40
  TRANSACTION_NAMING_SOURCES = [:child, :api].freeze
40
41
 
41
- MIDDLEWARE_SUMMARY_METRICS = ['Middleware/all'.freeze].freeze
42
+ MIDDLEWARE_SUMMARY_METRICS = ["Middleware/all"].freeze
43
+ WEB_SUMMARY_METRIC = "HttpDispatcher"
44
+ OTHER_SUMMARY_METRIC = "#{OTHER_TRANSACTION_PREFIX}all"
45
+ QUEUE_TIME_METRIC = "WebFrontend/QueueTime"
46
+
47
+ APDEX_S = "S"
48
+ APDEX_T = "T"
49
+ APDEX_F = "F"
50
+ APDEX_ALL_METRIC = "ApdexAll"
51
+ APDEX_METRIC = "Apdex"
52
+ APDEX_OTHER_METRIC = "ApdexOther"
53
+ APDEX_TXN_METRIC_PREFIX = "Apdex/"
54
+ APDEX_OTHER_TXN_METRIC_PREFIX = "ApdexOther/Transaction/"
55
+
56
+ JRUBY_CPU_TIME_ERROR = "Error calculating JRuby CPU Time"
42
57
 
43
58
  # reference to the transaction state managing this transaction
44
59
  attr_accessor :state
@@ -136,23 +151,22 @@ module NewRelic
136
151
 
137
152
  def self.nested_transaction_name(name)
138
153
  if name.start_with?(CONTROLLER_PREFIX) || name.start_with?(OTHER_TRANSACTION_PREFIX)
139
- "#{SUBTRANSACTION_PREFIX}#{name}"
154
+ "#{NESTED_TRANSACTION_PREFIX}#{name}"
140
155
  else
141
156
  name
142
157
  end
143
158
  end
144
159
 
145
- # Indicate that you don't want to keep the currently saved transaction
146
- # information
147
- def self.abort_transaction! #THREAD_LOCAL_ACCESS
148
- txn = Tracer.current_transaction
149
- txn.abort_transaction! if txn
160
+ # discards the currently saved transaction information
161
+ def self.abort_transaction!
162
+ if txn = Tracer.current_transaction
163
+ txn.abort_transaction!
164
+ end
150
165
  end
151
166
 
152
167
  # See NewRelic::Agent.notice_error for options and commentary
153
- def self.notice_error(e, options={}) #THREAD_LOCAL_ACCESS
154
- txn = Tracer.current_transaction
155
- if txn
168
+ def self.notice_error(e, options={})
169
+ if txn = Tracer.current_transaction
156
170
  txn.notice_error(e, options)
157
171
  elsif NewRelic::Agent.instance
158
172
  NewRelic::Agent.instance.error_collector.notice_error(e, options)
@@ -446,9 +460,9 @@ module NewRelic
446
460
 
447
461
  nest_initial_segment if nesting_max_depth == 1
448
462
  nested_name = self.class.nested_transaction_name options[:transaction_name]
449
- result = create_segment nested_name
463
+ segment = create_segment nested_name
450
464
  set_default_transaction_name(options[:transaction_name], category)
451
- result
465
+ segment
452
466
  end
453
467
 
454
468
  def nest_initial_segment
@@ -462,9 +476,6 @@ module NewRelic
462
476
  @ignore_trace = true
463
477
  end
464
478
 
465
- WEB_SUMMARY_METRIC = 'HttpDispatcher'.freeze
466
- OTHER_SUMMARY_METRIC = 'OtherTransaction/all'.freeze
467
-
468
479
  def summary_metrics
469
480
  if @frozen_name.start_with?(CONTROLLER_PREFIX)
470
481
  [WEB_SUMMARY_METRIC]
@@ -666,10 +677,6 @@ module NewRelic
666
677
  info[4]
667
678
  end
668
679
 
669
- APDEX_S = 'S'.freeze
670
- APDEX_T = 'T'.freeze
671
- APDEX_F = 'F'.freeze
672
-
673
680
  def append_apdex_perf_zone(payload)
674
681
  if recording_web_transaction?
675
682
  bucket = apdex_bucket(duration, apdex_t)
@@ -708,13 +715,21 @@ module NewRelic
708
715
  options[:metric] = best_name
709
716
  options[:attributes] = @attributes
710
717
 
711
- error_recorded = !!agent.error_collector.notice_error(exception, options) || error_recorded
718
+ span_id = options.delete :span_id
719
+ error_recorded = !!agent.error_collector.notice_error(exception, options, span_id) || error_recorded
712
720
  end
713
721
  payload[:error] = error_recorded if payload
714
722
  end
715
723
 
716
724
  # Do not call this. Invoke the class method instead.
717
725
  def notice_error(error, options={}) # :nodoc:
726
+
727
+ # Only the last error is kept
728
+ if @current_segment
729
+ @current_segment.notice_error error, expected: options[:expected]
730
+ options[:span_id] = @current_segment.guid
731
+ end
732
+
718
733
  if @exceptions[error]
719
734
  @exceptions[error].merge! options
720
735
  else
@@ -726,8 +741,6 @@ module NewRelic
726
741
  agent.transaction_event_recorder.record payload
727
742
  end
728
743
 
729
- QUEUE_TIME_METRIC = 'WebFrontend/QueueTime'.freeze
730
-
731
744
  def queue_time
732
745
  @apdex_start ? @start_time - @apdex_start : 0
733
746
  end
@@ -743,17 +756,9 @@ module NewRelic
743
756
  end
744
757
  end
745
758
 
746
- APDEX_ALL_METRIC = 'ApdexAll'.freeze
747
-
748
- APDEX_METRIC = 'Apdex'.freeze
749
- APDEX_OTHER_METRIC = 'ApdexOther'.freeze
750
-
751
- APDEX_TXN_METRIC_PREFIX = 'Apdex/'.freeze
752
- APDEX_OTHER_TXN_METRIC_PREFIX = 'ApdexOther/Transaction/'.freeze
753
-
754
759
  def had_error_affecting_apdex?
755
760
  @exceptions.each do |exception, options|
756
- ignored = NewRelic::Agent.instance.error_collector.error_is_ignored?(exception)
761
+ ignored = NewRelic::Agent.instance.error_collector.error_is_ignored?(exception)
757
762
  expected = options[:expected]
758
763
 
759
764
  return true unless ignored || expected
@@ -892,7 +897,6 @@ module NewRelic
892
897
  p.stime + p.utime
893
898
  end
894
899
 
895
- JRUBY_CPU_TIME_ERROR = "Error calculating JRuby CPU Time".freeze
896
900
  def jruby_cpu_time
897
901
  return nil unless @@java_classes_loaded
898
902
  threadMBean = Java::JavaLangManagement::ManagementFactory.getThreadMXBean()
@@ -23,6 +23,7 @@ module NewRelic
23
23
  attr_reader :start_time, :end_time, :duration, :exclusive_duration, :guid
24
24
  attr_accessor :name, :parent, :children_time, :transaction
25
25
  attr_writer :record_metrics, :record_scoped_metric, :record_on_finish
26
+ attr_reader :noticed_error
26
27
 
27
28
  def initialize name=nil, start_time=nil
28
29
  @name = name
@@ -42,6 +43,7 @@ module NewRelic
42
43
  @record_metrics = true
43
44
  @record_scoped_metric = true
44
45
  @record_on_finish = false
46
+ @noticed_error = nil
45
47
  end
46
48
 
47
49
  def start
@@ -119,6 +121,30 @@ module NewRelic
119
121
  def transaction_assigned
120
122
  end
121
123
 
124
+ def set_noticed_error noticed_error
125
+ if @noticed_error
126
+ NewRelic::Agent.logger.debug \
127
+ "Segment: #{name} overwriting previously noticed " \
128
+ "error: #{@noticed_error.inspect} with: #{noticed_error.inspect}"
129
+ end
130
+ @noticed_error = noticed_error
131
+ end
132
+
133
+ def notice_error exception, options={}
134
+ if Agent.config[:high_security]
135
+ NewRelic::Agent.logger.debug \
136
+ "Segment: #{name} ignores notice_error for " \
137
+ "error: #{exception.inspect} because :high_security is enabled"
138
+ else
139
+ NewRelic::Agent.instance.error_collector.notice_segment_error self, exception, options
140
+ end
141
+ end
142
+
143
+ def noticed_error_attributes
144
+ return unless @noticed_error
145
+ @noticed_error.attributes_from_notice_error
146
+ end
147
+
122
148
  protected
123
149
 
124
150
  attr_writer :range_recorded