fluent-plugin-ip2location 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +8 -0
- data/LICENSE.txt +21 -0
- data/README.md +185 -0
- data/lib/fluent/plugin/filter_ip2location.rb +228 -0
- data/lib/fluent/plugin/ip2location/version.rb +9 -0
- metadata +119 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 5b7b81c42ee55b5a20fcbf953dcfb6edd6076ae22af638e917bce7a779441ad8
|
|
4
|
+
data.tar.gz: 778f82f161d577d1a43b0b729c0f273730cbfc4a51fcb938666cd2695fd01743
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: cc6b58c35506a9862123f96bcb4f1f2c138d4d13e349b548ee0eb40114419789ba0c9c73ef9a4d0e9db0766ce53dd1ec648e11902aa366f1b53981b3a5a21d59
|
|
7
|
+
data.tar.gz: 4eb502dae00e7f66f6a872e2baf37f37b034bc867705150b91ac752eae78261a6e27ca611c19271e8a220f64ac5eef9e4d4144f210572258e57203f3c746a6bc
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 - 2026-06-24
|
|
4
|
+
|
|
5
|
+
- Initial release.
|
|
6
|
+
- Adds Fluentd filter plugin `@type ip2location`.
|
|
7
|
+
- Supports nested input and output fields through Fluentd record accessor syntax.
|
|
8
|
+
- Supports IP2Location BIN lookup, field selection, private IP skipping, error handling and in-memory lookup cache.
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 IP2Location.com
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# IP2Location Fluentd Filter Plugin
|
|
2
|
+
|
|
3
|
+
`fluent-plugin-ip2location` is a Fluentd filter plugin that enriches Fluentd events with IP geolocation data from an IP2Location BIN database.
|
|
4
|
+
|
|
5
|
+
It reads an IP address from a configured record field, queries the IP2Location Ruby library against an IP2Location BIN database, and writes selected lookup fields back into the event record.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Reads IP address from a top-level or nested record field, for example `ip`, `remote_addr`, or `$.client.ip`.
|
|
10
|
+
- Supports nested output fields, for example `ip2location` or `$.enrichment.ip2location`.
|
|
11
|
+
- Supports IP2Location geolocation fields including country, region, city, latitude, longitude, ISP, domain, ZIP code, time zone, usage type, ASN and AS name.
|
|
12
|
+
- Skips invalid IP addresses and private/local IP addresses by default.
|
|
13
|
+
- Supports configurable field selection.
|
|
14
|
+
- Supports an in-memory lookup cache.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
Install it into the Ruby environment used by Fluentd:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
fluent-gem install fluent-plugin-ip2location
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Or add it to your Gemfile:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
gem "fluent-plugin-ip2location"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Then run:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
bundle install
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## IP2Location database
|
|
37
|
+
|
|
38
|
+
This plugin requires an IP2Location BIN database file. For DB26, use a file such as:
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
IPV6-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ZIPCODE-TIMEZONE-ISP-DOMAIN-NETSPEED-AREACODE-WEATHER-MOBILE-ELEVATION-USAGETYPE-ADDRESSTYPE-CATEGORY-DISTRICT-ASN.BIN
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Place the BIN file somewhere readable by the Fluentd process, for example:
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
/opt/ip2location/IPV6-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ZIPCODE-TIMEZONE-ISP-DOMAIN-NETSPEED-AREACODE-WEATHER-MOBILE-ELEVATION-USAGETYPE-ADDRESSTYPE-CATEGORY-DISTRICT-ASN.BIN
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Fluentd configuration
|
|
51
|
+
|
|
52
|
+
```apache
|
|
53
|
+
<filter app.**>
|
|
54
|
+
@type ip2location
|
|
55
|
+
database /opt/ip2location/IPV6-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ZIPCODE-TIMEZONE-ISP-DOMAIN-NETSPEED-AREACODE-WEATHER-MOBILE-ELEVATION-USAGETYPE-ADDRESSTYPE-CATEGORY-DISTRICT-ASN.BIN
|
|
56
|
+
ip_field $.client.ip
|
|
57
|
+
output_field $.ip2location
|
|
58
|
+
fields country_short,country_long,region,city,latitude,longitude,isp,domain,zipcode,timezone,usagetype,asn,as
|
|
59
|
+
skip_private_ip true
|
|
60
|
+
skip_invalid_ip true
|
|
61
|
+
cache_size 10000
|
|
62
|
+
on_error warn
|
|
63
|
+
</filter>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Input record
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"client": {
|
|
71
|
+
"ip": "8.8.8.8"
|
|
72
|
+
},
|
|
73
|
+
"message": "hello"
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Output record
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"client": {
|
|
82
|
+
"ip": "8.8.8.8"
|
|
83
|
+
},
|
|
84
|
+
"message": "hello",
|
|
85
|
+
"ip2location": {
|
|
86
|
+
"country_short": "US",
|
|
87
|
+
"country_long": "United States of America",
|
|
88
|
+
"region": "California",
|
|
89
|
+
"city": "Mountain View",
|
|
90
|
+
"latitude": 37.40599,
|
|
91
|
+
"longitude": -122.078514,
|
|
92
|
+
"isp": "Google LLC",
|
|
93
|
+
"zipcode": "94043",
|
|
94
|
+
"timezone": "-08:00",
|
|
95
|
+
"asn": "15169",
|
|
96
|
+
"as": "Google LLC"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Configuration parameters
|
|
102
|
+
|
|
103
|
+
| Parameter | Required | Default | Description |
|
|
104
|
+
|---|---:|---|---|
|
|
105
|
+
| `database` | Yes | - | Absolute path to the IP2Location BIN database file. |
|
|
106
|
+
| `ip_field` | Yes | - | Record field containing the IP address. Supports Fluentd record accessor syntax, for example `ip`, `remote_addr`, or `$.client.ip`. |
|
|
107
|
+
| `output_field` | No | `ip2location` | Destination field for enrichment output. Supports record accessor syntax. Ignored when `merge_record true`. |
|
|
108
|
+
| `fields` | No | `all` | Comma-separated list of IP2Location fields to include. Use `all` to include every supported field. |
|
|
109
|
+
| `merge_record` | No | `false` | When `true`, writes enrichment fields into the root record instead of a nested object. |
|
|
110
|
+
| `prefix` | No | `ip2location_` | Prefix used when `merge_record true`. |
|
|
111
|
+
| `skip_invalid_ip` | No | `true` | When `true`, invalid IP values are ignored. When `false`, invalid IP values raise an error. |
|
|
112
|
+
| `skip_private_ip` | No | `true` | When `true`, private, loopback and link-local IPs are not looked up. |
|
|
113
|
+
| `include_unknown` | No | `false` | When `false`, empty values and `-` values returned by IP2Location are omitted. |
|
|
114
|
+
| `cache_size` | No | `10000` | Maximum number of IP lookup results kept in memory. Set `0` to disable caching. |
|
|
115
|
+
| `on_error` | No | `warn` | Lookup error behavior. One of `ignore`, `warn`, or `raise`. |
|
|
116
|
+
|
|
117
|
+
## Supported fields
|
|
118
|
+
|
|
119
|
+
```text
|
|
120
|
+
country_short,country_long,region,city,isp,latitude,longitude,domain,zipcode,timezone,netspeed,iddcode,areacode,weatherstationcode,weatherstationname,mcc,mnc,mobilebrand,elevation,usagetype,addresstype,category,district,asn,as,as_domain,as_usagetype,as_cidr
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Merge fields into the root record
|
|
124
|
+
|
|
125
|
+
```apache
|
|
126
|
+
<filter app.**>
|
|
127
|
+
@type ip2location
|
|
128
|
+
database /opt/ip2location/IPV6-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ZIPCODE-TIMEZONE-ISP-DOMAIN-NETSPEED-AREACODE-WEATHER-MOBILE-ELEVATION-USAGETYPE-ADDRESSTYPE-CATEGORY-DISTRICT-ASN.BIN
|
|
129
|
+
ip_field remote_addr
|
|
130
|
+
merge_record true
|
|
131
|
+
prefix geoip_
|
|
132
|
+
fields country_short,country_long,city,asn,as
|
|
133
|
+
</filter>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Output example:
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"remote_addr": "8.8.8.8",
|
|
141
|
+
"geoip_country_short": "US",
|
|
142
|
+
"geoip_country_long": "United States of America",
|
|
143
|
+
"geoip_city": "Mountain View",
|
|
144
|
+
"geoip_asn": "15169",
|
|
145
|
+
"geoip_as": "Google LLC"
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Development
|
|
150
|
+
|
|
151
|
+
Install dependencies:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
bundle install
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Run tests:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
bundle exec rake
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Build the gem locally:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
gem build fluent-plugin-ip2location.gemspec
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Install the local gem:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
gem install fluent-plugin-ip2location-0.1.0.gem
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Run the example configuration from the project directory:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
bundle exec fluentd -c example/fluent.conf -p ./lib
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Update the `database` path in `example/fluent.conf` before running it.
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
LICENSE.txt
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fluent/plugin/filter"
|
|
4
|
+
require "ip2location_ruby"
|
|
5
|
+
require "ipaddr"
|
|
6
|
+
require "thread"
|
|
7
|
+
|
|
8
|
+
module Fluent
|
|
9
|
+
module Plugin
|
|
10
|
+
class IP2LocationFilter < Filter
|
|
11
|
+
Fluent::Plugin.register_filter("ip2location", self)
|
|
12
|
+
|
|
13
|
+
helpers :record_accessor
|
|
14
|
+
|
|
15
|
+
KNOWN_FIELDS = %w[
|
|
16
|
+
country_short
|
|
17
|
+
country_long
|
|
18
|
+
region
|
|
19
|
+
city
|
|
20
|
+
isp
|
|
21
|
+
latitude
|
|
22
|
+
longitude
|
|
23
|
+
domain
|
|
24
|
+
zipcode
|
|
25
|
+
timezone
|
|
26
|
+
netspeed
|
|
27
|
+
iddcode
|
|
28
|
+
areacode
|
|
29
|
+
weatherstationcode
|
|
30
|
+
weatherstationname
|
|
31
|
+
mcc
|
|
32
|
+
mnc
|
|
33
|
+
mobilebrand
|
|
34
|
+
elevation
|
|
35
|
+
usagetype
|
|
36
|
+
addresstype
|
|
37
|
+
category
|
|
38
|
+
district
|
|
39
|
+
asn
|
|
40
|
+
as
|
|
41
|
+
as_domain
|
|
42
|
+
as_usagetype
|
|
43
|
+
as_cidr
|
|
44
|
+
].freeze
|
|
45
|
+
|
|
46
|
+
VALID_ERROR_MODES = %w[ignore warn raise].freeze
|
|
47
|
+
|
|
48
|
+
config_param :database, :string
|
|
49
|
+
config_param :ip_field, :string
|
|
50
|
+
config_param :output_field, :string, default: "ip2location"
|
|
51
|
+
config_param :fields, :string, default: "all"
|
|
52
|
+
config_param :merge_record, :bool, default: false
|
|
53
|
+
config_param :prefix, :string, default: "ip2location_"
|
|
54
|
+
config_param :skip_invalid_ip, :bool, default: true
|
|
55
|
+
config_param :skip_private_ip, :bool, default: true
|
|
56
|
+
config_param :include_unknown, :bool, default: false
|
|
57
|
+
config_param :cache_size, :integer, default: 10_000
|
|
58
|
+
config_param :on_error, :string, default: "warn"
|
|
59
|
+
|
|
60
|
+
def configure(conf)
|
|
61
|
+
super
|
|
62
|
+
|
|
63
|
+
raise Fluent::ConfigError, "database does not exist: #{@database}" unless File.file?(@database)
|
|
64
|
+
raise Fluent::ConfigError, "cache_size must be zero or greater" if @cache_size.negative?
|
|
65
|
+
raise Fluent::ConfigError, "on_error must be one of: #{VALID_ERROR_MODES.join(', ')}" unless VALID_ERROR_MODES.include?(@on_error)
|
|
66
|
+
raise Fluent::ConfigError, "prefix cannot be empty when merge_record is true" if @merge_record && @prefix.empty?
|
|
67
|
+
|
|
68
|
+
@selected_fields = parse_fields(@fields)
|
|
69
|
+
@ip_accessor = record_accessor_create(@ip_field)
|
|
70
|
+
@output_accessor = record_accessor_create(@output_field) unless @merge_record
|
|
71
|
+
@cache = {}
|
|
72
|
+
@cache_order = []
|
|
73
|
+
@cache_mutex = Mutex.new
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def start
|
|
77
|
+
super
|
|
78
|
+
@ip2location = Ip2location.new.open(@database)
|
|
79
|
+
rescue StandardError => e
|
|
80
|
+
raise Fluent::ConfigError, "failed to open IP2Location database #{@database}: #{e.message}"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def shutdown
|
|
84
|
+
@ip2location.close if @ip2location&.respond_to?(:close)
|
|
85
|
+
ensure
|
|
86
|
+
super
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def filter(_tag, _time, record)
|
|
90
|
+
ip = normalize_ip(@ip_accessor.call(record))
|
|
91
|
+
return record if ip.nil?
|
|
92
|
+
|
|
93
|
+
case ip_status(ip)
|
|
94
|
+
when :invalid
|
|
95
|
+
return handle_invalid_ip(record, ip)
|
|
96
|
+
when :private
|
|
97
|
+
return record
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
enriched = lookup(ip)
|
|
101
|
+
return record if enriched.empty?
|
|
102
|
+
|
|
103
|
+
if @merge_record
|
|
104
|
+
enriched.each { |key, value| record["#{@prefix}#{key}"] = value }
|
|
105
|
+
else
|
|
106
|
+
@output_accessor.set(record, enriched)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
record
|
|
110
|
+
rescue StandardError => e
|
|
111
|
+
handle_lookup_error(e, ip)
|
|
112
|
+
record
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
|
|
117
|
+
def parse_fields(value)
|
|
118
|
+
raw = value.to_s.strip
|
|
119
|
+
return KNOWN_FIELDS if raw.empty? || raw.casecmp("all").zero?
|
|
120
|
+
|
|
121
|
+
fields = raw.split(",").map(&:strip).reject(&:empty?)
|
|
122
|
+
invalid = fields - KNOWN_FIELDS
|
|
123
|
+
raise Fluent::ConfigError, "unknown fields: #{invalid.join(', ')}. Valid fields: #{KNOWN_FIELDS.join(', ')}" unless invalid.empty?
|
|
124
|
+
|
|
125
|
+
fields
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def normalize_ip(value)
|
|
129
|
+
return nil if value.nil?
|
|
130
|
+
|
|
131
|
+
ip = value.to_s.strip
|
|
132
|
+
ip.empty? ? nil : ip
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def ip_status(ip)
|
|
136
|
+
addr = IPAddr.new(ip)
|
|
137
|
+
return :private if @skip_private_ip && private_or_local_address?(addr)
|
|
138
|
+
|
|
139
|
+
:valid
|
|
140
|
+
rescue IPAddr::InvalidAddressError
|
|
141
|
+
:invalid
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def private_or_local_address?(addr)
|
|
145
|
+
%i[private? loopback? link_local?].any? do |method_name|
|
|
146
|
+
addr.respond_to?(method_name) && addr.public_send(method_name)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def handle_invalid_ip(record, ip)
|
|
151
|
+
if @skip_invalid_ip
|
|
152
|
+
log.debug "Skipping invalid IP address: #{ip}"
|
|
153
|
+
return record
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
raise ArgumentError, "invalid IP address: #{ip}"
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def lookup(ip)
|
|
160
|
+
cached = cache_read(ip)
|
|
161
|
+
return cached unless cached.nil?
|
|
162
|
+
|
|
163
|
+
raw = @ip2location.get_all(ip)
|
|
164
|
+
enriched = normalize_record(raw)
|
|
165
|
+
cache_write(ip, enriched)
|
|
166
|
+
enriched
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def normalize_record(raw)
|
|
170
|
+
hash = raw.respond_to?(:to_h) ? raw.to_h : raw
|
|
171
|
+
return {} unless hash.respond_to?(:key?)
|
|
172
|
+
|
|
173
|
+
@selected_fields.each_with_object({}) do |field, output|
|
|
174
|
+
next unless hash.key?(field)
|
|
175
|
+
|
|
176
|
+
value = hash[field]
|
|
177
|
+
next if unknown_value?(value)
|
|
178
|
+
|
|
179
|
+
output[field] = value
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def unknown_value?(value)
|
|
184
|
+
return false if @include_unknown
|
|
185
|
+
return true if value.nil?
|
|
186
|
+
|
|
187
|
+
string_value = value.to_s.strip
|
|
188
|
+
string_value.empty? || string_value == "-"
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def cache_read(ip)
|
|
192
|
+
return nil if @cache_size.zero?
|
|
193
|
+
|
|
194
|
+
@cache_mutex.synchronize { @cache[ip] }
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def cache_write(ip, value)
|
|
198
|
+
return if @cache_size.zero?
|
|
199
|
+
|
|
200
|
+
@cache_mutex.synchronize do
|
|
201
|
+
unless @cache.key?(ip)
|
|
202
|
+
@cache_order << ip
|
|
203
|
+
if @cache_order.length > @cache_size
|
|
204
|
+
oldest = @cache_order.shift
|
|
205
|
+
@cache.delete(oldest)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
@cache[ip] = value
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def handle_lookup_error(error, ip)
|
|
213
|
+
message = "IP2Location lookup failed"
|
|
214
|
+
message = "#{message} for #{ip}" unless ip.nil?
|
|
215
|
+
message = "#{message}: #{error.message}"
|
|
216
|
+
|
|
217
|
+
case @on_error
|
|
218
|
+
when "ignore"
|
|
219
|
+
log.debug message
|
|
220
|
+
when "warn"
|
|
221
|
+
log.warn message
|
|
222
|
+
when "raise"
|
|
223
|
+
raise error
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: fluent-plugin-ip2location
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- IP2Location
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: fluentd
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.16'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '2'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '1.16'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '2'
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: ip2location_ruby
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - ">="
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '8.8'
|
|
39
|
+
- - "<"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '9'
|
|
42
|
+
type: :runtime
|
|
43
|
+
prerelease: false
|
|
44
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '8.8'
|
|
49
|
+
- - "<"
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: '9'
|
|
52
|
+
- !ruby/object:Gem::Dependency
|
|
53
|
+
name: rake
|
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - "~>"
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '13.0'
|
|
59
|
+
type: :development
|
|
60
|
+
prerelease: false
|
|
61
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
62
|
+
requirements:
|
|
63
|
+
- - "~>"
|
|
64
|
+
- !ruby/object:Gem::Version
|
|
65
|
+
version: '13.0'
|
|
66
|
+
- !ruby/object:Gem::Dependency
|
|
67
|
+
name: test-unit
|
|
68
|
+
requirement: !ruby/object:Gem::Requirement
|
|
69
|
+
requirements:
|
|
70
|
+
- - "~>"
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: '3.6'
|
|
73
|
+
type: :development
|
|
74
|
+
prerelease: false
|
|
75
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
76
|
+
requirements:
|
|
77
|
+
- - "~>"
|
|
78
|
+
- !ruby/object:Gem::Version
|
|
79
|
+
version: '3.6'
|
|
80
|
+
description: Reads an IP address from a Fluentd record, queries an IP2Location BIN
|
|
81
|
+
file with ip2location_ruby, and enriches the event record with geolocation and network
|
|
82
|
+
fields.
|
|
83
|
+
email:
|
|
84
|
+
- support@ip2location.com
|
|
85
|
+
executables: []
|
|
86
|
+
extensions: []
|
|
87
|
+
extra_rdoc_files: []
|
|
88
|
+
files:
|
|
89
|
+
- CHANGELOG.md
|
|
90
|
+
- LICENSE.txt
|
|
91
|
+
- README.md
|
|
92
|
+
- lib/fluent/plugin/filter_ip2location.rb
|
|
93
|
+
- lib/fluent/plugin/ip2location/version.rb
|
|
94
|
+
homepage: https://github.com/ip2location/fluent-plugin-ip2location
|
|
95
|
+
licenses:
|
|
96
|
+
- MIT
|
|
97
|
+
metadata:
|
|
98
|
+
homepage_uri: https://github.com/ip2location/fluent-plugin-ip2location
|
|
99
|
+
source_code_uri: https://github.com/ip2location/fluent-plugin-ip2location
|
|
100
|
+
changelog_uri: https://github.com/ip2location/fluent-plugin-ip2location/blob/main/CHANGELOG.md
|
|
101
|
+
rubygems_mfa_required: 'true'
|
|
102
|
+
rdoc_options: []
|
|
103
|
+
require_paths:
|
|
104
|
+
- lib
|
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '3.2'
|
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
|
+
requirements:
|
|
112
|
+
- - ">="
|
|
113
|
+
- !ruby/object:Gem::Version
|
|
114
|
+
version: '0'
|
|
115
|
+
requirements: []
|
|
116
|
+
rubygems_version: 4.0.15
|
|
117
|
+
specification_version: 4
|
|
118
|
+
summary: Fluentd filter plugin for IP2Location BIN database enrichment.
|
|
119
|
+
test_files: []
|