Class: LogStruct::ParamFilters

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/log_struct/param_filters.rb

Overview

This class contains methods for filtering sensitive data in logs It is used by Formatter to determine which keys should be filtered

Class Method Summary collapse

Class Method Details

.should_filter_key?(key, value = nil) ⇒ Boolean

Check if a key should be filtered based on our defined sensitive keys

Parameters:

  • key (T.untyped)
  • value (T.untyped) (defaults to: nil)

Returns:

  • (Boolean)


18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/log_struct/param_filters.rb', line 18

def should_filter_key?(key, value = nil)
  filters = LogStruct.config.filters
  normalized_key = key.to_s
  normalized_symbol = normalized_key.downcase.to_sym

  return true if filters.filter_keys.include?(normalized_symbol)

  filters.filter_matchers.any? do |matcher|
    matcher.matches?(normalized_key, value)
  rescue => e
    handle_filter_matcher_error(e, matcher, normalized_key)
    false
  end
end

.should_include_string_hash?(key) ⇒ Boolean

Check if a key should be hashed rather than completely filtered

Parameters:

  • key (T.untyped)

Returns:

  • (Boolean)


35
36
37
# File 'lib/log_struct/param_filters.rb', line 35

def should_include_string_hash?(key)
  LogStruct.config.filters.filter_keys_with_hashes.include?(key.to_s.downcase.to_sym)
end

.summarize_array(array) ⇒ Hash{Symbol => T.untyped}

Summarize an Array for logging, including details about the size and items

Parameters:

  • array (Array<T.untyped>)

Returns:

  • (Hash{Symbol => T.untyped})


97
98
99
100
101
102
103
104
105
# File 'lib/log_struct/param_filters.rb', line 97

def summarize_array(array)
  return {_class: "Array", _empty: true} if array.empty?

  {
    _class: Array,
    _count: array.size,
    _bytes: array.to_json.bytesize
  }
end

.summarize_hash(hash) ⇒ Hash{Symbol => T.untyped}

Summarize a Hash for logging, including details about the size and keys

Parameters:

  • hash (Hash{T.untyped => T.untyped})

Returns:

  • (Hash{Symbol => T.untyped})


71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/log_struct/param_filters.rb', line 71

def summarize_hash(hash)
  return {_class: "Hash", _empty: true} if hash.empty?

  # Don't include byte size if hash contains any filtered keys
  has_sensitive_keys = T.let(false, T::Boolean)
  normalized_keys = []

  hash.each do |key, value|
    has_sensitive_keys ||= should_filter_key?(key, value)
    normalized_keys << normalize_summary_key(key)
  end

  summary = {
    _class: Hash,
    _keys_count: hash.keys.size,
    _keys: normalized_keys.take(10)
  }

  # Only add byte size if no sensitive keys are present
  summary[:_bytes] = hash.to_json.bytesize unless has_sensitive_keys

  summary
end

.summarize_json_attribute(key, data) ⇒ Hash{Symbol => T.untyped}

Convert a value to a filtered summary hash (e.g. { _filtered: { class: "String", ... }})

Parameters:

  • key (T.untyped)
  • data (T.untyped)

Returns:

  • (Hash{Symbol => T.untyped})


41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/log_struct/param_filters.rb', line 41

def summarize_json_attribute(key, data)
  case data
  when Hash
    summarize_hash(data)
  when Array
    summarize_array(data)
  when String
    summarize_string(data, should_include_string_hash?(key))
  else
    {_class: data.class}
  end
end

.summarize_string(string, include_hash) ⇒ Hash{Symbol => T.untyped}

Summarize a String for logging, including details and an SHA256 hash (if configured)

Parameters:

  • string (String)
  • include_hash (Boolean)

Returns:

  • (Hash{Symbol => T.untyped})


56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/log_struct/param_filters.rb', line 56

def summarize_string(string, include_hash)
  filtered_string = {
    _class: String
  }
  if include_hash
    filtered_string[:_hash] = HashUtils.hash_value(string)
  else
    filtered_string[:_bytes] = string.bytesize
  end

  filtered_string
end