fluent-plugin-filter-geoip 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +118 -5
- data/fluent-plugin-filter-geoip.gemspec +1 -1
- data/lib/fluent/plugin/filter_geoip.rb +96 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 592c7a6c492a234c331d225cf58de2d35c669a03
|
4
|
+
data.tar.gz: b59b98a1889229052058739831f17ce4516df099
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d723fa0a431a2eb320b59d5012e72153ab6e59786422411c965dbfc7e43a5f566663b437eaf660caa9d30f5ad5798888aa545c04538a7d4054fbf96d0c616292
|
7
|
+
data.tar.gz: 72919a44209008f6fb1d5ca9bf7bf58fadb5f1ce5827dd87f73a89082f318096bde0da9b0409748d9ba42f9167e4cdc271f257b78ad83a1a72d9dc71eb697cf3
|
data/README.md
CHANGED
@@ -7,7 +7,7 @@ This is a [Fluentd](http://fluentd.org/) filter plugin for adding [GeoIP data](h
|
|
7
7
|
Add this line to your application's Gemfile:
|
8
8
|
|
9
9
|
```
|
10
|
-
gem 'fluent-plugin-output-
|
10
|
+
gem 'fluent-plugin-output-geoip'
|
11
11
|
```
|
12
12
|
|
13
13
|
And then execute:
|
@@ -16,14 +16,32 @@ And then execute:
|
|
16
16
|
|
17
17
|
Or install it yourself as:
|
18
18
|
|
19
|
-
$ gem install fluent-plugin-output-
|
19
|
+
$ gem install fluent-plugin-output-geoip
|
20
20
|
|
21
21
|
## Config parameters
|
22
22
|
|
23
|
-
###
|
23
|
+
### download_url
|
24
24
|
|
25
25
|
```
|
26
|
-
|
26
|
+
download_url http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz
|
27
|
+
```
|
28
|
+
|
29
|
+
### md5_url
|
30
|
+
|
31
|
+
```
|
32
|
+
md5_url http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.md5
|
33
|
+
```
|
34
|
+
|
35
|
+
### database_path
|
36
|
+
|
37
|
+
```
|
38
|
+
database_path ./geoip/database/GeoLite2-City.mmdb
|
39
|
+
```
|
40
|
+
|
41
|
+
### md5_path
|
42
|
+
|
43
|
+
```
|
44
|
+
md5_path ./geoip/database/GeoLite2-City.md5
|
27
45
|
```
|
28
46
|
|
29
47
|
### lookup_field
|
@@ -116,7 +134,11 @@ connection_type true
|
|
116
134
|
<filter tail.log>
|
117
135
|
@type geoip
|
118
136
|
|
119
|
-
|
137
|
+
download_url http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz
|
138
|
+
md5_url http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.md5
|
139
|
+
database_path ./geoip/database/GeoLite2-City.mmdb
|
140
|
+
md5_path ./geoip/database/GeoLite2-City.md5
|
141
|
+
|
120
142
|
lookup_field host
|
121
143
|
field_prefix geoip
|
122
144
|
field_delimiter _
|
@@ -135,6 +157,97 @@ connection_type true
|
|
135
157
|
</filter>
|
136
158
|
```
|
137
159
|
|
160
|
+
Assuming following inputs are coming:
|
161
|
+
|
162
|
+
```javascript
|
163
|
+
{
|
164
|
+
"host":"212.99.123.25",
|
165
|
+
"user":"-",
|
166
|
+
"method":"GET",
|
167
|
+
"path":"/item/sports/4981",
|
168
|
+
"code":"200",
|
169
|
+
"size":"94",
|
170
|
+
"referer":"/category/electronics",
|
171
|
+
"agent":"Mozilla/5.0 (Windows NT 6.0; rv:10.0.1) Gecko/20100101 Firefox/10.0.1"
|
172
|
+
}
|
173
|
+
```
|
174
|
+
|
175
|
+
then output bocomes as belows:
|
176
|
+
|
177
|
+
```javascript
|
178
|
+
{
|
179
|
+
"host":"212.99.123.25",
|
180
|
+
"user":"-",
|
181
|
+
"method":"GET",
|
182
|
+
"path":"/item/sports/4981",
|
183
|
+
"code":"200",
|
184
|
+
"size":"94",
|
185
|
+
"referer":"/category/electronics",
|
186
|
+
"agent":"Mozilla/5.0 (Windows NT 6.0; rv:10.0.1) Gecko/20100101 Firefox/10.0.1",
|
187
|
+
"geoip_continent_code":"EU",
|
188
|
+
"geoip_continent_geoname_id":6255148,
|
189
|
+
"geoip_continent_names_de":"Europa",
|
190
|
+
"geoip_continent_names_en":"Europe",
|
191
|
+
"geoip_continent_names_es":"Europa",
|
192
|
+
"geoip_continent_names_fr":"Europe",
|
193
|
+
"geoip_continent_names_ja":"ヨーロッパ",
|
194
|
+
"geoip_continent_names_pt-BR":"Europa",
|
195
|
+
"geoip_continent_names_ru":"Европа",
|
196
|
+
"geoip_continent_names_zh-CN":"欧洲",
|
197
|
+
"geoip_country_geoname_id":3017382,
|
198
|
+
"geoip_country_iso_code":"FR",
|
199
|
+
"geoip_country_names_de":"Frankreich",
|
200
|
+
"geoip_country_names_en":"France",
|
201
|
+
"geoip_country_names_es":"Francia",
|
202
|
+
"geoip_country_names_fr":"France",
|
203
|
+
"geoip_country_names_ja":"フランス共和国",
|
204
|
+
"geoip_country_names_pt-BR":"França",
|
205
|
+
"geoip_country_names_ru":"Франция",
|
206
|
+
"geoip_country_names_zh-CN":"法国",
|
207
|
+
"geoip_city_geoname_id":3038354,
|
208
|
+
"geoip_city_names_de":"Aix-en-Provence",
|
209
|
+
"geoip_city_names_en":"Aix-en-Provence",
|
210
|
+
"geoip_city_names_es":"Aix-en-Provence",
|
211
|
+
"geoip_city_names_fr":"Aix-en-Provence",
|
212
|
+
"geoip_city_names_ja":"エクス=アン=プロヴァンス",
|
213
|
+
"geoip_city_names_pt-BR":"Aix-en-Provence",
|
214
|
+
"geoip_city_names_ru":"Экс-ан-Прованс",
|
215
|
+
"geoip_city_names_zh-CN":"普罗旺斯地区艾克斯",
|
216
|
+
"geoip_location_latitude":43.5283,
|
217
|
+
"geoip_location_longitude":5.4497,
|
218
|
+
"geoip_location_time_zone":"Europe/Paris",
|
219
|
+
"geoip_postal_code":"13090",
|
220
|
+
"geoip_registered_country_geoname_id":3017382,
|
221
|
+
"geoip_registered_country_iso_code":"FR",
|
222
|
+
"geoip_registered_country_names_de":"Frankreich",
|
223
|
+
"geoip_registered_country_names_en":"France",
|
224
|
+
"geoip_registered_country_names_es":"Francia",
|
225
|
+
"geoip_registered_country_names_fr":"France",
|
226
|
+
"geoip_registered_country_names_ja":"フランス共和国",
|
227
|
+
"geoip_registered_country_names_pt-BR":"França",
|
228
|
+
"geoip_registered_country_names_ru":"Франция",
|
229
|
+
"geoip_registered_country_names_zh-CN":"法国",
|
230
|
+
"geoip_subdivisions_0_geoname_id":2985244,
|
231
|
+
"geoip_subdivisions_0_iso_code":"U",
|
232
|
+
"geoip_subdivisions_0_names_de":"Provence-Alpes-Côte d’Azur",
|
233
|
+
"geoip_subdivisions_0_names_en":"Provence-Alpes-Côte d'Azur",
|
234
|
+
"geoip_subdivisions_0_names_es":"Provenza-Alpes-Costa Azul",
|
235
|
+
"geoip_subdivisions_0_names_fr":"Provence-Alpes-Côte d'Azur",
|
236
|
+
"geoip_subdivisions_0_names_ja":"プロヴァンス=アルプ=コート・ダジュール地域圏",
|
237
|
+
"geoip_subdivisions_0_names_pt-BR":"Provença-Alpes-Costa Azul",
|
238
|
+
"geoip_subdivisions_0_names_ru":"Прованс — Альпы — Лазурный Берег",
|
239
|
+
"geoip_subdivisions_0_names_zh-CN":"普罗旺斯-阿尔卑斯-蓝色海岸",
|
240
|
+
"geoip_subdivisions_1_geoname_id":3031359,
|
241
|
+
"geoip_subdivisions_1_iso_code":"13",
|
242
|
+
"geoip_subdivisions_1_names_de":"Bouches-du-Rhône",
|
243
|
+
"geoip_subdivisions_1_names_en":"Bouches-du-Rhône",
|
244
|
+
"geoip_subdivisions_1_names_es":"Bocas del Ródano",
|
245
|
+
"geoip_subdivisions_1_names_fr":"Bouches-du-Rhône",
|
246
|
+
"geoip_subdivisions_1_names_pt-BR":"Bocas do Ródano",
|
247
|
+
"geoip_localtion_latlon":"43.5283,5.4497"
|
248
|
+
}
|
249
|
+
```
|
250
|
+
|
138
251
|
## Development
|
139
252
|
|
140
253
|
After checking out the repo, run `bundle install` to install dependencies. Then, run `rake test` to run the tests.
|
@@ -1,10 +1,17 @@
|
|
1
1
|
require 'maxminddb'
|
2
2
|
require 'json'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'open-uri'
|
3
5
|
|
4
6
|
module Fluent
|
5
7
|
class GeoIPFilter < Filter
|
6
8
|
Fluent::Plugin.register_filter('geoip', self)
|
7
9
|
|
10
|
+
DEFAULT_DOWNLOAD_URL = 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz'
|
11
|
+
DEFAULT_MD5_URL = 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.md5'
|
12
|
+
DEFAULT_DATABASE_PATH = './geoip/database/GeoLite2-City.mmdb'
|
13
|
+
DEFAULT_MD5_PATH = './geoip/database/GeoLite2-City.md5'
|
14
|
+
|
8
15
|
DEFAULT_LOOKUP_FIELD = 'ip'
|
9
16
|
DEFAULT_FIELD_PREFIX = 'geoip'
|
10
17
|
DEFAULT_FIELD_DELIMITER = '_'
|
@@ -21,7 +28,16 @@ module Fluent
|
|
21
28
|
DEFAULT_TRAITS = true
|
22
29
|
DEFAULT_CONNECTION_TYPE = true
|
23
30
|
|
24
|
-
config_param :
|
31
|
+
config_param :download_url, :string, :default => DEFAULT_DOWNLOAD_URL,
|
32
|
+
:desc => ''
|
33
|
+
|
34
|
+
config_param :md5_url, :string, :default => DEFAULT_MD5_URL,
|
35
|
+
:desc => ''
|
36
|
+
|
37
|
+
config_param :database_path, :string, :default => DEFAULT_DATABASE_PATH,
|
38
|
+
:desc => ''
|
39
|
+
|
40
|
+
config_param :md5_path, :string, :default => DEFAULT_MD5_PATH,
|
25
41
|
:desc => ''
|
26
42
|
|
27
43
|
config_param :lookup_field, :string, :default => DEFAULT_LOOKUP_FIELD,
|
@@ -73,7 +89,13 @@ module Fluent
|
|
73
89
|
def configure(conf)
|
74
90
|
super
|
75
91
|
|
76
|
-
@
|
92
|
+
@download_url = conf.has_key?('download_url') ? conf['download_url'] : DEFAULT_DOWNLOAD_URL
|
93
|
+
|
94
|
+
@md5_url = conf.has_key?('md5_url') ? conf['md5_url'] : DEFAULT_MD5_URL
|
95
|
+
|
96
|
+
@database_path = conf.has_key?('database_path') ? conf['database_path'] : DEFAULT_DATABASE_PATH
|
97
|
+
|
98
|
+
@md5_path = conf.has_key?('md5_path') ? conf['md5_path'] : DEFAULT_MD5_PATH
|
77
99
|
|
78
100
|
@lookup_field = conf.has_key?('lookup_field') ? conf['lookup_field'] : DEFAULT_LOOKUP_FIELD
|
79
101
|
|
@@ -103,6 +125,8 @@ module Fluent
|
|
103
125
|
|
104
126
|
@connection_type = conf.has_key?('connection_type') ? to_boolean(conf['connection_type']) : DEFAULT_CONNECTION_TYPE
|
105
127
|
|
128
|
+
download_database @download_url, @md5_url, @database_path, @md5_path
|
129
|
+
|
106
130
|
@database = MaxMindDB.new(@database_path)
|
107
131
|
end
|
108
132
|
|
@@ -234,6 +258,75 @@ module Fluent
|
|
234
258
|
else
|
235
259
|
return false
|
236
260
|
end
|
237
|
-
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def download_database(download_url, md5_url, database_path, md5_path)
|
264
|
+
# database directory
|
265
|
+
database_dir = File.expand_path(File.dirname(database_path))
|
266
|
+
md5_dir = File.expand_path(File.dirname(md5_path))
|
267
|
+
|
268
|
+
# create database directory if directory does not exist.
|
269
|
+
FileUtils.mkdir_p(database_dir) unless File.exist?(database_dir)
|
270
|
+
FileUtils.mkdir_p(md5_dir) unless File.exist?(md5_dir)
|
271
|
+
|
272
|
+
# create empty md5 file if file does not exist.
|
273
|
+
File.open(md5_path, 'wb').close() unless File.exist?(md5_path)
|
274
|
+
|
275
|
+
# read saved md5
|
276
|
+
saved_md5 = nil
|
277
|
+
begin
|
278
|
+
open(md5_path, 'rb') do |data|
|
279
|
+
saved_md5 = data.read
|
280
|
+
end
|
281
|
+
rescue => e
|
282
|
+
log.warn e.message
|
283
|
+
end
|
284
|
+
|
285
|
+
# fetch md5
|
286
|
+
fetched_md5 = nil
|
287
|
+
begin
|
288
|
+
open(md5_url, 'rb') do |data|
|
289
|
+
fetched_md5 = data.read
|
290
|
+
end
|
291
|
+
rescue => e
|
292
|
+
log.warn e.message
|
293
|
+
end
|
294
|
+
|
295
|
+
# check md5
|
296
|
+
unless saved_md5 == fetched_md5 then
|
297
|
+
# download new database
|
298
|
+
download_path = database_dir + '/' + File.basename(download_url)
|
299
|
+
begin
|
300
|
+
open(download_path, 'wb') do |output|
|
301
|
+
open(download_url, 'rb') do |data|
|
302
|
+
output.write(data.read)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
rescue => e
|
306
|
+
log.warn e.message
|
307
|
+
end
|
308
|
+
|
309
|
+
# unzip new database temporaly
|
310
|
+
tmp_database_path = database_dir + '/tmp_' + File.basename(database_path)
|
311
|
+
begin
|
312
|
+
open(tmp_database_path, 'wb') do |output|
|
313
|
+
Zlib::GzipReader.open(download_path) do |gz|
|
314
|
+
output.write(gz.read)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
rescue => e
|
318
|
+
puts e.message
|
319
|
+
end
|
320
|
+
|
321
|
+
# check mkd5
|
322
|
+
temp_md5 = Digest::MD5.hexdigest(File.open(tmp_database_path, 'rb').read)
|
323
|
+
if fetched_md5 == temp_md5 then
|
324
|
+
FileUtils.mv(tmp_database_path, database_path)
|
325
|
+
|
326
|
+
# record new md5
|
327
|
+
File.write(md5_path, fetched_md5)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
238
331
|
end
|
239
332
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-filter-geoip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Minoru Osuka
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|