Skip to content

Commit

Permalink
Truncate Exception Messages if needed.
Browse files Browse the repository at this point in the history
If an exception occurs, such as a `Mysql2::Error::ConnectionError`, where the query is extremely long, this can cause the payload to exceed what Bugsnag will accept and throw a `Errno::EPIPE: Broken pipe` error when trying to send the request to Bugsnag.

A number of elements are already trimmed when the payload is too large, including meta data, stacktrace code, etc. However, the exception messages were not being trimmed.

This commit adds exception message trimming to `Bugsnag::Helpers.trim_if_needed`, which should help reduce errors when the queries causing the errors are exceptionally long.

It also adds a spec to `helper_spec.rb` that tests this functionality.
  • Loading branch information
joshuapinter committed Oct 15, 2020
1 parent fe82dca commit d9ce354
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 2 deletions.
17 changes: 15 additions & 2 deletions lib/bugsnag/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ def self.trim_if_needed(value)

return value unless payload_too_long?(value)

# Truncate exception messages
reduced_value = truncate_exception_messages(value)
return reduced_value unless payload_too_long?(reduced_value)

# Trim metadata
reduced_value = trim_metadata(value)
reduced_value = trim_metadata(reduced_value)
return reduced_value unless payload_too_long?(reduced_value)

# Trim code from stacktrace
Expand Down Expand Up @@ -71,6 +75,15 @@ def self.deep_merge!(l_hash, r_hash)

TRUNCATION_INFO = '[TRUNCATED]'

##
# Truncate exception messages
def self.truncate_exception_messages(payload)
extract_exception(payload) do |exception|
exception[:message] = trim_as_string(exception[:message])
end
payload
end

##
# Remove all code from stacktraces
def self.trim_stacktrace_code(payload)
Expand Down Expand Up @@ -98,7 +111,7 @@ def self.extract_exception(payload)
valid_payload = payload.is_a?(Hash) && payload[:events].respond_to?(:map)
return unless valid_payload && block_given?
payload[:events].each do |event|
event[:exceptions].each { |exception| yield exception }
event.fetch(:exceptions, []).each { |exception| yield exception }
end
end

Expand Down
16 changes: 16 additions & 0 deletions spec/helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@
end

context "payload length is greater than allowed" do
it "trims exception messages" do
payload = {
:events => [{
:exceptions => [{
:message => 50000.times.map {|i| "should truncate" }.join(""),
:preserved => "Foo"
}]
}]
}
expect(::JSON.dump(payload).length).to be > Bugsnag::Helpers::MAX_PAYLOAD_LENGTH
trimmed = Bugsnag::Helpers.trim_if_needed(payload)
expect(::JSON.dump(trimmed).length).to be <= Bugsnag::Helpers::MAX_PAYLOAD_LENGTH
expect(trimmed[:events][0][:exceptions][0][:message].length).to be <= Bugsnag::Helpers::MAX_STRING_LENGTH
expect(trimmed[:events][0][:exceptions][0][:preserved]).to eq("Foo")
end

it "trims metadata strings" do
payload = {
:events => [{
Expand Down

0 comments on commit d9ce354

Please sign in to comment.