class LogStash::Filters::Mutate

The mutate filter allows you to do general mutations to fields. You can rename, remove, replace, and modify fields in your events.

TODO(sissel): Support regexp replacements like String#gsub ?

Public Instance Methods

filter(event) click to toggle source
# File lib/logstash/filters/mutate.rb, line 203
def filter(event)
  return unless filter?(event)

  rename(event) if @rename
  update(event) if @update
  replace(event) if @replace
  convert(event) if @convert
  gsub(event) if @gsub
  uppercase(event) if @uppercase
  lowercase(event) if @lowercase
  strip(event) if @strip
  remove(event) if @remove
  split(event) if @split
  join(event) if @join
  merge(event) if @merge

  filter_matched(event)
end
register() click to toggle source
# File lib/logstash/filters/mutate.rb, line 175
def register
  valid_conversions = %w(string integer float)
  # TODO(sissel): Validate conversion requests if provided.
  @convert.nil? or @convert.each do |field, type|
    if !valid_conversions.include?(type)
      @logger.error("Invalid conversion type",
                    "type" => type, "expected one of" => valid_types)
      # TODO(sissel): It's 2011, man, let's actually make like.. a proper
      # 'configuration broken' exception
      raise "Bad configuration, aborting."
    end
  end # @convert.each
  
  @gsub_parsed = []
  @gsub.nil? or @gsub.each_slice(3) do |field, needle, replacement|
    if [field, needle, replacement].any? {|n| n.nil?}
      @logger.error("Invalid gsub configuration. gsub has to define 3 elements per config entry", :field => field, :needle => needle, :replacement => replacement)
      raise "Bad configuration, aborting."
    end
    @gsub_parsed << {
      :field        => field,
      :needle       => Regexp.new(needle),
      :replacement  => replacement
    }
  end
end

Private Instance Methods

convert(event) click to toggle source
# File lib/logstash/filters/mutate.rb, line 254
def convert(event)
  @convert.each do |field, type|
    next unless event.include?(field)
    original = event[field]

    # calls convert_{string,integer,float} depending on type requested.
    converter = method("convert_" + type)
    if original.nil?
      next
    elsif original.is_a?(Hash)
      @logger.debug("I don't know how to type convert a hash, skipping",
                    :field => field, :value => original)
      next
    elsif original.is_a?(Array)
      value = original.map { |v| converter.call(v) }
    else
      value = converter.call(original)
    end
    event[field] = value
  end
end
convert_float(value) click to toggle source
# File lib/logstash/filters/mutate.rb, line 284
def convert_float(value)
  return value.to_f
end
convert_integer(value) click to toggle source
# File lib/logstash/filters/mutate.rb, line 280
def convert_integer(value)
  return value.to_i
end
convert_string(value) click to toggle source
# File lib/logstash/filters/mutate.rb, line 276
def convert_string(value)
  return value.to_s
end
gsub(event) click to toggle source
# File lib/logstash/filters/mutate.rb, line 289
def gsub(event)
  @gsub_parsed.each do |config|
    field = config[:field]
    needle = config[:needle]
    replacement = config[:replacement]

    if event[field].is_a?(Array)
      event[field] = event[field].map do |v|
        if not v.is_a?(String)
          @logger.warn("gsub mutation is only applicable for Strings, " +
                        "skipping", :field => field, :value => v)
          v
        else
          v.gsub(needle, replacement)
        end
      end
    else
      if not event[field].is_a?(String)
        @logger.debug("gsub mutation is only applicable for Strings, " +
                      "skipping", :field => field, :value => event[field])
        next
      end
      event[field] = event[field].gsub(needle, replacement)
    end
  end # @gsub_parsed.each
end
join(event) click to toggle source
# File lib/logstash/filters/mutate.rb, line 357
def join(event)
  @join.each do |field, separator|
    if event[field].is_a?(Array)
      event[field] = event[field].join(separator)
    end
  end
end
lowercase(event) click to toggle source
# File lib/logstash/filters/mutate.rb, line 331
def lowercase(event)
  @lowercase.each do |field|
    if event[field].is_a?(Array)
      event[field].each { |v| v.downcase! }
    elsif event[field].is_a?(String)
      event[field].downcase!
    else
      @logger.debug("Can't lowercase something that isn't a string",
                    :field => field, :value => event[field])
    end
  end
end
merge(event) click to toggle source
# File lib/logstash/filters/mutate.rb, line 377
def merge(event)
  @merge.each do |dest_field, added_fields|
    #When multiple calls, added_field is an array
    added_fields = [ added_fields ] if ! added_fields.is_a?(Array)
    added_fields.each do |added_field|
      if event[dest_field].is_a?(Hash) ^ event[added_field].is_a?(Hash)
        @logger.error("Not possible to merge an array and a hash: ",
                      :dest_field => dest_field,
                      :added_field => added_field )
        next
      end
      if event[dest_field].is_a?(Hash) #No need to test the other
        event[dest_field].update(event[added_field])
      else
        event[dest_field] = [event[dest_field]] if ! event[dest_field].is_a?(Array)
        event[added_field] = [event[added_field]] if ! event[added_field].is_a?(Array)
       event[dest_field].concat(event[added_field])
      end
    end
  end
end
remove(event) click to toggle source
# File lib/logstash/filters/mutate.rb, line 223
def remove(event)
  # TODO(sissel): use event.sprintf on the field names?
  @remove.each do |field|
    event.remove(field)
  end
end
rename(event) click to toggle source
# File lib/logstash/filters/mutate.rb, line 231
def rename(event)
  # TODO(sissel): use event.sprintf on the field names?
  @rename.each do |old, new|
    next unless event.include?(old)
    event[new] = event.remove(old)
  end
end
replace(event) click to toggle source
# File lib/logstash/filters/mutate.rb, line 248
def replace(event)
  @replace.each do |field, newvalue|
    event[field] = event.sprintf(newvalue)
  end
end
split(event) click to toggle source
# File lib/logstash/filters/mutate.rb, line 345
def split(event)
  @split.each do |field, separator|
    if event[field].is_a?(String)
      event[field] = event[field].split(separator)
    else 
      @logger.debug("Can't split something that isn't a string",
                    :field => field, :value => event[field])
    end
  end
end
strip(event) click to toggle source
# File lib/logstash/filters/mutate.rb, line 366
def strip(event)
  @strip.each do |field|
    if event[field].is_a?(Array)
      event[field] = event[field].map{|s| s.strip }
    elsif event[field].is_a?(String)
      event[field] = event[field].strip
    end
  end
end
update(event) click to toggle source
# File lib/logstash/filters/mutate.rb, line 240
def update(event)
  @update.each do |field, newvalue|
    next unless event.include?(field)
    event[field] = event.sprintf(newvalue)
  end
end
uppercase(event) click to toggle source
# File lib/logstash/filters/mutate.rb, line 317
def uppercase(event)
  @uppercase.each do |field|
    if event[field].is_a?(Array)
      event[field].each { |v| v.upcase! }
    elsif event[field].is_a?(String)
      event[field].upcase!
    else
      @logger.debug("Can't uppercase something that isn't a string",
                    :field => field, :value => event[field])
    end
  end
end