fluent-plugin-geoip 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +90 -211
- data/fluent-plugin-geoip.gemspec +2 -1
- data/lib/fluent/plugin/filter_geoip.rb +180 -5
- data/test/helper.rb +1 -0
- data/test/plugin/test_filter_geoip.rb +137 -69
- metadata +17 -7
- data/lib/fluent/plugin/geoip.rb +0 -171
- data/lib/fluent/plugin/out_geoip.rb +0 -56
- data/test/plugin/test_out_geoip.rb +0 -1048
data/test/helper.rb
CHANGED
@@ -31,12 +31,12 @@ class GeoipFilterTest < Test::Unit::TestCase
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def setup_geoip_mock(d)
|
34
|
-
|
34
|
+
plugin = d.instance
|
35
35
|
db = Object.new
|
36
36
|
def db.lookup(ip)
|
37
37
|
{}
|
38
38
|
end
|
39
|
-
|
39
|
+
plugin.instance_variable_set(:@geoip, db)
|
40
40
|
end
|
41
41
|
|
42
42
|
sub_test_case "configure" do
|
@@ -58,11 +58,9 @@ class GeoipFilterTest < Test::Unit::TestCase
|
|
58
58
|
<record>
|
59
59
|
geoip_city ${city['host']}
|
60
60
|
</record>
|
61
|
-
tag geoip.${tag[1]}
|
62
61
|
]
|
63
62
|
d = create_driver(conf)
|
64
|
-
assert_equal(["host", "ip"],
|
65
|
-
d.instance.instance_variable_get(:@geoip).instance_variable_get(:@geoip_lookup_keys))
|
63
|
+
assert_equal(["host", "ip"], d.instance.geoip_lookup_keys)
|
66
64
|
end
|
67
65
|
|
68
66
|
test "invalid json structure w/ Ruby hash like" do
|
@@ -87,6 +85,36 @@ class GeoipFilterTest < Test::Unit::TestCase
|
|
87
85
|
}
|
88
86
|
end
|
89
87
|
|
88
|
+
test "dotted key is not treated as nested attributes" do
|
89
|
+
mock($log).warn("host.ip is not treated as nested attributes")
|
90
|
+
create_driver %[
|
91
|
+
geoip_lookup_keys host.ip
|
92
|
+
<record>
|
93
|
+
city ${city.names.en['host.ip']}
|
94
|
+
</record>
|
95
|
+
]
|
96
|
+
end
|
97
|
+
|
98
|
+
test "nested attributes bracket style" do
|
99
|
+
mock($log).warn(anything).times(0)
|
100
|
+
create_driver %[
|
101
|
+
geoip_lookup_keys $["host"]["ip"]
|
102
|
+
<record>
|
103
|
+
geoip_city ${city.names.en['$["host"]["ip"]']}
|
104
|
+
</record>
|
105
|
+
]
|
106
|
+
end
|
107
|
+
|
108
|
+
test "nested attributes dot style" do
|
109
|
+
mock($log).warn(anything).times(0)
|
110
|
+
create_driver %[
|
111
|
+
geoip_lookup_keys $.host.ip
|
112
|
+
<record>
|
113
|
+
geoip_city ${city['$.host.ip']}
|
114
|
+
</record>
|
115
|
+
]
|
116
|
+
end
|
117
|
+
|
90
118
|
data(geoip: "geoip",
|
91
119
|
geoip2_compat: "geoip2_compat")
|
92
120
|
test "unsupported key" do |backend|
|
@@ -197,21 +225,21 @@ class GeoipFilterTest < Test::Unit::TestCase
|
|
197
225
|
def test_filter_record_directive
|
198
226
|
config = %[
|
199
227
|
backend_library geoip2_c
|
200
|
-
geoip_lookup_keys from.ip
|
228
|
+
geoip_lookup_keys $.from.ip
|
201
229
|
<record>
|
202
|
-
from_city ${city.names.en['from.ip']}
|
203
|
-
from_country ${country.names.en['from.ip']}
|
204
|
-
latitude ${location.latitude['from.ip']}
|
205
|
-
longitude ${location.longitude['from.ip']}
|
206
|
-
float_concat ${location.latitude['from.ip']},${location.longitude['from.ip']}
|
207
|
-
float_array [${location.longitude['from.ip']}, ${location.latitude['from.ip']}]
|
208
|
-
float_nest { "lat" : ${location.latitude['from.ip']}, "lon" : ${location.longitude['from.ip']}}
|
209
|
-
string_concat ${city.names.en['from.ip']},${country.names.en['from.ip']}
|
210
|
-
string_array [${city.names.en['from.ip']}, ${country.names.en['from.ip']}]
|
211
|
-
string_nest { "city" : ${city.names.en['from.ip']}, "country_name" : ${country.names.en['from.ip']}}
|
230
|
+
from_city ${city.names.en['$.from.ip']}
|
231
|
+
from_country ${country.names.en['$.from.ip']}
|
232
|
+
latitude ${location.latitude['$.from.ip']}
|
233
|
+
longitude ${location.longitude['$.from.ip']}
|
234
|
+
float_concat ${location.latitude['$.from.ip']},${location.longitude['$.from.ip']}
|
235
|
+
float_array [${location.longitude['$.from.ip']}, ${location.latitude['$.from.ip']}]
|
236
|
+
float_nest { "lat" : ${location.latitude['$.from.ip']}, "lon" : ${location.longitude['$.from.ip']}}
|
237
|
+
string_concat ${city.names.en['$.from.ip']},${country.names.en['$.from.ip']}
|
238
|
+
string_array [${city.names.en['$.from.ip']}, ${country.names.en['$.from.ip']}]
|
239
|
+
string_nest { "city" : ${city.names.en['$.from.ip']}, "country_name" : ${country.names.en['$.from.ip']}}
|
212
240
|
unknown_city ${city.names.en['unknown_key']}
|
213
241
|
undefined ${city.names.en['undefined']}
|
214
|
-
broken_array1 [${location.longitude['from.ip']}, ${location.latitude['undefined']}]
|
242
|
+
broken_array1 [${location.longitude['$.from.ip']}, ${location.latitude['undefined']}]
|
215
243
|
broken_array2 [${location.longitude['undefined']}, ${location.latitude['undefined']}]
|
216
244
|
</record>
|
217
245
|
]
|
@@ -264,13 +292,13 @@ class GeoipFilterTest < Test::Unit::TestCase
|
|
264
292
|
def test_filter_record_directive_multiple_record
|
265
293
|
config = %[
|
266
294
|
backend_library geoip2_c
|
267
|
-
geoip_lookup_keys from.ip, to.ip
|
295
|
+
geoip_lookup_keys $.from.ip, $.to.ip
|
268
296
|
<record>
|
269
|
-
from_city ${city.names.en['from.ip']}
|
270
|
-
to_city ${city.names.en['to.ip']}
|
271
|
-
from_country ${country.names.en['from.ip']}
|
272
|
-
to_country ${country.names.en['to.ip']}
|
273
|
-
string_array [${country.names.en['from.ip']}, ${country.names.en['to.ip']}]
|
297
|
+
from_city ${city.names.en['$.from.ip']}
|
298
|
+
to_city ${city.names.en['$.to.ip']}
|
299
|
+
from_country ${country.names.en['$.from.ip']}
|
300
|
+
to_country ${country.names.en['$.to.ip']}
|
301
|
+
string_array [${country.names.en['$.from.ip']}, ${country.names.en['$.to.ip']}]
|
274
302
|
</record>
|
275
303
|
]
|
276
304
|
messages = [
|
@@ -417,6 +445,46 @@ class GeoipFilterTest < Test::Unit::TestCase
|
|
417
445
|
end
|
418
446
|
assert_equal(expected, filtered)
|
419
447
|
end
|
448
|
+
|
449
|
+
def test_filter_nested_attr_bracket_style_double_quote
|
450
|
+
config = %[
|
451
|
+
backend_library geoip2_c
|
452
|
+
geoip_lookup_keys $["host"]["ip"]
|
453
|
+
<record>
|
454
|
+
geoip_city ${city.names.en['$["host"]["ip"]']}
|
455
|
+
</record>
|
456
|
+
]
|
457
|
+
messages = [
|
458
|
+
{'host' => {'ip' => '66.102.3.80'}, 'message' => 'valid ip'},
|
459
|
+
{'message' => 'missing field'}
|
460
|
+
]
|
461
|
+
expected = [
|
462
|
+
{'host' => {'ip' => '66.102.3.80'}, 'message' => 'valid ip', 'geoip_city' => 'Mountain View'},
|
463
|
+
{'message' => 'missing field', 'geoip_city' => nil}
|
464
|
+
]
|
465
|
+
filtered = filter(config, messages)
|
466
|
+
assert_equal(expected, filtered)
|
467
|
+
end
|
468
|
+
|
469
|
+
def test_filter_nested_attr_bracket_style_single_quote
|
470
|
+
config = %[
|
471
|
+
backend_library geoip2_c
|
472
|
+
geoip_lookup_keys $['host']['ip']
|
473
|
+
<record>
|
474
|
+
geoip_city ${city.names.en["$['host']['ip']"]}
|
475
|
+
</record>
|
476
|
+
]
|
477
|
+
messages = [
|
478
|
+
{'host' => {'ip' => '66.102.3.80'}, 'message' => 'valid ip'},
|
479
|
+
{'message' => 'missing field'}
|
480
|
+
]
|
481
|
+
expected = [
|
482
|
+
{'host' => {'ip' => '66.102.3.80'}, 'message' => 'valid ip', 'geoip_city' => 'Mountain View'},
|
483
|
+
{'message' => 'missing field', 'geoip_city' => nil}
|
484
|
+
]
|
485
|
+
filtered = filter(config, messages)
|
486
|
+
assert_equal(expected, filtered)
|
487
|
+
end
|
420
488
|
end
|
421
489
|
|
422
490
|
sub_test_case "geoip2_compat" do
|
@@ -492,21 +560,21 @@ class GeoipFilterTest < Test::Unit::TestCase
|
|
492
560
|
def test_filter_record_directive
|
493
561
|
config = %[
|
494
562
|
backend_library geoip2_compat
|
495
|
-
geoip_lookup_keys from.ip
|
563
|
+
geoip_lookup_keys $.from.ip
|
496
564
|
<record>
|
497
|
-
from_city ${city['from.ip']}
|
498
|
-
from_country ${country_name['from.ip']}
|
499
|
-
latitude ${latitude['from.ip']}
|
500
|
-
longitude ${longitude['from.ip']}
|
501
|
-
float_concat ${latitude['from.ip']},${longitude['from.ip']}
|
502
|
-
float_array [${longitude['from.ip']}, ${latitude['from.ip']}]
|
503
|
-
float_nest { "lat" : ${latitude['from.ip']}, "lon" : ${longitude['from.ip']}}
|
504
|
-
string_concat ${city['from.ip']},${country_name['from.ip']}
|
505
|
-
string_array [${city['from.ip']}, ${country_name['from.ip']}]
|
506
|
-
string_nest { "city" : ${city['from.ip']}, "country_name" : ${country_name['from.ip']}}
|
565
|
+
from_city ${city['$.from.ip']}
|
566
|
+
from_country ${country_name['$.from.ip']}
|
567
|
+
latitude ${latitude['$.from.ip']}
|
568
|
+
longitude ${longitude['$.from.ip']}
|
569
|
+
float_concat ${latitude['$.from.ip']},${longitude['$.from.ip']}
|
570
|
+
float_array [${longitude['$.from.ip']}, ${latitude['$.from.ip']}]
|
571
|
+
float_nest { "lat" : ${latitude['$.from.ip']}, "lon" : ${longitude['$.from.ip']}}
|
572
|
+
string_concat ${city['$.from.ip']},${country_name['$.from.ip']}
|
573
|
+
string_array [${city['$.from.ip']}, ${country_name['$.from.ip']}]
|
574
|
+
string_nest { "city" : ${city['$.from.ip']}, "country_name" : ${country_name['$.from.ip']}}
|
507
575
|
unknown_city ${city['unknown_key']}
|
508
576
|
undefined ${city['undefined']}
|
509
|
-
broken_array1 [${longitude['from.ip']}, ${latitude['undefined']}]
|
577
|
+
broken_array1 [${longitude['$.from.ip']}, ${latitude['undefined']}]
|
510
578
|
broken_array2 [${longitude['undefined']}, ${latitude['undefined']}]
|
511
579
|
</record>
|
512
580
|
]
|
@@ -559,13 +627,13 @@ class GeoipFilterTest < Test::Unit::TestCase
|
|
559
627
|
def test_filter_record_directive_multiple_record
|
560
628
|
config = %[
|
561
629
|
backend_library geoip2_compat
|
562
|
-
geoip_lookup_keys from.ip, to.ip
|
630
|
+
geoip_lookup_keys $.from.ip, $.to.ip
|
563
631
|
<record>
|
564
|
-
from_city ${city['from.ip']}
|
565
|
-
to_city ${city['to.ip']}
|
566
|
-
from_country ${country_name['from.ip']}
|
567
|
-
to_country ${country_name['to.ip']}
|
568
|
-
string_array [${country_name['from.ip']}, ${country_name['to.ip']}]
|
632
|
+
from_city ${city['$.from.ip']}
|
633
|
+
to_city ${city['$.to.ip']}
|
634
|
+
from_country ${country_name['$.from.ip']}
|
635
|
+
to_country ${country_name['$.to.ip']}
|
636
|
+
string_array [${country_name['$.from.ip']}, ${country_name['$.to.ip']}]
|
569
637
|
</record>
|
570
638
|
]
|
571
639
|
messages = [
|
@@ -758,9 +826,9 @@ class GeoipFilterTest < Test::Unit::TestCase
|
|
758
826
|
def test_filter_nested_attr
|
759
827
|
config = %[
|
760
828
|
backend_library geoip
|
761
|
-
geoip_lookup_keys host.ip
|
829
|
+
geoip_lookup_keys $.host.ip
|
762
830
|
<record>
|
763
|
-
geoip_city ${city['host.ip']}
|
831
|
+
geoip_city ${city['$.host.ip']}
|
764
832
|
</record>
|
765
833
|
]
|
766
834
|
messages = [
|
@@ -827,10 +895,10 @@ class GeoipFilterTest < Test::Unit::TestCase
|
|
827
895
|
def test_filter_multiple_key
|
828
896
|
config = %[
|
829
897
|
backend_library geoip
|
830
|
-
geoip_lookup_keys from.ip, to.ip
|
898
|
+
geoip_lookup_keys $.from.ip, $.to.ip
|
831
899
|
<record>
|
832
|
-
from_city ${city['from.ip']}
|
833
|
-
to_city ${city['to.ip']}
|
900
|
+
from_city ${city['$.from.ip']}
|
901
|
+
to_city ${city['$.to.ip']}
|
834
902
|
</record>
|
835
903
|
]
|
836
904
|
messages = [
|
@@ -849,12 +917,12 @@ class GeoipFilterTest < Test::Unit::TestCase
|
|
849
917
|
def test_filter_multiple_key_multiple_record
|
850
918
|
config = %[
|
851
919
|
backend_library geoip
|
852
|
-
geoip_lookup_keys from.ip, to.ip
|
920
|
+
geoip_lookup_keys $.from.ip, $.to.ip
|
853
921
|
<record>
|
854
|
-
from_city ${city['from.ip']}
|
855
|
-
from_country ${country_name['from.ip']}
|
856
|
-
to_city ${city['to.ip']}
|
857
|
-
to_country ${country_name['to.ip']}
|
922
|
+
from_city ${city['$.from.ip']}
|
923
|
+
from_country ${country_name['$.from.ip']}
|
924
|
+
to_city ${city['$.to.ip']}
|
925
|
+
to_country ${country_name['$.to.ip']}
|
858
926
|
</record>
|
859
927
|
]
|
860
928
|
messages = [
|
@@ -893,21 +961,21 @@ class GeoipFilterTest < Test::Unit::TestCase
|
|
893
961
|
def test_filter_record_directive
|
894
962
|
config = %[
|
895
963
|
backend_library geoip
|
896
|
-
geoip_lookup_keys from.ip
|
964
|
+
geoip_lookup_keys $.from.ip
|
897
965
|
<record>
|
898
|
-
from_city ${city['from.ip']}
|
899
|
-
from_country ${country_name['from.ip']}
|
900
|
-
latitude ${latitude['from.ip']}
|
901
|
-
longitude ${longitude['from.ip']}
|
902
|
-
float_concat ${latitude['from.ip']},${longitude['from.ip']}
|
903
|
-
float_array [${longitude['from.ip']}, ${latitude['from.ip']}]
|
904
|
-
float_nest { "lat" : ${latitude['from.ip']}, "lon" : ${longitude['from.ip']}}
|
905
|
-
string_concat ${city['from.ip']},${country_name['from.ip']}
|
906
|
-
string_array [${city['from.ip']}, ${country_name['from.ip']}]
|
907
|
-
string_nest { "city" : ${city['from.ip']}, "country_name" : ${country_name['from.ip']}}
|
966
|
+
from_city ${city['$.from.ip']}
|
967
|
+
from_country ${country_name['$.from.ip']}
|
968
|
+
latitude ${latitude['$.from.ip']}
|
969
|
+
longitude ${longitude['$.from.ip']}
|
970
|
+
float_concat ${latitude['$.from.ip']},${longitude['$.from.ip']}
|
971
|
+
float_array [${longitude['$.from.ip']}, ${latitude['$.from.ip']}]
|
972
|
+
float_nest { "lat" : ${latitude['$.from.ip']}, "lon" : ${longitude['$.from.ip']}}
|
973
|
+
string_concat ${city['$.from.ip']},${country_name['$.from.ip']}
|
974
|
+
string_array [${city['$.from.ip']}, ${country_name['$.from.ip']}]
|
975
|
+
string_nest { "city" : ${city['$.from.ip']}, "country_name" : ${country_name['$.from.ip']}}
|
908
976
|
unknown_city ${city['unknown_key']}
|
909
977
|
undefined ${city['undefined']}
|
910
|
-
broken_array1 [${longitude['from.ip']}, ${latitude['undefined']}]
|
978
|
+
broken_array1 [${longitude['$.from.ip']}, ${latitude['undefined']}]
|
911
979
|
broken_array2 [${longitude['undefined']}, ${latitude['undefined']}]
|
912
980
|
</record>
|
913
981
|
]
|
@@ -960,13 +1028,13 @@ class GeoipFilterTest < Test::Unit::TestCase
|
|
960
1028
|
def test_filter_record_directive_multiple_record
|
961
1029
|
config = %[
|
962
1030
|
backend_library geoip
|
963
|
-
geoip_lookup_keys from.ip, to.ip
|
1031
|
+
geoip_lookup_keys $.from.ip, $.to.ip
|
964
1032
|
<record>
|
965
|
-
from_city ${city['from.ip']}
|
966
|
-
to_city ${city['to.ip']}
|
967
|
-
from_country ${country_name['from.ip']}
|
968
|
-
to_country ${country_name['to.ip']}
|
969
|
-
string_array [${country_name['from.ip']}, ${country_name['to.ip']}]
|
1033
|
+
from_city ${city['$.from.ip']}
|
1034
|
+
to_city ${city['$.to.ip']}
|
1035
|
+
from_country ${country_name['$.from.ip']}
|
1036
|
+
to_country ${country_name['$.to.ip']}
|
1037
|
+
string_array [${country_name['$.from.ip']}, ${country_name['$.to.ip']}]
|
970
1038
|
</record>
|
971
1039
|
]
|
972
1040
|
messages = [
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-geoip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kentaro Yoshida
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 3.1.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: test-unit-rr
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: geoip2_compat
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -172,11 +186,8 @@ files:
|
|
172
186
|
- gemfiles/fluentd_v1.0_with_backport_dig.gemfile
|
173
187
|
- gemfiles/fluentd_v1.0_without_backport_dig.gemfile
|
174
188
|
- lib/fluent/plugin/filter_geoip.rb
|
175
|
-
- lib/fluent/plugin/geoip.rb
|
176
|
-
- lib/fluent/plugin/out_geoip.rb
|
177
189
|
- test/helper.rb
|
178
190
|
- test/plugin/test_filter_geoip.rb
|
179
|
-
- test/plugin/test_out_geoip.rb
|
180
191
|
- utils/dump.rb
|
181
192
|
homepage: https://github.com/y-ken/fluent-plugin-geoip
|
182
193
|
licenses:
|
@@ -198,7 +209,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
198
209
|
version: '0'
|
199
210
|
requirements: []
|
200
211
|
rubyforge_project:
|
201
|
-
rubygems_version: 2.7.
|
212
|
+
rubygems_version: 2.7.6
|
202
213
|
signing_key:
|
203
214
|
specification_version: 4
|
204
215
|
summary: Fluentd Filter plugin to add information about geographical location of IP
|
@@ -206,4 +217,3 @@ summary: Fluentd Filter plugin to add information about geographical location of
|
|
206
217
|
test_files:
|
207
218
|
- test/helper.rb
|
208
219
|
- test/plugin/test_filter_geoip.rb
|
209
|
-
- test/plugin/test_out_geoip.rb
|
data/lib/fluent/plugin/geoip.rb
DELETED
@@ -1,171 +0,0 @@
|
|
1
|
-
require 'geoip'
|
2
|
-
require 'yajl'
|
3
|
-
unless {}.respond_to?(:dig)
|
4
|
-
begin
|
5
|
-
# backport_dig is faster than dig_rb so prefer backport_dig.
|
6
|
-
# And Fluentd v1.0.1 uses backport_dig
|
7
|
-
require 'backport_dig'
|
8
|
-
rescue LoadError
|
9
|
-
require 'dig_rb'
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
module Fluent
|
14
|
-
class GeoIP
|
15
|
-
BACKEND_LIBRARIES = [:geoip, :geoip2_compat, :geoip2_c]
|
16
|
-
|
17
|
-
REGEXP_PLACEHOLDER_SINGLE = /^\$\{(?<geoip_key>-?[^\[]+)\[['"](?<record_key>-?[^'"]+)['"]\]\}$/
|
18
|
-
REGEXP_PLACEHOLDER_SCAN = /['"]?(\$\{[^\}]+?\})['"]?/
|
19
|
-
|
20
|
-
GEOIP_KEYS = %w(city latitude longitude country_code3 country_code country_name dma_code area_code region)
|
21
|
-
GEOIP2_COMPAT_KEYS = %w(city country_code country_name latitude longitude postal_code region region_name)
|
22
|
-
|
23
|
-
attr_reader :log
|
24
|
-
|
25
|
-
def initialize(plugin, conf)
|
26
|
-
@map = {}
|
27
|
-
@geoip_lookup_keys = plugin.geoip_lookup_keys
|
28
|
-
if plugin.geoip_lookup_key
|
29
|
-
@geoip_lookup_keys = plugin.geoip_lookup_key.split(/\s*,\s*/)
|
30
|
-
end
|
31
|
-
@skip_adding_null_record = plugin.skip_adding_null_record
|
32
|
-
@log = plugin.log
|
33
|
-
|
34
|
-
if conf.keys.any? {|k| k =~ /^enable_key_/ }
|
35
|
-
raise Fluent::ConfigError, "geoip: 'enable_key_*' config format is obsoleted. use <record></record> directive instead."
|
36
|
-
end
|
37
|
-
|
38
|
-
# <record></record> directive
|
39
|
-
conf.elements.select { |element| element.name == 'record' }.each { |element|
|
40
|
-
element.each_pair { |k, v|
|
41
|
-
element.has_key?(k) # to suppress unread configuration warning
|
42
|
-
v = v[1..v.size-2] if quoted_value?(v)
|
43
|
-
@map[k] = v
|
44
|
-
validate_json = Proc.new {
|
45
|
-
begin
|
46
|
-
dummy_text = Yajl::Encoder.encode('dummy_text')
|
47
|
-
Yajl::Parser.parse(v.gsub(REGEXP_PLACEHOLDER_SCAN, dummy_text))
|
48
|
-
rescue Yajl::ParseError => e
|
49
|
-
message = "geoip: failed to parse '#{v}' as json."
|
50
|
-
log.error message, error: e
|
51
|
-
raise Fluent::ConfigError, message
|
52
|
-
end
|
53
|
-
}
|
54
|
-
validate_json.call if json?(v.tr('\'"\\', ''))
|
55
|
-
}
|
56
|
-
}
|
57
|
-
@placeholder_keys = @map.values.join.scan(REGEXP_PLACEHOLDER_SCAN).map{ |placeholder| placeholder[0] }.uniq
|
58
|
-
@placeholder_keys.each do |key|
|
59
|
-
geoip_key = key.match(REGEXP_PLACEHOLDER_SINGLE)[:geoip_key]
|
60
|
-
case plugin.backend_library
|
61
|
-
when :geoip
|
62
|
-
raise Fluent::ConfigError, "#{plugin.backend_library}: unsupported key #{geoip_key}" unless GEOIP_KEYS.include?(geoip_key)
|
63
|
-
when :geoip2_compat
|
64
|
-
raise Fluent::ConfigError, "#{plugin.backend_library}: unsupported key #{geoip_key}" unless GEOIP2_COMPAT_KEYS.include?(geoip_key)
|
65
|
-
when :geoip2_c
|
66
|
-
# Nothing to do.
|
67
|
-
# We cannot define supported key(s) before we fetch values from GeoIP2 database
|
68
|
-
# because geoip2_c can fetch any fields in GeoIP2 database.
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
@geoip = load_database(plugin)
|
73
|
-
end
|
74
|
-
|
75
|
-
def add_geoip_field(record)
|
76
|
-
placeholder = create_placeholder(geolocate(get_address(record)))
|
77
|
-
return record if @skip_adding_null_record && placeholder.values.first.nil?
|
78
|
-
@map.each do |record_key, value|
|
79
|
-
if value.match(REGEXP_PLACEHOLDER_SINGLE)
|
80
|
-
rewrited = placeholder[value]
|
81
|
-
elsif json?(value)
|
82
|
-
rewrited = value.gsub(REGEXP_PLACEHOLDER_SCAN) {|match|
|
83
|
-
match = match[1..match.size-2] if quoted_value?(match)
|
84
|
-
Yajl::Encoder.encode(placeholder[match])
|
85
|
-
}
|
86
|
-
rewrited = parse_json(rewrited)
|
87
|
-
else
|
88
|
-
rewrited = value.gsub(REGEXP_PLACEHOLDER_SCAN, placeholder)
|
89
|
-
end
|
90
|
-
record[record_key] = rewrited
|
91
|
-
end
|
92
|
-
return record
|
93
|
-
end
|
94
|
-
|
95
|
-
private
|
96
|
-
|
97
|
-
def json?(text)
|
98
|
-
text.match(/^\[.+\]$/) || text.match(/^\{.+\}$/)
|
99
|
-
end
|
100
|
-
|
101
|
-
def quoted_value?(text)
|
102
|
-
# to improbe compatibility with fluentd v1-config
|
103
|
-
text.match(/(^'.+'$|^".+"$)/)
|
104
|
-
end
|
105
|
-
|
106
|
-
def parse_json(message)
|
107
|
-
begin
|
108
|
-
return Yajl::Parser.parse(message)
|
109
|
-
rescue Yajl::ParseError => e
|
110
|
-
log.info "geoip: failed to parse '#{message}' as json.", error_class: e.class, error: e.message
|
111
|
-
return nil
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def get_address(record)
|
116
|
-
address = {}
|
117
|
-
@geoip_lookup_keys.each do |field|
|
118
|
-
address[field] = record[field] || record.dig(*field.split('.'))
|
119
|
-
end
|
120
|
-
address
|
121
|
-
end
|
122
|
-
|
123
|
-
def geolocate(addresses)
|
124
|
-
geodata = {}
|
125
|
-
addresses.each do |field, ip|
|
126
|
-
geo = nil
|
127
|
-
if ip
|
128
|
-
geo = if @geoip.respond_to?(:look_up)
|
129
|
-
@geoip.look_up(ip)
|
130
|
-
else
|
131
|
-
@geoip.lookup(ip)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
geodata[field] = geo
|
135
|
-
end
|
136
|
-
geodata
|
137
|
-
end
|
138
|
-
|
139
|
-
def create_placeholder(geodata)
|
140
|
-
placeholder = {}
|
141
|
-
@placeholder_keys.each do |placeholder_key|
|
142
|
-
position = placeholder_key.match(REGEXP_PLACEHOLDER_SINGLE)
|
143
|
-
next if position.nil? or geodata[position[:record_key]].nil?
|
144
|
-
keys = [position[:record_key]] + position[:geoip_key].split('.').map(&:to_sym)
|
145
|
-
value = geodata.dig(*keys)
|
146
|
-
value = if [:latitude, :longitude].include?(keys.last)
|
147
|
-
value || 0.0
|
148
|
-
else
|
149
|
-
value
|
150
|
-
end
|
151
|
-
placeholder[placeholder_key] = value
|
152
|
-
end
|
153
|
-
placeholder
|
154
|
-
end
|
155
|
-
|
156
|
-
def load_database(plugin)
|
157
|
-
case plugin.backend_library
|
158
|
-
when :geoip
|
159
|
-
::GeoIP::City.new(plugin.geoip_database, :memory, false)
|
160
|
-
when :geoip2_compat
|
161
|
-
require 'geoip2_compat'
|
162
|
-
GeoIP2Compat.new(plugin.geoip2_database)
|
163
|
-
when :geoip2_c
|
164
|
-
require 'geoip2'
|
165
|
-
GeoIP2::Database.new(plugin.geoip2_database)
|
166
|
-
end
|
167
|
-
rescue LoadError
|
168
|
-
raise Fluent::ConfigError, "You must install #{plugin.backend_library} gem."
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|