fluent-plugin-elb-log 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +12 -5
- data/fluent-plugin-elb-log.gemspec +1 -1
- data/lib/fluent/plugin/in_elb_log.rb +55 -33
- data/test/plugin/in_elb_log.rb +85 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d34dc14c5627860aa7787a9c0e0dbac19edaf9d
|
4
|
+
data.tar.gz: 57c8a63726d0ad90f47653b6f3d20286d1527129
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6854587f02206b4cdcd14863516d4df01b79eda6af2765d4250c3139e21ea1bb20896b7dba86cd29287aafa5b00e7983d02456ee50bfd29da6519d6c57622012
|
7
|
+
data.tar.gz: cfb29cc94c144bf8a877a3cd287510be473c31f23fa2f6879b0421ccba0e8a992559057e27f5f2c0edc12bd6877544872c878b570511bc1eb05b58d0e173b612
|
data/README.md
CHANGED
@@ -5,8 +5,6 @@
|
|
5
5
|
|
6
6
|
## Requirements
|
7
7
|
|
8
|
-
## Requirements
|
9
|
-
|
10
8
|
| fluent-plugin-elb-log | fluentd | ruby |
|
11
9
|
|-----------------------|------------|--------|
|
12
10
|
| >= 0.3.0 | >= v0.14.0 | >= 2.1 |
|
@@ -36,6 +34,12 @@
|
|
36
34
|
- user_agent
|
37
35
|
- option1, option2, option3
|
38
36
|
|
37
|
+
## Support Application Load Balancer (ver 0.4.0 or later)
|
38
|
+
- Support Access Logs for Application Load Balancer
|
39
|
+
- https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html
|
40
|
+
- Existing ELB is called Classic Load Balancer
|
41
|
+
- http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/access-log-collection.html
|
42
|
+
|
39
43
|
## When SSL certification error
|
40
44
|
log:
|
41
45
|
```
|
@@ -50,7 +54,7 @@ SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt (If you using amazon linux)
|
|
50
54
|
|
51
55
|
```config
|
52
56
|
<source>
|
53
|
-
type elb_log
|
57
|
+
@type elb_log
|
54
58
|
|
55
59
|
# following attibutes are required
|
56
60
|
region <region name>
|
@@ -70,7 +74,7 @@ SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt (If you using amazon linux)
|
|
70
74
|
### Example setting
|
71
75
|
```config
|
72
76
|
<source>
|
73
|
-
type elb_log
|
77
|
+
@type elb_log
|
74
78
|
region us-east-1
|
75
79
|
s3_bucketname my-elblog-bucket
|
76
80
|
s3_prefix prodcution/web
|
@@ -83,7 +87,7 @@ SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt (If you using amazon linux)
|
|
83
87
|
</source>
|
84
88
|
|
85
89
|
<match **>
|
86
|
-
type stdout
|
90
|
+
@type stdout
|
87
91
|
</match>
|
88
92
|
```
|
89
93
|
|
@@ -119,6 +123,9 @@ SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt (If you using amazon linux)
|
|
119
123
|
"user_agent":"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)",
|
120
124
|
"ssl_cipher":"DHE-RSA-AES128-SHA",
|
121
125
|
"ssl_protocol":"TLSv1.2",
|
126
|
+
"type":"http",
|
127
|
+
"target_group_arn":"arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/lbgrp1/605122a4e4ee9f2d",
|
128
|
+
"trace_id":"\"Root=1-xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx\""
|
122
129
|
"option3":null
|
123
130
|
}
|
124
131
|
```
|
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "fluent-plugin-elb-log"
|
7
|
-
spec.version = "0.
|
7
|
+
spec.version = "0.4.0"
|
8
8
|
spec.authors = ["shinsaka"]
|
9
9
|
spec.email = ["shinx1265@gmail.com"]
|
10
10
|
spec.summary = "Amazon ELB log input plugin"
|
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'time'
|
2
|
+
require 'zlib'
|
3
|
+
require 'fileutils'
|
2
4
|
require 'aws-sdk'
|
3
5
|
require 'fluent/input'
|
4
6
|
|
@@ -7,8 +9,8 @@ class Fluent::Plugin::Elb_LogInput < Fluent::Plugin::Input
|
|
7
9
|
|
8
10
|
helpers :timer
|
9
11
|
|
10
|
-
LOGFILE_REGEXP = /^((?<prefix>.+?)\/|)AWSLogs\/(?<account_id>[0-9]{12})\/elasticloadbalancing\/(?<region>.+?)\/(?<logfile_date>[0-9]{4}\/[0-9]{2}\/[0-9]{2})\/[0-9]{12}_elasticloadbalancing_.+?_(?<logfile_elb_name>[^_]+)_(?<elb_timestamp>[0-9]{8}T[0-9]{4}Z)_(?<elb_ip_address>.+?)_(?<logfile_hash>.+)\.log
|
11
|
-
ACCESSLOG_REGEXP = /^(?<time>\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}\.\d{6}Z) (?<elb>.+?) (?<client>[^ ]+)\:(?<client_port>.+?) (?<backend>.+?)(\:(?<backend_port>.+?))? (?<request_processing_time>.+?) (?<backend_processing_time>.+?) (?<response_processing_time>.+?) (?<elb_status_code>.+?) (?<backend_status_code>.+?) (?<received_bytes>.+?) (?<sent_bytes>.+?) \"(?<request_method>.+?) (?<request_uri>.+?) (?<request_protocol>.+?)\"( \"(?<user_agent>.*?)\" (?<ssl_cipher>.+?) (?<ssl_protocol
|
12
|
+
LOGFILE_REGEXP = /^((?<prefix>.+?)\/|)AWSLogs\/(?<account_id>[0-9]{12})\/elasticloadbalancing\/(?<region>.+?)\/(?<logfile_date>[0-9]{4}\/[0-9]{2}\/[0-9]{2})\/[0-9]{12}_elasticloadbalancing_.+?_(?<logfile_elb_name>[^_]+)_(?<elb_timestamp>[0-9]{8}T[0-9]{4}Z)_(?<elb_ip_address>.+?)_(?<logfile_hash>.+)\.log(.gz)?$/
|
13
|
+
ACCESSLOG_REGEXP = /^((?<type>[a-z0-9]+) )?(?<time>\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}\.\d{6}Z) (?<elb>.+?) (?<client>[^ ]+)\:(?<client_port>.+?) (?<backend>.+?)(\:(?<backend_port>.+?))? (?<request_processing_time>.+?) (?<backend_processing_time>.+?) (?<response_processing_time>.+?) (?<elb_status_code>.+?) (?<backend_status_code>.+?) (?<received_bytes>.+?) (?<sent_bytes>.+?) \"(?<request_method>.+?) (?<request_uri>.+?) (?<request_protocol>.+?)\"( \"(?<user_agent>.*?)\" (?<ssl_cipher>.+?) (?<ssl_protocol>[^\s]+)( (?<target_group_arn>arn:.+) (?<trace_id>[^\s]+))?(| (?<option3>.*)))?/
|
12
14
|
|
13
15
|
config_param :access_key_id, :string, default: nil, secret: true
|
14
16
|
config_param :secret_access_key, :string, default: nil, secret: true
|
@@ -146,38 +148,48 @@ class Fluent::Plugin::Elb_LogInput < Fluent::Plugin::Input
|
|
146
148
|
end
|
147
149
|
|
148
150
|
def get_object_keys(timestamp)
|
149
|
-
# get values from object file name
|
150
151
|
begin
|
151
152
|
object_keys = []
|
153
|
+
get_object_keys_from_s3.each do |object_key|
|
154
|
+
matches = LOGFILE_REGEXP.match(object_key)
|
155
|
+
next unless matches
|
156
|
+
|
157
|
+
# snip old items
|
158
|
+
elb_timestamp_unixtime = Time.parse(matches[:elb_timestamp]).to_i
|
159
|
+
next if elb_timestamp_unixtime <= timestamp
|
160
|
+
|
161
|
+
log.debug object_key
|
162
|
+
object_keys << {
|
163
|
+
key: object_key,
|
164
|
+
prefix: matches[:prefix],
|
165
|
+
account_id: matches[:account_id],
|
166
|
+
region: matches[:region],
|
167
|
+
logfile_date: matches[:logfile_date],
|
168
|
+
logfile_elb_name: matches[:logfile_elb_name],
|
169
|
+
elb_timestamp: matches[:elb_timestamp],
|
170
|
+
elb_ip_address: matches[:elb_ip_address],
|
171
|
+
logfile_hash: matches[:logfile_hash],
|
172
|
+
elb_timestamp_unixtime: elb_timestamp_unixtime,
|
173
|
+
}
|
174
|
+
end
|
175
|
+
return object_keys
|
176
|
+
rescue => e
|
177
|
+
log.warn "error occurred: #{e.message}"
|
178
|
+
end
|
179
|
+
end
|
152
180
|
|
181
|
+
def get_object_keys_from_s3
|
182
|
+
begin
|
153
183
|
objects = s3_client.list_objects(
|
154
184
|
bucket: @s3_bucketname,
|
155
185
|
max_keys: 100,
|
156
186
|
prefix: @s3_prefix,
|
157
187
|
)
|
158
|
-
|
188
|
+
|
189
|
+
object_keys = []
|
159
190
|
objects.each do |object|
|
160
191
|
object.contents.each do |content|
|
161
|
-
|
162
|
-
next unless matches
|
163
|
-
|
164
|
-
# snip old items
|
165
|
-
elb_timestamp_unixtime = Time.parse(matches[:elb_timestamp]).to_i
|
166
|
-
next if elb_timestamp_unixtime <= timestamp
|
167
|
-
|
168
|
-
log.debug content.key
|
169
|
-
object_keys << {
|
170
|
-
key: content.key,
|
171
|
-
prefix: matches[:prefix],
|
172
|
-
account_id: matches[:account_id],
|
173
|
-
region: matches[:region],
|
174
|
-
logfile_date: matches[:logfile_date],
|
175
|
-
logfile_elb_name: matches[:logfile_elb_name],
|
176
|
-
elb_timestamp: matches[:elb_timestamp],
|
177
|
-
elb_ip_address: matches[:elb_ip_address],
|
178
|
-
logfile_hash: matches[:logfile_hash],
|
179
|
-
elb_timestamp_unixtime: elb_timestamp_unixtime,
|
180
|
-
}
|
192
|
+
object_keys << content.key
|
181
193
|
end
|
182
194
|
end
|
183
195
|
return object_keys
|
@@ -200,17 +212,24 @@ class Fluent::Plugin::Elb_LogInput < Fluent::Plugin::Input
|
|
200
212
|
begin
|
201
213
|
log.debug "getting object from s3 name is #{object_name}"
|
202
214
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
215
|
+
Tempfile.create('fluent-elblog') do |tfile|
|
216
|
+
s3_client.get_object(bucket: @s3_bucketname, key: object_name) do |chunk|
|
217
|
+
tfile.write(chunk)
|
218
|
+
end
|
219
|
+
tfile.close
|
220
|
+
|
221
|
+
if File.extname(object_name) != '.gz'
|
222
|
+
FileUtils.cp(tfile.path, @buf_file)
|
223
|
+
else
|
224
|
+
File.open(@buf_file, File::WRONLY|File::CREAT|File::TRUNC) do |bfile|
|
225
|
+
Zlib::GzipReader.open(tfile.path) do |gz|
|
226
|
+
bfile.write gz.read
|
227
|
+
end
|
228
|
+
end
|
210
229
|
end
|
211
230
|
end
|
212
231
|
rescue => e
|
213
|
-
log.warn "error occurred: #{e.message}"
|
232
|
+
log.warn "error occurred: #{e.message}, #{e.backtrace}"
|
214
233
|
end
|
215
234
|
end
|
216
235
|
|
@@ -224,7 +243,7 @@ class Fluent::Plugin::Elb_LogInput < Fluent::Plugin::Input
|
|
224
243
|
log.info "nomatch log found: #{line} in #{record_common['key']}"
|
225
244
|
next
|
226
245
|
end
|
227
|
-
|
246
|
+
|
228
247
|
record = {
|
229
248
|
"time" => line_match[:time].gsub(/Z/, "+0000"),
|
230
249
|
"elb" => line_match[:elb],
|
@@ -245,6 +264,9 @@ class Fluent::Plugin::Elb_LogInput < Fluent::Plugin::Input
|
|
245
264
|
"user_agent" => line_match[:user_agent],
|
246
265
|
"ssl_cipher" => line_match[:ssl_cipher],
|
247
266
|
"ssl_protocol" => line_match[:ssl_protocol],
|
267
|
+
"type" => line_match[:type],
|
268
|
+
"target_group_arn" => line_match[:target_group_arn],
|
269
|
+
"trace_id" => line_match[:trace_id],
|
248
270
|
"option3" => line_match[:option3],
|
249
271
|
}
|
250
272
|
|
data/test/plugin/in_elb_log.rb
CHANGED
@@ -113,4 +113,89 @@ class Elb_LogInputTest < Test::Unit::TestCase
|
|
113
113
|
assert_equal('secret_access_key is required', exception.message)
|
114
114
|
end
|
115
115
|
|
116
|
+
def test_logfilename_classic_lb_parse
|
117
|
+
logfile_classic = 'classic/AWSLogs/123456789012/elasticloadbalancing/ap-northeast-1/2017/05/03/123456789012_elasticloadbalancing_ap-northeast-1_elbname_20170503T1250Z_10.0.0.1_43nzjpdj.log'
|
118
|
+
|
119
|
+
m = Fluent::Plugin::Elb_LogInput::LOGFILE_REGEXP.match(logfile_classic)
|
120
|
+
assert_equal('classic', m[:prefix])
|
121
|
+
assert_equal('123456789012', m[:account_id])
|
122
|
+
assert_equal('ap-northeast-1', m[:region])
|
123
|
+
assert_equal('2017/05/03', m[:logfile_date])
|
124
|
+
assert_equal('elbname', m[:logfile_elb_name])
|
125
|
+
assert_equal('20170503T1250Z', m[:elb_timestamp])
|
126
|
+
assert_equal('10.0.0.1', m[:elb_ip_address])
|
127
|
+
assert_equal('43nzjpdj', m[:logfile_hash])
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_logfilename_appication_lb_parse
|
131
|
+
logfile_applb = 'applb/AWSLogs/123456789012/elasticloadbalancing/ap-northeast-1/2017/05/03/123456789012_elasticloadbalancing_ap-northeast-1_app.elbname.59bfa19e900030c2_20170503T1310Z_10.0.0.1_2tko12gv.log.gz'
|
132
|
+
|
133
|
+
m = Fluent::Plugin::Elb_LogInput::LOGFILE_REGEXP.match(logfile_applb)
|
134
|
+
assert_equal('applb', m[:prefix])
|
135
|
+
assert_equal('123456789012', m[:account_id])
|
136
|
+
assert_equal('ap-northeast-1', m[:region])
|
137
|
+
assert_equal('2017/05/03', m[:logfile_date])
|
138
|
+
assert_equal('app.elbname.59bfa19e900030c2', m[:logfile_elb_name])
|
139
|
+
assert_equal('20170503T1310Z', m[:elb_timestamp])
|
140
|
+
assert_equal('10.0.0.1', m[:elb_ip_address])
|
141
|
+
assert_equal('2tko12gv', m[:logfile_hash])
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_log_classic_lb_parse
|
145
|
+
log = '2017-05-05T12:53:50.128456Z elbname 10.11.12.13:37852 192.168.30.186:443 0.00004 0.085372 0.000039 301 301 0 0 "GET https://elbname-123456789.ap-northeast-1.elb.amazonaws.com:443/ HTTP/1.1" "curl/7.51.0" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2'
|
146
|
+
|
147
|
+
m = Fluent::Plugin::Elb_LogInput::ACCESSLOG_REGEXP.match(log)
|
148
|
+
assert_equal('2017-05-05T12:53:50.128456Z', m[:time])
|
149
|
+
assert_equal('elbname', m[:elb])
|
150
|
+
assert_equal('10.11.12.13', m[:client])
|
151
|
+
assert_equal('37852', m[:client_port])
|
152
|
+
assert_equal('192.168.30.186', m[:backend])
|
153
|
+
assert_equal('443', m[:backend_port])
|
154
|
+
assert_equal('0.00004', m[:request_processing_time])
|
155
|
+
assert_equal('0.085372', m[:backend_processing_time])
|
156
|
+
assert_equal('0.000039', m[:response_processing_time])
|
157
|
+
assert_equal('301', m[:elb_status_code])
|
158
|
+
assert_equal('301', m[:backend_status_code])
|
159
|
+
assert_equal('0', m[:received_bytes])
|
160
|
+
assert_equal('0', m[:sent_bytes])
|
161
|
+
assert_equal('GET', m[:request_method])
|
162
|
+
assert_equal('https://elbname-123456789.ap-northeast-1.elb.amazonaws.com:443/', m[:request_uri])
|
163
|
+
assert_equal('HTTP/1.1', m[:request_protocol])
|
164
|
+
assert_equal('curl/7.51.0', m[:user_agent])
|
165
|
+
assert_equal('ECDHE-RSA-AES128-GCM-SHA256', m[:ssl_cipher])
|
166
|
+
assert_equal('TLSv1.2', m[:ssl_protocol])
|
167
|
+
assert_equal(nil, m[:type])
|
168
|
+
assert_equal(nil, m[:target_group_arn])
|
169
|
+
assert_equal(nil, m[:trace_id])
|
170
|
+
assert_equal(nil, m[:option3])
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_log_application_lb_parse
|
174
|
+
log = 'https 2017-05-05T13:07:53.468529Z app/elbname/59bfa19e900030c2 10.20.30.40:52730 192.168.30.186:443 0.006 0.000 0.086 301 301 117 507 "GET https://elbname-1121128512.ap-northeast-1.elb.amazonaws.com:443/ HTTP/1.1" "curl/7.51.0" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/lbgrp1/605122a4e4ee9f2d "Root=1-590c7929-4eb4cb393d46a01d22db8473"'
|
175
|
+
|
176
|
+
m = Fluent::Plugin::Elb_LogInput::ACCESSLOG_REGEXP.match(log)
|
177
|
+
assert_equal('2017-05-05T13:07:53.468529Z', m[:time])
|
178
|
+
assert_equal('app/elbname/59bfa19e900030c2', m[:elb])
|
179
|
+
assert_equal('10.20.30.40', m[:client])
|
180
|
+
assert_equal('52730', m[:client_port])
|
181
|
+
assert_equal('192.168.30.186', m[:backend])
|
182
|
+
assert_equal('443', m[:backend_port])
|
183
|
+
assert_equal('0.006', m[:request_processing_time])
|
184
|
+
assert_equal('0.000', m[:backend_processing_time])
|
185
|
+
assert_equal('0.086', m[:response_processing_time])
|
186
|
+
assert_equal('301', m[:elb_status_code])
|
187
|
+
assert_equal('301', m[:backend_status_code])
|
188
|
+
assert_equal('117', m[:received_bytes])
|
189
|
+
assert_equal('507', m[:sent_bytes])
|
190
|
+
assert_equal('GET', m[:request_method])
|
191
|
+
assert_equal('https://elbname-1121128512.ap-northeast-1.elb.amazonaws.com:443/', m[:request_uri])
|
192
|
+
assert_equal('HTTP/1.1', m[:request_protocol])
|
193
|
+
assert_equal('curl/7.51.0', m[:user_agent])
|
194
|
+
assert_equal('ECDHE-RSA-AES128-GCM-SHA256', m[:ssl_cipher])
|
195
|
+
assert_equal('TLSv1.2', m[:ssl_protocol])
|
196
|
+
assert_equal('https', m[:type])
|
197
|
+
assert_equal('arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/lbgrp1/605122a4e4ee9f2d', m[:target_group_arn])
|
198
|
+
assert_equal('"Root=1-590c7929-4eb4cb393d46a01d22db8473"', m[:trace_id])
|
199
|
+
assert_equal(nil, m[:option3])
|
200
|
+
end
|
116
201
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-elb-log
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- shinsaka
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -138,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
138
|
version: '0'
|
139
139
|
requirements: []
|
140
140
|
rubyforge_project:
|
141
|
-
rubygems_version: 2.
|
141
|
+
rubygems_version: 2.6.11
|
142
142
|
signing_key:
|
143
143
|
specification_version: 4
|
144
144
|
summary: Amazon ELB log input plugin
|