├── .gitignore
├── .travis.yml
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── fluent-plugin-elb-log.gemspec
├── fluent.conf.sample
├── lib
└── fluent
│ └── plugin
│ └── in_elb_log.rb
└── test
├── helper.rb
└── plugin
└── in_elb_log.rb
/.gitignore:
--------------------------------------------------------------------------------
1 | *.gem
2 | *.rbc
3 | .bundle
4 | .config
5 | .yardoc
6 | Gemfile.lock
7 | InstalledFiles
8 | _yardoc
9 | coverage
10 | doc/
11 | lib/bundler/man
12 | pkg
13 | rdoc
14 | spec/reports
15 | test/tmp
16 | test/version_tmp
17 | tmp
18 | .irb_history
19 | .ruby-version
20 | .vscode
21 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | env:
2 | global:
3 | - CC_TEST_REPORTER_ID=bca5d9771c392e374d213de82dde44181a12b4c8b5d5bd37b249c81ca5bf32f1
4 | - GIT_COMMITTED_AT=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then git log -1 --pretty=format:%ct; else git log -1 --skip 1 --pretty=format:%ct; fi)
5 | language: ruby
6 |
7 | rvm:
8 | - 2.1
9 | - 2.2
10 | - 2.3.3
11 | - 2.4.1
12 | branches:
13 | only:
14 | - master
15 |
16 | before_script:
17 | - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
18 | - chmod +x ./cc-test-reporter
19 | after_script:
20 | - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
21 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # Specify your gem's dependencies in fluent-plugin-elb-log.gemspec
4 | gemspec
5 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 shinsaka
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Amazon ELB log input plugin for fluentd
2 |
3 | [](https://badge.fury.io/rb/fluent-plugin-elb-log)
4 | [](https://travis-ci.org/shinsaka/fluent-plugin-elb-log)
5 | [](https://codeclimate.com/github/shinsaka/fluent-plugin-elb-log)
6 | [](https://codeclimate.com/github/shinsaka/fluent-plugin-elb-log/coverage)
7 |
8 | ## Overview
9 | - Amazon Web Services ELB log input plubin for fluentd
10 |
11 | ## Requirements
12 |
13 | | fluent-plugin-elb-log | fluentd | ruby |
14 | |-----------------------|------------|--------|
15 | | >= 0.3.0 | >= v0.14.0 | >= 2.1 |
16 | | < 0.3.0 | >= v0.12.0 | >= 1.9 |
17 |
18 | ## Installation
19 |
20 | $ fluentd-gem fluent-plugin-elb-log
21 |
22 | ## AWS ELB Settings
23 | - settings see: [Elastic Load Balancing](http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/enable-access-logs.html)
24 | - developer guide: [](http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/access-log-collection.html)
25 |
26 | ## Different from version 0.4.x
27 | - Using version 3 of the AWS SDK for Ruby.
28 |
29 | ## Support Application Load Balancer (ver 0.4.0 or later)
30 | - Support Access Logs for Application Load Balancer
31 | - https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html
32 | - Existing ELB is called Classic Load Balancer
33 | - http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/access-log-collection.html
34 |
35 | ## When SSL certification error
36 | log:
37 | ```
38 | SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
39 | ```
40 | Do env setting follows:
41 | ```
42 | SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt (If you using amazon linux)
43 | ```
44 |
45 | ## Configuration
46 |
47 | ```config
48 |
49 | @type elb_log
50 |
51 | # following attibutes are required
52 | region
53 | s3_bucketname
54 | s3_prefix
55 | timestamp_file
56 | buf_file
57 | refresh_interval
58 | tag
59 | delete
60 | include_all_message
61 | start_time
62 | exclude_pattern_logfile_elb_name
63 | use_sqs
64 |
65 | # following attibutes are required if you don't use IAM Role
66 | access_key_id
67 | secret_access_key
68 |
69 | ```
70 |
71 | `use_sqs` automatically creates an SQS queue named `fluent-plugin-elb-log-`
72 | and sets up the `all object create event` S3 event notification for the chosen S3 bucket. Stopping fluentd deletes both autmatically.
73 | To make it work, the following IAM policy should be attached to the instance IAM role or the user:
74 | ```
75 | {
76 | "Version": "2012-10-17",
77 | "Statement": [
78 | {
79 | "Sid": "FluentdPermissions",
80 | "Effect": "Allow",
81 | "Action": [
82 | "sqs:DeleteMessage",
83 | "s3:GetObject",
84 | "sqs:ReceiveMessage",
85 | "sqs:DeleteQueue",
86 | "sqs:GetQueueAttributes",
87 | "s3:ListBucket",
88 | "s3:PutBucketNotification",
89 | "sqs:CreateQueue"
90 | ],
91 | "Resource": [
92 | "arn:aws:sqs:*:123456789012:fluent-plugin-elb-log-*",
93 | "arn:aws:s3:::alb-logs-bucket/*",
94 | "arn:aws:s3:::alb-logs-bucket"
95 | ]
96 | }
97 | ]
98 | }
99 | ```
100 | When `use_sqs` is false:
101 | - 300 seconds is a good value for the `refresh_interval`
102 | - the plugin executes processing the whole S3 bucket (with the respect of `s3_prefix` and `start_time`/`timestamp_file`) every `refresh_interval`
103 |
104 | When `use_sqs` is true:
105 | - `refresh_interval` of 30-60 seconds should be fine.
106 | - the plugin executes processing the whole S3 bucket (with the respect of `s3_prefix` and `start_time`/`timestamp_file`) only once (at start) and then
107 | polls the SQS queue every `refresh_interval`.
108 |
109 | ### Example setting
110 | ```config
111 |
112 | @type elb_log
113 | region us-east-1
114 | s3_bucketname my-elblog-bucket
115 | s3_prefix prodcution/web
116 | timestamp_file /tmp/elb_last_at.dat
117 | buf_file /tmp/fluentd-elblog.tmpfile
118 | refresh_interval 30
119 | tag elb.access
120 | delete false
121 | include_all_message false
122 | exclude_pattern_logfile_elb_name "^app\.(uat|qa)\."
123 | start_time 2025-02-27T10:45:00
124 | use_sqs true
125 | access_key_id XXXXXXXXXXXXXXXXXXXX
126 | secret_access_key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
127 |
128 |
129 |
130 | @type record_transformer
131 |
132 | timestamp ${record["request_creation_time"]}
133 | logfile_name ${record["key"]}
134 |
135 | remove_keys prefix,logfile_date,logfile_elb_name,logfile_hash,logfile_timestamp,logfile_timestamp_unixtime,key,time,s3_last_modified_unixtime
136 |
137 |
138 |
139 | # @type stdout
140 | @type opensearch
141 | hosts node-1,node-2,node-3
142 | port 9200
143 | scheme https
144 | logstash_format true
145 | logstash_prefix alb-logs
146 | user fluentd
147 | password secret
148 | ssl_verify true
149 | ca_file /etc/fluentd/root-ca.pem
150 | flush_interval 300s
151 |
152 | ```
153 |
154 | ### json output example
155 | ```json
156 | {
157 | "account_id":"123456789012",
158 | "region":"ap-northeast-1",
159 | "logfile_date":"2015/06/15",
160 | "logfile_elb_name":"my-elb-name",
161 | "elb_ip_address":"52.0.0.0",
162 | "logfile_hash":"12squv5w",
163 | "logfile_timestamp":"20150615T0400Z",
164 | "key":"TEST/AWSLogs/123456789012/elasticloadbalancing/ap-northeast-1/2015/06/15/123456789012_elasticloadbalancing_ap-northeast-1_my-elb-name_20150615T0400Z_52.68.215.138_69squv5w.log",
165 | "prefix":"TEST",
166 | "elb_timestamp_unixtime":1434340800,
167 | "time":"2015-06-15T03:47:12.728427+0000",
168 | "elb":"my-elb-name",
169 | "client":"54.1.1.1",
170 | "client_port":"43759",
171 | "target":"10.0.0.1",
172 | "target_port":"80",
173 | "request_processing_time":4.0e-05,
174 | "target_processing_time":0.105048,
175 | "response_processing_time":2.4e-05,
176 | "elb_status_code":"200",
177 | "target_status_code":"200",
178 | "received_bytes":0,
179 | "sent_bytes":4622,
180 | "request_method":"GET",
181 | "request_uri":"https://my-elb-test.example.com/",
182 | "request_protocol":"HTTP/1.1",
183 | "user_agent":"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)",
184 | "ssl_cipher":"DHE-RSA-AES128-SHA",
185 | "ssl_protocol":"TLSv1.2",
186 | "type":"http",
187 | "target_group_arn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/lbgrp1/605122a4e4ee9f2d",
188 | "trace_id": "\"Root=1-xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx\"",
189 | "domain_name": "-",
190 | "chosen_cert_arn": "-",
191 | "matched_rule_priority": "0",
192 | "request_creation_time": "2099-10-26T06:10:03.050000Z",
193 | "actions_executed": "forward",
194 | "redirect_url": "-",
195 | "error_reason": "-",
196 | "target_port_list": "\"192.168.0.1:443\"",
197 | "target_status_code_list": "\"301\"",
198 | "classification": "-",
199 | "classification_reason": "-",
200 | "conn_trace_id": "TID_xxxxxxxxxxxxxxxxxxxxxxx"
201 | }
202 | ```
203 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require "bundler/gem_tasks"
2 |
3 | require 'rake/testtask'
4 | Rake::TestTask.new(:test) do |test|
5 | test.libs << 'lib' << 'test'
6 | test.pattern = 'test/**/*.rb'
7 | test.verbose = true
8 | test.warning = false
9 | end
10 |
11 | desc 'Run tests for all'
12 | task :default => :test
13 |
--------------------------------------------------------------------------------
/fluent-plugin-elb-log.gemspec:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | lib = File.expand_path('../lib', __FILE__)
3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4 |
5 | Gem::Specification.new do |spec|
6 | spec.name = "fluent-plugin-elb-log"
7 | spec.version = "1.4.0"
8 | spec.authors = ["shinsaka","jazzl0ver"]
9 | spec.email = ["shinx1265@gmail.com"]
10 | spec.summary = "Amazon ELB log input plugin"
11 | spec.description = "Amazon ELB log input plugin for fluentd"
12 | spec.homepage = "https://github.com/jazzl0ver/fluent-plugin-elb-log"
13 | spec.license = "MIT"
14 |
15 | spec.files = `git ls-files -z`.split("\x0")
16 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18 | spec.require_paths = ["lib"]
19 |
20 | spec.add_dependency "fluentd", ">= 0.14.0", "< 2"
21 | spec.add_dependency "aws-sdk-s3", "~> 1"
22 | spec.add_dependency "aws-sdk-ec2", "~> 1"
23 |
24 | spec.add_development_dependency "bundler", ">=1.17"
25 | spec.add_development_dependency "rake", "~> 12"
26 | spec.add_development_dependency "test-unit", "~> 3.2"
27 | spec.add_development_dependency "webmock", "~>3"
28 | spec.add_development_dependency "simplecov", "~>0"
29 | end
30 |
--------------------------------------------------------------------------------
/fluent.conf.sample:
--------------------------------------------------------------------------------
1 |
2 | @type elb_log
3 | region us-east-1
4 | s3_bucketname my-elblog-bucket
5 | s3_prefix prodcution/web
6 | timestamp_file /tmp/elb_last_at.dat
7 | buf_file /tmp/fluentd-elblog.tmpfile
8 | refresh_interval 30
9 | tag elb.access
10 | use_sqs true
11 | access_key_id XXXXXXXXXXXXXXXXXXXX
12 | secret_access_key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
13 |
14 |
15 |
16 | @type record_transformer
17 |
18 | timestamp ${record["request_creation_time"]}
19 | logfile_name ${record["key"]}
20 |
21 | remove_keys prefix,logfile_date,logfile_elb_name,logfile_hash,logfile_timestamp,logfile_timestamp_unixtime,key,time,s3_last_modified_unixtime
22 |
23 |
24 |
25 | @type stdout
26 |
27 |
--------------------------------------------------------------------------------
/lib/fluent/plugin/in_elb_log.rb:
--------------------------------------------------------------------------------
1 | require 'time'
2 | require 'zlib'
3 | require 'fileutils'
4 | require 'aws-sdk-s3'
5 | require 'aws-sdk-ec2'
6 | require 'aws-sdk-sqs'
7 | require 'fluent/input'
8 | require 'digest/sha1'
9 |
10 | class Fluent::Plugin::Elb_LogInput < Fluent::Plugin::Input
11 | Fluent::Plugin.register_input('elb_log', self)
12 |
13 | helpers :timer
14 |
15 | LOGFILE_REGEXP = /^((?.+?)\/|)AWSLogs\/(?[0-9]{12})\/elasticloadbalancing\/(?.+?)\/(?[0-9]{4}\/[0-9]{2}\/[0-9]{2})\/[0-9]{12}_elasticloadbalancing_.+?_(?[^_]+)_(?[0-9]{8}T[0-9]{4}Z)_(?.+?)_(?.+)\.log(.gz)?$/
16 | ACCESSLOG_REGEXP = /^((?[a-z0-9]+) )?(?