Class: Fluent::Plugin::GeoipFilter

Inherits:
Filter
  • Object
show all
Defined in:
lib/fluent/plugin/filter_geoip.rb

Constant Summary collapse

BACKEND_LIBRARIES =
[:geoip, :geoip2_compat, :geoip2_c]
REGEXP_PLACEHOLDER_SINGLE =
/^\$\{
(?<geoip_key>-?[^\[\]]+)
  \[
    (?:(?<dq>")|(?<sq>'))
      (?<record_key>-?(?(<dq>)[^"{}]+|[^'{}]+))
    (?(<dq>)"|')
  \]
\}$/x
REGEXP_PLACEHOLDER_SCAN =
/['"]?(\$\{[^\}]+?\})['"]?/
GEOIP_KEYS =
%w(city latitude longitude country_code3 country_code country_name dma_code area_code region)
GEOIP2_COMPAT_KEYS =
%w(city country_code country_name latitude longitude postal_code region region_name)

Instance Method Summary collapse

Instance Method Details

#configure(conf) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/fluent/plugin/filter_geoip.rb', line 46

def configure(conf)
  compat_parameters_convert(conf, :inject)
  super

  @map = {}
  if @geoip_lookup_key
    @geoip_lookup_keys = @geoip_lookup_key.split(/\s*,\s*/)
  end

  @geoip_lookup_keys.each do |key|
    if key.include?(".") && !key.start_with?("$")
      $log.warn("#{key} is not treated as nested attributes")
    end
  end
  @geoip_lookup_accessors = @geoip_lookup_keys.map {|key| [key, record_accessor_create(key)] }.to_h

  if conf.keys.any? {|k| k =~ /^enable_key_/ }
    raise Fluent::ConfigError, "geoip: 'enable_key_*' config format is obsoleted. use <record></record> directive instead."
  end

  # <record></record> directive
  conf.elements.select { |element| element.name == 'record' }.each { |element|
    element.each_pair { |k, v|
      element.has_key?(k) # to suppress unread configuration warning
      v = v[1..v.size-2] if quoted_value?(v)
      @map[k] = v
      validate_json = Proc.new {
        begin
          dummy_text = Yajl::Encoder.encode('dummy_text')
          Yajl::Parser.parse(v.gsub(REGEXP_PLACEHOLDER_SCAN, dummy_text))
        rescue Yajl::ParseError => e
          message = "geoip: failed to parse '#{v}' as json."
          log.error message, error: e
          raise Fluent::ConfigError, message
        end
      }
      validate_json.call if json?(v.tr('\'"\\', ''))
    }
  }

  @placeholder_keys = @map.values.join.scan(REGEXP_PLACEHOLDER_SCAN).map{|placeholder| placeholder[0] }.uniq
  @placeholder_keys.each do |key|
    m = key.match(REGEXP_PLACEHOLDER_SINGLE)
    raise Fluent::ConfigError, "Invalid placeholder attributes: #{key}" unless m
    geoip_key = m[:geoip_key]
    case @backend_library
    when :geoip
      raise Fluent::ConfigError, "#{@backend_library}: unsupported key #{geoip_key}" unless GEOIP_KEYS.include?(geoip_key)
    when :geoip2_compat
      raise Fluent::ConfigError, "#{@backend_library}: unsupported key #{geoip_key}" unless GEOIP2_COMPAT_KEYS.include?(geoip_key)
    when :geoip2_c
      # Nothing to do.
      # We cannot define supported key(s) before we fetch values from GeoIP2 database
      # because geoip2_c can fetch any fields in GeoIP2 database.
    end
  end

  @geoip = load_database
end

#filter(tag, time, record) ⇒ Object



106
107
108
109
110
111
112
113
# File 'lib/fluent/plugin/filter_geoip.rb', line 106

def filter(tag, time, record)
  filtered_record = add_geoip_field(record)
  if filtered_record
    record = filtered_record
  end
  record = inject_values_to_record(tag, time, record)
  record
end

#multi_workers_ready?Boolean

Returns:

  • (Boolean)


115
116
117
# File 'lib/fluent/plugin/filter_geoip.rb', line 115

def multi_workers_ready?
  true
end