fluent-plugin-sql 0.6.1 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8bdf7e835bed062213f63778607f5f4e3a6f9a02
4
- data.tar.gz: d9b7d721ef9ad035193fbf0eb5a5460e88caa9aa
3
+ metadata.gz: 3e683b76d37276e4bbe276dc6148216c113e5267
4
+ data.tar.gz: 374e957bfaf1f9eea818a6d3bc9c9b370c58604f
5
5
  SHA512:
6
- metadata.gz: ab807cd58fa29576d9164e4ab1e307a3b8cde72dd129e608acc78da01c15499e9ba9def596b044604bd2890c877fc3d66be79ca31d441e24f0d6f5cba8a741f6
7
- data.tar.gz: 23a7698d628cd9dad85b9d1ab8f50ade3d925531cb230cbc9a93ace20e03ab157bd0ed09c1a3f97a9380931135acda9837402249e6b360e1881f694b157eff3e
6
+ metadata.gz: 1a71af14e2817621d22c85ac31a49d54d6b7f224b605ce2febaf09fbe369b435b33df779b23196e37ac6fb5d3c5a26d2039cb5aadf24dc90ec5d105ba4b283c6
7
+ data.tar.gz: 593be077cfbc429c9502ad7b56c404cac24afbae65268d095c723339bb77a4645a5c4297d03a6cbf73dd269cdda69824d3e2e5d4d4b498406e8871c5e0fb775e
@@ -14,7 +14,6 @@ rvm:
14
14
 
15
15
  gemfile:
16
16
  - Gemfile
17
- - Gemfile.v0.12
18
17
 
19
18
  before_install:
20
19
  - gem install bundler
data/README.md CHANGED
@@ -7,6 +7,15 @@ This SQL plugin has two parts:
7
7
  1. SQL **input** plugin reads records from RDBMSes periodically. An example use case would be getting "diffs" of a table (based on the "updated_at" field).
8
8
  2. SQL **output** plugin that writes records into RDBMes. An example use case would be aggregating server/app/sensor logs into RDBMS systems.
9
9
 
10
+ ## Requirements
11
+
12
+ | fluent-plugin-sql | fluentd | ruby |
13
+ |-------------------|------------|--------|
14
+ | >= 1.0.0 | >= v0.14.4 | >= 2.1 |
15
+ | < 1.0.0 | < v0.14.0 | >= 1.9 |
16
+
17
+ NOTE: fluent-plugin-sql v1.0.0 is now RC. We will release stable v1.0.0 soon.
18
+
10
19
  ## Installation
11
20
 
12
21
  $ fluent-gem install fluent-plugin-sql --no-document
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.1
1
+ 1.0.0.rc1
@@ -16,59 +16,47 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
- require "fluent/input"
19
+ require "fluent/plugin/input"
20
20
 
21
- module Fluent
21
+ module Fluent::Plugin
22
22
 
23
23
  require 'active_record'
24
24
 
25
25
  class SQLInput < Input
26
- Plugin.register_input('sql', self)
27
-
28
- # For fluentd v0.12.16 or earlier
29
- class << self
30
- unless method_defined?(:desc)
31
- def desc(description)
32
- end
33
- end
34
- end
26
+ Fluent::Plugin.register_input('sql', self)
35
27
 
36
28
  desc 'RDBMS host'
37
29
  config_param :host, :string
38
30
  desc 'RDBMS port'
39
- config_param :port, :integer, :default => nil
31
+ config_param :port, :integer, default: nil
40
32
  desc 'RDBMS driver name.'
41
33
  config_param :adapter, :string
42
34
  desc 'RDBMS database name'
43
35
  config_param :database, :string
44
36
  desc 'RDBMS login user name'
45
- config_param :username, :string, :default => nil
37
+ config_param :username, :string, default: nil
46
38
  desc 'RDBMS login password'
47
- config_param :password, :string, :default => nil, :secret => true
39
+ config_param :password, :string, default: nil, secret: true
48
40
  desc 'RDBMS socket path'
49
- config_param :socket, :string, :default => nil
41
+ config_param :socket, :string, default: nil
50
42
 
51
43
  desc 'path to a file to store last rows'
