flydata 0.2.20 → 0.2.21

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: f4d29cd6b59f9acb406d62017d559296f0fa27b7
4
- data.tar.gz: ab8d2cdcebbaab49345f62da3aef259e5a977e02
3
+ metadata.gz: b2bb40962e8bd93a3daf20cee2de578c4abc1788
4
+ data.tar.gz: 266ca371867bd725c6721bae7d23fbea9fd4a0e6
5
5
  SHA512:
6
- metadata.gz: 6f590f2046f0c016a2beae67555a0544b919b9ff5873376ee190f6a2065ae30e6e961178926127537a97baab5140dc1e1c9c5e5051895a5661d4cf93b90ccc0a
7
- data.tar.gz: 6af1ee2c5597ed08e133650a5882ca6a4531ff47b0a25bf82566a3c3e0de4ecb3172c6c6da62449a853af49785197c15ae012ce59a4303e4a11d1826c02e7cd6
6
+ metadata.gz: daaa7f5468f4f334ef0b7d0cea6cfd672c0a816fd119ca4b54c4f6fa5619987ff37c5df587b11c734d4a29fd2518072277c98a810755d0f0db8008fc719a0ec1
7
+ data.tar.gz: 3140aea09a5fad9977f1a0bf9d60f317f71637129e0b7ac423198e43e84159534f1715d49d28db28ddc135e522bcbdc32f3ed1415904d2f6cffeffc1f46066c3
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.20
1
+ 0.2.21
data/flydata.gemspec CHANGED
@@ -2,14 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
+ # stub: flydata 0.2.21 ruby lib
5
6
 
6
7
  Gem::Specification.new do |s|
7
8
  s.name = "flydata"
8
- s.version = "0.2.20"
9
+ s.version = "0.2.21"
9
10
 
10
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
11
13
  s.authors = ["Koichi Fujikawa", "Masashi Miyazaki", "Matthew Luu", "Mak Inada", "Sriram NS"]
12
- s.date = "2014-12-05"
14
+ s.date = "2014-12-12"
13
15
  s.description = "FlyData Agent"
14
16
  s.email = "sysadmin@flydata.com"
15
17
  s.executables = ["fdmysqldump", "flydata", "serverinfo"]
@@ -100,6 +102,7 @@ Gem::Specification.new do |s|
100
102
  "lib/flydata/fluent-plugins/mysql/context.rb",
101
103
  "lib/flydata/fluent-plugins/mysql/ddl_query_handler.rb",
102
104
  "lib/flydata/fluent-plugins/mysql/dml_record_handler.rb",
105
+ "lib/flydata/fluent-plugins/mysql/table_meta.rb",
103
106
  "lib/flydata/fluent-plugins/out_forward_ssl.rb",
104
107
  "lib/flydata/fluent-plugins/preference.rb",
105
108
  "lib/flydata/flydata_crontab.sh",
@@ -127,6 +130,7 @@ Gem::Specification.new do |s|
127
130
  "spec/flydata/fluent-plugins/mysql/alter_table_query_handler_spec.rb",
128
131
  "spec/flydata/fluent-plugins/mysql/binlog_position_spec.rb",
129
132
  "spec/flydata/fluent-plugins/mysql/binlog_query_dispatcher_spec.rb",
133
+ "spec/flydata/fluent-plugins/mysql/table_meta_spec.rb",
130
134
  "spec/flydata/heroku_spec.rb",
131
135
  "spec/flydata/output/forwarder_spec.rb",
132
136
  "spec/flydata/parser/mysql/alter_table_parser_spec.rb",
@@ -139,8 +143,7 @@ Gem::Specification.new do |s|
139
143
  ]
140
144
  s.homepage = "http://flydata.com/"
141
145
  s.licenses = ["All right reserved."]
142
- s.require_paths = ["lib"]
143
- s.rubygems_version = "2.0.14"
146
+ s.rubygems_version = "2.2.2"
144
147
  s.summary = "FlyData Agent"
145
148
 
146
149
  if s.respond_to? :specification_version then
