How to filter nested parameters from Rails logs
Asked Answered
A

2

9

I see that I can filter keys from Rails logs here, but it's not entirely clear how I can filter a key that is nested inside the parameter hash.

My params hash looks like this:

{"download"=>{"attachment_id"=>"54039", "data"=>"data:image/png;base64,iVBORw0..."}}

Where params[:download][:data] is a base64 string. It is a large amount of data and I would like to remove it from my logs.

Is this possible?

I'm using Rails 4.0.4

Anvers answered 21/3, 2015 at 9:19 Comment(2)
did you try config.filter_parameters << {download: :data} ?Panne
That way doesn't work. It should be used in form of a string and not an hash. For this case, config.filter_parameters += ["download.data"], as it was pointed out by the accepted anwser for this questionPostfix
D
15

Simply put this in application.rb:

config.filter_parameters += [:data]

This would filter nested [:data] keys also.

In rails 5, you can define hierarchy of the key:

config.filter_parameters += ["download.data"]

This would filter all the [:data] keys which have [:download] as the immediate parent.

Danialdaniala answered 2/3, 2016 at 12:29 Comment(2)
hmm, that works fairly well, but can I specify that download must be a top level key only?Anvers
No. But in Rails 5 you can define that download should be child of a specific parent key. Details here github.com/rails/rails/pull/13897Danialdaniala
F
0

I guess the most straight-forward way is to monkeypatch Rails code for parameter filtering in your config/initializers/filter_parameter_logging.rb:

# monkeypatch to filter nested parameters
class ActionDispatch::Http::ParameterFilter::CompiledFilter
  def call(original_params, path = [])
    filtered_params = {}

    original_params.each do |key, value|
      if regexps.any? { |r| key =~ r || (path + [key]).join('/') =~ r  }
        value = ActionDispatch::Http::ParameterFilter::FILTERED
      elsif value.is_a?(Hash)
        value = call(value, path + [key])
      elsif value.is_a?(Array)
        value = value.map { |v| v.is_a?(Hash) ? call(v, path + [key]) : v }
      elsif blocks.any?
        key = key.dup
        value = value.dup if value.duplicable?
        blocks.each { |b| b.call(key, value) }
      end

      filtered_params[key] = value
    end

    filtered_params
  end
end

and then:

Rails.application.config.filter_parameters += ['download/data']

Festivity answered 28/3, 2015 at 18:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.