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