fluent-plugin-geoip-kk 1.0.1 → 1.0.3
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/.github/workflows/gem-push.yml +34 -0
- data/README.md +138 -38
- data/fluent-plugin-geoip-kk.gemspec +12 -9
- data/lib/fluent/plugin/filter_geoip.rb +154 -25
- data/push.rb +3 -0
- metadata +51 -28
- data/.gitattributes +0 -1
- data/data/GeoLiteCity.dat +0 -3
- data/test/plugin/test_filter_geoip.rb +0 -62
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a09c35276c49497e5ce32dfdb4be3ceb9281a4c74061c057ef63e3f2429c597e
|
4
|
+
data.tar.gz: d61d017ac27cd4ec7d7d3b448df7e34713dde36b36792cc7f43ee71dc88dc583
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '06163815ea4dcd37e4e42bad34d00991f7b38d21a1b05fb9b99f73821c45f570fa1706986b495d9e9225342ec0ea4cba73f4c5d26c92b161a1df19a5fdf77e1d'
|
7
|
+
data.tar.gz: fc25e0ab574149dcf1cc1bcd92e8d2ea6924b9ad2c9e955caca1b871a29aa002f5e802b4920e139b07b407c9587ca36a6ff8cc3b250e27823ac0e97460dd9fcc
|
@@ -0,0 +1,34 @@
|
|
1
|
+
name: Ruby Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ "main" ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ "main" ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
build:
|
11
|
+
name: Build + Publish
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
permissions:
|
14
|
+
contents: read
|
15
|
+
packages: write
|
16
|
+
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v4
|
19
|
+
|
20
|
+
- name: Set up Ruby
|
21
|
+
uses: ruby/setup-ruby@v1
|
22
|
+
with:
|
23
|
+
ruby-version: '3.2' # 你可以指定 3.1、3.2、3.3 等
|
24
|
+
|
25
|
+
- name: Publish to RubyGems
|
26
|
+
run: |
|
27
|
+
mkdir -p $HOME/.gem
|
28
|
+
touch $HOME/.gem/credentials
|
29
|
+
chmod 0600 $HOME/.gem/credentials
|
30
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
31
|
+
gem build *.gemspec
|
32
|
+
gem push *.gem
|
33
|
+
env:
|
34
|
+
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_API_KEY}}"
|
data/README.md
CHANGED
@@ -2,12 +2,14 @@
|
|
2
2
|
|
3
3
|
[Fluentd](http://fluentd.org) filter plugin to add geoip.
|
4
4
|
|
5
|
+
[](https://badge.fury.io/rb/fluent-plugin-geoip-kk)
|
6
|
+
[](https://github.com/kevin197011/fluent-plugin-geoip-kk/actions/workflows/gem-push.yml)
|
5
7
|
|
6
8
|
## Requirements
|
7
9
|
|
8
10
|
| fluent-plugin-geoip-kk | fluentd | ruby |
|
9
11
|
|----------------------------|------------|--------|
|
10
|
-
| >= 1.0.
|
12
|
+
| >= 1.0.2 | >= v0.14.0 | >= 2.1 |
|
11
13
|
| < 1.0.0 | >= v0.12.0 | >= 1.9 |
|
12
14
|
|
13
15
|
|
@@ -21,66 +23,149 @@ $ gem install fluent-plugin-geoip-kk
|
|
21
23
|
$ sudo td-agent-gem install fluent-plugin-geoip-kk
|
22
24
|
```
|
23
25
|
|
26
|
+
## Configuration Parameters
|
24
27
|
|
25
|
-
|
28
|
+
| Parameter | Type | Default | Description |
|
29
|
+
|-----------|------|---------|-------------|
|
30
|
+
| key_name | string | client_ip | Field name that contains the IP address |
|
31
|
+
| out_key | string | geo | Output field name to store GeoIP data |
|
32
|
+
| database_path | string | data/GeoLite2-City.mmdb | Path to the GeoIP database file |
|
33
|
+
| flatten | bool | false | Flatten the GeoIP data structure |
|
34
|
+
| cache_size | integer | 8192 | Size of the LRU cache |
|
35
|
+
| cache_ttl | integer | 3600 | TTL for cached items in seconds |
|
36
|
+
| skip_private_ip | bool | true | Skip adding GeoIP data for private IP addresses |
|
26
37
|
|
27
|
-
|
38
|
+
## Usage Examples
|
39
|
+
|
40
|
+
### Basic Configuration
|
28
41
|
|
29
42
|
```xml
|
30
43
|
<filter access.nginx.**>
|
31
44
|
@type geoip
|
32
|
-
|
33
|
-
|
34
|
-
# out_key geo
|
45
|
+
key_name client_ip
|
46
|
+
out_key geo
|
35
47
|
</filter>
|
36
48
|
```
|
37
49
|
|
38
|
-
|
50
|
+
### Advanced Configuration
|
51
|
+
|
52
|
+
```xml
|
53
|
+
<filter access.nginx.**>
|
54
|
+
@type geoip
|
55
|
+
|
56
|
+
# IP address field configuration
|
57
|
+
key_name client_ip
|
58
|
+
out_key geo
|
59
|
+
|
60
|
+
# Database configuration
|
61
|
+
database_path /path/to/GeoLite2-City.mmdb
|
62
|
+
|
63
|
+
# Cache configuration
|
64
|
+
cache_size 10000 # Cache up to 10000 IP addresses
|
65
|
+
cache_ttl 3600 # Cache TTL: 1 hour
|
66
|
+
|
67
|
+
# Output configuration
|
68
|
+
flatten false # Keep nested structure
|
69
|
+
|
70
|
+
# IP processing configuration
|
71
|
+
skip_private_ip true # Skip private IP addresses
|
72
|
+
</filter>
|
73
|
+
```
|
74
|
+
|
75
|
+
### Input Example
|
39
76
|
|
40
77
|
```json
|
41
|
-
|
42
|
-
"client_ip":"93.184.216.34",
|
43
|
-
"scheme":"http",
|
44
|
-
"
|
45
|
-
"
|
78
|
+
{
|
79
|
+
"client_ip": "93.184.216.34",
|
80
|
+
"scheme": "http",
|
81
|
+
"method": "GET",
|
82
|
+
"host": "example.com",
|
83
|
+
"path": "/",
|
84
|
+
"query": "-",
|
85
|
+
"req_bytes": 200,
|
86
|
+
"referer": "-",
|
87
|
+
"status": 200,
|
88
|
+
"res_bytes": 800,
|
89
|
+
"res_body_bytes": 600,
|
90
|
+
"taken_time": 0.001,
|
91
|
+
"user_agent": "Mozilla/5.0"
|
46
92
|
}
|
47
93
|
```
|
48
94
|
|
49
|
-
|
95
|
+
### Output Example (Default Structure)
|
50
96
|
|
51
97
|
```json
|
52
|
-
|
53
|
-
"client_ip":"93.184.216.34",
|
54
|
-
"scheme":"http",
|
55
|
-
"
|
56
|
-
|
98
|
+
{
|
99
|
+
"client_ip": "93.184.216.34",
|
100
|
+
"scheme": "http",
|
101
|
+
"method": "GET",
|
102
|
+
// ... other original fields ...
|
57
103
|
"geo": {
|
58
|
-
"coordinates":
|
59
|
-
|
60
|
-
|
61
|
-
|
104
|
+
"coordinates": {
|
105
|
+
"latitude": 42.150800000000004,
|
106
|
+
"longitude": -70.8228,
|
107
|
+
"accuracy_radius": 100
|
108
|
+
},
|
109
|
+
"country": {
|
110
|
+
"code": "US",
|
111
|
+
"name": "United States"
|
112
|
+
},
|
113
|
+
"city": {
|
114
|
+
"name": "Norwell",
|
115
|
+
"confidence": 90
|
116
|
+
},
|
117
|
+
"region": {
|
118
|
+
"code": "MA",
|
119
|
+
"name": "Massachusetts"
|
120
|
+
},
|
121
|
+
"postal": {
|
122
|
+
"code": "02061",
|
123
|
+
"confidence": 95
|
124
|
+
},
|
125
|
+
"timezone": "America/New_York"
|
62
126
|
}
|
63
127
|
}
|
64
128
|
```
|
65
129
|
|
130
|
+
### Output Example (Flattened Structure)
|
66
131
|
|
67
|
-
|
68
|
-
- key_name *field_key*
|
69
|
-
|
70
|
-
Target key name. default client_ip.
|
132
|
+
When `flatten true` is specified:
|
71
133
|
|
72
|
-
|
134
|
+
```json
|
135
|
+
{
|
136
|
+
"client_ip": "93.184.216.34",
|
137
|
+
// ... other original fields ...
|
138
|
+
"geo_coordinates_latitude": 42.150800000000004,
|
139
|
+
"geo_coordinates_longitude": -70.8228,
|
140
|
+
"geo_coordinates_accuracy_radius": 100,
|
141
|
+
"geo_country_code": "US",
|
142
|
+
"geo_country_name": "United States",
|
143
|
+
"geo_city_name": "Norwell",
|
144
|
+
"geo_city_confidence": 90,
|
145
|
+
"geo_region_code": "MA",
|
146
|
+
"geo_region_name": "Massachusetts",
|
147
|
+
"geo_postal_code": "02061",
|
148
|
+
"geo_postal_confidence": 95,
|
149
|
+
"geo_timezone": "America/New_York"
|
150
|
+
}
|
151
|
+
```
|
73
152
|
|
74
|
-
|
153
|
+
## Performance Optimization
|
75
154
|
|
76
|
-
|
155
|
+
The plugin includes several performance optimizations:
|
77
156
|
|
78
|
-
|
79
|
-
|
157
|
+
1. LRU Cache with TTL
|
158
|
+
- Caches GeoIP lookups to reduce database access
|
159
|
+
- Configurable cache size and TTL
|
160
|
+
- Automatic cache cleanup for expired entries
|
80
161
|
|
81
|
-
|
82
|
-
|
162
|
+
2. Skip Private IPs
|
163
|
+
- Optionally skip processing private IP addresses
|
164
|
+
- Reduces unnecessary database lookups
|
83
165
|
|
166
|
+
3. Efficient Record Access
|
167
|
+
- Uses Fluentd's record accessor for optimized field access
|
168
|
+
- Reduces memory allocations
|
84
169
|
|
85
170
|
## VS.
|
86
171
|
[fluent-plugin-geoip](https://github.com/y-ken/fluent-plugin-geoip)
|
@@ -93,26 +178,41 @@ It is able to customize fields with placeholder.
|
|
93
178
|
* 5-10 times faster by the LRU cache.
|
94
179
|
* See [benchmark](test/bench_geoip_filter.rb).
|
95
180
|
|
181
|
+
## Development
|
182
|
+
|
183
|
+
After checking out the repo, run `bundle install` to install dependencies. Then, run `rake test` to run the tests.
|
184
|
+
|
185
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
96
186
|
|
97
|
-
##
|
187
|
+
## Publishing
|
98
188
|
|
99
|
-
|
189
|
+
This gem uses GitHub Actions for automated publishing. To publish a new version:
|
100
190
|
|
191
|
+
1. Update the version number in `fluent-plugin-geoip-kk.gemspec`
|
192
|
+
2. Commit the changes:
|
193
|
+
```bash
|
194
|
+
git add fluent-plugin-geoip-kk.gemspec
|
195
|
+
git commit -m "Bump version to x.x.x"
|
196
|
+
```
|
197
|
+
3. Create and push a new tag:
|
198
|
+
```bash
|
199
|
+
git tag vx.x.x
|
200
|
+
git push origin main vx.x.x
|
201
|
+
```
|
202
|
+
4. The GitHub Action will automatically build and publish the gem to RubyGems.org
|
101
203
|
|
102
204
|
## Contributing
|
103
205
|
|
104
|
-
1. Fork it ( https://github.com/
|
206
|
+
1. Fork it ( https://github.com/kevin197011/fluent-plugin-geoip-kk/fork )
|
105
207
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
106
208
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
107
209
|
4. Push to the branch (`git push origin my-new-feature`)
|
108
210
|
5. Create a new Pull Request
|
109
211
|
|
110
|
-
|
111
212
|
## Copyright
|
112
213
|
|
113
214
|
Copyright (c) 2015 Yuri Umezaki
|
114
215
|
|
115
|
-
|
116
216
|
## License
|
117
217
|
|
118
218
|
[Apache License, Version 2.0.](http://www.apache.org/licenses/LICENSE-2.0)
|
@@ -5,12 +5,12 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'fluent-plugin-geoip-kk'
|
8
|
-
spec.version = '1.0.
|
8
|
+
spec.version = '1.0.3'
|
9
9
|
spec.authors = ['kevin197011']
|
10
10
|
spec.email = ['kevin197011@outlook.com']
|
11
11
|
spec.homepage = 'https://github.com/kevin197011/fluent-plugin-geoip-kk'
|
12
12
|
spec.summary = 'Fluentd filter plugin to add geoip'
|
13
|
-
spec.description =
|
13
|
+
spec.description = 'A Fluentd filter plugin that adds GeoIP information to records. Supports both legacy GeoIP and GeoIP2 databases, with LRU caching for improved performance.'
|
14
14
|
spec.license = 'Apache-2.0'
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
@@ -18,11 +18,14 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_runtime_dependency 'fluentd', '>= 0.14.0'
|
22
|
-
spec.add_runtime_dependency 'geoip', '>= 1.
|
23
|
-
spec.add_runtime_dependency 'lru_redux', '>= 1.0.0'
|
24
|
-
spec.add_runtime_dependency 'maxminddb', '>=
|
25
|
-
|
26
|
-
spec.add_development_dependency '
|
27
|
-
spec.add_development_dependency '
|
21
|
+
spec.add_runtime_dependency 'fluentd', ['>= 0.14.0', '< 2']
|
22
|
+
spec.add_runtime_dependency 'geoip', '~> 0.1', '>= 0.1.22'
|
23
|
+
spec.add_runtime_dependency 'lru_redux', '~> 1.0', '>= 1.0.0'
|
24
|
+
spec.add_runtime_dependency 'maxminddb', '~> 1.5', '>= 1.5.0'
|
25
|
+
|
26
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
27
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
28
|
+
spec.add_development_dependency 'test-unit', '~> 3.0' if defined?(RUBY_VERSION) && RUBY_VERSION > '2.2'
|
29
|
+
|
30
|
+
spec.required_ruby_version = '>= 2.1.0'
|
28
31
|
end
|
@@ -3,45 +3,93 @@
|
|
3
3
|
require 'maxminddb'
|
4
4
|
require 'lru_redux'
|
5
5
|
require 'fluent/plugin/filter'
|
6
|
+
require 'ipaddr'
|
6
7
|
|
7
8
|
module Fluent
|
8
9
|
module Plugin
|
9
10
|
class GeoipFilter < Filter
|
10
11
|
Fluent::Plugin.register_filter('geoip', self)
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
helpers :record_accessor
|
14
|
+
|
15
|
+
# Default cache size (number of IP addresses to cache)
|
16
|
+
DEFAULT_CACHE_SIZE = 8192
|
17
|
+
DEFAULT_CACHE_TTL = 3600 # 1 hour in seconds
|
16
18
|
|
19
|
+
desc 'Path to the GeoIP database file'
|
17
20
|
config_param :database_path, :string, default: "#{File.dirname(__FILE__)}/../../../data/GeoLite2-City.mmdb"
|
21
|
+
|
22
|
+
desc 'Field name that contains the IP address'
|
18
23
|
config_param :key_name, :string, default: 'client_ip'
|
24
|
+
|
25
|
+
desc 'Output field name to store GeoIP data'
|
19
26
|
config_param :out_key, :string, default: 'geo'
|
27
|
+
|
28
|
+
desc 'Flatten the GeoIP data structure'
|
20
29
|
config_param :flatten, :bool, default: false
|
21
30
|
|
31
|
+
desc 'Size of the LRU cache'
|
32
|
+
config_param :cache_size, :integer, default: DEFAULT_CACHE_SIZE
|
33
|
+
|
34
|
+
desc 'TTL for cached items in seconds'
|
35
|
+
config_param :cache_ttl, :integer, default: DEFAULT_CACHE_TTL
|
36
|
+
|
37
|
+
desc 'Skip adding GeoIP data for private IP addresses'
|
38
|
+
config_param :skip_private_ip, :bool, default: true
|
39
|
+
|
40
|
+
def initialize
|
41
|
+
super
|
42
|
+
@geoip = nil
|
43
|
+
@ip_accessor = nil
|
44
|
+
end
|
45
|
+
|
22
46
|
def configure(conf)
|
23
47
|
super
|
48
|
+
|
49
|
+
unless File.exist?(@database_path)
|
50
|
+
raise Fluent::ConfigError, "GeoIP database file '#{@database_path}' does not exist"
|
51
|
+
end
|
52
|
+
|
53
|
+
# Initialize MaxMindDB
|
24
54
|
begin
|
25
55
|
@geoip = MaxMindDB.new(@database_path)
|
26
56
|
rescue StandardError => e
|
27
|
-
|
28
|
-
log.warn_backtrace
|
57
|
+
raise Fluent::ConfigError, "Failed to load GeoIP database: #{e.message}"
|
29
58
|
end
|
59
|
+
|
60
|
+
# Initialize IP field accessor
|
61
|
+
@ip_accessor = record_accessor_create(@key_name)
|
62
|
+
|
63
|
+
# Initialize cache with TTL support
|
64
|
+
@geoip_cache = LruRedux::TTL::Cache.new(@cache_size, @cache_ttl)
|
65
|
+
|
66
|
+
log.info 'Initialized GeoIP filter', database: @database_path, cache_size: @cache_size, cache_ttl: @cache_ttl
|
30
67
|
end
|
31
68
|
|
32
|
-
def filter(
|
33
|
-
ip_addr = record
|
69
|
+
def filter(tag, time, record)
|
70
|
+
ip_addr = @ip_accessor.call(record)
|
71
|
+
return record if ip_addr.nil? || ip_addr.empty? || ip_addr == '-'
|
34
72
|
|
35
|
-
|
73
|
+
begin
|
74
|
+
ip = IPAddr.new(ip_addr)
|
75
|
+
return record if @skip_private_ip && ip.private?
|
76
|
+
rescue IPAddr::InvalidAddressError => e
|
77
|
+
log.debug 'Invalid IP address', ip: ip_addr, error: e.message
|
78
|
+
return record
|
79
|
+
end
|
36
80
|
|
37
81
|
geo_ip = @geoip_cache.getset(ip_addr) { get_geoip(ip_addr) }
|
82
|
+
return record if geo_ip.empty?
|
38
83
|
|
39
|
-
if flatten
|
40
|
-
record.merge!
|
84
|
+
if @flatten
|
85
|
+
record.merge!(hash_flatten(geo_ip, [@out_key]))
|
41
86
|
else
|
42
87
|
record[@out_key] = geo_ip
|
43
88
|
end
|
44
89
|
|
90
|
+
record
|
91
|
+
rescue StandardError => e
|
92
|
+
log.error 'Failed to process GeoIP lookup', error_class: e.class, error: e.message, tag: tag, time: time
|
45
93
|
record
|
46
94
|
end
|
47
95
|
|
@@ -49,24 +97,105 @@ module Fluent
|
|
49
97
|
|
50
98
|
def get_geoip(ip_addr)
|
51
99
|
geo_ip = @geoip.lookup(ip_addr)
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
100
|
+
return {} if geo_ip.nil?
|
101
|
+
|
102
|
+
result = {}
|
103
|
+
|
104
|
+
if coordinates = get_coordinates(geo_ip)
|
105
|
+
result['coordinates'] = coordinates
|
106
|
+
end
|
107
|
+
|
108
|
+
if country = get_country_info(geo_ip)
|
109
|
+
result['country'] = country
|
110
|
+
end
|
111
|
+
|
112
|
+
if city = get_city_info(geo_ip)
|
113
|
+
result['city'] = city
|
114
|
+
end
|
115
|
+
|
116
|
+
if region = get_region_info(geo_ip)
|
117
|
+
result['region'] = region
|
118
|
+
end
|
119
|
+
|
120
|
+
if postal = get_postal_info(geo_ip)
|
121
|
+
result['postal'] = postal
|
122
|
+
end
|
123
|
+
|
124
|
+
result['timezone'] = geo_ip.location.time_zone if geo_ip.location && geo_ip.location.time_zone
|
125
|
+
|
126
|
+
result
|
127
|
+
end
|
128
|
+
|
129
|
+
def get_coordinates(geo_ip)
|
130
|
+
return nil unless geo_ip.location
|
131
|
+
|
132
|
+
result = {}
|
133
|
+
location = geo_ip.location
|
134
|
+
|
135
|
+
result['latitude'] = location.latitude if location.latitude
|
136
|
+
result['longitude'] = location.longitude if location.longitude
|
137
|
+
result['accuracy_radius'] = location.accuracy_radius if location.accuracy_radius
|
138
|
+
|
139
|
+
result.empty? ? nil : result
|
140
|
+
end
|
141
|
+
|
142
|
+
def get_country_info(geo_ip)
|
143
|
+
return nil unless geo_ip.country
|
144
|
+
|
145
|
+
result = {}
|
146
|
+
country = geo_ip.country
|
147
|
+
|
148
|
+
result['code'] = country.iso_code if country.iso_code
|
149
|
+
result['name'] = country.name if country.name
|
150
|
+
|
151
|
+
result.empty? ? nil : result
|
152
|
+
end
|
153
|
+
|
154
|
+
def get_city_info(geo_ip)
|
155
|
+
return nil unless geo_ip.city
|
156
|
+
|
157
|
+
result = {}
|
158
|
+
city = geo_ip.city
|
159
|
+
|
160
|
+
result['name'] = city.name if city.name
|
161
|
+
result['confidence'] = city.confidence if city.confidence
|
162
|
+
|
163
|
+
result.empty? ? nil : result
|
164
|
+
end
|
165
|
+
|
166
|
+
def get_region_info(geo_ip)
|
167
|
+
return nil unless geo_ip.subdivisions && !geo_ip.subdivisions.empty?
|
168
|
+
|
169
|
+
subdivision = geo_ip.subdivisions.first
|
170
|
+
return nil unless subdivision
|
171
|
+
|
172
|
+
result = {}
|
173
|
+
result['code'] = subdivision.iso_code if subdivision.iso_code
|
174
|
+
result['name'] = subdivision.name if subdivision.name
|
175
|
+
|
176
|
+
result.empty? ? nil : result
|
177
|
+
end
|
178
|
+
|
179
|
+
def get_postal_info(geo_ip)
|
180
|
+
return nil unless geo_ip.postal
|
181
|
+
|
182
|
+
result = {}
|
183
|
+
postal = geo_ip.postal
|
184
|
+
|
185
|
+
result['code'] = postal.code if postal.code
|
186
|
+
result['confidence'] = postal.confidence if postal.confidence
|
187
|
+
|
188
|
+
result.empty? ? nil : result
|
60
189
|
end
|
61
190
|
|
62
|
-
def hash_flatten(
|
191
|
+
def hash_flatten(hash, keys = [])
|
63
192
|
ret = {}
|
64
|
-
|
65
|
-
|
66
|
-
if v.
|
67
|
-
ret.merge!(hash_flatten(v,
|
193
|
+
hash.each do |k, v|
|
194
|
+
key_chain = keys + [k]
|
195
|
+
if v.is_a?(Hash)
|
196
|
+
ret.merge!(hash_flatten(v, key_chain))
|
68
197
|
else
|
69
|
-
ret.
|
198
|
+
ret[key_chain.join('_')] = v
|
70
199
|
end
|
71
200
|
end
|
72
201
|
ret
|
data/push.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-geoip-kk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kevin197011
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -17,6 +17,9 @@ dependencies:
|
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 0.14.0
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2'
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -24,24 +27,36 @@ dependencies:
|
|
24
27
|
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: 0.14.0
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2'
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: geoip
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
30
36
|
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.1'
|
31
40
|
- - ">="
|
32
41
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.
|
42
|
+
version: 0.1.22
|
34
43
|
type: :runtime
|
35
44
|
prerelease: false
|
36
45
|
version_requirements: !ruby/object:Gem::Requirement
|
37
46
|
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.1'
|
38
50
|
- - ">="
|
39
51
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.
|
52
|
+
version: 0.1.22
|
41
53
|
- !ruby/object:Gem::Dependency
|
42
54
|
name: lru_redux
|
43
55
|
requirement: !ruby/object:Gem::Requirement
|
44
56
|
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '1.0'
|
45
60
|
- - ">="
|
46
61
|
- !ruby/object:Gem::Version
|
47
62
|
version: 1.0.0
|
@@ -49,6 +64,9 @@ dependencies:
|
|
49
64
|
prerelease: false
|
50
65
|
version_requirements: !ruby/object:Gem::Requirement
|
51
66
|
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.0'
|
52
70
|
- - ">="
|
53
71
|
- !ruby/object:Gem::Version
|
54
72
|
version: 1.0.0
|
@@ -56,84 +74,90 @@ dependencies:
|
|
56
74
|
name: maxminddb
|
57
75
|
requirement: !ruby/object:Gem::Requirement
|
58
76
|
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '1.5'
|
59
80
|
- - ">="
|
60
81
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
82
|
+
version: 1.5.0
|
62
83
|
type: :runtime
|
63
84
|
prerelease: false
|
64
85
|
version_requirements: !ruby/object:Gem::Requirement
|
65
86
|
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.5'
|
66
90
|
- - ">="
|
67
91
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
92
|
+
version: 1.5.0
|
69
93
|
- !ruby/object:Gem::Dependency
|
70
94
|
name: bundler
|
71
95
|
requirement: !ruby/object:Gem::Requirement
|
72
96
|
requirements:
|
73
|
-
- - "
|
97
|
+
- - "~>"
|
74
98
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
99
|
+
version: '2.0'
|
76
100
|
type: :development
|
77
101
|
prerelease: false
|
78
102
|
version_requirements: !ruby/object:Gem::Requirement
|
79
103
|
requirements:
|
80
|
-
- - "
|
104
|
+
- - "~>"
|
81
105
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
106
|
+
version: '2.0'
|
83
107
|
- !ruby/object:Gem::Dependency
|
84
108
|
name: rake
|
85
109
|
requirement: !ruby/object:Gem::Requirement
|
86
110
|
requirements:
|
87
|
-
- - "
|
111
|
+
- - "~>"
|
88
112
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
113
|
+
version: '13.0'
|
90
114
|
type: :development
|
91
115
|
prerelease: false
|
92
116
|
version_requirements: !ruby/object:Gem::Requirement
|
93
117
|
requirements:
|
94
|
-
- - "
|
118
|
+
- - "~>"
|
95
119
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
120
|
+
version: '13.0'
|
97
121
|
- !ruby/object:Gem::Dependency
|
98
122
|
name: test-unit
|
99
123
|
requirement: !ruby/object:Gem::Requirement
|
100
124
|
requirements:
|
101
|
-
- - "
|
125
|
+
- - "~>"
|
102
126
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
127
|
+
version: '3.0'
|
104
128
|
type: :development
|
105
129
|
prerelease: false
|
106
130
|
version_requirements: !ruby/object:Gem::Requirement
|
107
131
|
requirements:
|
108
|
-
- - "
|
132
|
+
- - "~>"
|
109
133
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
|
-
description: Fluentd filter plugin to
|
134
|
+
version: '3.0'
|
135
|
+
description: A Fluentd filter plugin that adds GeoIP information to records. Supports
|
136
|
+
both legacy GeoIP and GeoIP2 databases, with LRU caching for improved performance.
|
112
137
|
email:
|
113
138
|
- kevin197011@outlook.com
|
114
139
|
executables: []
|
115
140
|
extensions: []
|
116
141
|
extra_rdoc_files: []
|
117
142
|
files:
|
118
|
-
- ".
|
143
|
+
- ".github/workflows/gem-push.yml"
|
119
144
|
- ".gitignore"
|
120
145
|
- Gemfile
|
121
146
|
- LICENSE
|
122
147
|
- README.md
|
123
148
|
- Rakefile
|
124
149
|
- data/GeoLite2-City.mmdb
|
125
|
-
- data/GeoLiteCity.dat
|
126
150
|
- fluent-plugin-geoip-kk.gemspec
|
127
151
|
- lib/fluent/plugin/filter_geoip.rb
|
152
|
+
- push.rb
|
128
153
|
- test.rb
|
129
154
|
- test/bench_geoip_filter.rb
|
130
155
|
- test/helper.rb
|
131
|
-
- test/plugin/test_filter_geoip.rb
|
132
156
|
homepage: https://github.com/kevin197011/fluent-plugin-geoip-kk
|
133
157
|
licenses:
|
134
158
|
- Apache-2.0
|
135
159
|
metadata: {}
|
136
|
-
post_install_message:
|
160
|
+
post_install_message:
|
137
161
|
rdoc_options: []
|
138
162
|
require_paths:
|
139
163
|
- lib
|
@@ -141,18 +165,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
141
165
|
requirements:
|
142
166
|
- - ">="
|
143
167
|
- !ruby/object:Gem::Version
|
144
|
-
version:
|
168
|
+
version: 2.1.0
|
145
169
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
170
|
requirements:
|
147
171
|
- - ">="
|
148
172
|
- !ruby/object:Gem::Version
|
149
173
|
version: '0'
|
150
174
|
requirements: []
|
151
|
-
rubygems_version: 3.
|
152
|
-
signing_key:
|
175
|
+
rubygems_version: 3.4.19
|
176
|
+
signing_key:
|
153
177
|
specification_version: 4
|
154
178
|
summary: Fluentd filter plugin to add geoip
|
155
179
|
test_files:
|
156
180
|
- test/bench_geoip_filter.rb
|
157
181
|
- test/helper.rb
|
158
|
-
- test/plugin/test_filter_geoip.rb
|
data/.gitattributes
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
*.dat filter=lfs diff=lfs merge=lfs -text
|
data/data/GeoLiteCity.dat
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'helper'
|
4
|
-
|
5
|
-
class GeoipFilterTest < Test::Unit::TestCase
|
6
|
-
def setup
|
7
|
-
Fluent::Test.setup
|
8
|
-
end
|
9
|
-
|
10
|
-
CONFIG = %(
|
11
|
-
@type geoip
|
12
|
-
key_name client_ip
|
13
|
-
out_key geo
|
14
|
-
)
|
15
|
-
|
16
|
-
def create_driver(conf = CONFIG)
|
17
|
-
Fluent::Test::Driver::Filter.new(Fluent::Plugin::GeoipFilter).configure(conf)
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_configure
|
21
|
-
d = create_driver(CONFIG)
|
22
|
-
assert_equal 'client_ip', d.instance.config['key_name']
|
23
|
-
assert_equal 'geo', d.instance.config['out_key']
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_emit
|
27
|
-
d1 = create_driver(CONFIG)
|
28
|
-
ip_iddr = '93.184.216.34'
|
29
|
-
|
30
|
-
d1.run(default_tag: 'test') do
|
31
|
-
d1.feed({ 'client_ip' => ip_iddr })
|
32
|
-
end
|
33
|
-
emits = d1.filtered
|
34
|
-
assert_equal 1, emits.length
|
35
|
-
geo_object = emits[0][1]['geo']
|
36
|
-
assert_equal [-70.8228, 42.150800000000004], geo_object['coordinates']
|
37
|
-
assert_equal 'US', geo_object['country_code']
|
38
|
-
assert_equal 'Norwell', geo_object['city']
|
39
|
-
assert_equal 'MA', geo_object['region_code']
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_emit_flatten
|
43
|
-
d1 = create_driver(%(
|
44
|
-
@type geoip
|
45
|
-
key_name ip_iddr
|
46
|
-
flatten
|
47
|
-
))
|
48
|
-
ip_iddr = '93.184.216.34'
|
49
|
-
|
50
|
-
d1.run(default_tag: 'test') do
|
51
|
-
d1.feed({ 'ip_iddr' => ip_iddr })
|
52
|
-
end
|
53
|
-
|
54
|
-
emits = d1.filtered
|
55
|
-
assert_equal 1, emits.length
|
56
|
-
geo_object = emits[0][1]
|
57
|
-
assert_equal [-70.8228, 42.150800000000004], geo_object['geo_coordinates']
|
58
|
-
assert_equal 'US', geo_object['geo_country_code']
|
59
|
-
assert_equal 'Norwell', geo_object['geo_city']
|
60
|
-
assert_equal 'MA', geo_object['geo_region_code']
|
61
|
-
end
|
62
|
-
end
|