Class: LogStash::Filters::GeoIP2

Inherits:
Base
  • Object
show all
Defined in:
lib/logstash/filters/geoip2.rb

Overview

The GeoIP2 filter adds information about the geographical location of IP addresses, based on data from the Maxmind database.

Starting with version 1.3.0 of Logstash, a ‘[geoip]` field is created if the GeoIP lookup returns a latitude and longitude. The field is stored in geojson.org/geojson-spec.html[GeoJSON] format. Additionally, the default Elasticsearch template provided with the <<plugins-outputs-elasticsearch,`elasticsearch` output>> maps the `[geoip]` field to an www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-geo-point-type.html#_mapping_options[Elasticsearch geo_point].

As this field is a ‘geo_point` and it is still valid GeoJSON, you get the awesomeness of Elasticsearch’s geospatial query, facet and filter functions and the flexibility of having GeoJSON for all other applications (like Kibana’s map visualization).

This product includes GeoLite2 data created by MaxMind, available from <dev.maxmind.com/geoip/geoip2/geolite2/>.

Instance Method Summary collapse

Instance Method Details

#filter(event) ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/logstash/filters/geoip2.rb', line 147

def filter(event)
  return unless filter?(event)

  begin
    ip = event[@source]
    ip = ip.first if ip.is_a? Array
    ip_address = InetAddress.getByName(ip)
    response = @parser.city(ip_address)
    country = response.getCountry()
    subdivision = response.getMostSpecificSubdivision()
    city = response.getCity()
    postal = response.getPostal()
    location = response.getLocation()

    geo_data_hash = Hash.new()

    @fields.each do |field|
      case field
      when "city_name"
        geo_data_hash["city_name"] = city.getName()
      when "country_name"
        geo_data_hash["country_name"] = country.getName()
      when "continent_code"
        geo_data_hash["continent_code"] = response.getContinent().getCode()
      when "continent_name"
        geo_data_hash["continent_name"] = response.getContinent().getName()
      when "country_code2"
        geo_data_hash["country_code2"] = country.getIsoCode()
      when "country_code3"
        geo_data_hash["country_code3"] = country.getIsoCode()
      when "ip"
        geo_data_hash["ip"] = ip_address.getHostAddress()
      when "postal_code"
        geo_data_hash["postal_code"] = postal.getCode()
      when "dma_code"
        geo_data_hash["dma_code"] = location.getMetroCode()
      when "region_name"
        geo_data_hash["region_name"] = subdivision.getName()
      when "region_code"
        geo_data_hash["region_code"] = subdivision.getIsoCode()
      when "timezone"
        geo_data_hash["timezone"] = location.getTimeZone()
      when "location"
        geo_data_hash["location"] = [ location.getLongitude(), location.getLatitude() ]
      when "latitude"
        geo_data_hash["latitude"] = location.getLatitude()
      when "longitude"
        geo_data_hash["longitude"] = location.getLongitude()
      else
        raise Exception.new("[#{field}] is not a supported field option.")
      end
    end

  rescue com.maxmind.geoip2.exception.AddressNotFoundException => e
    @logger.debug("IP not found!", :exception => e, :field => @source, :event => event)
    event[@target] = {}
    return
  rescue java.net.UnknownHostException => e
    @logger.error("IP Field contained invalid IP address or hostname", :exception => e, :field => @source, :event => event)
    event[@target] = {}
    return
  rescue Exception => e
    @logger.error("Unknown error while looking up GeoIP data", :exception => e, :field => @source, :event => event)
    event[@target] = {}
    return
  end

  event[@target] = geo_data_hash

  filter_matched(event)
end

#registerObject



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/logstash/filters/geoip2.rb', line 124

def register
  suppress_all_warnings do
    if @database.nil?
      @database = ::Dir.glob(::File.join(::File.expand_path("../../../vendor/", ::File.dirname(__FILE__)),"GeoLite2-City.mmdb")).first

      if @database.nil? || !File.exists?(@database)
        raise "You must specify 'database => ...' in your geoip filter (I looked for '#{@database}')"
      end
    end

    @logger.info("Using geoip database", :path => @database)

    db_file = JavaIO::File.new(@database)
    begin
      @parser = DatabaseReader::Builder.new(db_file).withCache(CHMCache.new(@cache_size)).build();
    rescue Java::ComMaxmindDb::InvalidDatabaseException => e
      @logger.error("The Geoip2 MMDB database provided is invalid or corrupted.", :exception => e, :field => @source)
      raise e
    end
  end
end