52
- config_param :state_file, :string, :default => nil
44
+ config_param :state_file, :string, default: nil
53
45
  desc 'prefix of tags of events. actual tag will be this_tag_prefix.tables_tag (optional)'
54
- config_param :tag_prefix, :string, :default => nil
46
+ config_param :tag_prefix, :string, default: nil
55
47
  desc 'interval to run SQLs (optional)'
56
- config_param :select_interval, :time, :default => 60
48
+ config_param :select_interval, :time, default: 60
57
49
  desc 'limit of number of rows for each SQL(optional)'
58
- config_param :select_limit, :time, :default => 500
59
-
60
- unless method_defined?(:log)
61
- define_method(:log) { $log }
62
- end
50
+ config_param :select_limit, :time, default: 500
63
51
 
64
52
  class TableElement
65
- include Configurable
53
+ include Fluent::Configurable
66
54
 
67
55
  config_param :table, :string
68
- config_param :tag, :string, :default => nil
69
- config_param :update_column, :string, :default => nil
70
- config_param :time_column, :string, :default => nil
71
- config_param :primary_key, :string, :default => nil
56
+ config_param :tag, :string, default: nil
57
+ config_param :update_column, :string, default: nil
58
+ config_param :time_column, :string, default: nil
59
+ config_param :primary_key, :string, default: nil
72
60
 
73
61
  def configure(conf)
74
62
  super
@@ -127,9 +115,9 @@ module Fluent
127
115
  relation = relation.order("#{@update_column} ASC")
128
116
  relation = relation.limit(limit) if limit > 0
129
117
 
130
- now = Engine.now
118
+ now = Fluent::Engine.now
131
119
 
132
- me = MultiEventStream.new
120
+ me = Fluent::MultiEventStream.new
133
121
  relation.each do |obj|
134
122
  record = obj.serializable_hash rescue nil
135
123
  if record
@@ -181,13 +169,13 @@ module Fluent
181
169
  @state_store = @state_file.nil? ? MemoryStateStore.new : StateStore.new(@state_file)
182
170
 
183
171
  config = {
184
- :adapter => @adapter,
185
- :host => @host,
186
- :port => @port,
187
- :database => @database,
188
- :username => @username,
189
- :password => @password,
190
- :socket => @socket,
172
+ adapter: @adapter,
173
+ host: @host,
174
+ port: @port,
175
+ database: @database,
176
+ username: @username,
177
+ password: @password,
178
+ socket: @socket,
191
179
  }
192
180
 
193
181
  # creates subclass of ActiveRecord::Base so that it can have different
@@ -230,7 +218,7 @@ module Fluent
230
218
  log.info "Selecting '#{te.table}' table"
231
219
  false
232
220
  rescue => e
233
- log.warn "Can't handle '#{te.table}' table. Ignoring.", :error => e.message, :error_class => e.class
221
+ log.warn "Can't handle '#{te.table}' table. Ignoring.", error: e
234
222
  log.warn_backtrace e.backtrace
235
223
  true
236
224
  end
@@ -264,7 +252,7 @@ module Fluent
264
252
  @state_store.last_records[t.table] = t.emit_next_records(last_record, @select_limit)
265
253
  @state_store.update!
266
254
  rescue => e
267
- log.error "unexpected error", :error => e.message, :error_class => e.class
255
+ log.error "unexpected error", error: e
268
256
  log.error_backtrace e.backtrace
269
257
  end
270
258
  end
@@ -1,59 +1,52 @@
1
- require "fluent/output"
1
+ require "fluent/plugin/output"
2
2
 
3
- module Fluent
4
- class SQLOutput < BufferedOutput
5
- Plugin.register_output('sql', self)
3
+ module Fluent::Plugin
4
+ class SQLOutput < Output
5
+ Fluent::Plugin.register_output('sql', self)
6
6
 
7
- include SetTimeKeyMixin
8
- include SetTagKeyMixin
7
+ DEFAULT_BUFFER_TYPE = "memory"
9
8
 
10
- # For fluentd v0.12.16 or earlier
11
- class << self
12
- unless method_defined?(:desc)
13
- def desc(description)
14
- end
15
- end
16
- end
9
+ helpers :inject, :compat_parameters, :event_emitter
17
10
 
