fluentd-plugin-cassandra-cqlfunction 1.1.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3094462b950e5bcfa5e519cdd12a1d6aa5ab11de
4
+ data.tar.gz: '0258a672d85301f78ce523605e35bfa7f79021a9'
5
+ SHA512:
6
+ metadata.gz: d45322120cc5230c15412810f4581b597f76e82a9e4c2cd123f6d13784eeaf003f6cf166e1f024ae5f478403fb9fd3b7bc8f019b1886d731bcfca0d2971d1304
7
+ data.tar.gz: 302e8c634cf70714f8b1e5a1b29f96b962fc5fe499fc7890c4910b52ea59267c82aac36b05c4c494beffbbfe07ae7d24f2688455837354079ae971125790afbd
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --format documentation
3
+ --backtrace
4
+ --default_path spec
@@ -0,0 +1,5 @@
1
+ # configure code coverage
2
+ SimpleCov.start do
3
+ # exclude directories and files
4
+ add_filter "/spec/"
5
+ end
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'fluentd', '>=0.12.29'
4
+ gem 'cassandra-driver', '>=3.0.3'
5
+
6
+ group :development, :test do
7
+ gem 'rdoc', '>=3.12'
8
+ gem 'bundler', '>=1.0.0'
9
+ gem 'jeweler', '>=1.8.4'
10
+ gem 'rspec', '>=0'
11
+ gem 'simplecov'
12
+ gem 'test-unit', '>=0'
13
+ end
@@ -0,0 +1,29 @@
1
+ Copyright © 2016 by Yaroslav Lukyanov (c_sharp@mail.ru)
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions
6
+ are met:
7
+
8
+ * Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+ * Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in
12
+ the documentation and/or other materials provided with the
13
+ distribution.
14
+ * Neither the name of the copyright holder nor the names of its
15
+ contributors may be used to endorse or promote products derived
16
+ from this software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22
+ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
+ POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,75 @@
1
+ # Cassandra plugin for Fluentd
2
+
3
+ Cassandra output plugin for Fluentd.
4
+
5
+ Implemented using the Datastax Ruby Driver for Apache Cassandra gem and targets [CQL3](https://docs.datastax.com/en/cql/3.3/)
6
+ and Cassandra 1.2 - 3.x
7
+
8
+ # Installation
9
+
10
+ via RubyGems : https://rubygems.org/gems/fluentd-plugin-cassandra-cqlfunction
11
+
12
+ fluent-gem install fluentd-plugin-cassandra-cqlfunction
13
+
14
+ ## Fluentd.conf Configuration
15
+ ### Filter Plugin:
16
+ <filter **>
17
+ @type cassandra_selector # fluent filter plugin
18
+ host 127.0.0.1,127.0.0.2 # default => 127.0.0.1
19
+ port 9042 # default => 9092
20
+ username # default => null
21
+ password # default => null
22
+ connect_timeout # default => 10 (sec)
23
+ keyspace ex # cassandra keyspace
24
+ tablename tb_ex # cassandra table
25
+ field fieldA,fieldB # select field normal
26
+ field_json fieldC # select field json string on base(ex fieldC='{"a":"1"}')
27
+ where_condition fieldA='xxx' and fieldB=':keyfrominput;' # keyfrominput (fieldB=':a;' --> fieldB='1')
28
+ </filter>
29
+
30
+ ### ex Filter ::
31
+ input -> {'a':'1'}
32
+ output 1 rec -> {'a':'1', 'fieldA':'xxx', 'fieldB':'yyy'}
33
+ output 2+ rec -> {'a':'1', 'data_cassandra': [{fieldA':'xxx', 'fieldB':'yyy'},{fieldA':'aaa', 'fieldB':'bbb'}]}
34
+
35
+ ### Output Plugin:
36
+ <match **>
37
+ @type cassandra_upsert
38
+ host 127.0.0.1,127.0.0.2
39
+ port 9042
40
+ username # default => null
41
+ password # default => null
42
+ connect_timeout # default => 10 (sec)
43
+ keyspace ex
44
+ tablename tb_ex
45
+ case_insert_value fieldPk='xxx', fieldB=':keyfrominput;' #For insert case
46
+ case_update_value fieldA='xxx', fieldB=':keyfrominput;' #For update case
47
+ where_condition_upd fieldPk='xxx' or fieldPk=':keyfrominput;'
48
+ </match>
49
+
50
+ <match **>
51
+ @type cassandra_insert
52
+ host 127.0.0.1,127.0.0.2
53
+ port 9042
54
+ username # default => null
55
+ password # default => null
56
+ connect_timeout # default => 10 (sec)
57
+
58
+ keyspace ex
59
+ tablename tb_ex
60
+ insert_value fieldPk='xxx', fieldB=':keyfrominput;'
61
+ </match>
62
+
63
+ <match **>
64
+ @type cassandra_update
65
+ host 127.0.0.1,127.0.0.2
66
+ port 9092
67
+ username # default => null
68
+ password # default => null
69
+ connect_timeout # default => 10 (sec)
70
+
71
+ keyspace ex
72
+ tablename tb_ex
73
+ update_value fieldPk='xxx', fieldB=':keyfrominput;'
74
+ where_condition_upd fieldPk='xxx' or fieldPk=':keyfrominput;'
75
+ </match>
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+
6
+ begin
7
+ Bundler.setup(:default, :development)
8
+ rescue Bundler::BundlerError => e
9
+ $stderr.puts e.message
10
+ $stderr.puts 'Run `bundle install` to install missing gems'
11
+ exit e.status_code
12
+ end
13
+
14
+ require 'rake'
15
+ require 'jeweler'
16
+
17
+ Jeweler::Tasks.new do |gem|
18
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
19
+ gem.name = 'fluentd-plugin-cassandra-cqlfunction'
20
+ gem.homepage = 'https://github.com/gozzip2009/fluentd-plugin-cassandra-cqlfunction.git'
21
+ gem.license = 'BSD-3-Clause'
22
+ gem.summary = 'Fluent selector filter plugin for Cassandra'
23
+ gem.description = 'Fluent selector filter plugin for Cassandra via Datastax Ruby Driver for Apache Cassandra'
24
+ gem.email = 'got@gmail.com'
25
+ gem.authors = ['Got jirayu']
26
+ # dependencies defined in Gemfile
27
+ end
28
+
29
+ Jeweler::RubygemsDotOrgTasks.new
30
+
31
+ require 'rdoc/task'
32
+
33
+ Rake::RDocTask.new do |rdoc|
34
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
35
+
36
+ rdoc.rdoc_dir = 'rdoc'
37
+ rdoc.title = "fluentd-plugin-cassandra-cqlfunction #{version}"
38
+ rdoc.rdoc_files.include('README*')
39
+ rdoc.rdoc_files.include('lib/**/*.rb')
40
+ end
41
+
42
+ # Get spec rake tasks working in RSpec 2.0
43
+ require 'rspec/core/rake_task'
44
+
45
+ desc 'Default: run specs.'
46
+ task :default => :spec
47
+
48
+ desc 'Run specs'
49
+ RSpec::Core::RakeTask.new do |t|
50
+
51
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.1
@@ -0,0 +1,75 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: fluentd-plugin-cassandra-cqlfunction 1.0.0 ruby lib
6
+
7
+ $:.push File.expand_path('../lib', __FILE__)
8
+ Gem::Specification.new do |s|
9
+ s.name = "fluentd-plugin-cassandra-cqlfunction".freeze
10
+ s.version = "1.1.1"
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib".freeze]
13
+ s.authors = ["Got jirayu".freeze]
14
+ s.date = "2016-11-12"
15
+ s.description = "Fluent output plugin for Cassandra via Datastax Ruby Driver for Apache Cassandra".freeze
16
+ s.email = "got@gmail.com".freeze
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".rspec",
23
+ ".simplecov",
24
+ "Gemfile",
25
+ "LICENSE.txt",
26
+ "README.md",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "fluentd-plugin-cassandra-cqlfunction.gemspec",
30
+ "spec/spec.opts",
31
+ "spec/spec_helper.rb",
32
+ "lib/fluent/plugin/filter_cassandra_selector.rb",
33
+ "lib/fluent/plugin/out_cassandra_upsert.rb",
34
+ "lib/fluent/plugin/out_cassandra_insert.rb",
35
+ "lib/fluent/plugin/out_cassandra_update.rb",
36
+ "lib/fluent/plugin/filter_example.rb",
37
+ "lib/fluent/plugin/utils/cassandra_connection.rb",
38
+ ]
39
+ s.homepage = "https://github.com/gozzip2009/fluentd-plugin-cassandra-cqlfunction".freeze
40
+ s.licenses = ["BSD-3-Clause".freeze]
41
+ s.rubygems_version = "2.6.8".freeze
42
+ s.summary = "Fluent selector filter plugin for Cassandra".freeze
43
+ s.add_development_dependency("test-unit", ["~> 3.1.4"])
44
+
45
+ if s.respond_to? :specification_version then
46
+ s.specification_version = 4
47
+
48
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
49
+ s.add_runtime_dependency(%q<fluentd>.freeze, [">= 0.12.29"])
50
+ s.add_runtime_dependency(%q<cassandra-driver>.freeze, [">= 3.0.3"])
51
+ s.add_development_dependency(%q<rdoc>.freeze, [">= 3.12"])
52
+ s.add_development_dependency(%q<bundler>.freeze, [">= 1.0.0"])
53
+ s.add_development_dependency(%q<jeweler>.freeze, [">= 1.8.4"])
54
+ s.add_development_dependency(%q<rspec>.freeze, [">= 0"])
55
+ s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
56
+ else
57
+ s.add_dependency(%q<fluentd>.freeze, [">= 0.12.29"])
58
+ s.add_dependency(%q<cassandra-driver>.freeze, [">= 3.0.3"])
59
+ s.add_dependency(%q<rdoc>.freeze, [">= 3.12"])
60
+ s.add_dependency(%q<bundler>.freeze, [">= 1.0.0"])
61
+ s.add_dependency(%q<jeweler>.freeze, [">= 1.8.4"])
62
+ s.add_dependency(%q<rspec>.freeze, [">= 0"])
63
+ s.add_dependency(%q<simplecov>.freeze, [">= 0"])
64
+ end
65
+ else
66
+ s.add_dependency(%q<fluentd>.freeze, [">= 0.12.29"])
67
+ s.add_dependency(%q<cassandra-driver>.freeze, [">= 3.0.3"])
68
+ s.add_dependency(%q<rdoc>.freeze, [">= 3.12"])
69
+ s.add_dependency(%q<bundler>.freeze, [">= 1.0.0"])
70
+ s.add_dependency(%q<jeweler>.freeze, [">= 1.8.4"])
71
+ s.add_dependency(%q<rspec>.freeze, [">= 0"])
72
+ s.add_dependency(%q<simplecov>.freeze, [">= 0"])
73
+ end
74
+ end
75
+
@@ -0,0 +1,161 @@
1
+ require 'fluent/plugin/filter'
2
+ require 'fluent/plugin/utils/cassandra_connection'
3
+
4
+ #module Fluent
5
+ # class Plugin::CassandraSelector < Plugin::Filter
6
+
7
+ class Fluent::CassandraSelector < Fluent::Filter
8
+ Fluent::Plugin.register_filter('cassandra_selector', self)
9
+
10
+ include CassandraConnection
11
+
12
+ config_param :host, :string, :default => '127.0.0.1'
13
+ config_param :port, :integer, :default => 9042
14
+
15
+ config_param :username, :string, :default => nil
16
+ config_param :password, :string, :default => nil
17
+
18
+ config_param :connect_timeout, :integer, :default => 10
19
+
20
+ config_param :field, :string, :default => nil
21
+ config_param :keyspace, :string
22
+ config_param :tablename, :string
23
+ config_param :where_condition, :string, :default => nil
24
+
25
+ config_param :field_json, :string, :default => nil
26
+ def start
27
+ super
28
+ @session ||= get_session(self.host, self.port, self.keyspace, self.connect_timeout, self.username, self.password)
29
+ end # start
30
+
31
+ def shutdown
32
+ super
33
+ @session.close if @session
34
+ end # shutdown
35
+
36
+ def configure(conf)
37
+ super
38
+
39
+ raise ConfigError, "params 'field' or 'field_json' is require least once" if self.field_json.nil? && self.field.nil?
40
+
41
+ end # configure
42
+
43
+ def filter(tag, time, record)
44
+
45
+ dataList = nil
46
+ cql = getCql(record)
47
+
48
+ begin
49
+ dataList = @session.execute(cql)
50
+ rescue Exception => e
51
+ $log.error "Cannot select Cassandra: #{e.message}\nTrace: #{e.backtrace.to_s}"
52
+ raise e
53
+ end
54
+
55
+ if dataList.length == 1
56
+ dataList.each do |row|
57
+ record = prepareRowToHash(row, record)
58
+ end
59
+ elsif dataList.length > 1
60
+ if self.field_json.nil? || self.field_json.empty?
61
+ record["data_cassandra"] = dataList.rows.to_a
62
+ else
63
+ tmpListRec = []
64
+ tmpRec = nil
65
+ dataList.each do |row|
66
+ tmpRec = prepareRowToHash(row,{})
67
+ tmpListRec.push(tmpRec)
68
+ end
69
+
70
+ record["data_cassandra"] = tmpListRec
71
+ end
72
+ end
73
+ record
74
+ end # filter
75
+
76
+ private
77
+
78
+ def prepareRowToHash(row, record)
79
+ if self.field
80
+ self.field.split(",").each do |col|
81
+ record[col] = "#{row[col]}"
82
+ end
83
+ end
84
+
85
+ if self.field_json
86
+ self.field_json.split(",").each do |col|
87
+ record = getDataStrJson("#{row[col]}", record)
88
+ end
89
+ end
90
+ record
91
+ end
92
+
93
+ def getDataStrJson(jsonData, record)
94
+ if jsonData && !jsonData.empty?
95
+ jsonData = eval(jsonData)
96
+
97
+ jsonData.each do |k,v|
98
+ record[k.to_s] = v
99
+ end
100
+ end
101
+
102
+ record
103
+ end # getDataStrJson
104
+
105
+ def getCql(record)
106
+ cql = "select "
107
+ if self.field
108
+ cql += self.field + ","
109
+ end
110
+
111
+ if self.field_json
112
+ cql += self.field_json + ","
113
+ end
114
+
115
+ cql = cql.gsub(/,$/, '')
116
+
117
+ cql += " from #{self.keyspace}.#{self.tablename}"
118
+
119
+ if self.where_condition
120
+ cql += " where "+prepareCondition(record)
121
+ end
122
+
123
+ cql += ";"
124
+
125
+ cql
126
+ end # getCql
127
+
128
+ def prepareCondition(record)
129
+ tmpCondVal = {}
130
+ tmpStr = nil
131
+ count = 0
132
+
133
+ self.where_condition.split(":").each do |str|
134
+ if count > 0
135
+ tmpStr = str.gsub(/(;.*)/, '')
136
+ tmpCondVal[tmpStr] = record[tmpStr]
137
+ end
138
+ count += 1
139
+ end
140
+
141
+ tmpStr = self.where_condition
142
+ tmpCondVal.each do |k,v|
143
+ tmpStr = tmpStr.gsub(k,v)
144
+ end
145
+
146
+ tmpStr = tmpStr.gsub(':','')
147
+ tmpStr = tmpStr.gsub(';','')
148
+
149
+ tmpStr
150
+ end # prepareCondition
151
+
152
+ # def filterExample(tag, time, record)
153
+ # sessionExcute = @session
154
+ #
155
+ # sessionExcute.execute("select service_id, golden_id from journey.mobile_state where service_id = '66910000136';").each do |row|
156
+ # record["golden_id"] = "#{row['golden_id']}"
157
+ # end
158
+ #
159
+ # record
160
+ # end filterExample
161
+ end
@@ -0,0 +1,20 @@
1
+ require 'fluent/plugin/filter'
2
+
3
+ class Fluent::ExampleFilter < Fluent::Filter
4
+ Fluent::Plugin.register_filter('example_filter', self)
5
+
6
+ config_param :host, :string
7
+
8
+ def configure(conf)
9
+ super
10
+
11
+ end # configure
12
+
13
+ def filter(tag, time, record)
14
+ if @host
15
+ record["host"] = @host
16
+ end
17
+
18
+ record
19
+ end # filter
20
+ end
@@ -0,0 +1,99 @@
1
+ require 'msgpack'
2
+ require 'fluent/output'
3
+
4
+ module Fluent
5
+ class CassandraInsertor < BufferedOutput
6
+
7
+ Fluent::Plugin.register_output('cassandra_insert', self)
8
+ include CassandraConnection
9
+
10
+ config_param :host, :string, :default => '127.0.0.1'
11
+ config_param :port, :integer, :default => 9042
12
+
13
+ config_param :username, :string, :default => nil
14
+ config_param :password, :string, :default => nil
15
+
16
+ config_param :connect_timeout, :integer, :default => 5
17
+
18
+ config_param :keyspace, :string
19
+ config_param :tablename, :string
20
+
21
+ config_param :insert_value, :string
22
+ def start
23
+ super
24
+ @session ||= get_session(self.host, self.port, self.keyspace, self.connect_timeout, self.username, self.password)
25
+ end # start
26
+
27
+ def shutdown
28
+ super
29
+ @session.close if @session
30
+ end # shutdown
31
+
32
+ def configure(conf)
33
+ super
34
+
35
+ @insertValue = self.insert_value
36
+ end # configure
37
+
38
+ def format(tag, time, record)
39
+ record.to_msgpack
40
+ end
41
+
42
+ def write(chunk)
43
+ chunk.msgpack_each { |record|
44
+ @insertValue = prepareParameter(@insertValue, record)
45
+ insertCassandra(@insertValue)
46
+ }
47
+ end # write
48
+
49
+ private
50
+
51
+ def insertCassandra(insertVal)
52
+ colIns = []
53
+ valIns = []
54
+ tmpStr = nil
55
+
56
+ insertVal.split(",").each do |str|
57
+ tmpStr = str.split("=")
58
+ colIns.push(tmpStr[0])
59
+ valIns.push(tmpStr[1])
60
+ end
61
+
62
+ cql = "INSERT INTO #{self.keyspace}.#{self.tablename} (#{colIns.join(',')}) VALUES (#{valIns.join(',')});"
63
+
64
+ print cql
65
+
66
+ begin
67
+ @session.execute(cql)
68
+ rescue Exception => e
69
+ $log.error "Cannot insert record Cassandra: #{e.message}\nTrace: #{e.backtrace.to_s}"
70
+
71
+ raise e
72
+ end
73
+ end # insertCassandra
74
+
75
+ def prepareParameter(strOri,record)
76
+ tmpCondVal = {}
77
+ tmpStr = nil
78
+ count = 0
79
+
80
+ strOri.split(":").each do |str|
81
+ if count > 0
82
+ tmpStr = str.gsub(/(;.*)/, '')
83
+ tmpCondVal[tmpStr] = record[tmpStr]
84
+ end
85
+ count += 1
86
+ end
87
+
88
+ tmpCondVal.each do |k,v|
89
+ strOri= strOri.gsub(k,v)
90
+ end
91
+
92
+ strOri = strOri.gsub(':','')
93
+ strOri = strOri.gsub(';','')
94
+
95
+ strOri
96
+ end # prepareParameter
97
+
98
+ end
99
+ end
@@ -0,0 +1,96 @@
1
+ require 'msgpack'
2
+ require 'fluent/output'
3
+
4
+ module Fluent
5
+ class CassandraUpdatetor < BufferedOutput
6
+
7
+ Fluent::Plugin.register_output('cassandra_update', self)
8
+ include CassandraConnection
9
+
10
+ config_param :host, :string, :default => '127.0.0.1'
11
+ config_param :port, :integer, :default => 9042
12
+
13
+ config_param :username, :string, :default => nil
14
+ config_param :password, :string, :default => nil
15
+
16
+ config_param :connect_timeout, :integer, :default => 5
17
+
18
+ config_param :keyspace, :string
19
+ config_param :tablename, :string
20
+
21
+ config_param :update_value, :string
22
+ config_param :where_condition_upd, :string
23
+ def start
24
+ super
25
+ @session ||= get_session(self.host, self.port, self.keyspace, self.connect_timeout, self.username, self.password)
26
+ end # start
27
+
28
+ def shutdown
29
+ super
30
+ @session.close if @session
31
+ end # shutdown
32
+
33
+ def configure(conf)
34
+ super
35
+
36
+ @updateValue = self.update_value
37
+ @whereCondUpd = self.where_condition_upd
38
+ end # configure
39
+
40
+ def format(tag, time, record)
41
+ record.to_msgpack
42
+ end
43
+
44
+ def write(chunk)
45
+ chunk.msgpack_each { |record|
46
+
47
+ whereCondition = prepareParameter(@whereCondUpd, record)
48
+
49
+ @updateValue = prepareParameter(@updateValue, record)
50
+ updateCassandra(@updateValue, whereCondition)
51
+
52
+ }
53
+ end # write
54
+
55
+ private
56
+
57
+ def updateCassandra(updateVal, whereCondition)
58
+
59
+ cql = "update #{self.keyspace}.#{self.tablename} set "
60
+ cql += updateVal + " where " + whereCondition + ";"
61
+
62
+ print cql
63
+ begin
64
+ @session.execute(cql)
65
+ rescue Exception => e
66
+ $log.error "Cannot update record Cassandra: #{e.message}\nTrace: #{e.backtrace.to_s}"
67
+
68
+ raise e
69
+ end
70
+ end # updateCassandra
71
+
72
+ def prepareParameter(strOri,record)
73
+ tmpCondVal = {}
74
+ tmpStr = nil
75
+ count = 0
76
+
77
+ strOri.split(":").each do |str|
78
+ if count > 0
79
+ tmpStr = str.gsub(/(;.*)/, '')
80
+ tmpCondVal[tmpStr] = record[tmpStr]
81
+ end
82
+ count += 1
83
+ end
84
+
85
+ tmpCondVal.each do |k,v|
86
+ strOri= strOri.gsub(k,v)
87
+ end
88
+
89
+ strOri = strOri.gsub(':','')
90
+ strOri = strOri.gsub(';','')
91
+
92
+ strOri
93
+ end # prepareParameter
94
+
95
+ end
96
+ end
@@ -0,0 +1,152 @@
1
+ require 'msgpack'
2
+ require 'fluent/output'
3
+
4
+ module Fluent
5
+ class CassandraUpsertor < BufferedOutput
6
+
7
+ Fluent::Plugin.register_output('cassandra_upsert', self)
8
+ include CassandraConnection
9
+
10
+ config_param :host, :string, :default => '127.0.0.1'
11
+ config_param :port, :integer, :default => 9042
12
+
13
+ config_param :username, :string, :default => nil
14
+ config_param :password, :string, :default => nil
15
+
16
+ config_param :connect_timeout, :integer, :default => 5
17
+
18
+ config_param :keyspace, :string
19
+ config_param :tablename, :string
20
+
21
+ config_param :case_insert_value, :string
22
+ config_param :case_update_value, :string
23
+ config_param :where_condition_upd, :string, :default => nil
24
+
25
+ def start
26
+ super
27
+ @session ||= get_session(self.host, self.port, self.keyspace, self.connect_timeout, self.username, self.password)
28
+ end # start
29
+
30
+ def shutdown
31
+ super
32
+ @session.close if @session
33
+ end # shutdown
34
+
35
+ def configure(conf)
36
+ super
37
+
38
+ # perform validations
39
+ raise ConfigError, "params 'where_condition_upd' is require condition or primarykey for case update" if self.where_condition_upd.nil?
40
+
41
+ @caseInsertValue = self.case_insert_value
42
+ @caseUpdateValue = self.case_update_value
43
+ @whereCondUpd = self.where_condition_upd
44
+ end # configure
45
+
46
+ def format(tag, time, record)
47
+ record.to_msgpack
48
+ end
49
+
50
+ def write(chunk)
51
+ chunk.msgpack_each { |record|
52
+
53
+ whereCondition = prepareParameter(@whereCondUpd, record)
54
+
55
+ cql = "select count(*) from #{self.keyspace}.#{self.tablename}"
56
+ cql += " where " + whereCondition + ";"
57
+
58
+ countRow = nil
59
+ begin
60
+ countRow = @session.execute(cql)
61
+ rescue Exception => e
62
+ $log.error "Cannot select Cassandra: #{e.message}\nTrace: #{e.backtrace.to_s}"
63
+ raise e
64
+ end
65
+
66
+ countRow = getRowCount(countRow)
67
+
68
+ if countRow > 0
69
+ @caseUpdateValue = prepareParameter(@caseUpdateValue, record)
70
+ updateCassandra(@caseUpdateValue, whereCondition)
71
+ else
72
+ @caseInsertValue = prepareParameter(@caseInsertValue, record)
73
+ insertCassandra(@caseInsertValue)
74
+ end
75
+
76
+ }
77
+ end # write
78
+
79
+ private
80
+
81
+ def insertCassandra(insertVal)
82
+ colIns = []
83
+ valIns = []
84
+ tmpStr = nil
85
+
86
+ insertVal.split(",").each do |str|
87
+ tmpStr = str.split("=")
88
+ colIns.push(tmpStr[0])
89
+ valIns.push(tmpStr[1])
90
+ end
91
+
92
+ cql = "INSERT INTO #{self.keyspace}.#{self.tablename} (#{colIns.join(',')}) VALUES (#{valIns.join(',')});"
93
+
94
+ begin
95
+ @session.execute(cql)
96
+ rescue Exception => e
97
+ $log.error "Cannot insert record Cassandra: #{e.message}\nTrace: #{e.backtrace.to_s}"
98
+
99
+ raise e
100
+ end
101
+ end # insertCassandra
102
+
103
+ def updateCassandra(updateVal, whereCondition)
104
+
105
+ cql = "update #{self.keyspace}.#{self.tablename} set "
106
+ cql += updateVal + " where " + whereCondition + ";"
107
+
108
+ begin
109
+ @session.execute(cql)
110
+ rescue Exception => e
111
+ $log.error "Cannot update record Cassandra: #{e.message}\nTrace: #{e.backtrace.to_s}"
112
+
113
+ raise e
114
+ end
115
+ end # updateCassandra
116
+
117
+ def getRowCount(countRow)
118
+ rc = 0
119
+ if countRow.length > 0
120
+ countRow.each do |row|
121
+ rc = "#{row['count']}"
122
+ end
123
+ rc = rc.to_i
124
+ end
125
+ rc
126
+ end # getRowCount
127
+
128
+ def prepareParameter(strOri,record)
129
+ tmpCondVal = {}
130
+ tmpStr = nil
131
+ count = 0
132
+
133
+ strOri.split(":").each do |str|
134
+ if count > 0
135
+ tmpStr = str.gsub(/(;.*)/, '')
136
+ tmpCondVal[tmpStr] = record[tmpStr]
137
+ end
138
+ count += 1
139
+ end
140
+
141
+ tmpCondVal.each do |k,v|
142
+ strOri= strOri.gsub(k,v)
143
+ end
144
+
145
+ strOri = strOri.gsub(':','')
146
+ strOri = strOri.gsub(';','')
147
+
148
+ strOri
149
+ end # prepareParameter
150
+
151
+ end
152
+ end
@@ -0,0 +1,15 @@
1
+ require 'cassandra'
2
+
3
+ module CassandraConnection
4
+
5
+ def get_session(host, port, keyspace, connect_timeout, username, password)
6
+ hostNode = host.split(",")
7
+ if self.username
8
+ cluster = ::Cassandra.cluster(hosts: hostNode, port: port, connect_timeout: connect_timeout, username: username, password: password)
9
+ else
10
+ cluster = ::Cassandra.cluster(hosts: hostNode, port: port, connect_timeout: connect_timeout)
11
+ end
12
+ cluster.connect(keyspace)
13
+ end # get_session
14
+
15
+ end
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format
@@ -0,0 +1,9 @@
1
+ require 'simplecov'
2
+ require 'rspec'
3
+ require 'fluent/test'
4
+
5
+ # require the library files
6
+ Dir["./lib/**/*.rb"].each {|f| require f}
7
+
8
+ # require the shared example files
9
+ Dir["./spec/support/**/*.rb"].each {|f| require f}
metadata ADDED
@@ -0,0 +1,174 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluentd-plugin-cassandra-cqlfunction
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Got jirayu
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-11-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: test-unit
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.1.4
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.1.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: fluentd
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.12.29
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.12.29
41
+ - !ruby/object:Gem::Dependency
42
+ name: cassandra-driver
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 3.0.3
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 3.0.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: rdoc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '3.12'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '3.12'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 1.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: 1.0.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: jeweler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 1.8.4
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 1.8.4
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Fluent output plugin for Cassandra via Datastax Ruby Driver for Apache
126
+ Cassandra
127
+ email: got@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files:
131
+ - LICENSE.txt
132
+ - README.md
133
+ files:
134
+ - ".rspec"
135
+ - ".simplecov"
136
+ - Gemfile
137
+ - LICENSE.txt
138
+ - README.md
139
+ - Rakefile
140
+ - VERSION
141
+ - fluentd-plugin-cassandra-cqlfunction.gemspec
142
+ - lib/fluent/plugin/filter_cassandra_selector.rb
143
+ - lib/fluent/plugin/filter_example.rb
144
+ - lib/fluent/plugin/out_cassandra_insert.rb
145
+ - lib/fluent/plugin/out_cassandra_update.rb
146
+ - lib/fluent/plugin/out_cassandra_upsert.rb
147
+ - lib/fluent/plugin/utils/cassandra_connection.rb
148
+ - spec/spec.opts
149
+ - spec/spec_helper.rb
150
+ homepage: https://github.com/gozzip2009/fluentd-plugin-cassandra-cqlfunction
151
+ licenses:
152
+ - BSD-3-Clause
153
+ metadata: {}
154
+ post_install_message:
155
+ rdoc_options: []
156
+ require_paths:
157
+ - lib
158
+ required_ruby_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: '0'
163
+ required_rubygems_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ requirements: []
169
+ rubyforge_project:
170
+ rubygems_version: 2.6.14.3
171
+ signing_key:
172
+ specification_version: 4
173
+ summary: Fluent selector filter plugin for Cassandra
174
+ test_files: []