fluent-plugin-mongo 0.7.16 → 0.8.0.rc1
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 +4 -4
- data/.travis.yml +4 -1
- data/VERSION +1 -1
- data/bin/mongo-tail +37 -30
- data/fluent-plugin-mongo.gemspec +1 -1
- data/lib/fluent/plugin/in_mongo_tail.rb +122 -138
- data/lib/fluent/plugin/logger_support.rb +25 -0
- data/lib/fluent/plugin/mongo_auth.rb +32 -0
- data/lib/fluent/plugin/out_mongo.rb +83 -136
- data/lib/fluent/plugin/out_mongo_replset.rb +20 -31
- data/test/helper.rb +6 -0
- data/test/plugin/test_in_mongo_tail.rb +96 -0
- data/test/plugin/test_out_mongo.rb +282 -0
- data/test/plugin/test_out_mongo_replset.rb +125 -0
- metadata +16 -22
- data/lib/fluent/plugin/mongo_util.rb +0 -27
- data/lib/fluent/plugin/out_mongo_tag_collection.rb +0 -20
- data/test/plugin/in_mongo_tail.rb +0 -73
- data/test/plugin/out_mongo.rb +0 -298
- data/test/plugin/out_mongo_tag_mapped.rb +0 -69
- data/test/test_helper.rb +0 -59
- data/test/tools/auth_repl_set_manager.rb +0 -14
- data/test/tools/repl_set_manager.rb +0 -420
- data/test/tools/rs_test_helper.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5a76dcf9763e4ba6cd2ad37a15b1f5b3145d31e
|
4
|
+
data.tar.gz: 17f1414c1edf96ae7009ad701815b2f120eb6018
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e45d8d167be9f710635f207edde89c8b2962f7ee16a59f34eb406617c6839ba1021ced2ae508c8450ad36f4e2a8d9475eb53020ecc4984329615105f3a3d87b
|
7
|
+
data.tar.gz: 2bbeb260a265b4fd040577862d8b39b72b7d3045c5e2083f758671a80eb8da1a440f6e2c5b3dd8ec1ecfde9043796a46039a82935c32279ff87f4d7e5c7a8e2f
|
data/.travis.yml
CHANGED
@@ -10,12 +10,15 @@ gemfile:
|
|
10
10
|
- Gemfile
|
11
11
|
- Gemfile.v0.12
|
12
12
|
|
13
|
+
services:
|
14
|
+
- mongodb
|
15
|
+
|
13
16
|
before_install:
|
14
17
|
- gem update bundler
|
15
18
|
before_script:
|
16
19
|
- git submodule update -i
|
17
20
|
|
18
|
-
script:
|
21
|
+
script: bundle exec rake test
|
19
22
|
|
20
23
|
matrix:
|
21
24
|
allow_failures:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.8.0.rc1
|
data/bin/mongo-tail
CHANGED
@@ -8,11 +8,11 @@ require 'json'
|
|
8
8
|
require 'mongo'
|
9
9
|
|
10
10
|
TailConfig = {
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
11
|
+
d: 'fluent',
|
12
|
+
c: 'out_mongo_backup',
|
13
|
+
h: 'localhost',
|
14
|
+
p: 27017,
|
15
|
+
n: 10
|
16
16
|
}
|
17
17
|
|
18
18
|
OptionParser.new { |opt|
|
@@ -28,51 +28,58 @@ OptionParser.new { |opt|
|
|
28
28
|
opt.parse!(ARGV)
|
29
29
|
}
|
30
30
|
|
31
|
+
def get_client_options(conf)
|
32
|
+
client_options = {}
|
33
|
+
client_options[:database] = conf[:d]
|
34
|
+
client_options
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_collection_options
|
38
|
+
collection_options = {}
|
39
|
+
collection_options[:capped] = true
|
40
|
+
collection_options
|
41
|
+
end
|
42
|
+
|
31
43
|
def get_capped_collection(conf)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
puts "#{conf[:c]} is not capped. mongo-tail can not tail normal collection."
|
39
|
-
end
|
44
|
+
client_options = get_client_options(conf)
|
45
|
+
collection_options = get_collection_options
|
46
|
+
client = Mongo::Client.new(["#{conf[:h]}:#{conf[:p]}"], client_options)
|
47
|
+
collection = client["#{conf[:c]}", collection_options]
|
48
|
+
if collection.capped?
|
49
|
+
collection
|
40
50
|
else
|
41
|
-
puts "#{conf[:c]} not
|
51
|
+
puts "#{conf[:c]} is not capped. mongo-tail can not tail normal collection."
|
42
52
|
end
|
43
53
|
end
|
44
54
|
|
45
|
-
def
|
55
|
+
def create_skip_number(collection, conf)
|
46
56
|
skip = collection.count - conf[:n]
|
47
|
-
|
48
|
-
cursor_conf[:skip] = skip if skip > 0
|
49
|
-
cursor_conf
|
57
|
+
skip
|
50
58
|
end
|
51
59
|
|
52
60
|
def tail_n(collection, conf)
|
53
|
-
collection.find(
|
61
|
+
collection.find().skip(create_skip_number(collection, conf)).each {|doc|
|
54
62
|
puts doc.to_json
|
55
63
|
}
|
56
64
|
end
|
57
65
|
|
58
66
|
def tail_forever(collection, conf)
|
59
|
-
cursor_conf = create_cursor_conf(collection, conf)
|
60
|
-
cursor_conf[:tailable] = true
|
61
|
-
|
62
|
-
cursor = Mongo::Cursor.new(collection, cursor_conf)
|
63
67
|
loop {
|
64
|
-
|
65
|
-
cursor = Mongo::Cursor.new(collection, cursor_conf) unless cursor.alive?
|
68
|
+
option['_id'] = {'$gt' => BSON::ObjectId(@last_id)} if @last_id
|
66
69
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
+
documents = collection.find(option)
|
71
|
+
if documents.count >= 1
|
72
|
+
documents.each {|doc|
|
73
|
+
STDOUT.puts doc.to_json
|
74
|
+
STDOUT.flush
|
75
|
+
if id = doc.delete('_id')
|
76
|
+
@last_id = id.to_s
|
77
|
+
end
|
78
|
+
}
|
70
79
|
else
|
71
80
|
sleep 1
|
72
81
|
end
|
73
82
|
}
|
74
|
-
rescue
|
75
|
-
# ignore Mongo::OperationFailuer at CURSOR_NOT_FOUND
|
76
83
|
end
|
77
84
|
|
78
85
|
exit unless collection = get_capped_collection(TailConfig)
|
data/fluent-plugin-mongo.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.require_paths = ['lib']
|
19
19
|
|
20
20
|
gem.add_dependency "fluentd", [">= 0.10.58", "< 2"]
|
21
|
-
gem.
|
21
|
+
gem.add_runtime_dependency "mongo", "~> 2.2.0"
|
22
22
|
gem.add_development_dependency "rake", ">= 0.9.2"
|
23
23
|
gem.add_development_dependency "simplecov", ">= 0.5.4"
|
24
24
|
gem.add_development_dependency "rr", ">= 1.0.0"
|
@@ -4,38 +4,56 @@ module Fluent
|
|
4
4
|
class MongoTailInput < Input
|
5
5
|
Plugin.register_input('mongo_tail', self)
|
6
6
|
|
7
|
-
require 'fluent/plugin/mongo_util'
|
8
|
-
include MongoUtil
|
9
|
-
|
10
|
-
config_param :database, :string, :default => nil
|
11
|
-
config_param :collection, :string
|
12
|
-
config_param :host, :string, :default => 'localhost'
|
13
|
-
config_param :port, :integer, :default => 27017
|
14
|
-
config_param :wait_time, :integer, :default => 1
|
15
|
-
config_param :url, :string, :default => nil
|
16
|
-
|
17
|
-
config_param :tag, :string, :default => nil
|
18
|
-
config_param :tag_key, :string, :default => nil
|
19
|
-
config_param :time_key, :string, :default => nil
|
20
|
-
config_param :time_format, :string, :default => nil
|
21
|
-
config_param :object_id_keys, :array, :default => nil
|
22
|
-
|
23
|
-
# To store last ObjectID
|
24
|
-
config_param :id_store_file, :string, :default => nil
|
25
|
-
config_param :id_store_collection, :string, :default => nil
|
26
|
-
|
27
|
-
# SSL connection
|
28
|
-
config_param :ssl, :bool, :default => false
|
29
|
-
|
30
7
|
unless method_defined?(:log)
|
31
8
|
define_method(:log) { $log }
|
32
9
|
end
|
33
10
|
|
11
|
+
# Define `router` method of v0.12 to support v0.10 or earlier
|
12
|
+
unless method_defined?(:router)
|
13
|
+
define_method("router") { ::Fluent::Engine }
|
14
|
+
end
|
15
|
+
|
16
|
+
require 'fluent/plugin/mongo_auth'
|
17
|
+
include MongoAuthParams
|
18
|
+
include MongoAuth
|
19
|
+
require 'fluent/plugin/logger_support'
|
20
|
+
include LoggerSupport
|
21
|
+
|
22
|
+
desc "MongoDB database"
|
23
|
+
config_param :database, :string, default: nil
|
24
|
+
desc "MongoDB collection"
|
25
|
+
config_param :collection, :string
|
26
|
+
desc "MongoDB host"
|
27
|
+
config_param :host, :string, default: 'localhost'
|
28
|
+
desc "MongoDB port"
|
29
|
+
config_param :port, :integer, default: 27017
|
30
|
+
desc "Tailing interval"
|
31
|
+
config_param :wait_time, :integer, default: 1
|
32
|
+
desc "MongoDB node URL"
|
33
|
+
config_param :url, :string, default: nil
|
34
|
+
|
35
|
+
desc "Input tag"
|
36
|
+
config_param :tag, :string, default: nil
|
37
|
+
desc "Treat key as tag"
|
38
|
+
config_param :tag_key, :string, default: nil
|
39
|
+
desc "Treat key as time"
|
40
|
+
config_param :time_key, :string, default: nil
|
41
|
+
desc "Time format"
|
42
|
+
config_param :time_format, :string, default: nil
|
43
|
+
config_param :object_id_keys, :array, default: nil
|
44
|
+
|
45
|
+
desc "To store last ObjectID"
|
46
|
+
config_param :id_store_file, :string, default: nil
|
47
|
+
|
48
|
+
desc "SSL connection"
|
49
|
+
config_param :ssl, :bool, default: false
|
50
|
+
|
34
51
|
def initialize
|
35
52
|
super
|
36
53
|
require 'mongo'
|
37
54
|
require 'bson'
|
38
55
|
|
56
|
+
@client_options = {}
|
39
57
|
@connection_options = {}
|
40
58
|
end
|
41
59
|
|
@@ -54,86 +72,72 @@ module Fluent
|
|
54
72
|
raise ConfigError, "One of 'database' or 'url' must be specified"
|
55
73
|
end
|
56
74
|
|
57
|
-
@last_id = get_last_id
|
75
|
+
@last_id = @id_store_file ? get_last_id : nil
|
58
76
|
@connection_options[:ssl] = @ssl
|
59
77
|
|
60
|
-
|
78
|
+
configure_logger(@mongo_log_level)
|
61
79
|
end
|
62
80
|
|
63
81
|
def start
|
64
82
|
super
|
65
|
-
|
66
|
-
@
|
83
|
+
|
84
|
+
@file = get_id_store_file if @id_store_file
|
85
|
+
@collection = get_collection
|
86
|
+
# Resume tailing from last inserted id.
|
87
|
+
# Because tailable option is obsoleted since mongo driver 2.0.
|
88
|
+
@last_id = get_last_inserted_id if !@id_store_file and get_last_inserted_id
|
67
89
|
@thread = Thread.new(&method(:run))
|
68
90
|
end
|
69
91
|
|
70
92
|
def shutdown
|
71
|
-
|
72
|
-
|
93
|
+
if @id_store_file
|
94
|
+
save_last_id
|
95
|
+
@file.close
|
96
|
+
end
|
73
97
|
|
74
98
|
@stop = true
|
75
99
|
@thread.join
|
76
|
-
@client.
|
100
|
+
@client.close
|
101
|
+
|
77
102
|
super
|
78
103
|
end
|
79
104
|
|
80
105
|
def run
|
81
106
|
loop {
|
82
|
-
|
107
|
+
option = {}
|
83
108
|
begin
|
84
109
|
loop {
|
85
110
|
return if @stop
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
111
|
+
|
112
|
+
option['_id'] = {'$gt' => BSON::ObjectId(@last_id)} if @last_id
|
113
|
+
documents = @collection.find(option)
|
114
|
+
if documents.count >= 1
|
115
|
+
process_documents(documents)
|
90
116
|
else
|
91
117
|
sleep @wait_time
|
92
118
|
end
|
93
119
|
}
|
94
120
|
rescue
|
95
|
-
# ignore
|
121
|
+
# ignore Exceptions
|
96
122
|
end
|
97
123
|
}
|
98
124
|
end
|
99
125
|
|
100
126
|
private
|
101
127
|
|
102
|
-
def
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
raise ConfigError, "'#{database_name}.#{@collection}' is not capped: node = #{node_string}" unless collection.capped?
|
108
|
-
collection
|
109
|
-
rescue Mongo::ConnectionFailure => e
|
110
|
-
log.fatal "Failed to connect to 'mongod'. Please restart 'fluentd' after 'mongod' started: #{e}"
|
111
|
-
exit!
|
112
|
-
rescue Mongo::OperationFailure => e
|
113
|
-
log.fatal "Operation failed. Probably, 'mongod' needs an authentication: #{e}"
|
114
|
-
exit!
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def get_database
|
119
|
-
case
|
120
|
-
when @database
|
121
|
-
authenticate(Mongo::Connection.new(@host, @port, @connection_options).db(@database))
|
122
|
-
when @url
|
123
|
-
parser = Mongo::URIParser.new(@url)
|
124
|
-
parser.connection.db(parser.db_name)
|
125
|
-
end
|
128
|
+
def client
|
129
|
+
@client_options[:database] = @database
|
130
|
+
@client_options[:user] = @user if @user
|
131
|
+
@client_options[:password] = @password if @password
|
132
|
+
Mongo::Client.new(["#{node_string}"], @client_options)
|
126
133
|
end
|
127
|
-
|
128
|
-
def
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
when @url
|
133
|
-
Mongo::URIParser.new(@url).db_name
|
134
|
-
end
|
134
|
+
|
135
|
+
def get_collection
|
136
|
+
@client = client
|
137
|
+
@client = authenticate(@client)
|
138
|
+
@client["#{@collection}"]
|
135
139
|
end
|
136
|
-
|
140
|
+
|
137
141
|
def node_string
|
138
142
|
case
|
139
143
|
when @database
|
@@ -143,87 +147,67 @@ module Fluent
|
|
143
147
|
end
|
144
148
|
end
|
145
149
|
|
146
|
-
def
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
@last_id = id.to_s
|
167
|
-
doc['_id_str'] = @last_id
|
168
|
-
save_last_id(@last_id)
|
169
|
-
end
|
170
|
-
|
171
|
-
# Should use MultiEventStream?
|
172
|
-
router.emit(tag, time, doc)
|
173
|
-
end
|
150
|
+
def process_documents(documents)
|
151
|
+
es = MultiEventStream.new
|
152
|
+
documents.each {|doc|
|
153
|
+
time = if @time_key
|
154
|
+
t = doc.delete(@time_key)
|
155
|
+
t.nil? ? Engine.now : t.to_i
|
156
|
+
else
|
157
|
+
Engine.now
|
158
|
+
end
|
159
|
+
tag = if @tag_key
|
160
|
+
t = doc.delete(@tag_key)
|
161
|
+
t.nil? ? 'mongo.missing_tag' : t
|
162
|
+
else
|
163
|
+
@tag
|
164
|
+
end
|
165
|
+
if @object_id_keys
|
166
|
+
@object_id_keys.each {|id_key|
|
167
|
+
doc[id_key] = doc[id_key].to_s
|
168
|
+
}
|
169
|
+
end
|
174
170
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
171
|
+
if id = doc.delete('_id')
|
172
|
+
@last_id = id.to_s
|
173
|
+
doc['_id_str'] = @last_id
|
174
|
+
save_last_id if @id_store_file
|
175
|
+
end
|
176
|
+
es.add(time, doc)
|
177
|
+
}
|
178
|
+
router.emit_stream(tag, es)
|
180
179
|
end
|
181
180
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
if
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
@id_storage = get_database.collection(@id_store_collection)
|
181
|
+
def get_last_inserted_id
|
182
|
+
last_inserted_id = nil
|
183
|
+
documents = @collection.find()
|
184
|
+
if documents.count >= 1
|
185
|
+
documents.each {|doc|
|
186
|
+
if id = doc.delete('_id')
|
187
|
+
last_inserted_id = id
|
188
|
+
end
|
189
|
+
}
|
192
190
|
end
|
191
|
+
last_inserted_id
|
193
192
|
end
|
194
|
-
|
195
|
-
def
|
196
|
-
|
197
|
-
|
198
|
-
|
193
|
+
|
194
|
+
def get_id_store_file
|
195
|
+
file = File.open(@id_store_file, 'w')
|
196
|
+
file.sync
|
197
|
+
file
|
199
198
|
end
|
200
199
|
|
201
200
|
def get_last_id
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
end
|
206
|
-
|
207
|
-
if @id_store_collection
|
208
|
-
collection = get_database.collection(@id_store_collection)
|
209
|
-
count = collection.find.count
|
210
|
-
doc = collection.find.skip(count - 1).limit(1).first
|
211
|
-
return doc && doc["last_id"]
|
212
|
-
end
|
213
|
-
rescue
|
201
|
+
if File.exist?(@id_store_file)
|
202
|
+
BSON::ObjectId(File.read(@id_store_file)).to_s rescue nil
|
203
|
+
else
|
214
204
|
nil
|
215
205
|
end
|
216
206
|
end
|
217
207
|
|
218
|
-
def save_last_id
|
219
|
-
|
220
|
-
|
221
|
-
@id_storage.write(last_id)
|
222
|
-
end
|
223
|
-
|
224
|
-
if @id_storage.is_a?(Mongo::Collection)
|
225
|
-
@id_storage.insert("last_id" => last_id)
|
226
|
-
end
|
208
|
+
def save_last_id
|
209
|
+
@file.pos = 0
|
210
|
+
@file.write(@last_id)
|
227
211
|
end
|
228
212
|
end
|
229
213
|
end
|