flydata 0.2.20 → 0.2.21

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: 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