18
11
  desc 'RDBMS host'
19
12
  config_param :host, :string
20
13
  desc 'RDBMS port'
21
- config_param :port, :integer, :default => nil
14
+ config_param :port, :integer, default: nil
22
15
  desc 'RDBMS driver name.'
23
16
  config_param :adapter, :string
24
17
  desc 'RDBMS login user name'
25
- config_param :username, :string, :default => nil
18
+ config_param :username, :string, default: nil
26
19
  desc 'RDBMS login password'
27
- config_param :password, :string, :default => nil, :secret => true
20
+ config_param :password, :string, default: nil, secret: true
28
21
  desc 'RDBMS database name'
29
22
  config_param :database, :string
30
23
  desc 'RDBMS socket path'
31
- config_param :socket, :string, :default => nil
24
+ config_param :socket, :string, default: nil
32
25
  desc 'remove the given prefix from the events'
33
- config_param :remove_tag_prefix, :string, :default => nil
26
+ config_param :remove_tag_prefix, :string, default: nil
34
27
  desc 'enable fallback'
35
- config_param :enable_fallback, :bool, :default => true
36
-
37
- attr_accessor :tables
28
+ config_param :enable_fallback, :bool, default: true
38
29
 
39
- unless method_defined?(:log)
40
- define_method(:log) { $log }
30
+ config_section :buffer do
31
+ config_set_default :@type, DEFAULT_BUFFER_TYPE
41
32
  end
42
33
 
34
+ attr_accessor :tables
35
+
43
36
  # TODO: Merge SQLInput's TableElement
44
37
  class TableElement
45
- include Configurable
38
+ include Fluent::Configurable
46
39
 
47
40
  config_param :table, :string
48
41
  config_param :column_mapping, :string
49
- config_param :num_retries, :integer, :default => 5
42
+ config_param :num_retries, :integer, default: 5
50
43
 
51
44
  attr_reader :model
52
45
  attr_reader :pattern
53
46
 
54
47
  def initialize(pattern, log, enable_fallback)
55
48
  super()
56
- @pattern = MatchPattern.create(pattern)
49
+ @pattern = Fluent::MatchPattern.create(pattern)
57
50
  @log = log
58
51
  @enable_fallback = enable_fallback
59
52
  end
@@ -95,7 +88,7 @@ module Fluent
95
88
  # format process should be moved to emit / format after supports error stream.
96
89
  records << @model.new(@format_proc.call(data))
97
90
  rescue => e
98
- args = {:error => e.message, :error_class => e.class, :table => @table, :record => Yajl.dump(data)}
91
+ args = {error: e, table: @table, record: Yajl.dump(data)}
99
92
  @log.warn "Failed to create the model. Ignore a record:", args
100
93
  end
101
94
  }
@@ -104,10 +97,10 @@ module Fluent
104
97
  rescue ActiveRecord::StatementInvalid, ActiveRecord::Import::MissingColumnError => e
105
98
  if @enable_fallback
106
99
  # ignore other exceptions to use Fluentd retry mechanizm
107
- @log.warn "Got deterministic error. Fallback to one-by-one import", :error => e.message, :error_class => e.class
100
+ @log.warn "Got deterministic error. Fallback to one-by-one import", error: e
108
101
  one_by_one_import(records)
109
102
  else
110
- $log.warn "Got deterministic error. Fallback is disabled", :error => e.message, :error_class => e.class
103
+ $log.warn "Got deterministic error. Fallback is disabled", error: e
111
104
  raise e
112
105
  end
113
106
  end
@@ -119,15 +112,15 @@ module Fluent
119
112
  begin
120
113
  @model.import([record])
121
114
  rescue ActiveRecord::StatementInvalid, ActiveRecord::Import::MissingColumnError => e
122
- @log.error "Got deterministic error again. Dump a record", :error => e.message, :error_class => e.class, :record => record
115
+ @log.error "Got deterministic error again. Dump a record", error: e, record: record
123
116
  rescue => e
124
117
  retries += 1
125
118
  if retries > @num_retries
