Skip to content

Commit

Permalink
Merge pull request #865 from rollbar/wj-string-truncation
Browse files Browse the repository at this point in the history
Iterate more aggressive string truncation if needed
  • Loading branch information
waltjones authored May 8, 2019
2 parents 83ef1ac + ed3112c commit 7dd2d9a
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 15 deletions.
24 changes: 18 additions & 6 deletions lib/rollbar/item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,25 +106,37 @@ def dump
# Ensure all keys are strings since we can receive the payload inline or
# from an async handler job, which can be serialized.
stringified_payload = Util::Hash.deep_stringify_keys(payload)
result = Truncation.truncate(stringified_payload)
attempts = []
result = Truncation.truncate(stringified_payload, attempts)

return result unless Truncation.truncate?(result)

handle_too_large_payload(stringified_payload, result)
handle_too_large_payload(stringified_payload, result, attempts)

nil
end

def handle_too_large_payload(stringified_payload, final_payload)
original_size = Rollbar::JSON.dump(stringified_payload).bytesize
final_size = final_payload.bytesize
def handle_too_large_payload(stringified_payload, final_payload, attempts)
uuid = stringified_payload['data']['uuid']
host = stringified_payload['data'].fetch('server', {})['host']

notifier.send_failsafe("Could not send payload due to it being too large after truncating attempts. Original size: #{original_size} Final size: #{final_size}", nil, uuid, host)
notifier.send_failsafe(
too_large_payload_string(stringified_payload, final_payload, attempts),
nil,
uuid,
host
)
logger.error("[Rollbar] Payload too large to be sent for UUID #{uuid}: #{Rollbar::JSON.dump(payload)}")
end

def too_large_payload_string(stringified_payload, final_payload, attempts)
original_size = Rollbar::JSON.dump(stringified_payload).bytesize
final_size = final_payload.bytesize

'Could not send payload due to it being too large after truncating attempts. ' \
"Original size: #{original_size} Attempts: #{attempts.join(', ')} Final size: #{final_size}"
end

def ignored?
data = payload['data']

Expand Down
3 changes: 2 additions & 1 deletion lib/rollbar/truncation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ module Truncation
StringsStrategy,
MinBodyStrategy].freeze

def self.truncate(payload)
def self.truncate(payload, attempts = [])
result = nil

STRATEGIES.each do |strategy|
result = strategy.call(payload)
attempts << result.bytesize
break unless truncate?(result)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/rollbar/truncation/strings_strategy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module Truncation
class StringsStrategy
include ::Rollbar::Truncation::Mixin

STRING_THRESHOLDS = [1024, 512, 256].freeze
STRING_THRESHOLDS = [1024, 512, 256, 128, 64].freeze

def self.call(payload)
new.call(payload)
Expand Down
10 changes: 6 additions & 4 deletions spec/rollbar/item_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -750,9 +750,10 @@ def as_json(*)

it 'calls Notifier#send_failsafe and logs the error' do
original_size = Rollbar::JSON.dump(payload).bytesize
final_size = Rollbar::Truncation.truncate(payload.clone).bytesize
attempts = []
final_size = Rollbar::Truncation.truncate(payload.clone, attempts).bytesize
# final_size = original_size
rollbar_message = "Could not send payload due to it being too large after truncating attempts. Original size: #{original_size} Final size: #{final_size}"
rollbar_message = "Could not send payload due to it being too large after truncating attempts. Original size: #{original_size} Attempts: #{attempts.join(', ')} Final size: #{final_size}"
uuid = payload['data']['uuid']
host = payload['data']['server']['host']
log_message = "[Rollbar] Payload too large to be sent for UUID #{uuid}: #{Rollbar::JSON.dump(payload)}"
Expand All @@ -767,9 +768,10 @@ def as_json(*)
it 'calls Notifier#send_failsafe and logs the error' do
payload['data'].delete('server')
original_size = Rollbar::JSON.dump(payload).bytesize
final_size = Rollbar::Truncation.truncate(payload.clone).bytesize
attempts = []
final_size = Rollbar::Truncation.truncate(payload.clone, attempts).bytesize
# final_size = original_size
rollbar_message = "Could not send payload due to it being too large after truncating attempts. Original size: #{original_size} Final size: #{final_size}"
rollbar_message = "Could not send payload due to it being too large after truncating attempts. Original size: #{original_size} Attempts: #{attempts.join(', ')} Final size: #{final_size}"
uuid = payload['data']['uuid']
log_message = "[Rollbar] Payload too large to be sent for UUID #{uuid}: #{Rollbar::JSON.dump(payload)}"

Expand Down
6 changes: 3 additions & 3 deletions spec/rollbar/truncation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
context 'if truncation is not needed' do
it 'only calls RawStrategy is truncation is not needed' do
allow(described_class).to receive(:truncate?).and_return(false)
expect(Rollbar::Truncation::RawStrategy).to receive(:call).with(payload)
expect(Rollbar::Truncation::RawStrategy).to receive(:call).with(payload).and_return('')

Rollbar::Truncation.truncate(payload)
end
Expand All @@ -17,8 +17,8 @@
context 'if truncation is needed' do
it 'calls the next strategy, FramesStrategy' do
allow(described_class).to receive(:truncate?).and_return(true, false)
expect(Rollbar::Truncation::RawStrategy).to receive(:call).with(payload)
expect(Rollbar::Truncation::FramesStrategy).to receive(:call).with(payload)
expect(Rollbar::Truncation::RawStrategy).to receive(:call).with(payload).and_return('')
expect(Rollbar::Truncation::FramesStrategy).to receive(:call).with(payload).and_return('')

Rollbar::Truncation.truncate(payload)
end
Expand Down

0 comments on commit 7dd2d9a

Please sign in to comment.