@@ -1,3 +1,6 @@
1
+ require 'slop'
2
+ require 'flydata/api_client'
3
+
1
4
  module Flydata
2
5
  module Command
3
6
  class Base
@@ -19,7 +19,7 @@ module Flydata
19
19
  log_warn(message, log_params, {stderr: true})
20
20
  end
21
21
 
22
- def log_error_stderr(message)
22
+ def log_error_stderr(message, log_params = {})
23
23
  log_error(message, log_params, {stderr: true})
24
24
  end
25
25
  end
@@ -14,6 +14,7 @@ require_relative 'preference'
14
14
  require_relative 'mysql/binlog_position_file'
15
15
  require_relative 'mysql/binlog_record_dispatcher'
16
16
  require_relative 'mysql/context'
17
+ require_relative 'mysql/table_meta'
17
18
 
18
19
  #Monkey-patch fluentd class (EngineClass) to support shutdown for input plugin.
19
20
  #This will be called when USR1 signal is received
@@ -69,9 +70,14 @@ class MysqlBinlogFlydataInput < MysqlBinlogInput
69
70
  end
70
71
  sync_fm = Flydata::FileUtil::SyncFileManager.new(nil) # Passing nil for data_entry as this class does not use methods which require data_entry
71
72
 
73
+ table_meta = Mysql::TableMeta.new(
74
+ mysql_url: mysql_url, database: @database, tables: @tables)
75
+ table_meta.update
76
+
72
77
  @context = Mysql::Context.new(
73
78
  database: @database, tables: @tables,
74
- tag: @tag, sync_fm: sync_fm, omit_events: @omit_events
79
+ tag: @tag, sync_fm: sync_fm, omit_events: @omit_events,
80
+ table_meta: table_meta,
75
81
  )
76
82
  @record_dispatcher = Mysql::FlydataBinlogRecordDispatcher.new(@context)
77
83
  end
@@ -14,6 +14,7 @@ module Mysql
14
14
  def initialize(context)
15
15
  @context = context
16
16
  @first_empty_binlog = true
17
+ @table_meta = @context.table_meta
17
18
 
18
19
  # Load per-table binlog position
19
20
  @table_binlog_pos = {}
@@ -1,7 +1,7 @@
1
1
  module Mysql
2
2
  class Context
3
3
  MANDATORY_OPTS = [
4
- :database, :tables, :tag, :sync_fm, :omit_events
4
+ :database, :tables, :tag, :sync_fm, :omit_events, :table_meta
5
5
  ]