126
- @log.error "Can't recover undeterministic error. Dump a record", :error => e.message, :error_class => e.class, :record => record
119
+ @log.error "Can't recover undeterministic error. Dump a record", error: e, record: record
127
120
  next
128
121
  end
129
122
 
130
- @log.warn "Failed to import a record: retry number = #{retries}", :error => e.message, :error_class => e.class
123
+ @log.warn "Failed to import a record: retry number = #{retries}", error: e
131
124
  sleep 0.5
132
125
  retry
133
126
  end
@@ -154,6 +147,8 @@ module Fluent
154
147
  end
155
148
 
156
149
  def configure(conf)
150
+ compat_parameters_convert(conf, :inject, :buffer)
151
+
157
152
  super
158
153
 
159
154
  if remove_tag_prefix = conf['remove_tag_prefix']
@@ -177,7 +172,7 @@ module Fluent
177
172
  @only_default = @tables.empty?
178
173
 
179
174
  if @default_table.nil?
180
- raise ConfigError, "There is no default table. <table> is required in sql output"
175
+ raise Fluent::ConfigError, "There is no default table. <table> is required in sql output"
181
176
  end
182
177
  end
183
178
 
@@ -185,13 +180,13 @@ module Fluent
185
180
  super
186
181
 
187
182
  config = {
188
- :adapter => @adapter,
189
- :host => @host,
190
- :port => @port,
191
- :database => @database,
192
- :username => @username,
193
- :password => @password,
194
- :socket => @socket,
183
+ adapter: @adapter,
184
+ host: @host,
185
+ port: @port,
186
+ database: @database,
187
+ username: @username,
188
+ password: @password,
189
+ socket: @socket,
195
190
  }
196
191
 
197
192
  @base_model = Class.new(ActiveRecord::Base) do
@@ -221,9 +216,14 @@ module Fluent
221
216
  end
222
217
 
223
218
  def format(tag, time, record)
219
+ record = inject_values_to_record(tag, time, record)
224
220
  [tag, time, record].to_msgpack
225
221
  end
226
222
 
223
+ def formatted_to_msgpack_binary
224
+ true
225
+ end
226
+
227
227
  def write(chunk)
228
228
  ActiveRecord::Base.connection_pool.with_connection do
229
229
 
@@ -244,7 +244,7 @@ module Fluent
244
244
  log.info "Selecting '#{te.table}' table"
245
245
  false
246
246
  rescue => e
247
- log.warn "Can't handle '#{te.table}' table. Ignoring.", :error => e.message, :error_class => e.class
247
+ log.warn "Can't handle '#{te.table}' table. Ignoring.", error: e
248
248
  log.warn_backtrace e.backtrace
249
249
  true
250
250
  end
@@ -1,4 +1,5 @@
1
1
  require "helper"
2
+ require "fluent/test/driver/input"
2
3
 
3
4
  class SqlInputTest < Test::Unit::TestCase
4
5
  def setup
@@ -28,7 +29,7 @@ class SqlInputTest < Test::Unit::TestCase
28
29
  ]
29
30
 
30
31
  def create_driver(conf = CONFIG)
31
- Fluent::Test::InputTestDriver.new(Fluent::SQLInput).configure(conf)
32
+ Fluent::Test::Driver::Input.new(Fluent::Plugin::SQLInput).configure(conf)
32
33
  end
33
34
 
34
35
  def test_configure
@@ -65,18 +66,21 @@ class SqlInputTest < Test::Unit::TestCase
65
66
  Message.create!(message: "message 2")
66
67
  Message.create!(message: "message 3")
67
68
 
69
+ d.end_if do
70
+ d.record_count >= 3
71
+ end
68
72
  d.run
69
73
 
70
- assert_equal("db.logs", d.emits[0][0])
74
+ assert_equal("db.logs", d.events[0][0])
71
75
  expected = [
72
- [d.emits[0][1], "message 1"],
73
- [d.emits[1][1], "message 2"],
74
- [d.emits[2][1], "message 3"],
76
+ [d.events[0][1], "message 1"],
77
+ [d.events[1][1], "message 2"],
78
+ [d.events[2][1], "message 3"],
75
79
  ]
