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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9e2cdd52d7bb6925077930b4af585a251b7adefc
4
- data.tar.gz: 64429389036f8c97f4a502dad80cfebce71aaa83
3
+ metadata.gz: 6d34dc14c5627860aa7787a9c0e0dbac19edaf9d
4
+ data.tar.gz: 57c8a63726d0ad90f47653b6f3d20286d1527129
5
5
  SHA512:
6
- metadata.gz: 05735444de0f2eceaaa76a417cd146971bc90ac614626dbaab1d4881b85651c06ab24aabad039fa9c90047f96e53e9dc406ba12c47743522d8f6947e34dce660
7
- data.tar.gz: 8592521b71b5bb4df3311ea87f833627e129e7582ccb5cb8360a5bab67140e4efc284a35d273b767ec088db432aebea1505ba2b76efa2e1871027e989181e2a9
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.3.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>.+)(| (?<option3>.*)))?/
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
- matches = LOGFILE_REGEXP.match(content.key)
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
- # read an object from S3 to a file and write buffer file
204
- File.open(@buf_file, File::WRONLY|File::CREAT|File::TRUNC) do |file|
205
- s3_client.get_object(
206
- bucket: @s3_bucketname,
207
- key: object_name
208
- ) do |chunk|
209
- file.write(chunk)
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
 
@@ -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.3.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-03-29 00:00:00.000000000 Z
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.4.5.1
141
+ rubygems_version: 2.6.11
142
142
  signing_key:
143
143
  specification_version: 4
144
144
  summary: Amazon ELB log input plugin