fluent-plugin-geoip-kk 1.0.2 → 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/README.md +116 -36
- data/fluent-plugin-geoip-kk.gemspec +1 -1
- data/lib/fluent/plugin/filter_geoip.rb +65 -33
- metadata +1 -1
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
|
data/README.md
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
|
10
10
|
| fluent-plugin-geoip-kk | fluentd | ruby |
|
11
11
|
|----------------------------|------------|--------|
|
12
|
-
| >= 1.0.
|
12
|
+
| >= 1.0.2 | >= v0.14.0 | >= 2.1 |
|
13
13
|
| < 1.0.0 | >= v0.12.0 | >= 1.9 |
|
14
14
|
|
15
15
|
|
@@ -23,66 +23,149 @@ $ gem install fluent-plugin-geoip-kk
|
|
23
23
|
$ sudo td-agent-gem install fluent-plugin-geoip-kk
|
24
24
|
```
|
25
25
|
|
26
|
+
## Configuration Parameters
|
26
27
|
|
27
|
-
|
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 |
|
28
37
|
|
29
|
-
|
38
|
+
## Usage Examples
|
39
|
+
|
40
|
+
### Basic Configuration
|
41
|
+
|
42
|
+
```xml
|
43
|
+
<filter access.nginx.**>
|
44
|
+
@type geoip
|
45
|
+
key_name client_ip
|
46
|
+
out_key geo
|
47
|
+
</filter>
|
48
|
+
```
|
49
|
+
|
50
|
+
### Advanced Configuration
|
30
51
|
|
31
52
|
```xml
|
32
53
|
<filter access.nginx.**>
|
33
54
|
@type geoip
|
34
|
-
|
35
|
-
#
|
36
|
-
|
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
|
37
72
|
</filter>
|
38
73
|
```
|
39
74
|
|
40
|
-
|
75
|
+
### Input Example
|
41
76
|
|
42
77
|
```json
|
43
|
-
|
44
|
-
"client_ip":"93.184.216.34",
|
45
|
-
"scheme":"http",
|
46
|
-
"
|
47
|
-
"
|
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"
|
48
92
|
}
|
49
93
|
```
|
50
94
|
|
51
|
-
|
95
|
+
### Output Example (Default Structure)
|
52
96
|
|
53
97
|
```json
|
54
|
-
|
55
|
-
"client_ip":"93.184.216.34",
|
56
|
-
"scheme":"http",
|
57
|
-
"
|
58
|
-
|
98
|
+
{
|
99
|
+
"client_ip": "93.184.216.34",
|
100
|
+
"scheme": "http",
|
101
|
+
"method": "GET",
|
102
|
+
// ... other original fields ...
|
59
103
|
"geo": {
|
60
|
-
"coordinates":
|
61
|
-
|
62
|
-
|
63
|
-
|
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"
|
64
126
|
}
|
65
127
|
}
|
66
128
|
```
|
67
129
|
|
130
|
+
### Output Example (Flattened Structure)
|
68
131
|
|
69
|
-
|
70
|
-
- key_name *field_key*
|
132
|
+
When `flatten true` is specified:
|
71
133
|
|
72
|
-
|
73
|
-
|
74
|
-
|
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
|
+
```
|
75
152
|
|
76
|
-
|
153
|
+
## Performance Optimization
|
77
154
|
|
78
|
-
|
155
|
+
The plugin includes several performance optimizations:
|
79
156
|
|
80
|
-
|
81
|
-
|
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
|
82
161
|
|
83
|
-
|
84
|
-
|
162
|
+
2. Skip Private IPs
|
163
|
+
- Optionally skip processing private IP addresses
|
164
|
+
- Reduces unnecessary database lookups
|
85
165
|
|
166
|
+
3. Efficient Record Access
|
167
|
+
- Uses Fluentd's record accessor for optimized field access
|
168
|
+
- Reduces memory allocations
|
86
169
|
|
87
170
|
## VS.
|
88
171
|
[fluent-plugin-geoip](https://github.com/y-ken/fluent-plugin-geoip)
|
@@ -95,7 +178,6 @@ It is able to customize fields with placeholder.
|
|
95
178
|
* 5-10 times faster by the LRU cache.
|
96
179
|
* See [benchmark](test/bench_geoip_filter.rb).
|
97
180
|
|
98
|
-
|
99
181
|
## Development
|
100
182
|
|
101
183
|
After checking out the repo, run `bundle install` to install dependencies. Then, run `rake test` to run the tests.
|
@@ -127,12 +209,10 @@ This gem uses GitHub Actions for automated publishing. To publish a new version:
|
|
127
209
|
4. Push to the branch (`git push origin my-new-feature`)
|
128
210
|
5. Create a new Pull Request
|
129
211
|
|
130
|
-
|
131
212
|
## Copyright
|
132
213
|
|
133
214
|
Copyright (c) 2015 Yuri Umezaki
|
134
215
|
|
135
|
-
|
136
216
|
## License
|
137
217
|
|
138
218
|
[Apache License, Version 2.0.](http://www.apache.org/licenses/LICENSE-2.0)
|
@@ -5,7 +5,7 @@ $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'
|
@@ -63,7 +63,7 @@ module Fluent
|
|
63
63
|
# Initialize cache with TTL support
|
64
64
|
@geoip_cache = LruRedux::TTL::Cache.new(@cache_size, @cache_ttl)
|
65
65
|
|
66
|
-
log.info
|
66
|
+
log.info 'Initialized GeoIP filter', database: @database_path, cache_size: @cache_size, cache_ttl: @cache_ttl
|
67
67
|
end
|
68
68
|
|
69
69
|
def filter(tag, time, record)
|
@@ -74,7 +74,7 @@ module Fluent
|
|
74
74
|
ip = IPAddr.new(ip_addr)
|
75
75
|
return record if @skip_private_ip && ip.private?
|
76
76
|
rescue IPAddr::InvalidAddressError => e
|
77
|
-
log.debug
|
77
|
+
log.debug 'Invalid IP address', ip: ip_addr, error: e.message
|
78
78
|
return record
|
79
79
|
end
|
80
80
|
|
@@ -89,7 +89,7 @@ module Fluent
|
|
89
89
|
|
90
90
|
record
|
91
91
|
rescue StandardError => e
|
92
|
-
log.error
|
92
|
+
log.error 'Failed to process GeoIP lookup', error_class: e.class, error: e.message, tag: tag, time: time
|
93
93
|
record
|
94
94
|
end
|
95
95
|
|
@@ -99,61 +99,93 @@ module Fluent
|
|
99
99
|
geo_ip = @geoip.lookup(ip_addr)
|
100
100
|
return {} if geo_ip.nil?
|
101
101
|
|
102
|
-
{
|
103
|
-
|
104
|
-
|
105
|
-
'
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
110
127
|
end
|
111
128
|
|
112
129
|
def get_coordinates(geo_ip)
|
113
130
|
return nil unless geo_ip.location
|
114
131
|
|
115
|
-
{
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
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
|
120
140
|
end
|
121
141
|
|
122
142
|
def get_country_info(geo_ip)
|
123
143
|
return nil unless geo_ip.country
|
124
144
|
|
125
|
-
{
|
126
|
-
|
127
|
-
|
128
|
-
|
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
|
129
152
|
end
|
130
153
|
|
131
154
|
def get_city_info(geo_ip)
|
132
155
|
return nil unless geo_ip.city
|
133
156
|
|
134
|
-
{
|
135
|
-
|
136
|
-
|
137
|
-
|
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
|
138
164
|
end
|
139
165
|
|
140
166
|
def get_region_info(geo_ip)
|
141
|
-
return nil unless geo_ip.subdivisions
|
167
|
+
return nil unless geo_ip.subdivisions && !geo_ip.subdivisions.empty?
|
142
168
|
|
143
169
|
subdivision = geo_ip.subdivisions.first
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
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
|
148
177
|
end
|
149
178
|
|
150
179
|
def get_postal_info(geo_ip)
|
151
180
|
return nil unless geo_ip.postal
|
152
181
|
|
153
|
-
{
|
154
|
-
|
155
|
-
|
156
|
-
|
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
|
157
189
|
end
|
158
190
|
|
159
191
|
def hash_flatten(hash, keys = [])
|