fluent-plugin-geoip 1.0.0 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,27 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require "geoip"
4
+ require "geoip2_compat"
5
+ require "geoip2"
6
+ require "pp"
7
+
8
+ backend = ARGV[0]
9
+ ip = ARGV[1]
10
+
11
+ geoip_database = File.expand_path("../data/GeoLiteCity.dat", __dir__)
12
+ geoip2_database = File.expand_path("../data/GeoLite2-City.mmdb", __dir__)
13
+
14
+ geoip = GeoIP::City.new(geoip_database, :memory, false)
15
+ geoip2_compat = GeoIP2Compat.new(geoip2_database)
16
+ geoip2 = GeoIP2::Database.new(geoip2_database)
17
+
18
+ record = case backend
19
+ when "geoip"
20
+ geoip.look_up(ip)
21
+ when "geoip2_compat"
22
+ geoip2_compat.lookup(ip)
23
+ when "geoip2"
24
+ geoip2.lookup(ip)
25
+ end
26
+
27
+ pp record.to_h
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.0.0
4
+ version: 1.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kentaro Yoshida
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-19 00:00:00.000000000 Z
11
+ date: 2020-06-18 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
@@ -149,6 +163,7 @@ executables: []
149
163
  extensions: []
150
164
  extra_rdoc_files: []
151
165
  files:
166
+ - ".github/ISSUE_TEMPLATE.md"
152
167
  - ".gitignore"
153
168
  - ".travis.yml"
154
169
  - Appraisals
@@ -166,15 +181,14 @@ files:
166
181
  - dockerfiles/Dockerfile-ruby2.2
167
182
  - dockerfiles/Dockerfile-ruby2.3
168
183
  - dockerfiles/Dockerfile-ruby2.4
184
+ - dockerfiles/Dockerfile-ruby2.5
169
185
  - fluent-plugin-geoip.gemspec
170
186
  - gemfiles/fluentd_v1.0_with_backport_dig.gemfile
171
187
  - gemfiles/fluentd_v1.0_without_backport_dig.gemfile
172
188
  - lib/fluent/plugin/filter_geoip.rb
173
- - lib/fluent/plugin/geoip.rb
174
- - lib/fluent/plugin/out_geoip.rb
175
189
  - test/helper.rb
176
190
  - test/plugin/test_filter_geoip.rb
177
- - test/plugin/test_out_geoip.rb
191
+ - utils/dump.rb
178
192
  homepage: https://github.com/y-ken/fluent-plugin-geoip
179
193
  licenses:
180
194
  - Apache-2.0
@@ -194,8 +208,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
208
  - !ruby/object:Gem::Version
195
209
  version: '0'
196
210
  requirements: []
197
- rubyforge_project:
198
- rubygems_version: 2.6.13
211
+ rubygems_version: 3.0.3
199
212
  signing_key:
200
213
  specification_version: 4
201
214
  summary: Fluentd Filter plugin to add information about geographical location of IP
@@ -203,4 +216,3 @@ summary: Fluentd Filter plugin to add information about geographical location of
203
216
  test_files:
204
217
  - test/helper.rb
205
218
  - test/plugin/test_filter_geoip.rb
