require "logstash/filters/base"

gem "jls-grok", ">=0.2.3071"
require "grok" # rubygem 'jls-grok'

class LogStash::Filters::Grok < LogStash::Filters::Base
  def initialize(config = {})
    super

    @grokpiles = {}
  end # def initialize

  def register
    # TODO(sissel): Make patterns files come from the config
    @config.each do |type, typeconfig|
      @logger.debug("Registering type with grok: #{type}")
      pile = Grok::Pile.new
      patterndir = "#{File.dirname(__FILE__)}/../../../patterns/*"
      Dir.glob(patterndir).each do |path|
        pile.add_patterns_from_file(path)
      end
      typeconfig["patterns"].each do |pattern|
        groks = pile.compile(pattern)
        @logger.debug(["Compiled pattern", pattern, groks[-1].expanded_pattern])
      end
      @grokpiles[type] = pile
    end # @config.each
  end # def register

  def filter(event)
    # parse it with grok
    message = event.message
    match = false

    if event.type
      if @grokpiles.include?(event.type)
        @logger.debug(["Running grok filter", event])
        pile = @grokpiles[event.type]
        grok, match = pile.match(message)
      end # @grokpiles.include?(event.type)
      # TODO(2.0): support grok pattern discovery
    else
      @logger.info("Unknown type for #{event.source} (type: #{event.type})")
      @logger.debug(event.to_hash)
    end

    if match
      match.each_capture do |key, value|
        if key.include?(":")
          key = key.split(":")[1]
        end
        if event.message == value
          # Skip patterns that match the entire line
          @logger.debug("Skipping capture '#{key}' since it matches the whole line.")
          next
        end

        if event.fields[key].is_a?(String)
          event.fields[key] = [event.fields[key]]
        elsif event.fields[key] == nil
          event.fields[key] = []
        end

        event.fields[key] << value
      end
    else
      # Tag this event if we can't parse it. We can use this later to
      # reparse+reindex logs if we improve the patterns given .
      event.tags << "_grokparsefailure"
    end

    @logger.debug(["Event now: ", event.to_hash])
  end # def filter
end # class LogStash::Filters::Grok