Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Truncate Exception Messages if needed #646

Merged
merged 3 commits into from
Dec 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Changelog
=========

## TBD

### Enhancements

* Exception messages will be truncated if they have a length greater than 3,072
| [#636](https://github.com/bugsnag/bugsnag-ruby/pull/636)
| [joshuapinter](https://github.com/joshuapinter)

## 6.18.0 (27 October 2020)

### Enhancements
Expand Down
17 changes: 15 additions & 2 deletions lib/bugsnag/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


module Bugsnag
module Helpers
module Helpers # rubocop:todo Metrics/ModuleLength
MAX_STRING_LENGTH = 3072
MAX_PAYLOAD_LENGTH = 512000
MAX_ARRAY_LENGTH = 80
Expand All @@ -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
50 changes: 47 additions & 3 deletions spec/helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,31 +41,75 @@
end

context "payload length is greater than allowed" do
it "trims exception messages" do
long_message = "should truncate" * 50000

payload = {
:events => [{
:exceptions => [{
:message => long_message,
: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

truncation_info = "[TRUNCATED]"
expected_length = Bugsnag::Helpers::MAX_STRING_LENGTH - truncation_info.length
expected_truncation = long_message[0...expected_length] + truncation_info

expect(trimmed[:events][0][:exceptions][0][:message]).to eq(expected_truncation)
expect(trimmed[:events][0][:exceptions][0][:preserved]).to eq("Foo")
end

it "trims metadata strings" do
long_message = "should truncate" * 50000

payload = {
:events => [{
:metaData => 50000.times.map {|i| "should truncate" }.join(""),
:exceptions => [],
:metaData => long_message,
: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][:metaData].length).to be <= Bugsnag::Helpers::MAX_STRING_LENGTH

truncation_info = "[TRUNCATED]"
expected_length = Bugsnag::Helpers::MAX_STRING_LENGTH - truncation_info.length
expected_truncation = long_message[0...expected_length] + truncation_info

expect(trimmed[:events][0][:metaData]).to eq(expected_truncation)
expect(trimmed[:events][0][:preserved]).to eq("Foo")
end

it "truncates metadata arrays" do
payload = {
:events => [{
:exceptions => [],
:metaData => 50000.times.map {|i| "should truncate" },
: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][:metaData].length).to be <= Bugsnag::Helpers::MAX_ARRAY_LENGTH

expected_meta_data = payload[:events][0][:metaData].take(Bugsnag::Helpers::MAX_ARRAY_LENGTH)

expect(trimmed[:events][0][:metaData]).to eq(expected_meta_data)
expect(trimmed[:events][0][:preserved]).to eq("Foo")
end

Expand Down