206
- - test/plugin/test_out_geoip.rb
@@ -1,174 +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
- plugin.geoip_lookup_key = plugin.geoip_lookup_key.split(/\s*,\s*/)
28
- @geoip_lookup_key = plugin.geoip_lookup_key
29
- @skip_adding_null_record = plugin.skip_adding_null_record
30
- @log = plugin.log
31
-
32
- # enable_key_* format (legacy format)
33
- conf.keys.select{|k| k =~ /^enable_key_/}.each do |key|
34
- geoip_key = key.sub('enable_key_','')
35
- raise Fluent::ConfigError, "geoip: unsupported key #{geoip_key}" unless GEOIP_KEYS.include?(geoip_key)
36
- @geoip_lookup_key.zip(conf[key].split(/\s*,\s*/)).each do |lookup_field,record_key|
37
- if record_key.nil?
38
- raise Fluent::ConfigError, "geoip: missing value found at '#{key} #{lookup_field}'"
39
- end
40
- @map[record_key] = "${#{geoip_key}['#{lookup_field}']}"
41
- end
42
- end
43
- if conf.keys.select{|k| k =~ /^enable_key_/}.size > 0
44
- log.warn "geoip: 'enable_key_*' config format is obsoleted. use <record></record> directive for now."
45
- log.warn "geoip: for further details referable to https://github.com/y-ken/fluent-plugin-geoip"
46
- end
47
-
48
- # <record></record> directive
49
- conf.elements.select { |element| element.name == 'record' }.each { |element|
50
- element.each_pair { |k, v|
51
- element.has_key?(k) # to suppress unread configuration warning
52
- v = v[1..v.size-2] if quoted_value?(v)
53
- @map[k] = v
54
- validate_json = Proc.new {
55
- begin
56
- dummy_text = Yajl::Encoder.encode('dummy_text')
57
- Yajl::Parser.parse(v.gsub(REGEXP_PLACEHOLDER_SCAN, dummy_text))
58
- rescue Yajl::ParseError => e
59
- raise Fluent::ConfigError, "geoip: failed to parse '#{v}' as json."
60
- end
61
- }
62
- validate_json.call if json?(v.tr('\'"\\', ''))
63
- }
64
- }
65
- @placeholder_keys = @map.values.join.scan(REGEXP_PLACEHOLDER_SCAN).map{ |placeholder| placeholder[0] }.uniq
66
- @placeholder_keys.each do |key|
67
- geoip_key = key.match(REGEXP_PLACEHOLDER_SINGLE)[:geoip_key]
68
- case plugin.backend_library
69
- when :geoip
70
- raise Fluent::ConfigError, "#{plugin.backend_library}: unsupported key #{geoip_key}" unless GEOIP_KEYS.include?(geoip_key)
71
- when :geoip2_compat
72
- raise Fluent::ConfigError, "#{plugin.backend_library}: unsupported key #{geoip_key}" unless GEOIP2_COMPAT_KEYS.include?(geoip_key)
73
- when :geoip2_c
74
- # Nothing to do.
75
- # We cannot define supported key(s) before we fetch values from GeoIP2 database
76
- # because geoip2_c can fetch any fields in GeoIP2 database.
77
- end
78
- end
79
-
80
- @geoip = load_database(plugin)
81
- end
82
-
83
- def add_geoip_field(record)
84
- placeholder = create_placeholder(geolocate(get_address(record)))
85
- return record if @skip_adding_null_record && placeholder.values.first.nil?
86
- @map.each do |record_key, value|
87
- if value.match(REGEXP_PLACEHOLDER_SINGLE)
88
- rewrited = placeholder[value]
89
- elsif json?(value)
90
- rewrited = value.gsub(REGEXP_PLACEHOLDER_SCAN) {|match|
91
- match = match[1..match.size-2] if quoted_value?(match)
92
- Yajl::Encoder.encode(placeholder[match])
93
- }
94
- rewrited = parse_json(rewrited)
95
- else
96
- rewrited = value.gsub(REGEXP_PLACEHOLDER_SCAN, placeholder)
97
- end
98
- record[record_key] = rewrited
99
- end
100
- return record
101
- end
102
-
103
- private
104
-
105
- def json?(text)
106
- text.match(/^\[.+\]$/) || text.match(/^\{.+\}$/)
107
- end
108
-
109
- def quoted_value?(text)
110
- # to improbe compatibility with fluentd v1-config
111
- trim_quote = text[1..text.size-2]
112
- text.match(/(^'.+'$|^".+"$)/)
113
- end
114
-
115
- def parse_json(message)
116
- begin
117
- return Yajl::Parser.parse(message)
118
- rescue Yajl::ParseError => e
119
- log.info "geoip: failed to parse '#{message}' as json.", error_class: e.class, error: e.message
120
- return nil
121
- end
122
- end
123
-
124
- def get_address(record)
125
- address = {}
126
- @geoip_lookup_key.each do |field|
127
- address[field] = record[field] || record.dig(*field.split('.'))
128
- end
129
- address
130
- end
131
-
132
- def geolocate(addresses)
133
- geodata = {}
134
- addresses.each do |field, ip|
135
- geo = nil
136
- if ip
137
- geo = if @geoip.respond_to?(:look_up)
138
- @geoip.look_up(ip)
139
- else
140
- @geoip.lookup(ip)
141
- end
142
- end
143
- geodata[field] = geo
144
- end
145
- geodata
146
- end
147
-
148
- def create_placeholder(geodata)
149
- placeholder = {}
150
- @placeholder_keys.each do |placeholder_key|
151
- position = placeholder_key.match(REGEXP_PLACEHOLDER_SINGLE)
152
- next if position.nil? or geodata[position[:record_key]].nil?
153
- keys = [position[:record_key]] + position[:geoip_key].split('.').map(&:to_sym)
154
- placeholder[placeholder_key] = geodata.dig(*keys)
155
- end
156
- placeholder
157
- end
158
-
159
- def load_database(plugin)
160
- case plugin.backend_library
161
- when :geoip
162
- ::GeoIP::City.new(plugin.geoip_database, :memory, false)
163
- when :geoip2_compat
164
- require 'geoip2_compat'
165
- GeoIP2Compat.new(plugin.geoip2_database)
166
- when :geoip2_c
167
- require 'geoip2'
168
- GeoIP2::Database.new(plugin.geoip2_database)
169
- end
170
- rescue LoadError
171
- raise Fluent::ConfigError, "You must install #{plugin.backend_library} gem."
172
- end
173
- end
174
- end
@@ -1,51 +0,0 @@
1
- require 'fluent/plugin/output'
2
- require 'fluent/plugin/geoip'
3
-
4
- class Fluent::Plugin::GeoipOutput < Fluent::Plugin::Output
5
- Fluent::Plugin.register_output('geoip', self)
6
-
7
- helpers :event_emitter, :inject, :compat_parameters
8
-
9
- config_param :geoip_database, :string, default: File.dirname(__FILE__) + '/../../../data/GeoLiteCity.dat'
10
- config_param :geoip2_database, :string, default: File.dirname(__FILE__) + '/../../../data/GeoLite2-City.mmdb'
11
- config_param :geoip_lookup_key, :string, default: 'host'
12
- config_param :tag, :string, default: nil
13
- config_param :skip_adding_null_record, :bool, default: false
14
-
15
- config_param :flush_interval, :time, default: 0
16
- config_param :log_level, :string, default: 'warn'
17
-
18
- config_param :backend_library, :enum, list: Fluent::GeoIP::BACKEND_LIBRARIES, default: :geoip2_c
19
- config_section :buffer do
20
- config_set_default :@type, :memory
21
- config_set_default :chunk_keys, ['tag']
22
- end
23
-
24
- def configure(conf)
25
- compat_parameters_convert(conf, :buffer, default_chunk_key: 'tag')
26
- super
27
- raise Fluetn::ConfigError, "chunk key must include 'tag'" unless @chunk_key_tag
28
- placeholder_validate!(:tag, @tag) if @tag
29
- @geoip = Fluent::GeoIP.new(self, conf)
30
- end
31
-
32
- def format(tag, time, record)
33
- record = inject_values_to_record(tag, time, record)
34
- [tag, time, record].to_msgpack
35
- end
36
-
37
- def formatted_to_msgpack_binary
38
- true
39
- end
40
-
41
- def write(chunk)
42
- es = Fluent::MultiEventStream.new
43
- tag = ""
44
- chunk.each do |_tag, time, record|
45
- tag = _tag
46
- es.add(time, @geoip.add_geoip_field(record))
47
- end
48
- tag = extract_placeholders(@tag, chunk.metadata) if @tag
49
- router.emit_stream(tag, es)
50
- end
51
- end
@@ -1,1076 +0,0 @@
1
- require 'helper'
2
- require 'fluent/plugin/out_geoip'
3
- require 'fluent/test/driver/output'
4
-
5
- class GeoipOutputTest < Test::Unit::TestCase
6
- def setup
7
- Fluent::Test.setup
8
- end
9
-
10
- CONFIG = %[
11
- geoip_lookup_key host
12
- enable_key_city geoip_city
13
- tag geoip.${tag[1]}
14
- ]
15
-
16
- def create_driver(conf = CONFIG, syntax: :v1)
17
- Fluent::Test::Driver::Output.new(Fluent::Plugin::GeoipOutput).configure(conf, syntax: syntax)
18
- end
19
-
20
- sub_test_case "configure" do
21
- test "empty" do
22
- assert_nothing_raised do
23
- create_driver('')
24
- end
25
- end
26
-
27
- test "missing required parameters" do
28
- assert_raise(Fluent::ConfigError) {
29
- create_driver('enable_key_cities')
30
- }
31
- end
32
-
33
- test "minimum" do
34
- d = create_driver %[
35
- enable_key_city geoip_city
36
- tag geoip.${tag[1]}
37
- ]
38
- assert_equal 'geoip_city', d.instance.config['enable_key_city']
39
- end
40
-
41
- test "invalid key name" do
42
- assert_raise(Fluent::ConfigError.new("geoip: unsupported key cities")) do
43
- create_driver('enable_key_cities')
44
- end
45
- end
46
-
47
- test "multiple key config" do
48
- d = create_driver %[
49
- geoip_lookup_key from.ip, to.ip
50
- enable_key_city from_city, to_city
51
- tag geoip.${tag[1]}
52
- ]
53
- assert_equal 'from_city, to_city', d.instance.config['enable_key_city']
54
- end
55
-
56
- test "multiple key config (bad configure)" do
57
- assert_raise(Fluent::ConfigError) do
58
- create_driver %[
59
- geoip_lookup_key from.ip, to.ip
60
- enable_key_city from_city
61
- enable_key_region from_region
62
- tag geoip.${tag[1]}
63
- ]
64
- end
65
- end
66
-
67
- test "invalid json structure w/ Ruby hash like" do
68
- assert_raise(Fluent::ConfigParseError) do
69
- create_driver %[
70
- geoip_lookup_key host
71
- <record>
72
- invalid_json {"foo" => 123}
73
- </record>
74
- tag geoip.${tag[1]}
75
- ]
76
- end
77
- end
78
-
79
- test "invalid json structure w/ unquoted string literal" do
80
- assert_raise(Fluent::ConfigParseError) do
81
- create_driver %[
82
- geoip_lookup_key host
83
- <record>
84
- invalid_json {"foo" : string, "bar" : 123}
85
- </record>
86
- tag geoip.${tag[1]}
87
- ]
88
- end
89
- end
90
-
91
- data(geoip: "geoip",
92
- geoip2_compat: "geoip2_compat")
93
- test "unsupported key" do |backend|
94
- assert_raise(Fluent::ConfigError.new("#{backend}: unsupported key unknown")) do
95
- create_driver %[
96
- backend_library #{backend}
97
- <record>
98
- city ${unknown["host"]}
99
- </record>
100
- tag geoip.${tag[1]}
101
- ]
102
- end
103
- end
104
-
105
- data(geoip: ["geoip", '${city["host"]}'],
106
- geoip2_compat: ["geoip2_compat", '${city["host"]}'],
107
- geoip2_c: ["geoip2_c", '${city.names.en["host"]}'])
108
- test "supported backend" do |(backend, placeholder)|
109
- create_driver %[
110
- backend_library #{backend}
111
- <record>
112
- city #{placeholder}
113
- </record>
114
- tag geoip.${tag[1]}
115
- ]
116
- end
117
-
118
- test "unsupported backend" do
119
- assert_raise(Fluent::ConfigError) do
120
- create_driver %[
121
- backend_library hive_geoip2
122
- <record>
123
- city ${city["host"]}
124
- </record>
125
- tag geoip.${tag[1]}
126
- ]
127
- end
128
- end
129
- end
130
-
131
- sub_test_case "geoip2_c" do
132
- def test_emit_tag_option
133
- d1 = create_driver(%[
134
- backend_library geoip2_c
135
- geoip_lookup_key host
136
- <record>
137
- geoip_city ${city.names.en['host']}
138
- </record>
139
- tag geoip.${tag[1]}
140
- ])
141
- d1.run(default_tag: 'input.access') do
142
- d1.feed({'host' => '66.102.3.80', 'message' => 'valid ip'})
143
- d1.feed({'message' => 'missing field'})
144
- end
145
- events = d1.events
146
- assert_equal 2, events.length
147
- assert_equal 'geoip.access', events[0][0] # tag
148
- assert_equal 'Mountain View', events[0][2]['geoip_city']
149
- assert_equal nil, events[1][2]['geoip_city']
150
- end
151
-
152
- def test_emit_tag_parts
153
- d1 = create_driver(%[
154
- backend_library geoip2_c
155
- geoip_lookup_key host
156
- <record>
157
- geoip_city ${city.names.en['host']}
158
- </record>
159
- tag geoip.${tag[1]}.${tag[2]}.${tag[3]}
160
- ])
161
- d1.run(default_tag: '0.1.2.3') do
162
- d1.feed({'host' => '66.102.3.80'})
163
- end
164
- events = d1.events
165
- assert_equal 1, events.length
166
- assert_equal 'geoip.1.2.3', events[0][0] # tag
167
- assert_equal 'Mountain View', events[0][2]['geoip_city']
168
- end
169
-
170
- def test_emit_with_dot_key
171
- d1 = create_driver(%[
172
- backend_library geoip2_c
173
- geoip_lookup_key ip.origin, ip.dest
174
- <record>
175
- origin_country ${country.iso_code['ip.origin']}
176
- dest_country ${country.iso_code['ip.dest']}
177
- </record>
178
- tag geoip.${tag[1]}
179
- ])
180
- d1.run(default_tag: 'input.access') do
181
- d1.feed({'ip.origin' => '66.102.3.80', 'ip.dest' => '8.8.8.8'})
182
- end
183
- events = d1.events
184
- assert_equal 1, events.length
185
- assert_equal 'geoip.access', events[0][0] # tag
186
- assert_equal 'US', events[0][2]['origin_country']
187
- assert_equal 'US', events[0][2]['dest_country']
188
- end
189
-
190
- def test_emit_with_unknown_address
191
- d1 = create_driver(%[
192
- backend_library geoip2_c
193
- geoip_lookup_key host
194
- <record>
195
- geoip_city ${city.names.en['host']}
196
- geopoint [${location.longitude['host']}, ${location.latitude['host']}]
197
- </record>
198
- skip_adding_null_record false
199
- tag geoip.${tag[1]}
200
- ], syntax: :v0)
201
- d1.run(default_tag: 'input.access') do
202
- # 203.0.113.1 is a test address described in RFC5737
203
- d1.feed({'host' => '203.0.113.1', 'message' => 'invalid ip'})
204
- d1.feed({'host' => '0', 'message' => 'invalid ip'})
205
- end
206
- events = d1.events
207
- assert_equal 2, events.length
208
- assert_equal 'geoip.access', events[0][0] # tag
209
- assert_equal nil, events[0][2]['geoip_city']
210
- assert_equal 'geoip.access', events[1][0] # tag
211
- assert_equal nil, events[1][2]['geoip_city']
212
- end
213
-
214
- def test_emit_with_skip_unknown_address
215
- d1 = create_driver(%[
216
- backend_library geoip2_c
217
- geoip_lookup_key host
218
- <record>
219
- geoip_city ${city.names.en['host']}
220
- geopoint [${location.longitude['host']}, ${location.latitude['host']}]
221
- </record>
222
- skip_adding_null_record true
223
- tag geoip.${tag[1]}
224
- ], syntax: :v0)
225
- d1.run(default_tag: 'input.access') do
226
- # 203.0.113.1 is a test address described in RFC5737
227
- d1.feed({'host' => '203.0.113.1', 'message' => 'invalid ip'})
228
- d1.feed({'host' => '0', 'message' => 'invalid ip'})
229
- d1.feed({'host' => '66.102.3.80', 'message' => 'google bot'})
230
- end
231
- events = d1.events
232
- assert_equal 3, events.length
233
- assert_equal 'geoip.access', events[0][0] # tag
234
- assert_equal nil, events[0][2]['geoip_city']
235
- assert_equal nil, events[0][2]['geopoint']
236
- assert_equal 'geoip.access', events[1][0] # tag
237
- assert_equal nil, events[1][2]['geoip_city']
238
- assert_equal nil, events[1][2]['geopoint']
239
- assert_equal 'Mountain View', events[2][2]['geoip_city']
240
- assert_equal [-122.0574, 37.419200000000004], events[2][2]['geopoint']
241
- end
242
-
243
- def test_emit_record_directive
244
- d1 = create_driver(%[
245
- backend_library geoip2_c
246
- geoip_lookup_key from.ip
247
- <record>
248
- from_city ${city.names.en['from.ip']}
249
- from_country ${country.names.en['from.ip']}
250
- latitude ${location.latitude['from.ip']}
251
- longitude ${location.longitude['from.ip']}
252
- float_concat ${location.latitude['from.ip']},${location.longitude['from.ip']}
253
- float_array [${location.longitude['from.ip']}, ${location.latitude['from.ip']}]
254
- float_nest { "lat" : ${location.latitude['from.ip']}, "lon" : ${location.longitude['from.ip']}}
255
- string_concat ${location.latitude['from.ip']},${location.longitude['from.ip']}
256
- string_array [${city.names.en['from.ip']}, ${country.names.en['from.ip']}]
257
- string_nest { "city" : ${city.names.en['from.ip']}, "country_name" : ${country.names.en['from.ip']}}
258
- unknown_city ${city.names.en['unknown_key']}
259
- undefined ${city.names.en['undefined']}
260
- broken_array1 [${location.longitude['from.ip']}, ${location.latitude['undefined']}]
261
- broken_array2 [${location.longitude['undefined']}, ${location.latitude['undefined']}]
262
- </record>
263
- tag geoip.${tag[1]}
264
- ], syntax: :v0)
265
- d1.run(default_tag: 'input.access') do
266
- d1.feed({'from' => {'ip' => '66.102.3.80'}})
267
- d1.feed({'message' => 'missing field'})
268
- end
269
- events = d1.events
270
- assert_equal 2, events.length
271
-
272
- assert_equal 'geoip.access', events[0][0] # tag
273
- assert_equal 'Mountain View', events[0][2]['from_city']
274
- assert_equal 'United States', events[0][2]['from_country']
275
- assert_equal 37.419200000000004, events[0][2]['latitude']
276
- assert_equal -122.0574, events[0][2]['longitude']
277
- assert_equal '37.419200000000004,-122.0574', events[0][2]['float_concat']
278
- assert_equal [-122.0574, 37.419200000000004], events[0][2]['float_array']
279
- float_nest = {"lat" => 37.419200000000004, "lon" => -122.0574 }
280
- assert_equal float_nest, events[0][2]['float_nest']
281
- assert_equal '37.419200000000004,-122.0574', events[0][2]['string_concat']
282
- assert_equal ["Mountain View", "United States"], events[0][2]['string_array']
283
- string_nest = {"city" => "Mountain View", "country_name" => "United States"}
284
- assert_equal string_nest, events[0][2]['string_nest']
285
- assert_equal nil, events[0][2]['unknown_city']
286
- assert_equal nil, events[0][2]['undefined']
287
- assert_equal [-122.0574, nil], events[0][2]['broken_array1']
288
- assert_equal [nil, nil], events[0][2]['broken_array2']
289
-
290
- assert_equal nil, events[1][2]['from_city']
291
- assert_equal nil, events[1][2]['from_country']
292
- assert_equal nil, events[1][2]['latitude']
293
- assert_equal nil, events[1][2]['longitude']
294
- assert_equal ',', events[1][2]['float_concat']
295
- assert_equal [nil, nil], events[1][2]['float_array']
296
- float_nest = {"lat" => nil, "lon" => nil}
297
- assert_equal float_nest, events[1][2]['float_nest']
298
- assert_equal ',', events[1][2]['string_concat']
299
- assert_equal [nil, nil], events[1][2]['string_array']
300
- string_nest = {"city" => nil, "country_name" => nil}
301
- assert_equal string_nest, events[1][2]['string_nest']
302
- assert_equal nil, events[1][2]['unknown_city']
303
- assert_equal nil, events[1][2]['undefined']
304
- assert_equal [nil, nil], events[1][2]['broken_array1']
305
- assert_equal [nil, nil], events[1][2]['broken_array2']
306
- end
307
-
308
- def test_emit_record_directive_multiple_record
309
- d1 = create_driver(%[
310
- backend_library geoip2_c
311
- geoip_lookup_key from.ip, to.ip
312
- <record>
313
- from_city ${city.names.en['from.ip']}
314
- to_city ${city.names.en['to.ip']}
315
- from_country ${country.names.en['from.ip']}
316
- to_country ${country.names.en['to.ip']}
317
- string_array [${country.names.en['from.ip']}, ${country.names.en['to.ip']}]
318
- </record>
319
- tag geoip.${tag[1]}
320
- ], syntax: :v0)
321
- d1.run(default_tag: 'input.access') do
322
- d1.feed({'from' => {'ip' => '66.102.3.80'}, 'to' => {'ip' => '125.54.15.42'}})
323
- d1.feed({'message' => 'missing field'})
324
- end
325
- events = d1.events
326
- assert_equal 2, events.length
327
-
328
- assert_equal 'geoip.access', events[0][0] # tag
329
- assert_equal 'Mountain View', events[0][2]['from_city']
330
- assert_equal 'United States', events[0][2]['from_country']
331
- assert_equal 'Tokorozawa', events[0][2]['to_city']
332
- assert_equal 'Japan', events[0][2]['to_country']
333
- assert_equal ['United States','Japan'], events[0][2]['string_array']
334
-
335
- assert_equal nil, events[1][2]['from_city']
336
- assert_equal nil, events[1][2]['to_city']
337
- assert_equal nil, events[1][2]['from_country']
338
- assert_equal nil, events[1][2]['to_country']
339
- assert_equal [nil, nil], events[1][2]['string_array']
340
- end
341
-
342
- def config_quoted_record
343
- %[
344
- backend_library geoip2_c
345
- geoip_lookup_key host
346
- <record>
347
- location_properties '{ "country_code" : "${country.iso_code["host"]}", "lat": ${location.latitude["host"]}, "lon": ${location.longitude["host"]} }'
348
- location_string ${location.latitude['host']},${location.longitude['host']}
349
- location_string2 ${country.iso_code["host"]}
350
- location_array "[${location.longitude['host']},${location.latitude['host']}]"
351
- location_array2 '[${location.longitude["host"]},${location.latitude["host"]}]'
352
- peculiar_pattern '[GEOIP] message => {"lat":${location.latitude["host"]}, "lon":${location.longitude["host"]}}'
353
- </record>
354
- tag geoip.${tag[1]}
355
- ]
356
- end
357
-
358
- def test_emit_quoted_record
359
- d1 = create_driver(config_quoted_record)
360
- d1.run(default_tag: 'input.access') do
361
- d1.feed({'host' => '66.102.3.80', 'message' => 'valid ip'})
362
- end
363
- events = d1.events
364
- assert_equal 1, events.length
365
- assert_equal 'geoip.access', events[0][0] # tag
366
- location_properties = { "country_code" => "US", "lat" => 37.419200000000004, "lon"=> -122.0574 }
367
- assert_equal location_properties, events[0][2]['location_properties']
368
- assert_equal '37.419200000000004,-122.0574', events[0][2]['location_string']
369
- assert_equal 'US', events[0][2]['location_string2']
370
- assert_equal [-122.0574, 37.419200000000004], events[0][2]['location_array']
371
- assert_equal [-122.0574, 37.419200000000004], events[0][2]['location_array2']
372
- assert_equal '[GEOIP] message => {"lat":37.419200000000004, "lon":-122.0574}', events[0][2]['peculiar_pattern']
373
- end
374
-
375
- def test_emit_v1_config_compatibility
376
- d1 = create_driver(config_quoted_record)
377
- d1.run(default_tag: 'input.access') do
378
- d1.feed({'host' => '66.102.3.80', 'message' => 'valid ip'})
379
- end
380
- events = d1.events
381
- assert_equal 1, events.length
382
- assert_equal 'geoip.access', events[0][0] # tag
383
- location_properties = { "country_code" => "US", "lat" => 37.419200000000004, "lon"=> -122.0574 }
384
- assert_equal location_properties, events[0][2]['location_properties']
385
- assert_equal '37.419200000000004,-122.0574', events[0][2]['location_string']
386
- assert_equal 'US', events[0][2]['location_string2']
387
- assert_equal [-122.0574, 37.419200000000004], events[0][2]['location_array']
388
- assert_equal [-122.0574, 37.419200000000004], events[0][2]['location_array2']
389
- assert_equal '[GEOIP] message => {"lat":37.419200000000004, "lon":-122.0574}', events[0][2]['peculiar_pattern']
390
- end
391
-
392
- def test_emit_multiline_v1_config
393
- d1 = create_driver(%[
394
- backend_library geoip2_c
395
- geoip_lookup_key host
396
- <record>
397
- location_properties {
398
- "city": "${city.names.en['host']}",
399
- "country_code": "${country.iso_code['host']}",
400
- "latitude": "${location.latitude['host']}",
401
- "longitude": "${location.longitude['host']}"
402
- }
403
- </record>
404
- tag geoip.${tag[1]}
405
- ])
406
- d1.run(default_tag: 'input.access') do
407
- d1.feed({'host' => '66.102.3.80', 'message' => 'valid ip'})
408
- end
409
- events = d1.events
410
- assert_equal 1, events.length
411
- assert_equal 'geoip.access', events[0][0] # tag
412
- location_properties = { "city"=>"Mountain View", "country_code"=>"US", "latitude"=>37.419200000000004, "longitude"=>-122.0574 }
413
- assert_equal location_properties, events[0][2]['location_properties']
414
- end
415
- end
416
-
417
- sub_test_case "geoip2_compat" do
418
- def test_emit_tag_option
419
- d1 = create_driver(%[
420
- backend_library geoip2_compat
421
- geoip_lookup_key host
422
- <record>
423
- geoip_city ${city['host']}
424
- </record>
425
- tag geoip.${tag[1]}
426
- ])
427
- d1.run(default_tag: 'input.access') do
428
- d1.feed({'host' => '66.102.3.80', 'message' => 'valid ip'})
429
- d1.feed({'message' => 'missing field'})
430
- end
431
- events = d1.events
432
- assert_equal 2, events.length
433
- assert_equal 'geoip.access', events[0][0] # tag
434
- assert_equal 'Mountain View', events[0][2]['geoip_city']
435
- assert_equal nil, events[1][2]['geoip_city']
436
- end
437
-
438
- def test_emit_tag_parts
439
- d1 = create_driver(%[
440
- backend_library geoip2_compat
441
- geoip_lookup_key host
442
- <record>
443
- geoip_city ${city['host']}
444
- </record>
445
- tag geoip.${tag[1]}.${tag[2]}.${tag[3]}
446
- ])
447
- d1.run(default_tag: '0.1.2.3') do
448
- d1.feed({'host' => '66.102.3.80'})
449
- end
450
- events = d1.events
451
- assert_equal 1, events.length
452
- assert_equal 'geoip.1.2.3', events[0][0] # tag
453
- assert_equal 'Mountain View', events[0][2]['geoip_city']
454
- end
455
-
456
- def test_emit_with_dot_key
457
- d1 = create_driver(%[
458
- backend_library geoip2_compat
459
- geoip_lookup_key ip.origin, ip.dest
460
- <record>
461
- origin_country ${country_code['ip.origin']}
462
- dest_country ${country_code['ip.dest']}
463
- </record>
464
- tag geoip.${tag[1]}
465
- ])
466
- d1.run(default_tag: 'input.access') do
467
- d1.feed({'ip.origin' => '66.102.3.80', 'ip.dest' => '8.8.8.8'})
468
- end
469
- events = d1.events
470
- assert_equal 1, events.length
471
- assert_equal 'geoip.access', events[0][0] # tag
472
- assert_equal 'US', events[0][2]['origin_country']
473
- assert_equal 'US', events[0][2]['dest_country']
474
- end
475
-
476
- def test_emit_with_unknown_address
477
- d1 = create_driver(%[
478
- backend_library geoip2_compat
479
- geoip_lookup_key host
480
- <record>
481
- geoip_city ${city['host']}
482
- geopoint [${longitude['host']}, ${latitude['host']}]
483
- </record>
484
- skip_adding_null_record false
485
- tag geoip.${tag[1]}
486
- ], syntax: :v0)
487
- d1.run(default_tag: 'input.access') do
488
- # 203.0.113.1 is a test address described in RFC5737
489
- d1.feed({'host' => '203.0.113.1', 'message' => 'invalid ip'})
490
- d1.feed({'host' => '0', 'message' => 'invalid ip'})
491
- end
492
- events = d1.events
493
- assert_equal 2, events.length
494
- assert_equal 'geoip.access', events[0][0] # tag
495
- assert_equal nil, events[0][2]['geoip_city']
496
- assert_equal 'geoip.access', events[1][0] # tag
497
- assert_equal nil, events[1][2]['geoip_city']
498
- end
499
-
500
- def test_emit_with_skip_unknown_address
501
- d1 = create_driver(%[
502
- backend_library geoip2_compat
503
- geoip_lookup_key host
504
- <record>
505
- geoip_city ${city['host']}
506
- geopoint [${longitude['host']}, ${latitude['host']}]
507
- </record>
508
- skip_adding_null_record true
509
- tag geoip.${tag[1]}
510
- ], syntax: :v0)
511
- d1.run(default_tag: 'input.access') do
512
- # 203.0.113.1 is a test address described in RFC5737
513
- d1.feed({'host' => '203.0.113.1', 'message' => 'invalid ip'})
514
- d1.feed({'host' => '0', 'message' => 'invalid ip'})
515
- d1.feed({'host' => '66.102.3.80', 'message' => 'google bot'})
516
- end
517
- events = d1.events
518
- assert_equal 3, events.length
519
- assert_equal 'geoip.access', events[0][0] # tag
520
- assert_equal nil, events[0][2]['geoip_city']
521
- assert_equal nil, events[0][2]['geopoint']
522
- assert_equal 'geoip.access', events[1][0] # tag
523
- assert_equal nil, events[1][2]['geoip_city']
524
- assert_equal nil, events[1][2]['geopoint']
525
- assert_equal 'Mountain View', events[2][2]['geoip_city']
526
- assert_equal [-122.0574, 37.419200000000004], events[2][2]['geopoint']
527
- end
528
-
529
- def test_emit_record_directive
530
- d1 = create_driver(%[
531
- backend_library geoip2_compat
532
- geoip_lookup_key from.ip
533
- <record>
534
- from_city ${city['from.ip']}
535
- from_country ${country_name['from.ip']}
536
- latitude ${latitude['from.ip']}
537
- longitude ${longitude['from.ip']}
538
- float_concat ${latitude['from.ip']},${longitude['from.ip']}
539
- float_array [${longitude['from.ip']}, ${latitude['from.ip']}]
540
- float_nest { "lat" : ${latitude['from.ip']}, "lon" : ${longitude['from.ip']}}
541
- string_concat ${latitude['from.ip']},${longitude['from.ip']}
542
- string_array [${city['from.ip']}, ${country_name['from.ip']}]
543
- string_nest { "city" : ${city['from.ip']}, "country_name" : ${country_name['from.ip']}}
544
- unknown_city ${city['unknown_key']}
545
- undefined ${city['undefined']}
546
- broken_array1 [${longitude['from.ip']}, ${latitude['undefined']}]
547
- broken_array2 [${longitude['undefined']}, ${latitude['undefined']}]
548
- </record>
549
- tag geoip.${tag[1]}
550
- ], syntax: :v0)
551
- d1.run(default_tag: 'input.access') do
552
- d1.feed({'from' => {'ip' => '66.102.3.80'}})
553
- d1.feed({'message' => 'missing field'})
554
- end
555
- events = d1.events
556
- assert_equal 2, events.length
557
-
558
- assert_equal 'geoip.access', events[0][0] # tag
559
- assert_equal 'Mountain View', events[0][2]['from_city']
560
- assert_equal 'United States', events[0][2]['from_country']
561
- assert_equal 37.419200000000004, events[0][2]['latitude']
562
- assert_equal -122.0574, events[0][2]['longitude']
563
- assert_equal '37.419200000000004,-122.0574', events[0][2]['float_concat']
564
- assert_equal [-122.0574, 37.419200000000004], events[0][2]['float_array']
565
- float_nest = {"lat" => 37.419200000000004, "lon" => -122.0574 }
566
- assert_equal float_nest, events[0][2]['float_nest']
567
- assert_equal '37.419200000000004,-122.0574', events[0][2]['string_concat']
568
- assert_equal ["Mountain View", "United States"], events[0][2]['string_array']
569
- string_nest = {"city" => "Mountain View", "country_name" => "United States"}
570
- assert_equal string_nest, events[0][2]['string_nest']
571
- assert_equal nil, events[0][2]['unknown_city']
572
- assert_equal nil, events[0][2]['undefined']
573
- assert_equal [-122.0574, nil], events[0][2]['broken_array1']
574
- assert_equal [nil, nil], events[0][2]['broken_array2']
575
-
576
- assert_equal nil, events[1][2]['from_city']
577
- assert_equal nil, events[1][2]['from_country']
578
- assert_equal nil, events[1][2]['latitude']
579
- assert_equal nil, events[1][2]['longitude']
580
- assert_equal ',', events[1][2]['float_concat']
581
- assert_equal [nil, nil], events[1][2]['float_array']
582
- float_nest = {"lat" => nil, "lon" => nil}
583
- assert_equal float_nest, events[1][2]['float_nest']
584
- assert_equal ',', events[1][2]['string_concat']
585
- assert_equal [nil, nil], events[1][2]['string_array']
586
- string_nest = {"city" => nil, "country_name" => nil}
587
- assert_equal string_nest, events[1][2]['string_nest']
588
- assert_equal nil, events[1][2]['unknown_city']
589
- assert_equal nil, events[1][2]['undefined']
590
- assert_equal [nil, nil], events[1][2]['broken_array1']
591
- assert_equal [nil, nil], events[1][2]['broken_array2']
592
- end
593
-
594
- def test_emit_record_directive_multiple_record
595
- d1 = create_driver(%[
596
- backend_library geoip2_compat
597
- geoip_lookup_key from.ip, to.ip
598
- <record>
599
- from_city ${city['from.ip']}
600
- to_city ${city['to.ip']}
601
- from_country ${country_name['from.ip']}
602
- to_country ${country_name['to.ip']}
603
- string_array [${country_name['from.ip']}, ${country_name['to.ip']}]
604
- </record>
605
- tag geoip.${tag[1]}
606
- ], syntax: :v0)
607
- d1.run(default_tag: 'input.access') do
608
- d1.feed({'from' => {'ip' => '66.102.3.80'}, 'to' => {'ip' => '125.54.15.42'}})
609
- d1.feed({'message' => 'missing field'})
610
- end
611
- events = d1.events
612
- assert_equal 2, events.length
613
-
614
- assert_equal 'geoip.access', events[0][0] # tag
615
- assert_equal 'Mountain View', events[0][2]['from_city']
616
- assert_equal 'United States', events[0][2]['from_country']
617
- assert_equal 'Tokorozawa', events[0][2]['to_city']
618
- assert_equal 'Japan', events[0][2]['to_country']
619
- assert_equal ['United States','Japan'], events[0][2]['string_array']
620
-
621
- assert_equal nil, events[1][2]['from_city']
622
- assert_equal nil, events[1][2]['to_city']
623
- assert_equal nil, events[1][2]['from_country']
624
- assert_equal nil, events[1][2]['to_country']
625
- assert_equal [nil, nil], events[1][2]['string_array']
626
- end
627
-
628
- def config_quoted_record
629
- %[
630
- backend_library geoip2_compat
631
- geoip_lookup_key host
632
- <record>
633
- location_properties '{ "country_code" : "${country_code["host"]}", "lat": ${latitude["host"]}, "lon": ${longitude["host"]} }'
634
- location_string ${latitude['host']},${longitude['host']}
635
- location_string2 ${country_code["host"]}
636
- location_array "[${longitude['host']},${latitude['host']}]"
637
- location_array2 '[${longitude["host"]},${latitude["host"]}]'
638
- peculiar_pattern '[GEOIP] message => {"lat":${latitude["host"]}, "lon":${longitude["host"]}}'
639
- </record>
640
- tag geoip.${tag[1]}
641
- ]
642
- end
643
-
644
- def test_emit_quoted_record
645
- d1 = create_driver(config_quoted_record)
646
- d1.run(default_tag: 'input.access') do
647
- d1.feed({'host' => '66.102.3.80', 'message' => 'valid ip'})
648
- end
649
- events = d1.events
650
- assert_equal 1, events.length
651
- assert_equal 'geoip.access', events[0][0] # tag
652
- location_properties = { "country_code" => "US", "lat" => 37.419200000000004, "lon"=> -122.0574 }
653
- assert_equal location_properties, events[0][2]['location_properties']
654
- assert_equal '37.419200000000004,-122.0574', events[0][2]['location_string']
655
- assert_equal 'US', events[0][2]['location_string2']
656
- assert_equal [-122.0574, 37.419200000000004], events[0][2]['location_array']
657
- assert_equal [-122.0574, 37.419200000000004], events[0][2]['location_array2']
658
- assert_equal '[GEOIP] message => {"lat":37.419200000000004, "lon":-122.0574}', events[0][2]['peculiar_pattern']
659
- end
660
-
661
- def test_emit_v1_config_compatibility
662
- d1 = create_driver(config_quoted_record)
663
- d1.run(default_tag: 'input.access') do
664
- d1.feed({'host' => '66.102.3.80', 'message' => 'valid ip'})
665
- end
666
- events = d1.events
667
- assert_equal 1, events.length
668
- assert_equal 'geoip.access', events[0][0] # tag
669
- location_properties = { "country_code" => "US", "lat" => 37.419200000000004, "lon"=> -122.0574 }
670
- assert_equal location_properties, events[0][2]['location_properties']
671
- assert_equal '37.419200000000004,-122.0574', events[0][2]['location_string']
672
- assert_equal 'US', events[0][2]['location_string2']
673
- assert_equal [-122.0574, 37.419200000000004], events[0][2]['location_array']
674
- assert_equal [-122.0574, 37.419200000000004], events[0][2]['location_array2']
675
- assert_equal '[GEOIP] message => {"lat":37.419200000000004, "lon":-122.0574}', events[0][2]['peculiar_pattern']
676
- end
677
-
678
- def test_emit_multiline_v1_config
679
- d1 = create_driver(%[
680
- backend_library geoip2_compat
681
- geoip_lookup_key host
682
- <record>
683
- location_properties {
684
- "city": "${city['host']}",
685
- "country_code": "${country_code['host']}",
686
- "latitude": "${latitude['host']}",
687
- "longitude": "${longitude['host']}"
688
- }
689
- </record>
690
- tag geoip.${tag[1]}
691
- ])
692
- d1.run(default_tag: 'input.access') do
693
- d1.feed({'host' => '66.102.3.80', 'message' => 'valid ip'})
694
- end
695
- events = d1.events
696
- assert_equal 1, events.length
697
- assert_equal 'geoip.access', events[0][0] # tag
698
- location_properties = { "city"=>"Mountain View", "country_code"=>"US", "latitude"=>37.419200000000004, "longitude"=>-122.0574 }
699
- assert_equal location_properties, events[0][2]['location_properties']
700
- end
701
- end
702
-
703
- sub_test_case "geoip legacy" do
704
- def test_emit
705
- d1 = create_driver(%[
706
- backend_library geoip
707
- geoip_lookup_key host
708
- enable_key_city geoip_city
709
- tag geoip.${tag[1]}
710
- ])
711
- d1.run(default_tag: 'input.access') do
712
- d1.feed({'host' => '66.102.3.80', 'message' => 'valid ip'})
713
- d1.feed({'message' => 'missing field'})
714
- end
715
- events = d1.events
716
- assert_equal 2, events.length
717
- assert_equal 'geoip.access', events[0][0] # tag
718
- assert_equal 'Mountain View', events[0][2]['geoip_city']
719
- assert_equal nil, events[1][2]['geoip_city']
720
- end
721
-
722
- def test_emit_tag_option
723
- d1 = create_driver(%[
724
- backend_library geoip
725
- geoip_lookup_key host
726
- <record>
727
- geoip_city ${city['host']}
728
- </record>
729
- tag geoip.${tag[1]}
730
- ])
731
- d1.run(default_tag: 'input.access') do
732
- d1.feed({'host' => '66.102.3.80', 'message' => 'valid ip'})
733
- d1.feed({'message' => 'missing field'})
734
- end
735
- events = d1.events
736
- assert_equal 2, events.length
737
- assert_equal 'geoip.access', events[0][0] # tag
738
- assert_equal 'Mountain View', events[0][2]['geoip_city']
739
- assert_equal nil, events[1][2]['geoip_city']
740
- end
741
-
742
- def test_emit_tag_parts
743
- d1 = create_driver(%[
744
- backend_library geoip
745
- geoip_lookup_key host
746
- <record>
747
- geoip_city ${city['host']}
748
- </record>
749
- tag geoip.${tag[1]}.${tag[2]}.${tag[3]}
750
- ])
751
- d1.run(default_tag: '0.1.2.3') do
752
- d1.feed({'host' => '66.102.3.80'})
753
- end
754
- events = d1.events
755
- assert_equal 1, events.length
756
- assert_equal 'geoip.1.2.3', events[0][0] # tag
757
- assert_equal 'Mountain View', events[0][2]['geoip_city']
758
- end
759
-
760
- def test_emit_with_dot_key
761
- d1 = create_driver(%[
762
- backend_library geoip
763
- geoip_lookup_key ip.origin, ip.dest
764
- <record>
765
- origin_country ${country_code['ip.origin']}
766
- dest_country ${country_code['ip.dest']}
767
- </record>
768
- tag geoip.${tag[1]}
769
- ])
770
- d1.run(default_tag: 'input.access') do
771
- d1.feed({'ip.origin' => '66.102.3.80', 'ip.dest' => '8.8.8.8'})
772
- end
773
- events = d1.events
774
- assert_equal 1, events.length
775
- assert_equal 'geoip.access', events[0][0] # tag
776
- assert_equal 'US', events[0][2]['origin_country']
777
- assert_equal 'US', events[0][2]['dest_country']
778
- end
779
-
780
- def test_emit_nested_attr
781
- d1 = create_driver(%[
782
- backend_library geoip
783
- geoip_lookup_key host.ip
784
- enable_key_city geoip_city
785
- tag geoip.${tag[1]}
786
- ])
787
- d1.run(default_tag: 'input.access') do
788
- d1.feed({'host' => {'ip' => '66.102.3.80'}, 'message' => 'valid ip'})
789
- d1.feed({'message' => 'missing field'})
790
- end
791
- events = d1.events
792
- assert_equal 2, events.length
793
- assert_equal 'geoip.access', events[0][0] # tag
794
- assert_equal 'Mountain View', events[0][2]['geoip_city']
795
- assert_equal nil, events[1][2]['geoip_city']
796
- end
797
-
798
- def test_emit_with_unknown_address
799
- d1 = create_driver(%[
800
- backend_library geoip
801
- geoip_lookup_key host
802
- <record>
803
- geoip_city ${city['host']}
804
- geopoint [${longitude['host']}, ${latitude['host']}]
805
- </record>
806
- skip_adding_null_record false
807
- tag geoip.${tag[1]}
808
- ], syntax: :v0)
809
- d1.run(default_tag: 'input.access') do
810
- # 203.0.113.1 is a test address described in RFC5737
811
- d1.feed({'host' => '203.0.113.1', 'message' => 'invalid ip'})
812
- d1.feed({'host' => '0', 'message' => 'invalid ip'})
813
- end
814
- events = d1.events
815
- assert_equal 2, events.length
816
- assert_equal 'geoip.access', events[0][0] # tag
817
- assert_equal nil, events[0][2]['geoip_city']
818
- assert_equal 'geoip.access', events[1][0] # tag
819
- assert_equal nil, events[1][2]['geoip_city']
820
- end
821
-
822
- def test_emit_with_skip_unknown_address
823
- d1 = create_driver(%[
824
- backend_library geoip
825
- geoip_lookup_key host
826
- <record>
827
- geoip_city ${city['host']}
828
- geopoint [${longitude['host']}, ${latitude['host']}]
829
- </record>
830
- skip_adding_null_record true
831
- tag geoip.${tag[1]}
832
- ], syntax: :v0)
833
- d1.run(default_tag: 'input.access') do
834
- # 203.0.113.1 is a test address described in RFC5737
835
- d1.feed({'host' => '203.0.113.1', 'message' => 'invalid ip'})
836
- d1.feed({'host' => '0', 'message' => 'invalid ip'})
837
- d1.feed({'host' => '66.102.3.80', 'message' => 'google bot'})
838
- end
839
- events = d1.events
840
- assert_equal 3, events.length
841
- assert_equal 'geoip.access', events[0][0] # tag
842
- assert_equal nil, events[0][2]['geoip_city']
843
- assert_equal nil, events[0][2]['geopoint']
844
- assert_equal 'geoip.access', events[1][0] # tag
845
- assert_equal nil, events[1][2]['geoip_city']
846
- assert_equal nil, events[1][2]['geopoint']
847
- assert_equal 'Mountain View', events[2][2]['geoip_city']
848
- assert_equal [-122.05740356445312, 37.4192008972168], events[2][2]['geopoint']
849
- end
850
-
851
- def test_emit_multiple_key
852
- d1 = create_driver(%[
853
- backend_library geoip
854
- geoip_lookup_key from.ip, to.ip
855
- enable_key_city from_city, to_city
856
- tag geoip.${tag[1]}
857
- ])
858
- d1.run(default_tag: 'input.access') do
859
- d1.feed({'from' => {'ip' => '66.102.3.80'}, 'to' => {'ip' => '125.54.15.42'}})
860
- d1.feed({'message' => 'missing field'})
861
- end
862
- events = d1.events
863
- assert_equal 2, events.length
864
- assert_equal 'geoip.access', events[0][0] # tag
865
- assert_equal 'Mountain View', events[0][2]['from_city']
866
- assert_equal 'Tokorozawa', events[0][2]['to_city']
867
- assert_equal nil, events[1][2]['from_city']
868
- assert_equal nil, events[1][2]['to_city']
869
- end
870
-
871
- def test_emit_multiple_key_multiple_record
872
- d1 = create_driver(%[
873
- backend_library geoip
874
- geoip_lookup_key from.ip, to.ip
875
- enable_key_city from_city, to_city
876
- enable_key_country_name from_country, to_country
877
- tag geoip.${tag[1]}
878
- ])
879
- d1.run(default_tag: 'input.access') do
880
- d1.feed({'from' => {'ip' => '66.102.3.80'}, 'to' => {'ip' => '125.54.15.42'}})
881
- d1.feed({'from' => {'ip' => '66.102.3.80'}})
882
- d1.feed({'message' => 'missing field'})
883
- end
884
- events = d1.events
885
- assert_equal 3, events.length
886
- assert_equal 'geoip.access', events[0][0] # tag
887
- assert_equal 'Mountain View', events[0][2]['from_city']
888
- assert_equal 'United States', events[0][2]['from_country']
889
- assert_equal 'Tokorozawa', events[0][2]['to_city']
890
- assert_equal 'Japan', events[0][2]['to_country']
891
-
892
- assert_equal 'Mountain View', events[1][2]['from_city']
893
- assert_equal 'United States', events[1][2]['from_country']
894
- assert_equal nil, events[1][2]['to_city']
895
- assert_equal nil, events[1][2]['to_country']
896
-
897
- assert_equal nil, events[2][2]['from_city']
898
- assert_equal nil, events[2][2]['from_country']
899
- assert_equal nil, events[2][2]['to_city']
900
- assert_equal nil, events[2][2]['to_country']
901
- end
902
-
903
- def test_emit_record_directive
904
- d1 = create_driver(%[
905
- backend_library geoip
906
- geoip_lookup_key from.ip
907
- <record>
908
- from_city ${city['from.ip']}
909
- from_country ${country_name['from.ip']}
910
- latitude ${latitude['from.ip']}
911
- longitude ${longitude['from.ip']}
912
- float_concat ${latitude['from.ip']},${longitude['from.ip']}
913
- float_array [${longitude['from.ip']}, ${latitude['from.ip']}]
914
- float_nest { "lat" : ${latitude['from.ip']}, "lon" : ${longitude['from.ip']}}
915
- string_concat ${latitude['from.ip']},${longitude['from.ip']}
916
- string_array [${city['from.ip']}, ${country_name['from.ip']}]
917
- string_nest { "city" : ${city['from.ip']}, "country_name" : ${country_name['from.ip']}}
918
- unknown_city ${city['unknown_key']}
919
- undefined ${city['undefined']}
920
- broken_array1 [${longitude['from.ip']}, ${latitude['undefined']}]
921
- broken_array2 [${longitude['undefined']}, ${latitude['undefined']}]
922
- </record>
923
- tag geoip.${tag[1]}
924
- ], syntax: :v0)
925
- d1.run(default_tag: 'input.access') do
926
- d1.feed({'from' => {'ip' => '66.102.3.80'}})
927
- d1.feed({'message' => 'missing field'})
928
- end
929
- events = d1.events
930
- assert_equal 2, events.length
931
-
932
- assert_equal 'geoip.access', events[0][0] # tag
933
- assert_equal 'Mountain View', events[0][2]['from_city']
934
- assert_equal 'United States', events[0][2]['from_country']
935
- assert_equal 37.4192008972168, events[0][2]['latitude']
936
- assert_equal -122.05740356445312, events[0][2]['longitude']
937
- assert_equal '37.4192008972168,-122.05740356445312', events[0][2]['float_concat']
938
- assert_equal [-122.05740356445312, 37.4192008972168], events[0][2]['float_array']
939
- float_nest = {"lat" => 37.4192008972168, "lon" => -122.05740356445312 }
940
- assert_equal float_nest, events[0][2]['float_nest']
941
- assert_equal '37.4192008972168,-122.05740356445312', events[0][2]['string_concat']
942
- assert_equal ["Mountain View", "United States"], events[0][2]['string_array']
943
- string_nest = {"city" => "Mountain View", "country_name" => "United States"}
944
- assert_equal string_nest, events[0][2]['string_nest']
945
- assert_equal nil, events[0][2]['unknown_city']
946
- assert_equal nil, events[0][2]['undefined']
947
- assert_equal [-122.05740356445312, nil], events[0][2]['broken_array1']
948
- assert_equal [nil, nil], events[0][2]['broken_array2']
949
-
950
- assert_equal nil, events[1][2]['from_city']
951
- assert_equal nil, events[1][2]['from_country']
952
- assert_equal nil, events[1][2]['latitude']
953
- assert_equal nil, events[1][2]['longitude']
954
- assert_equal ',', events[1][2]['float_concat']
955
- assert_equal [nil, nil], events[1][2]['float_array']
956
- float_nest = {"lat" => nil, "lon" => nil}
957
- assert_equal float_nest, events[1][2]['float_nest']
958
- assert_equal ',', events[1][2]['string_concat']
959
- assert_equal [nil, nil], events[1][2]['string_array']
960
- string_nest = {"city" => nil, "country_name" => nil}
961
- assert_equal string_nest, events[1][2]['string_nest']
962
- assert_equal nil, events[1][2]['unknown_city']
963
- assert_equal nil, events[1][2]['undefined']
964
- assert_equal [nil, nil], events[1][2]['broken_array1']
965
- assert_equal [nil, nil], events[1][2]['broken_array2']
966
- end
967
-
968
- def test_emit_record_directive_multiple_record
969
- d1 = create_driver(%[
970
- backend_library geoip
971
- geoip_lookup_key from.ip, to.ip
972
- <record>
973
- from_city ${city['from.ip']}
974
- to_city ${city['to.ip']}
975
- from_country ${country_name['from.ip']}
976
- to_country ${country_name['to.ip']}
977
- string_array [${country_name['from.ip']}, ${country_name['to.ip']}]
978
- </record>
979
- tag geoip.${tag[1]}
980
- ], syntax: :v0)
981
- d1.run(default_tag: 'input.access') do
982
- d1.feed({'from' => {'ip' => '66.102.3.80'}, 'to' => {'ip' => '125.54.15.42'}})
983
- d1.feed({'message' => 'missing field'})
984
- end
985
- events = d1.events
986
- assert_equal 2, events.length
987
-
988
- assert_equal 'geoip.access', events[0][0] # tag
989
- assert_equal 'Mountain View', events[0][2]['from_city']
990
- assert_equal 'United States', events[0][2]['from_country']
991
- assert_equal 'Tokorozawa', events[0][2]['to_city']
992
- assert_equal 'Japan', events[0][2]['to_country']
993
- assert_equal ['United States','Japan'], events[0][2]['string_array']
994
-
995
- assert_equal nil, events[1][2]['from_city']
996
- assert_equal nil, events[1][2]['to_city']
997
- assert_equal nil, events[1][2]['from_country']
998
- assert_equal nil, events[1][2]['to_country']
999
- assert_equal [nil, nil], events[1][2]['string_array']
1000
- end
1001
-
1002
- def config_quoted_record
1003
- %[
1004
- backend_library geoip
1005
- geoip_lookup_key host
1006
- <record>
1007
- location_properties '{ "country_code" : "${country_code["host"]}", "lat": ${latitude["host"]}, "lon": ${longitude["host"]} }'
1008
- location_string ${latitude['host']},${longitude['host']}
1009
- location_string2 ${country_code["host"]}
1010
- location_array "[${longitude['host']},${latitude['host']}]"
1011
- location_array2 '[${longitude["host"]},${latitude["host"]}]'
1012
- peculiar_pattern '[GEOIP] message => {"lat":${latitude["host"]}, "lon":${longitude["host"]}}'
1013
- </record>
1014
- tag geoip.${tag[1]}
1015
- ]
1016
- end
1017
-
1018
- def test_emit_quoted_record
1019
- d1 = create_driver(config_quoted_record)
1020
- d1.run(default_tag: 'input.access') do
1021
- d1.feed({'host' => '66.102.3.80', 'message' => 'valid ip'})
1022
- end
1023
- events = d1.events
1024
- assert_equal 1, events.length
1025
- assert_equal 'geoip.access', events[0][0] # tag
1026
- location_properties = { "country_code" => "US", "lat" => 37.4192008972168, "lon"=> -122.05740356445312 }
1027
- assert_equal location_properties, events[0][2]['location_properties']
1028
- assert_equal '37.4192008972168,-122.05740356445312', events[0][2]['location_string']
1029
- assert_equal 'US', events[0][2]['location_string2']
1030
- assert_equal [-122.05740356445312, 37.4192008972168], events[0][2]['location_array']
1031
- assert_equal [-122.05740356445312, 37.4192008972168], events[0][2]['location_array2']
1032
- assert_equal '[GEOIP] message => {"lat":37.4192008972168, "lon":-122.05740356445312}', events[0][2]['peculiar_pattern']
1033
- end
1034
-
1035
- def test_emit_v1_config_compatibility
1036
- d1 = create_driver(config_quoted_record)
1037
- d1.run(default_tag: 'input.access') do
1038
- d1.feed({'host' => '66.102.3.80', 'message' => 'valid ip'})
1039
- end
1040
- events = d1.events
1041
- assert_equal 1, events.length
1042
- assert_equal 'geoip.access', events[0][0] # tag
1043
- location_properties = { "country_code" => "US", "lat" => 37.4192008972168, "lon"=> -122.05740356445312 }
1044
- assert_equal location_properties, events[0][2]['location_properties']
1045
- assert_equal '37.4192008972168,-122.05740356445312', events[0][2]['location_string']
1046
- assert_equal 'US', events[0][2]['location_string2']
1047
- assert_equal [-122.05740356445312, 37.4192008972168], events[0][2]['location_array']
1048
- assert_equal [-122.05740356445312, 37.4192008972168], events[0][2]['location_array2']
1049
- assert_equal '[GEOIP] message => {"lat":37.4192008972168, "lon":-122.05740356445312}', events[0][2]['peculiar_pattern']
1050
- end
1051
-
1052
- def test_emit_multiline_v1_config
1053
- d1 = create_driver(%[
1054
- backend_library geoip
1055
- geoip_lookup_key host
1056
- <record>
1057
- location_properties {
1058
- "city": "${city['host']}",
1059
- "country_code": "${country_code['host']}",
1060
- "latitude": "${latitude['host']}",
1061
- "longitude": "${longitude['host']}"
1062
- }
1063
- </record>
1064
- tag geoip.${tag[1]}
1065
- ])
1066
- d1.run(default_tag: 'input.access') do
1067
- d1.feed({'host' => '66.102.3.80', 'message' => 'valid ip'})
1068
- end
1069
- events = d1.events
1070
- assert_equal 1, events.length
1071
- assert_equal 'geoip.access', events[0][0] # tag
1072
- location_properties = { "city"=>"Mountain View", "country_code"=>"US", "latitude"=>37.4192008972168, "longitude"=>-122.05740356445312 }
1073
- assert_equal location_properties, events[0][2]['location_properties']
1074
- end
1075
- end
1076
- end