6
6
  OPTIONAL_OPTS = [
7
7
  :current_binlog_file
@@ -42,25 +42,34 @@ module Mysql
42
42
 
43
43
  def emit_rows(type, record)
44
44
  emit_record(type, record) do |opt|
45
+ table_name = record['table_name']
45
46
  records = record["rows"].collect do |row|
46
47
  row = yield(row) if block_given? # Give the caller a chance to generate the correct row
47
- { ROW => convert_to_flydata_row_format(row) }
48
+ { ROW => convert_to_flydata_row_format(table_name, row) }
48
49
  end
49
50
  encode_signless_integer(records, record["columns"])
50
51
  records
51
52
  end
52
53
  end
53
54
 
54
- def convert_to_flydata_row_format(row)
55
+ def convert_to_flydata_row_format(table_name, row)
55
56
  row.each.with_index(1).inject({}) do |h, (v, i)|
56
57
  if v.kind_of?(String)
57
- v = v.encode('utf-16', :undef => :replace, :invalid => :replace).encode('utf-8')
58
+ v = encode_row_value(table_name, v)
58
59
  end
59
60
  h[i.to_s] = v
60
61
  h
61
62
  end
62
63
  end
63
64
 
65
+ def encode_row_value(table_name, value)
66
+ if src_encoding = @table_meta[table_name][:encoding]
67
+ value.encode('utf-8', src_encoding, :undef => :replace, :invalid => :replace)
68
+ else
69
+ value.encode('utf-16', :undef => :replace, :invalid => :replace).encode('utf-8')
70
+ end
71
+ end
72
+
64
73
  def encode_signless_integer(records, column_types)
65
74
  records.each do |record|
66
75
  record[ROW].keys.each do |position|
@@ -0,0 +1,83 @@
1
+ require 'mysql2'
2
+
3
+ module Mysql
4
+ class TableMeta
5
+ MANDATORY_OPTS = [
6
+ :mysql_url, :database, :tables
7
+ ]
8
+ OPTIONAL_OPTS = [
9
+ ]
10
+
11
+ GET_TABLE_META_SQL = <<EOT
12
+ SELECT
13
+ T.table_name as table_name,
14
+ CCSA.character_set_name as character_set_name
15
+ FROM
16
+ information_schema.`TABLES` T,
17
+ information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA
18
+ WHERE
19
+ CCSA.collation_name = T.table_collation
20
+ AND T.table_schema = '%{database}'
21
+ AND T.table_name in (%{tables});
22
+ EOT
23
+
24
+ def initialize(opts)
25
+ missing_opts = MANDATORY_OPTS - opts.keys
26
+ raise "Mandatory option(s) are missing: #{missing_opts.join(', ')}" unless (missing_opts.empty?)
27
+ @mysql_url = opts[:mysql_url]
28
+ @database = opts[:database]
29
+ @tables = opts[:tables]
30
+ @table_meta = Hash.new{|h, k| h[k] = {}}
31
+ end
32
+
33
+ def update
34
+ conn = Mysql2::Client.new(@mysql_url)
35
+ sql = GET_TABLE_META_SQL % {
36
+ database: @database, tables: @tables.collect{|t| "'#{t}'"}.join(',') }
37
+ columns = conn.query(sql)
38
+ columns.collect do |col|
39
+ @table_meta[col['table_name'].to_sym][:encoding] = get_ruby_charset_name(col['character_set_name'])
40
+ end
41
+ ensure
42
+ conn.close rescue nil if conn
43
+ end
44
+
45
+ # Charset naming conversion rule. mysql => ruby
46
+ #
47
+ # mysql
48
+ # http://dev.mysql.com/doc/refman/5.6/en/charset-charsets.html
49
+ # mysql(supported CJK character sets)
50
+ # http://dev.mysql.com/doc/refman/5.6/en/faqs-cjk.html#qandaitem-A-11-1-1
51
+ # For ruby, you can see encoding list with "Encoding.list"
52
+ CHARSET_ENCODE_RULE = {
53
+ 'ascii' => nil, # 'ASCII-8BIT', (not need to be encoded)
54
+ 'utf8' => nil, # 'UTF-8', (not need to be encoded)
55
+ 'utf16' => 'UTF-16',
56
+ 'utf32' => 'UTF-32',
57
+ 'latin1' => 'ISO-8859-1',
58
+ 'latin2' => 'ISO-8859-2',
59
+ 'big5' => 'Big5',
60
+ 'cp932' => 'CP932',
61
+ 'eucjpms' => 'eucJP-ms',
62
+ 'euckr' => 'EUC-KR',
63
+ 'gb18030' => 'GB18030',
64
+ 'gb2312' => 'GB2312',
65
+ 'gbk' => 'GBK',
66
+ 'sjis' => 'Shift_JIS',
67
+ 'ujis' => 'EUC-JP',
68
+ }
69
+
70
+ def get_ruby_charset_name(mysql_charset)
71
+ return nil if mysql_charset.to_s.empty?
72
+ raise "Unsupported charset:#{mysql_charset}." unless CHARSET_ENCODE_RULE.has_key?(mysql_charset)
73
+ charset = CHARSET_ENCODE_RULE[mysql_charset]
74
+ return charset
75
+ end
76
+
77
+ # Return table meta
78
+ # :character_set_name
79
+ def [](table_name)
80
+ @table_meta[table_name.to_sym]
81
+ end
82
+ end
83
+ end
@@ -1,5 +1,7 @@
1
+ require 'spec_helper'
1
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib', 'flydata', 'fluent-plugins'))
2
- require 'rspec'
3
+ $log = nil
4
+
3
5
  require 'fluent/test'
4
6
 
5
7
  module Fluent
@@ -40,7 +40,7 @@ module Flydata
40
40
  expect(a.to_hash).to be_empty
41
41
  }.and_return(command_obj)
