fluent-plugin-mongo 0.4.0 → 0.5.0
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.
- data/.gitignore +5 -0
- data/.gitmodules +3 -0
- data/.travis.yml +9 -0
- data/AUTHORS +1 -0
- data/Gemfile +5 -0
- data/README.rdoc +63 -13
- data/Rakefile +10 -25
- data/VERSION +1 -1
- data/fluent-plugin-mongo.gemspec +24 -0
- data/lib/fluent/plugin/in_mongo_tail.rb +132 -0
- data/lib/fluent/plugin/out_mongo.rb +56 -15
- data/lib/fluent/plugin/out_mongo_tag_collection.rb +29 -0
- data/test/plugin/in_mongo_tail.rb +36 -0
- data/test/plugin/out_mongo.rb +14 -8
- data/test/plugin/out_mongo_tag_collection.rb +61 -0
- data/test/test_helper.rb +20 -0
- metadata +92 -64
data/.gitignore
ADDED
data/.gitmodules
ADDED
data/.travis.yml
ADDED
data/AUTHORS
CHANGED
data/Gemfile
ADDED
data/README.rdoc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= MongoDB
|
1
|
+
= MongoDB plugin for Fluent
|
2
2
|
|
3
3
|
== Component
|
4
4
|
|
@@ -9,11 +9,19 @@ Store fluent-event as MongoDB Document to MongoDB database.
|
|
9
9
|
MongoOutput set 'time' field to a document by default.
|
10
10
|
You set -false- to 'include_time_key' parameter if you disable this behaivor.
|
11
11
|
|
12
|
-
===
|
12
|
+
=== MongoBackupOutput
|
13
13
|
|
14
|
-
Store fluent-event to capped collection for backup.
|
14
|
+
Store fluent-event to local capped collection for backup.
|
15
15
|
|
16
|
-
|
16
|
+
=== MongoTagOutputCollection
|
17
|
+
|
18
|
+
Tag mapping to MongoDB collection automatically.
|
19
|
+
|
20
|
+
=== MongoTailInput
|
21
|
+
|
22
|
+
Tail capped collection to input data.
|
23
|
+
|
24
|
+
== Configuration
|
17
25
|
|
18
26
|
=== MongoOutput
|
19
27
|
|
@@ -22,20 +30,31 @@ Store fluent-event to capped collection for backup.
|
|
22
30
|
database fluent
|
23
31
|
collection test
|
24
32
|
|
25
|
-
#
|
33
|
+
# Following attibutes are optional
|
26
34
|
host fluenter
|
27
35
|
port 10000
|
28
36
|
|
29
37
|
# You can use 'capped' if you want to use capped collection
|
30
|
-
capped
|
38
|
+
capped true
|
31
39
|
capped_size 100m
|
32
40
|
|
33
41
|
# Other buffer configurations here
|
34
42
|
</match>
|
35
43
|
|
36
|
-
|
44
|
+
==== NOTE
|
45
|
+
|
46
|
+
MongoDB's output plugins have the limitation of buffer size.
|
47
|
+
Because MongoDB and Ruby-Driver checks the total object size at each insertion.
|
48
|
+
If total object size gets over the size limitation,
|
49
|
+
MongoDB returns error or Ruby-Driver raises an Exception.
|
50
|
+
|
51
|
+
So, MongoDB's output plugins reset :buffer_chunk_limit if configurated value is larger than above limitation.
|
52
|
+
- Before v1.8, max of :buffer_chunk_limit is 2MB
|
53
|
+
- After v1.8, max of :buffer_chunk_limit is 10MB
|
37
54
|
|
38
|
-
|
55
|
+
=== MongoBackupOutput
|
56
|
+
|
57
|
+
Use mongo_backup type in match. mongo_backup alwalys use capped collection.
|
39
58
|
|
40
59
|
<match ...>
|
41
60
|
type mongo_backup
|
@@ -48,6 +67,42 @@ Use mongo_backup type. mongo_backup alwalys use capped collection.
|
|
48
67
|
</store>
|
49
68
|
</match>
|
50
69
|
|
70
|
+
=== MongoTagOutputCollection
|
71
|
+
|
72
|
+
Use mongo_tag_collection type in match.
|
73
|
+
|
74
|
+
If tag name is "foo.bar", auto create collection "foo.bar" and insert data.
|
75
|
+
|
76
|
+
<match forward.*>
|
77
|
+
type mongo_tag_collection
|
78
|
+
database fluent
|
79
|
+
|
80
|
+
# This configuration is used if tag not found. Default is 'untagged'
|
81
|
+
collection misc
|
82
|
+
|
83
|
+
# Tag "forward.foo.bar" remove prefix "forward.".
|
84
|
+
# Collection Mapping name is "foo.bar".
|
85
|
+
remove_prefix_collection forward.
|
86
|
+
</match>
|
87
|
+
|
88
|
+
=== Tail capped collection
|
89
|
+
|
90
|
+
Use mongo_tail type in source.
|
91
|
+
|
92
|
+
<source>
|
93
|
+
type mongo_tail
|
94
|
+
database fluent
|
95
|
+
collection capped_log
|
96
|
+
|
97
|
+
tag app.mongo_log
|
98
|
+
|
99
|
+
# Convert 'time'(BSON's time) to fluent time(Unix time).
|
100
|
+
time_key time
|
101
|
+
|
102
|
+
# You can store last ObjectId to tail over server's shutdown
|
103
|
+
id_store_file /Users/repeatedly/devel/fluent-plugin-mongo/last_id
|
104
|
+
</source>
|
105
|
+
|
51
106
|
== TODO
|
52
107
|
|
53
108
|
=== More configuration
|
@@ -56,11 +111,6 @@ Use mongo_backup type. mongo_backup alwalys use capped collection.
|
|
56
111
|
- Select insert or update
|
57
112
|
- etc
|
58
113
|
|
59
|
-
=== Infer collection name
|
60
|
-
|
61
|
-
Fluent tag is similar to database.collection in Mongo.
|
62
|
-
This feature makes configuration more easily.
|
63
|
-
|
64
114
|
== Tool
|
65
115
|
|
66
116
|
You can tail mongo capped collection.
|
data/Rakefile
CHANGED
@@ -1,32 +1,17 @@
|
|
1
|
-
require '
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
2
4
|
require 'rake/testtask'
|
3
|
-
require 'rake/clean'
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
gemspec.summary = "MongoDB output plugin for Fluent event collector"
|
10
|
-
gemspec.author = "Masahiro Nakagawa"
|
11
|
-
gemspec.email = "repeatedly@gmail.com"
|
12
|
-
gemspec.homepage = "http://github.com/fluent"
|
13
|
-
gemspec.has_rdoc = false
|
14
|
-
gemspec.require_paths = ["lib"]
|
15
|
-
gemspec.add_dependency "fluentd", "~> 0.10.1"
|
16
|
-
gemspec.add_dependency "mongo", ">= 1.2.0"
|
17
|
-
gemspec.test_files = Dir["test/**/*.rb"]
|
18
|
-
gemspec.files = Dir["bin/**/*", "lib/**/*", "test/**/*.rb"] + %w[VERSION AUTHORS Rakefile]
|
19
|
-
gemspec.executables = []
|
20
|
-
end
|
21
|
-
Jeweler::GemcutterTasks.new
|
22
|
-
rescue LoadError
|
23
|
-
puts "Jeweler not available. Install it with: gem install jeweler"
|
6
|
+
Rake::TestTask.new(:test) do |test|
|
7
|
+
test.libs << 'lib' << 'test'
|
8
|
+
test.test_files = FileList['test/plugin/*.rb']
|
9
|
+
test.verbose = true
|
24
10
|
end
|
25
11
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
t.ruby_opts << '-I.'
|
12
|
+
task :coverage do |t|
|
13
|
+
ENV['SIMPLE_COV'] = '1'
|
14
|
+
Rake::Task["test"].invoke
|
30
15
|
end
|
31
16
|
|
32
17
|
task :default => [:build]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "fluent-plugin-mongo"
|
6
|
+
gem.description = "MongoDB output plugin for Fluent event collector"
|
7
|
+
gem.homepage = "http://fluentd.org/"
|
8
|
+
gem.summary = gem.description
|
9
|
+
gem.version = File.read("VERSION").strip
|
10
|
+
gem.authors = ["Masahiro Nakagawa"]
|
11
|
+
gem.email = "repeatedly@gmail.com"
|
12
|
+
gem.has_rdoc = false
|
13
|
+
#gem.platform = Gem::Platform::RUBY
|
14
|
+
gem.files = `git ls-files`.split("\n")
|
15
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
gem.require_paths = ['lib']
|
18
|
+
|
19
|
+
gem.add_dependency "fluentd", "~> 0.10.6"
|
20
|
+
gem.add_dependency "mongo", ">= 1.4.0"
|
21
|
+
gem.add_development_dependency "rake", ">= 0.9.2"
|
22
|
+
gem.add_development_dependency "simplecov", ">= 0.5.4"
|
23
|
+
gem.add_development_dependency "rr", ">= 1.0.0"
|
24
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module Fluent
|
2
|
+
|
3
|
+
|
4
|
+
class MongoTailInput < Input
|
5
|
+
Plugin.register_input('mongo_tail', self)
|
6
|
+
|
7
|
+
config_param :database, :string
|
8
|
+
config_param :collection, :string
|
9
|
+
config_param :host, :string, :default => 'localhost'
|
10
|
+
config_param :port, :integer, :default => 27017
|
11
|
+
|
12
|
+
config_param :tag, :string, :default => nil
|
13
|
+
config_param :tag_key, :string, :default => nil
|
14
|
+
config_param :time_key, :string, :default => nil
|
15
|
+
config_param :time_format, :string, :default => nil
|
16
|
+
|
17
|
+
# To store last ObjectID
|
18
|
+
config_param :id_store_file, :string, :default => nil
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
require 'mongo'
|
22
|
+
require 'bson'
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def configure(conf)
|
27
|
+
super
|
28
|
+
|
29
|
+
if !@tag && !@tag_key
|
30
|
+
raise ConfigError, "'tag' or 'tag_key' option is required on mongo_tail input"
|
31
|
+
end
|
32
|
+
|
33
|
+
@last_id = @id_store_file ? get_last_id : nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def start
|
37
|
+
super
|
38
|
+
@file = get_id_store_file if @id_store_file
|
39
|
+
@client = get_capped_collection
|
40
|
+
@thread = Thread.new(&method(:run))
|
41
|
+
end
|
42
|
+
|
43
|
+
def shutdown
|
44
|
+
if @id_store_file
|
45
|
+
save_last_id
|
46
|
+
@file.close
|
47
|
+
end
|
48
|
+
|
49
|
+
@thread.join
|
50
|
+
@client.db.connection.close
|
51
|
+
super
|
52
|
+
end
|
53
|
+
|
54
|
+
def run
|
55
|
+
loop {
|
56
|
+
tailoop(Mongo::Cursor.new(@client, cursor_conf))
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def get_capped_collection
|
63
|
+
db = Mongo::Connection.new(@host, @port).db(@database)
|
64
|
+
raise ConfigError, "'#{@database}.#{@collection}' not found: server = #{@host}:#{@port}" unless db.collection_names.include?(@collection)
|
65
|
+
collection = db.collection(@collection)
|
66
|
+
raise ConfigError, "'#{@database}.#{@collection}' is not capped: server = #{@host}:#{@port}" unless collection.capped?
|
67
|
+
collection
|
68
|
+
end
|
69
|
+
|
70
|
+
def tailoop(cursor)
|
71
|
+
loop {
|
72
|
+
cursor = Mongo::Cursor.new(@client, cursor_conf) unless cursor.alive?
|
73
|
+
if doc = cursor.next_document
|
74
|
+
time = if @time_key
|
75
|
+
t = doc.delete(@time_key)
|
76
|
+
t.nil? ? Engine.now : t.to_i
|
77
|
+
else
|
78
|
+
Engine.now
|
79
|
+
end
|
80
|
+
tag = if @tag_key
|
81
|
+
t = doc.delete(@tag_key)
|
82
|
+
t.nil? ? 'mongo.missing_tag' : t
|
83
|
+
else
|
84
|
+
@tag
|
85
|
+
end
|
86
|
+
if id = doc.delete('_id')
|
87
|
+
@last_id = id.to_s
|
88
|
+
doc['_id_str'] = @last_id
|
89
|
+
save_last_id if @id_store_file
|
90
|
+
end
|
91
|
+
|
92
|
+
# Should use MultiEventStream?
|
93
|
+
Engine.emit(tag, time, doc)
|
94
|
+
else
|
95
|
+
sleep 1
|
96
|
+
end
|
97
|
+
}
|
98
|
+
rescue
|
99
|
+
# ignore Mongo::OperationFailuer at CURSOR_NOT_FOUND
|
100
|
+
end
|
101
|
+
|
102
|
+
def cursor_conf
|
103
|
+
conf = {}
|
104
|
+
conf[:tailable] = true
|
105
|
+
conf[:selector] = {'_id' => {'$gt' => BSON::ObjectId(@last_id)}} if @last_id
|
106
|
+
conf
|
107
|
+
end
|
108
|
+
|
109
|
+
# following methods are used when id_store_file is true
|
110
|
+
|
111
|
+
def get_id_store_file
|
112
|
+
file = File.open(@id_store_file, 'w')
|
113
|
+
file.sync
|
114
|
+
file
|
115
|
+
end
|
116
|
+
|
117
|
+
def get_last_id
|
118
|
+
if File.exist?(@id_store_file)
|
119
|
+
BSON::ObjectId(File.read(@id_store_file)).to_s rescue nil
|
120
|
+
else
|
121
|
+
nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def save_last_id
|
126
|
+
@file.pos = 0
|
127
|
+
@file.write(@last_id)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
end
|
@@ -18,6 +18,7 @@ class MongoOutput < BufferedOutput
|
|
18
18
|
attr_reader :argument
|
19
19
|
|
20
20
|
def initialize
|
21
|
+
@clients = {}
|
21
22
|
super
|
22
23
|
require 'mongo'
|
23
24
|
require 'msgpack'
|
@@ -36,6 +37,12 @@ class MongoOutput < BufferedOutput
|
|
36
37
|
@argument[:max] = Config.size_value(conf['capped_max']) if conf.has_key?('capped_max')
|
37
38
|
end
|
38
39
|
|
40
|
+
if @buffer.respond_to?(:buffer_chunk_limit)
|
41
|
+
@buffer.buffer_chunk_limit = available_buffer_chunk_limit
|
42
|
+
else
|
43
|
+
$log.warn "#{Fluent::VERSION} does not have :buffer_chunk_limit. Be careful when insert large documents to MongoDB"
|
44
|
+
end
|
45
|
+
|
39
46
|
# MongoDB uses BSON's Date for time.
|
40
47
|
def @timef.format_nocache(time)
|
41
48
|
time
|
@@ -44,12 +51,11 @@ class MongoOutput < BufferedOutput
|
|
44
51
|
|
45
52
|
def start
|
46
53
|
super
|
47
|
-
@client = get_or_create_collection
|
48
54
|
end
|
49
55
|
|
50
56
|
def shutdown
|
51
57
|
# Mongo::Connection checks alive or closed myself
|
52
|
-
@client.db.connection.close
|
58
|
+
@clients.values.each { |client| client.db.connection.close }
|
53
59
|
super
|
54
60
|
end
|
55
61
|
|
@@ -58,31 +64,66 @@ class MongoOutput < BufferedOutput
|
|
58
64
|
end
|
59
65
|
|
60
66
|
def write(chunk)
|
67
|
+
operate(@collection, collect_records(chunk))
|
68
|
+
end
|
69
|
+
|
70
|
+
def format_collection_name(collection_name)
|
71
|
+
formatted = collection_name
|
72
|
+
formatted = formatted.gsub(@remove_prefix_collection, '') if @remove_prefix_collection
|
73
|
+
formatted = formatted.gsub(/(^\.+)|(\.+$)/, '')
|
74
|
+
formatted = @collection if formatted.size == 0 # set default for nil tag
|
75
|
+
formatted
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def operate(collection_name, records)
|
81
|
+
get_or_create_collection(collection_name).insert(records)
|
82
|
+
end
|
83
|
+
|
84
|
+
def collect_records(chunk)
|
61
85
|
records = []
|
62
86
|
chunk.msgpack_each { |record|
|
63
87
|
record[@time_key] = Time.at(record[@time_key]) if @include_time_key
|
64
88
|
records << record
|
65
89
|
}
|
66
|
-
|
90
|
+
records
|
67
91
|
end
|
68
92
|
|
69
|
-
|
93
|
+
def get_or_create_collection(collection_name)
|
94
|
+
collection_name = format_collection_name(collection_name)
|
95
|
+
return @clients[collection_name] if @clients[collection_name]
|
96
|
+
|
97
|
+
@db ||= Mongo::Connection.new(@host, @port).db(@database)
|
98
|
+
if @db.collection_names.include?(collection_name)
|
99
|
+
collection = @db.collection(collection_name)
|
100
|
+
unless @argument[:capped] == collection.capped? # TODO: Verify capped configuration
|
101
|
+
# raise Exception if old collection does not match lastest configuration
|
102
|
+
raise ConfigError, "New configuration is different from existing collection"
|
103
|
+
end
|
104
|
+
else
|
105
|
+
collection = @db.create_collection(collection_name, @argument)
|
106
|
+
end
|
70
107
|
|
71
|
-
|
72
|
-
|
73
|
-
if db.collection_names.include?(@collection)
|
74
|
-
collection = db.collection(@collection)
|
75
|
-
return collection if @argument[:capped] == collection.capped? # TODO: Verify capped configuration
|
108
|
+
@clients[collection_name] = collection
|
109
|
+
end
|
76
110
|
|
77
|
-
|
78
|
-
|
111
|
+
# Following limits are heuristic. BSON is sometimes bigger than MessagePack and JSON.
|
112
|
+
LIMIT_BEFORE_v1_8 = 2 * 1024 * 1024 # 2MB = 4MB / 2
|
113
|
+
LIMIT_AFTER_v1_8 = 10 * 1024 * 1024 # 10MB = 16MB / 2 + alpha
|
114
|
+
|
115
|
+
def available_buffer_chunk_limit
|
116
|
+
limit = mongod_version >= "1.8.0" ? LIMIT_AFTER_v1_8 : LIMIT_BEFORE_v1_8 # TODO: each version comparison
|
117
|
+
if @buffer.buffer_chunk_limit > limit
|
118
|
+
$log.warn ":buffer_chunk_limit(#{@buffer.buffer_chunk_limit}) is large. Reset :buffer_chunk_limit with #{limit}"
|
119
|
+
limit
|
120
|
+
else
|
121
|
+
@buffer.buffer_chunk_limit
|
79
122
|
end
|
80
|
-
|
81
|
-
db.create_collection(@collection, @argument)
|
82
123
|
end
|
83
124
|
|
84
|
-
def
|
85
|
-
|
125
|
+
def mongod_version
|
126
|
+
Mongo::Connection.new.db('admin').command('serverStatus' => 1)['version']
|
86
127
|
end
|
87
128
|
end
|
88
129
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'fluent/plugin/out_mongo'
|
2
|
+
|
3
|
+
module Fluent
|
4
|
+
|
5
|
+
|
6
|
+
class MongoOutputTagCollection < MongoOutput
|
7
|
+
Fluent::Plugin.register_output('mongo_tag_collection', self)
|
8
|
+
|
9
|
+
config_param :collection, :string, :default => 'untagged'
|
10
|
+
|
11
|
+
def configure(conf)
|
12
|
+
super
|
13
|
+
|
14
|
+
if remove_prefix_collection = conf['remove_prefix_collection']
|
15
|
+
@remove_prefix_collection = Regexp.new('^' + Regexp.escape(remove_prefix_collection))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def emit(tag, es, chain)
|
20
|
+
super(tag, es, chain, tag)
|
21
|
+
end
|
22
|
+
|
23
|
+
def write(chunk)
|
24
|
+
operate(chunk.key, collect_records(chunk))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class MongoTailInputTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
Fluent::Test.setup
|
6
|
+
require 'fluent/plugin/in_mongo_tail'
|
7
|
+
end
|
8
|
+
|
9
|
+
CONFIG = %[
|
10
|
+
type mongo_tail
|
11
|
+
database test
|
12
|
+
collection log
|
13
|
+
tag_key tag
|
14
|
+
time_key time
|
15
|
+
id_store_file /tmp/fluent_mongo_last_id
|
16
|
+
]
|
17
|
+
|
18
|
+
def create_driver(conf = CONFIG)
|
19
|
+
Fluent::Test::InputTestDriver.new(Fluent::MongoTailInput).configure(conf)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_configure
|
23
|
+
d = create_driver
|
24
|
+
assert_equal('localhost', d.instance.host)
|
25
|
+
assert_equal(27017, d.instance.port)
|
26
|
+
assert_equal('test', d.instance.database)
|
27
|
+
assert_equal('log', d.instance.collection)
|
28
|
+
assert_equal('tag', d.instance.tag_key)
|
29
|
+
assert_equal('time', d.instance.time_key)
|
30
|
+
assert_equal('/tmp/fluent_mongo_last_id', d.instance.id_store_file)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_emit
|
34
|
+
# TODO: write actual code
|
35
|
+
end
|
36
|
+
end
|
data/test/plugin/out_mongo.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require '
|
2
|
-
require 'fluent/test'
|
1
|
+
require 'test_helper'
|
3
2
|
|
4
3
|
class MongoOutputTest < Test::Unit::TestCase
|
5
4
|
def setup
|
@@ -23,8 +22,12 @@ class MongoOutputTest < Test::Unit::TestCase
|
|
23
22
|
super
|
24
23
|
end
|
25
24
|
|
26
|
-
def operate(records)
|
27
|
-
records
|
25
|
+
def operate(collection_name, records)
|
26
|
+
[format_collection_name(collection_name), records]
|
27
|
+
end
|
28
|
+
|
29
|
+
def mongod_version
|
30
|
+
"1.6.0"
|
28
31
|
end
|
29
32
|
}.configure(conf)
|
30
33
|
end
|
@@ -47,6 +50,7 @@ class MongoOutputTest < Test::Unit::TestCase
|
|
47
50
|
assert_equal('fluenter', d.instance.host)
|
48
51
|
assert_equal(27018, d.instance.port)
|
49
52
|
assert_equal({:capped => true, :size => 100}, d.instance.argument)
|
53
|
+
assert_equal(Fluent::MongoOutput::LIMIT_BEFORE_v1_8, d.instance.instance_variable_get(:@buffer).buffer_chunk_limit)
|
50
54
|
end
|
51
55
|
|
52
56
|
def test_format
|
@@ -72,20 +76,22 @@ class MongoOutputTest < Test::Unit::TestCase
|
|
72
76
|
d = create_driver
|
73
77
|
t = emit_documents(d)
|
74
78
|
|
75
|
-
documents = d.run
|
79
|
+
collection_name, documents = d.run
|
76
80
|
assert_equal([{'a' => 1, d.instance.time_key => Time.at(t)},
|
77
81
|
{'a' => 2, d.instance.time_key => Time.at(t)}], documents)
|
82
|
+
assert_equal('test', collection_name)
|
78
83
|
end
|
79
84
|
|
80
85
|
def test_write_at_enable_tag
|
81
86
|
d = create_driver(CONFIG + %[
|
82
|
-
|
83
|
-
|
87
|
+
include_tag_key true
|
88
|
+
include_time_key false
|
84
89
|
])
|
85
90
|
t = emit_documents(d)
|
86
91
|
|
87
|
-
documents = d.run
|
92
|
+
collection_name, documents = d.run
|
88
93
|
assert_equal([{'a' => 1, d.instance.tag_key => 'test'},
|
89
94
|
{'a' => 2, d.instance.tag_key => 'test'}], documents)
|
95
|
+
assert_equal('test', collection_name)
|
90
96
|
end
|
91
97
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
class MongoTagCollectionTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
Fluent::Test.setup
|
7
|
+
require 'fluent/plugin/out_mongo_tag_collection'
|
8
|
+
end
|
9
|
+
|
10
|
+
CONFIG = %[
|
11
|
+
type mongo_tag_collection
|
12
|
+
database fluent
|
13
|
+
remove_prefix_collection should.remove.
|
14
|
+
]
|
15
|
+
|
16
|
+
def create_driver(conf = CONFIG)
|
17
|
+
Fluent::Test::BufferedOutputTestDriver.new(Fluent::MongoOutputTagCollection) {
|
18
|
+
def start
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def shutdown
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def operate(collection_name, records)
|
27
|
+
[format_collection_name(collection_name), records]
|
28
|
+
end
|
29
|
+
}.configure(conf)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_configure
|
33
|
+
d = create_driver(CONFIG)
|
34
|
+
assert_equal(/^should\.remove\./, d.instance.instance_variable_get(:@remove_prefix_collection))
|
35
|
+
end
|
36
|
+
|
37
|
+
def emit_documents(d)
|
38
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
39
|
+
d.emit({'a' => 1}, time)
|
40
|
+
d.emit({'a' => 2}, time)
|
41
|
+
time
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_write
|
45
|
+
skip('BufferedOutputTestDriver should support emit arguments(chain and key)')
|
46
|
+
|
47
|
+
d = create_driver(CONFIG)
|
48
|
+
d.tag = 'mytag'
|
49
|
+
t = emit_documents(d)
|
50
|
+
mock(d.instance).operate('mytag', [{'a' => 1, d.instance.time_key => Time.at(t)},
|
51
|
+
{'a' => 2, d.instance.time_key => Time.at(t)}])
|
52
|
+
d.run
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_remove_prefix_collection
|
56
|
+
d = create_driver(CONFIG)
|
57
|
+
assert_equal('prefix', d.instance.format_collection_name('should.remove.prefix'))
|
58
|
+
assert_equal('test', d.instance.format_collection_name('..test..'))
|
59
|
+
assert_equal('test.foo', d.instance.format_collection_name('..test.foo.'))
|
60
|
+
end
|
61
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'rr'
|
5
|
+
require 'test/unit'
|
6
|
+
class Test::Unit::TestCase
|
7
|
+
include RR::Adapters::TestUnit
|
8
|
+
end
|
9
|
+
|
10
|
+
if ENV['SIMPLE_COV']
|
11
|
+
require 'simplecov'
|
12
|
+
SimpleCov.start do
|
13
|
+
add_filter 'test/'
|
14
|
+
add_filter 'pkg/'
|
15
|
+
add_filter 'vendor/'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'test/unit'
|
20
|
+
require 'fluent/test'
|
metadata
CHANGED
@@ -1,100 +1,128 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-mongo
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 4
|
8
|
-
- 0
|
9
|
-
version: 0.4.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Masahiro Nakagawa
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
dependencies:
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-11-25 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: fluentd
|
22
|
-
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &2152820220 !ruby/object:Gem::Requirement
|
24
17
|
none: false
|
25
|
-
requirements:
|
18
|
+
requirements:
|
26
19
|
- - ~>
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
- 0
|
30
|
-
- 10
|
31
|
-
- 1
|
32
|
-
version: 0.10.1
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.10.6
|
33
22
|
type: :runtime
|
34
|
-
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: mongo
|
37
23
|
prerelease: false
|
38
|
-
|
24
|
+
version_requirements: *2152820220
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: mongo
|
27
|
+
requirement: &2152819600 !ruby/object:Gem::Requirement
|
39
28
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
44
|
-
- 1
|
45
|
-
- 2
|
46
|
-
- 0
|
47
|
-
version: 1.2.0
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.4.0
|
48
33
|
type: :runtime
|
49
|
-
|
50
|
-
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2152819600
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &2152819040 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.9.2
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2152819040
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: simplecov
|
49
|
+
requirement: &2152818480 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.5.4
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2152818480
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rr
|
60
|
+
requirement: &2152817940 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.0.0
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *2152817940
|
69
|
+
description: MongoDB output plugin for Fluent event collector
|
51
70
|
email: repeatedly@gmail.com
|
52
|
-
executables:
|
53
|
-
|
71
|
+
executables:
|
72
|
+
- mongo-tail
|
54
73
|
extensions: []
|
55
|
-
|
56
|
-
|
57
|
-
-
|
58
|
-
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- .gitmodules
|
78
|
+
- .travis.yml
|
59
79
|
- AUTHORS
|
80
|
+
- Gemfile
|
81
|
+
- README.rdoc
|
60
82
|
- Rakefile
|
61
83
|
- VERSION
|
62
84
|
- bin/mongo-tail
|
85
|
+
- fluent-plugin-mongo.gemspec
|
86
|
+
- lib/fluent/plugin/in_mongo_tail.rb
|
63
87
|
- lib/fluent/plugin/out_mongo.rb
|
64
88
|
- lib/fluent/plugin/out_mongo_backup.rb
|
89
|
+
- lib/fluent/plugin/out_mongo_tag_collection.rb
|
90
|
+
- test/plugin/in_mongo_tail.rb
|
65
91
|
- test/plugin/out_mongo.rb
|
66
|
-
-
|
67
|
-
|
68
|
-
homepage: http://
|
92
|
+
- test/plugin/out_mongo_tag_collection.rb
|
93
|
+
- test/test_helper.rb
|
94
|
+
homepage: http://fluentd.org/
|
69
95
|
licenses: []
|
70
|
-
|
71
96
|
post_install_message:
|
72
97
|
rdoc_options: []
|
73
|
-
|
74
|
-
require_paths:
|
98
|
+
require_paths:
|
75
99
|
- lib
|
76
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
101
|
none: false
|
78
|
-
requirements:
|
79
|
-
- -
|
80
|
-
- !ruby/object:Gem::Version
|
81
|
-
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
segments:
|
82
107
|
- 0
|
83
|
-
|
84
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
hash: -3018735046089263817
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
110
|
none: false
|
86
|
-
requirements:
|
87
|
-
- -
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
|
111
|
+
requirements:
|
112
|
+
- - ! '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
segments:
|
90
116
|
- 0
|
91
|
-
|
117
|
+
hash: -3018735046089263817
|
92
118
|
requirements: []
|
93
|
-
|
94
119
|
rubyforge_project:
|
95
|
-
rubygems_version: 1.
|
120
|
+
rubygems_version: 1.8.10
|
96
121
|
signing_key:
|
97
122
|
specification_version: 3
|
98
123
|
summary: MongoDB output plugin for Fluent event collector
|
99
|
-
test_files:
|
124
|
+
test_files:
|
125
|
+
- test/plugin/in_mongo_tail.rb
|
100
126
|
- test/plugin/out_mongo.rb
|
127
|
+
- test/plugin/out_mongo_tag_collection.rb
|
128
|
+
- test/test_helper.rb
|