76
80
  actual = [
77
- [Time.parse(d.emits[0][2]["updated_at"]).to_i, d.emits[0][2]["message"]],
78
- [Time.parse(d.emits[1][2]["updated_at"]).to_i, d.emits[1][2]["message"]],
79
- [Time.parse(d.emits[2][2]["updated_at"]).to_i, d.emits[2][2]["message"]],
81
+ [Time.parse(d.events[0][2]["updated_at"]).to_i, d.events[0][2]["message"]],
82
+ [Time.parse(d.events[1][2]["updated_at"]).to_i, d.events[1][2]["message"]],
83
+ [Time.parse(d.events[2][2]["updated_at"]).to_i, d.events[2][2]["message"]],
80
84
  ]
81
85
  assert_equal(expected, actual)
82
86
  end
@@ -1,4 +1,5 @@
1
1
  require "helper"
2
+ require "fluent/test/driver/output"
2
3
 
3
4
  class SqlOutputTest < Test::Unit::TestCase
4
5
  def setup
@@ -26,7 +27,7 @@ class SqlOutputTest < Test::Unit::TestCase
26
27
  ]
27
28
 
28
29
  def create_driver(conf = CONFIG)
29
- Fluent::Test::BufferedOutputTestDriver.new(Fluent::SQLOutput).configure(conf)
30
+ Fluent::Test::Driver::Output.new(Fluent::Plugin::SQLOutput).configure(conf)
30
31
  end
31
32
 
32
33
  def test_configure
@@ -61,10 +62,10 @@ class SqlOutputTest < Test::Unit::TestCase
61
62
  d = create_driver
62
63
  time = Time.parse("2011-01-02 13:14:15 UTC").to_i
63
64
 
64
- d.emit({"message" => "message1"}, time)
65
- d.emit({"message" => "message2"}, time)
66
-
67
- d.run
65
+ d.run(default_tag: 'test') do
66
+ d.feed(time, {"message" => "message1"})
67
+ d.feed(time, {"message" => "message2"})
68
+ end
68
69
 
69
70
  default_table = d.instance.instance_variable_get(:@default_table)
70
71
  model = default_table.instance_variable_get(:@model)
@@ -78,10 +79,10 @@ class SqlOutputTest < Test::Unit::TestCase
78
79
  d = create_driver
79
80
  time = Time.parse("2011-01-02 13:14:15 UTC").to_i
80
81
 
81
- d.emit({"message" => "message1"}, time)
82
- d.emit({"message" => "message2"}, time)
82
+ d.run(default_tag: 'test') do
83
+ d.feed(time, {"message" => "message1"})
84
+ d.feed(time, {"message" => "message2"})
83
85
 
84
- d.run do
85
86
  default_table = d.instance.instance_variable_get(:@default_table)
86
87
  model = default_table.instance_variable_get(:@model)
87
88
  mock(model).import(anything).at_least(1) do
@@ -95,10 +96,10 @@ class SqlOutputTest < Test::Unit::TestCase
95
96
  d = create_driver
96
97
  time = Time.parse("2011-01-02 13:14:15 UTC").to_i
97
98
 
98
- d.emit({"message" => "message1"}, time)
99
- d.emit({"message" => "message2"}, time)
99
+ d.run(default_tag: 'test') do
100
+ d.feed(time, {"message" => "message1"})
101
+ d.feed(time, {"message" => "message2"})
100
102
 
101
- d.run do
102
103
  default_table = d.instance.instance_variable_get(:@default_table)
103
104
  model = default_table.instance_variable_get(:@model)
104
105
  mock(model).import([anything, anything]).once do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-sql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 1.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-27 00:00:00.000000000 Z
11
+ date: 2017-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -162,12 +162,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
162
162
  version: '0'
163
163
  required_rubygems_version: !ruby/object:Gem::Requirement
164
164
  requirements:
165
- - - ">="
165
+ - - ">"
166
166
  - !ruby/object:Gem::Version
167
- version: '0'
167
+ version: 1.3.1
168
168
  requirements: []
169
169
  rubyforge_project:
170
- rubygems_version: 2.6.11
170
+ rubygems_version: 2.6.13
171
171
  signing_key:
172
172
  specification_version: 4
173
173
  summary: SQL input/output plugin for Fluentd event collector