42
42
  expect(command_obj).to receive(:run).with(*options)
43
-
43
+
44
44
  subject.run
45
45
  end
46
46
  end
@@ -225,6 +225,7 @@ EOT
225
225
  setup_initial_flydata_files
226
226
  allow(MysqlBinlogInput::BinlogUtil).to receive(:to_hash) {|e| e}
227
227
  allow(Mysql::BinLogPositionFile).to receive(:new).with(TEST_POSITION_FILE).and_return(binlog_position_file)
228
+ allow(Mysql::TableMeta).to receive(:update)
228
229
  allow(plugin).to receive(:`).with("mysql -V").and_return("mysql Ver 14.14 Distrib 5.5.40")
229
230
  allow(plugin).to receive(:`).with(/^echo 'select version\(\);'/).and_return("version()\n5.5.40-0ubuntu0.12.04.1-log")
230
231
  Timecop.freeze(now)
@@ -1,4 +1,4 @@
1
- require_relative '../../../spec_helper'
1
+ require 'fluent_plugins_spec_helper'
2
2
  require 'flydata/fluent-plugins/mysql/alter_table_query_handler'
3
3
 
4
4
  module Mysql
@@ -10,11 +10,13 @@ module Mysql
10
10
  end
11
11
  let(:database) { "testdb" }
12
12
  let(:table) { "foo" }
13
+ let(:table_meta) { double'table_meta' }
13
14
  let(:context) do
14
15
  r = double('context')
15
16
  allow(r).to receive(:sync_fm).and_return(sync_fm)
16
17
  allow(r).to receive(:database).and_return([database])
17
18
  allow(r).to receive(:tables).and_return([table])
19
+ allow(r).to receive(:table_meta).and_return(table_meta)
18
20
  r
19
21
  end
20
22
  subject { described_class.new(context) }
@@ -38,7 +40,8 @@ module Mysql
38
40
  r
39
41
  end
40
42
  before do
41
- allow(MysqlAlterTableParser).to receive(:new).and_return(parser)
43
+ parser_class = ParserProvider.parser(:mysql, :mysql_alter_table)
44
+ allow(parser_class).to receive(:new).and_return(parser)
42
45
  allow(subject).to receive(:acceptable_table?).and_return(true)
43
46
  allow(subject).to receive(:acceptable_db?).and_return(true)
44
47
  allow(subject).to receive(:check_empty_binlog)
@@ -1,4 +1,5 @@
1
- require_relative '../../../spec_helper'
1
+ require 'fluent_plugins_spec_helper'
2
+ require 'mysql/binlog_position'
2
3
 
3
4
  module Mysql
4
5
  describe BinLogPosition do
@@ -1,4 +1,4 @@
1
- require_relative '../../../spec_helper'
1
+ require 'fluent_plugins_spec_helper'
2
2
  require 'flydata/fluent-plugins/mysql/binlog_query_dispatcher'
3
3
 
4
4
  module Mysql
