lib/timber/util/hash.rb in timber-2.5.1 vs lib/timber/util/hash.rb in timber-2.6.0.pre.beta1

- old
+ new

@@ -1,9 +1,10 @@ module Timber module Util # @private module Hash + BINARY_LIMIT_THRESHOLD = 1_000.freeze SANITIZED_VALUE = '[sanitized]'.freeze extend self # Deeply reduces a hash into a new hash, passing the current key, value, @@ -23,18 +24,67 @@ end new_hash end - def sanitize(hash, keys_to_sanitize) + # Recursively traverses a hash, dropping non-JSON compatible types. + # If the string is a binary, and it is > 1000 characters, it is dropped. + # We are assuming it represents file contents that should not be included + # in the logs. + def jsonify(hash) + deep_reduce(hash) do |k, v, h| + if v.is_a?(String) + if v.encoding == ::Encoding::ASCII_8BIT + # Only keep binary values less than a certain size. Sizes larger than this + # are almost always file uploads and data we do not want to log. + if v.length < BINARY_LIMIT_THRESHOLD + # Attempt to safely encode the data to UTF-8 + encoded_value = encode_string(v) + if !encoded_value.nil? + h[k] = encoded_value + end + end + elsif v.encoding != ::Encoding::UTF_8 + h[k] = encode_string(v) + else + h[k] = v + end + elsif is_a_primitive_type?(v) + # Keep all other primitive types + h[k] = v + end + end + end + + # Replaces matching keys with a `[Sanitized]` value. + def sanitize_keys(hash, keys_to_sanitize) hash.each_with_object({}) do |(k, v), h| k = k.to_s.downcase if keys_to_sanitize.include?(k) h[k] = SANITIZED_VALUE else h[k] = v end end end + + private + # Attempts to encode a non UTF-8 string into UTF-8, discarding invalid characters. + # If it fails, a nil is returned. + def encode_string(string) + string.encode('UTF-8', { + :invalid => :replace, + :undef => :replace, + :replace => '?' + }) + rescue Exception + nil + end + + # We use is_a? because it accounts for inheritance. + def is_a_primitive_type?(v) + v.is_a?(Array) || v.is_a?(Integer) || v.is_a?(Float) || v.is_a?(TrueClass) || + v.is_a?(FalseClass) || v.is_a?(String) || v.is_a?(Time) + end end end end \ No newline at end of file