fluent-plugin-aurora-slowquerylog 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9829f923bc32db96e938ead936dd483631510115
4
+ data.tar.gz: fa6d2a8526c68d94952eb0a30fe6ccd0238fb169
5
+ SHA512:
6
+ metadata.gz: 341d4e4863651fb0b0b717e0d2df52d959f65fb485b6b7ae7a66922c664191e20333601392185b1ae1be234c3fa88770dfff9984a49fbc38732ebebcc93ea703
7
+ data.tar.gz: 2c45ea22e75312ab2a2de7a0ac96e75c5cd0c73c9ed75306d5b136f5ee0abcb89a5086614c059d817e478e634bf71c70fc4789ede188af65ec465385fe519d46
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ vendor
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.4
4
+ before_install: gem install bundler -v 1.11.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-aurora-slowquerylog.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Takayuki WATANABE
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
13
+ all 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
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # Fluent::Plugin::Aurora::Slowquerylog
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/fluent/plugin/aurora/slowquerylog`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'fluent-plugin-aurora-slowquerylog'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install fluent-plugin-aurora-slowquerylog
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/fluent-plugin-aurora-slowquerylog.
36
+
37
+
38
+ ## License
39
+
40
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
+
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rake/testtask"
4
+
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "fluent/plugin/aurora/slowquerylog"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,27 @@
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-aurora-slowquerylog"
7
+ spec.version = "0.0.1"
8
+ spec.authors = ["Takayuki WATANABE"]
9
+ spec.email = ["takanabe.w@gmail.com"]
10
+
11
+ spec.summary = "A fluentd plugin that collects AWS Aurora slow query logs with `log_output=FILE`"
12
+ spec.description = "A fluentd plugin that collects AWS Aurora slow query logs with `log_output=FILE`"
13
+ spec.homepage = "https://github.com/takanabe/fluent-plugin-aurora-slowquerylog"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_runtime_dependency "fluentd"
21
+ spec.add_runtime_dependency "aws-sdk", '~> 2'
22
+ spec.add_runtime_dependency "myslog"
23
+ spec.add_runtime_dependency "activesupport"
24
+
25
+ spec.add_development_dependency "test-unit", ">= 3.0.0"
26
+ spec.add_development_dependency "pry-byebug"
27
+ end
@@ -0,0 +1,232 @@
1
+ require 'active_support/all'
2
+ require 'aws-sdk-core'
3
+ require 'fluent/input'
4
+ require "json"
5
+ require 'myslog'
6
+ require 'yaml'
7
+
8
+ module Fluent
9
+ class AuroraSlowqueryLog < Input
10
+ # First, register the plugin. NAME is the name of this plugin
11
+ # and identifies the plugin in the configuration file.
12
+ Fluent::Plugin.register_input('NAME', self)
13
+
14
+ # config_param defines a parameter. You can refer a parameter via @port instance variable
15
+ # :default means this parameter is optional
16
+ config_param :tag, :string # tag.child_tag
17
+ config_param :db_instance_identifier, :string # rds-instance-id
18
+ config_param :region, :string # us-east-1
19
+ config_param :log_file_name, :string # slowquery/mysql-slowquery.log
20
+ config_param :aurora_state_file, :string #/tmp/marker_state
21
+
22
+ # Following configs are necessary if you don't use IAM instance profile
23
+ config_param :log_fetch_interval, :time, :default => 60
24
+ config_param :aws_access_key_id, :string, default: nil
25
+ config_param :aws_secret_access_key, :string, default: nil
26
+ config_param :filename_contains, :string, default: 'mysql-slowquery.log'
27
+
28
+ def initialize
29
+ super
30
+ @current_slowlog = nil
31
+ @previous_slowlog = nil
32
+ end
33
+
34
+ # This method is called before starting.
35
+ # 'conf' is a Hash that includes configuration parameters.
36
+ # If the configuration is invalid, raise Fluent::ConfigError.
37
+ def configure(conf)
38
+ super
39
+ end
40
+
41
+ # This method is called when starting.
42
+ # Open sockets or files and create a thread here.
43
+ def start
44
+ super
45
+ @stop_flag = false
46
+ $log.debug 'Start aurora log collection thread'
47
+ @thread = Thread.new(&method(:thread_main))
48
+ end
49
+
50
+ # This method is called when shutting down.
51
+ def shutdown
52
+ super
53
+ @stop_flag = true
54
+ $log.debug 'Waiting for thread to finish'
55
+ @thread.join
56
+ end
57
+
58
+ def thread_main
59
+ until @stop_flag
60
+ begin
61
+ fetch_aurora_slow_log
62
+ rescue => e
63
+ log.error 'unexpected error', :error => e.message, :error_class => e.class
64
+ log.error_backtrace e.backtrace
65
+ end
66
+ sleep @log_fetch_interval
67
+ end
68
+ end
69
+
70
+ def create_rds_client
71
+ @rds_client = if @aws_access_key_id && @aws_secret_access_key
72
+ Aws::RDS::Client.new(
73
+ region: @region,
74
+ access_key_id: @aws_access_key_id,
75
+ secret_access_key: @aws_secret_access_key
76
+ )
77
+ else # Use IAM Profile
78
+ Aws::RDS::Client.new(region: @region)
79
+ end
80
+ end
81
+
82
+ def fetch_aurora_slow_log
83
+ create_rds_client
84
+ fetch_recent_slowlogs
85
+ if File.exist?(@aurora_state_file)
86
+ state = load_state
87
+ if slowlog_rotated?(state)
88
+ if state["additional_data_pending"]
89
+ log_file_name = "#{@log_file_name}.#{Time.now.utc.strftime("%Y-%m-%d.%H")}"
90
+ fetch_and_emit_log(log_file_name, state["marker"],true)
91
+ else
92
+ log_file_name = "#{@log_file_name}.#{Time.now.utc.strftime("%Y-%m-%d.%H")}"
93
+ fetch_and_emit_log(@log_file_name, state["marker"],false)
94
+ end
95
+ else
96
+ fetch_and_emit_log(@log_file_name, state["marker"],true)
97
+ end
98
+ else
99
+ fetch_and_emit_log(@log_file_name, false, true)
100
+ end
101
+ end
102
+
103
+ def fetch_and_emit_log(log_file_name,marker,save)
104
+ if save
105
+ if marker
106
+ fetched_file = @rds_client.download_db_log_file_portion(
107
+ db_instance_identifier: @db_instance_identifier,
108
+ log_file_name: log_file_name,
109
+ marker: marker)
110
+ save_state(fetched_file)
111
+ records = parse_fetched_file(fetched_file)
112
+ emit_slowlogs(records)
113
+ else
114
+ fetched_file = @rds_client.download_db_log_file_portion(
115
+ db_instance_identifier: @db_instance_identifier,
116
+ log_file_name: "slowquery/mysql-slowquery.log")
117
+ save_state(fetched_file)
118
+ records = parse_fetched_file(fetched_file)
119
+ emit_slowlogs(records)
120
+ end
121
+ else # Executed when log rotation occurs without pending data
122
+ fetched_file = @rds_client.download_db_log_file_portion(
123
+ db_instance_identifier: @db_instance_identifier,
124
+ log_file_name: log_file_name,
125
+ marker: marker)
126
+ system("rm #{@aurora_state_file}")
127
+ records = parse_fetched_file(fetched_file)
128
+ emit_slowlogs(records)
129
+ end
130
+ end
131
+
132
+ def parse_fetched_file(fetched_file)
133
+ parsed_log_data= parse_query(fetched_file)
134
+ exclude_useless_sql(parsed_log_data)
135
+ end
136
+
137
+ def parse_query(fetched_file)
138
+ myslog = MySlog.new
139
+ myslog.parse(fetched_file.log_file_data)
140
+ end
141
+
142
+ def load_state
143
+ begin
144
+ YAML.load_file(@aurora_state_file)
145
+ rescue SystemCallError => e
146
+ puts %Q(class=[#{e.class}] message=[#{e.message}])
147
+ rescue IOError => e
148
+ puts %Q(class=[#{e.class}] message=[#{e.message}])
149
+ end
150
+ end
151
+
152
+ def slowlog_rotated?(state)
153
+ if @previous_slowlog == state["previous_slowlog"]
154
+ false
155
+ else
156
+ true
157
+ end
158
+ end
159
+
160
+ def fetch_recent_slowlogs
161
+ log_files = []
162
+ unix_time_2hours_ago = (2.hours.ago.to_f * 1000).floor
163
+
164
+ @rds_client.describe_db_log_files(db_instance_identifier: @db_instance_identifier, filename_contains: @filename_contains, file_last_written: unix_time_2hours_ago).each do |page|
165
+ page.describe_db_log_files.each do |f|
166
+ log_files << f
167
+ end
168
+ end
169
+
170
+ sorted_slow_log_files = log_files.sort_by do |f|
171
+ f.last_written
172
+ end
173
+
174
+ if sorted_slow_log_files.length >= 2
175
+ current,previous = sorted_slow_log_files[-1], sorted_slow_log_files[-2]
176
+ @current_slowlog = current.log_file_name
177
+ @previous_slowlog = previous.log_file_name
178
+ elsif sorted_slow_log_files.length >= 1
179
+ current = sorted_slow_log_files[-1]
180
+ @current_slowlog = current.log_file_name
181
+ else
182
+ raise "There is no slowlog. Please set log_output=FILE"
183
+ end
184
+ end
185
+
186
+ def save_state(fetched_file)
187
+ open(@aurora_state_file, 'w') do |f|
188
+ state_keys={}
189
+ state_keys["marker"] = fetched_file.marker
190
+ state_keys["additional_data_pending"] = fetched_file.additional_data_pending
191
+ state_keys["current_slowlog"] = @current_slowlog
192
+ state_keys["previous_slowlog"] = @previous_slowlog
193
+ YAML.dump(state_keys,f)
194
+ end
195
+ end
196
+
197
+ # Exclude useless SQL queries
198
+ def exclude_useless_sql(parsed_log_data)
199
+ responses = []
200
+ parsed_log_data.each do |record|
201
+ if m = record[:sql].match(/^\/rdsdbbin\/oscar\/bin\/mysqld/)
202
+ next
203
+ elsif m = record[:sql].match(/^(.+); \/rdsdbbin\/oscar\/bin\/mysqld,.+ Argument/)
204
+ responses << record
205
+ responses.last[:sql] = m[1]
206
+ elsif m = record[:sql].match(/^use .+; SET timestamp=\d+; (.+)/)
207
+ responses << record
208
+ responses.last[:sql] = m[1]
209
+ elsif m = record[:sql].match(/^SET timestamp=\d+; (.+)/)
210
+ responses << record
211
+ responses.last[:sql] = m[1]
212
+ else
213
+ responses << record
214
+ end
215
+ end
216
+ responses
217
+ end
218
+
219
+ def emit_slowlogs(records)
220
+ es = MultiEventStream.new
221
+ records.each do |record|
222
+ es.add(record[:date], record)
223
+ end
224
+ unless es.empty?
225
+ begin
226
+ router.emit_stream(@tag, es)
227
+ rescue
228
+ end
229
+ end
230
+ end
231
+ end
232
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-aurora-slowquerylog
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Takayuki WATANABE
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-10-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluentd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-sdk
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: myslog
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: test-unit
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 3.0.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 3.0.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry-byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: A fluentd plugin that collects AWS Aurora slow query logs with `log_output=FILE`
98
+ email:
99
+ - takanabe.w@gmail.com
100
+ executables:
101
+ - console
102
+ - setup
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".gitignore"
107
+ - ".travis.yml"
108
+ - Gemfile
109
+ - LICENSE.txt
110
+ - README.md
111
+ - Rakefile
112
+ - bin/console
113
+ - bin/setup
114
+ - fluent-plugin-aurora-slowquerylog.gemspec
115
+ - lib/fluent/plugin/in_aurora_slow_query_log.rb
116
+ homepage: https://github.com/takanabe/fluent-plugin-aurora-slowquerylog
117
+ licenses:
118
+ - MIT
119
+ metadata: {}
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 2.4.5.1
137
+ signing_key:
138
+ specification_version: 4
139
+ summary: A fluentd plugin that collects AWS Aurora slow query logs with `log_output=FILE`
140
+ test_files: []