@@ -0,0 +1,61 @@
1
+ require 'fluent_plugins_spec_helper'
2
+ require 'flydata/fluent-plugins/mysql/table_meta'
3
+
4
+ module Mysql
5
+ describe TableMeta do
6
+ let(:mysql_url) { double('mysql_url') }
7
+ let(:database) { 'test-db' }
8
+ let(:tables) { %w(a_table b_table c_table) }
9
+
10
+ let(:conn) { double('conn') }
11
+ let(:table_meta) { TableMeta.new(
12
+ mysql_url: mysql_url, database: database, tables: tables) }
13
+
14
+ before do
15
+ allow(conn).to receive(:close)
16
+ allow(Mysql2::Client).to receive(:new).and_return(conn)
17
+ end
18
+
19
+ describe '.update' do
20
+ let(:query_result) {[]}
21
+ before do
22
+ allow(conn).to receive(:query).and_return(query_result)
23
+ end
24
+
25
+ context 'when character_set_name is supported' do
26
+ context 'when encoding is not necessary' do
27
+ let(:query_result) {[
28
+ {'table_name' => 'a_table', 'character_set_name' => 'utf8' }
29
+ ]}
30
+ it 'set nil for encoding' do
31
+ table_meta.update
32
+ expect(table_meta['a_table'][:encoding]).to be_nil
33
+ end
34
+ end
35
+
36
+ context 'when encoding is needed' do
37
+ let(:query_result) {[
38
+ {'table_name' => 'a_table', 'character_set_name' => 'latin1' },
39
+ {'table_name' => 'b_table', 'character_set_name' => 'cp932' }
40
+ ]}
41
+ it 'set ruby encoding encoding' do
42
+ table_meta.update
43
+ expect(table_meta['a_table'][:encoding]).to eq('ISO-8859-1')
44
+ expect(table_meta['b_table'][:encoding]).to eq('CP932')
45
+ end
46
+ end
47
+ end
48
+
49
+ context 'when character_set_name is not supported' do
50
+ let(:query_result) {[
51
+ {'table_name' => 'a_table', 'character_set_name' => 'xxxx' }
52
+ ]}
53
+ it 'raise an error' do
54
+ expect{table_meta.update}.to raise_error('Unsupported charset:xxxx.')
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'flydata/parser_provider'
2
3
 
3
4
  describe 'MysqlAlterTableParser' do
4
5
  before do
@@ -1,5 +1,7 @@
1
1
  # coding: utf-8
2
2
  require 'spec_helper'
3
+ require 'flydata/sync_file_manager'
4
+ require 'flydata/parser/mysql/dump_parser'
3
5
 
4
6
  module Flydata
5
7
  module FileUtil
data/spec/spec_helper.rb CHANGED
@@ -12,6 +12,9 @@ File.open(File.join(temp_dir_path, 'flydata_api_host'), 'w') do |f|
12
12
  f.write('http://0.0.0.0:3000')
13
13
  end
14
14
 
15
+ require 'logger'
16
+ $log = Logger.new(STDOUT)
17
+
15
18
  require 'flydata'
16
19
 
17
20
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flydata
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.20
4
+ version: 0.2.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Koichi Fujikawa
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2014-12-05 00:00:00.000000000 Z
15
+ date: 2014-12-12 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rest-client
@@ -485,6 +485,7 @@ files:
485
485
  - lib/flydata/fluent-plugins/mysql/context.rb
486
486
  - lib/flydata/fluent-plugins/mysql/ddl_query_handler.rb
487
487
  - lib/flydata/fluent-plugins/mysql/dml_record_handler.rb
488
+ - lib/flydata/fluent-plugins/mysql/table_meta.rb
488
489
  - lib/flydata/fluent-plugins/out_forward_ssl.rb
489
490
  - lib/flydata/fluent-plugins/preference.rb
490
491
  - lib/flydata/flydata_crontab.sh
@@ -512,6 +513,7 @@ files:
512
513
  - spec/flydata/fluent-plugins/mysql/alter_table_query_handler_spec.rb
513
514
  - spec/flydata/fluent-plugins/mysql/binlog_position_spec.rb
514
515
  - spec/flydata/fluent-plugins/mysql/binlog_query_dispatcher_spec.rb
516
+ - spec/flydata/fluent-plugins/mysql/table_meta_spec.rb
515
517
  - spec/flydata/heroku_spec.rb
516
518
  - spec/flydata/output/forwarder_spec.rb
517
519
  - spec/flydata/parser/mysql/alter_table_parser_spec.rb
@@ -541,7 +543,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
541
543
  version: '0'
542
544
  requirements: []
543
545
  rubyforge_project:
544
- rubygems_version: 2.0.14
546
+ rubygems_version: 2.2.2
545
547
  signing_key:
546
548
  specification_version: 4
547
549
  summary: FlyData Agent