class NewRelic::NoticedError
This class encapsulates an error that was noticed by New Relic in a managed app.
Constants
- AGENT_ATTRIBUTES
- AGENT_ATTRIBUTE_ERROR_GROUP
- DESTINATION
- ERROR_CLASS_KEY
- ERROR_EXPECTED_KEY
- ERROR_MESSAGE_KEY
- ERROR_PREFIX_KEY
- INTRINSIC_ATTRIBUTES
- NIL_ERROR_MESSAGE
- STRIPPED_EXCEPTION_REPLACEMENT_MESSAGE
- UNKNOWN_ERROR_CLASS_NAME
- USER_ATTRIBUTES
Attributes
Public Class Methods
Source
# File lib/new_relic/noticed_error.rb, line 37 def initialize(path, exception, timestamp = Process.clock_gettime(Process::CLOCK_REALTIME), expected = false) @exception_id = exception.object_id @path = path # It's critical that we not hold onto the exception class constant in this # class. These objects get serialized for Resque to a process that might # not have the original exception class loaded, so do all processing now # while we have the actual exception! @is_internal = (exception.class < NewRelic::Agent::InternalAgentError) extract_class_name_and_message_from(exception) @transaction_id = NewRelic::Agent::Tracer&.current_transaction&.guid # clamp long messages to 4k so that we don't send a lot of # overhead across the wire @message = @message[0..4095] if @message.length > 4096 # replace error message if enabled if NewRelic::Agent.config[:'strip_exception_messages.enabled'] && !self.class.passes_message_allowlist(exception.class) @message = STRIPPED_EXCEPTION_REPLACEMENT_MESSAGE end @attributes_from_notice_error = nil @attributes = nil @timestamp = timestamp @expected = expected end
Source
# File lib/new_relic/noticed_error.rb, line 74 def self.passes_message_allowlist(exception_class) NewRelic::Agent.config[:'strip_exception_messages.allowed_classes'].any? do |klass| exception_class <= klass end end
Public Instance Methods
Source
# File lib/new_relic/noticed_error.rb, line 66 def ==(other) if other.respond_to?(:exception_id) exception_id == other.exception_id else false end end
Source
# File lib/new_relic/noticed_error.rb, line 166 def agent_attributes processed_attributes[AGENT_ATTRIBUTES] end
Source
# File lib/new_relic/noticed_error.rb, line 162 def append_attributes(outgoing_params, outgoing_key, source_attributes) outgoing_params[outgoing_key] = source_attributes || {} end
Source
# File lib/new_relic/noticed_error.rb, line 106 def base_parameters params = {} params[:file_name] = file_name if file_name params[:line_number] = line_number if line_number params[:stack_trace] = stack_trace if stack_trace params[ERROR_EXPECTED_KEY.to_sym] = expected params end
Source
# File lib/new_relic/noticed_error.rb, line 148 def build_agent_attributes(merged_attributes) return NewRelic::EMPTY_HASH unless @attributes @attributes.agent_attributes_for(DESTINATION) end
Source
# File lib/new_relic/noticed_error.rb, line 140 def build_error_attributes @attributes_from_notice_error ||= {} @attributes_from_notice_error[ERROR_MESSAGE_KEY] = string(message) @attributes_from_notice_error[ERROR_CLASS_KEY] = string(exception_class_name) @attributes_from_notice_error[ERROR_EXPECTED_KEY] = true if expected end
Source
# File lib/new_relic/noticed_error.rb, line 154 def build_intrinsic_attributes if @attributes @attributes.intrinsic_attributes_for(DESTINATION) else NewRelic::EMPTY_HASH end end
Source
# File lib/new_relic/noticed_error.rb, line 170 def custom_attributes processed_attributes[USER_ATTRIBUTES] end
Source
# File lib/new_relic/noticed_error.rb, line 194 def error_group=(name) return if name.nil? || name.empty? if agent_attributes.frozen? processed_attributes[AGENT_ATTRIBUTES] = agent_attributes.merge(AGENT_ATTRIBUTE_ERROR_GROUP => name) else agent_attributes[AGENT_ATTRIBUTE_ERROR_GROUP] = name end @error_group = name end
Source
# File lib/new_relic/noticed_error.rb, line 178 def extract_class_name_and_message_from(exception) if exception.nil? @exception_class_name = UNKNOWN_ERROR_CLASS_NAME @message = NIL_ERROR_MESSAGE elsif exception.is_a?(NewRelic::Agent::NoticeableError) @exception_class_name = exception.class_name @message = exception.message else if defined?(Rails::VERSION::MAJOR) && Rails::VERSION::MAJOR < 5 && exception.respond_to?(:original_exception) exception = exception.original_exception || exception end @exception_class_name = exception.is_a?(Exception) ? exception.class.name : UNKNOWN_ERROR_CLASS_NAME @message = exception.to_s end end
Source
# File lib/new_relic/noticed_error.rb, line 174 def intrinsic_attributes processed_attributes[INTRINSIC_ATTRIBUTES] end
Source
# File lib/new_relic/noticed_error.rb, line 133 def merge_custom_attributes_from_notice_error(merged_attributes) if @attributes_from_notice_error from_notice_error = NewRelic::NoticedError.normalize_params(@attributes_from_notice_error) merged_attributes.merge_custom_attributes(from_notice_error) end end
Source
# File lib/new_relic/noticed_error.rb, line 126 def merge_custom_attributes_from_transaction(merged_attributes) if @attributes from_transaction = @attributes.custom_attributes_for(DESTINATION) merged_attributes.merge_custom_attributes(from_transaction) end end
Source
# File lib/new_relic/noticed_error.rb, line 119 def merged_custom_attributes(merged_attributes) merge_custom_attributes_from_transaction(merged_attributes) merge_custom_attributes_from_notice_error(merged_attributes) merged_attributes.custom_attributes_for(DESTINATION) end
We can get custom attributes from two sources–the transaction, which we hold in @attributes, or passed options to notice_error which show up in @attributes_from_notice_error. Both need filtering, so merge them together in our Attributes class for consistent handling
Source
# File lib/new_relic/noticed_error.rb, line 95 def processed_attributes @processed_attributes ||= begin attributes = base_parameters merged_attributes = NewRelic::Agent::Attributes.new(NewRelic::Agent.instance.attribute_filter) append_attributes(attributes, USER_ATTRIBUTES, merged_custom_attributes(merged_attributes)) append_attributes(attributes, AGENT_ATTRIBUTES, build_agent_attributes(merged_attributes)) append_attributes(attributes, INTRINSIC_ATTRIBUTES, build_intrinsic_attributes) attributes end end
Note that we process attributes lazily and store the result. This is because there is a possibility that a noticed error will be discarded and not sent back as a traced error or TransactionError.
Source
# File lib/new_relic/noticed_error.rb, line 82 def to_collector_array(encoder = nil) arr = [NewRelic::Helper.time_to_millis(timestamp), string(path), string(message), string(exception_class_name), processed_attributes] arr << @transaction_id if @transaction_id arr end