class Airbrake::Truncator

This class is responsible for truncation of too big objects. Mainly, you should use it for simple objects such as strings, hashes, & arrays.

@api private @since v1.0.0

Constants

CIRCULAR

@return [String] what to append when something is a circular reference

CIRCULAR_TYPES

@return [Array<Class>] The types that can contain references to itself

ENCODING_OPTIONS

@return [Hash] the options for +String#encode+

SUPPORTED_ENCODINGS

@return [Array<Encoding>] encodings that are eligible for fixing invalid

characters
TEMP_ENCODING

@return [String] the temporary encoding to be used when fixing invalid

strings with +ENCODING_OPTIONS+
TRUNCATED

@return [String] what to append when something is truncated

Public Class Methods

new(max_size) click to toggle source

@param [Integer] max_size maximum size of hashes, arrays and strings

# File lib/airbrake-ruby/truncator.rb, line 29
def initialize(max_size)
  @max_size = max_size
end

Public Instance Methods

reduce_max_size() click to toggle source

Reduces maximum allowed size of hashes, arrays, sets & strings by half. @return [Integer] current max_size value

# File lib/airbrake-ruby/truncator.rb, line 50
def reduce_max_size
  @max_size /= 2
end
truncate(object, seen = Set.new) click to toggle source

Performs deep truncation of arrays, hashes, sets & strings. Uses a placeholder for recursive objects (‘[Circular]`).

@param [Object] object The object to truncate @param [Set] seen The cache that helps to detect recursion @return [Object] truncated object

# File lib/airbrake-ruby/truncator.rb, line 39
def truncate(object, seen = Set.new)
  if seen.include?(object.object_id)
    return CIRCULAR if CIRCULAR_TYPES.any? { |t| object.is_a?(t) }

    return object
  end
  truncate_object(object, seen << object.object_id)
end

Private Instance Methods

replace_invalid_characters(str) click to toggle source

Replaces invalid characters in a string with arbitrary encoding.

@param [String] str The string to replace characters @return [String] a UTF-8 encoded string @see github.com/flori/json/commit/3e158410e81f94dbbc3da6b7b35f4f64983aa4e3

# File lib/airbrake-ruby/truncator.rb, line 112
def replace_invalid_characters(str)
  utf8_string = SUPPORTED_ENCODINGS.include?(str.encoding)
  return str if utf8_string && str.valid_encoding?

  temp_str = str.dup
  temp_str.encode!(TEMP_ENCODING, **ENCODING_OPTIONS) if utf8_string
  temp_str.encode!('utf-8', **ENCODING_OPTIONS)
end
stringify_object(object) click to toggle source
# File lib/airbrake-ruby/truncator.rb, line 75
def stringify_object(object)
  object.to_json
rescue *Notice::JSON_EXCEPTIONS
  object.to_s
end
truncate_array(array, seen) click to toggle source
# File lib/airbrake-ruby/truncator.rb, line 92
def truncate_array(array, seen)
  array.slice(0, @max_size).map! { |elem| truncate(elem, seen) }.freeze
end
truncate_hash(hash, seen) click to toggle source
# File lib/airbrake-ruby/truncator.rb, line 81
def truncate_hash(hash, seen)
  truncated_hash = {}
  hash.each_with_index do |(key, val), idx|
    break if idx + 1 > @max_size

    truncated_hash[key] = truncate(val, seen)
  end

  truncated_hash.freeze
end
truncate_object(object, seen) click to toggle source
# File lib/airbrake-ruby/truncator.rb, line 56
def truncate_object(object, seen)
  case object
  when Hash then truncate_hash(object, seen)
  when Array then truncate_array(object, seen)
  when Set then truncate_set(object, seen)
  when String then truncate_string(object)
  when Numeric, TrueClass, FalseClass, Symbol, NilClass then object
  else
    truncate_string(stringify_object(object))
  end
end
truncate_set(set, seen) click to toggle source
# File lib/airbrake-ruby/truncator.rb, line 96
def truncate_set(set, seen)
  truncated_set = Set.new

  set.each do |elem|
    truncated_set << truncate(elem, seen)
    break if truncated_set.size >= @max_size
  end

  truncated_set.freeze
end
truncate_string(str) click to toggle source
# File lib/airbrake-ruby/truncator.rb, line 68
def truncate_string(str)
  fixed_str = replace_invalid_characters(str)
  return fixed_str if fixed_str.length <= @max_size

  (fixed_str.slice(0, @max_size) + TRUNCATED).freeze
end