fluent-plugin-mongo 0.8.1 → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -9
- data/ChangeLog +0 -11
- data/README.rdoc +7 -0
- data/VERSION +1 -1
- data/fluent-plugin-mongo.gemspec +1 -0
- data/lib/fluent/plugin/in_mongo_tail.rb +29 -45
- data/lib/fluent/plugin/out_mongo.rb +48 -50
- data/lib/fluent/plugin/out_mongo_replset.rb +10 -12
- data/test/plugin/test_in_mongo_tail.rb +76 -1
- data/test/plugin/test_out_mongo.rb +85 -77
- data/test/plugin/test_out_mongo_replset.rb +30 -45
- metadata +18 -5
- data/Gemfile.v0.12 +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 130e2e8712112dcda7b7d44b19448f5cd2177ccc
|
4
|
+
data.tar.gz: 79e4d7512049f24a830ccfef2b973084f9847b21
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 635611797a2fae046e0961801e8a7f1fee7d436fcc2356406f5227b78916c6e7feb954b2d1d4d129e4573dffdf9c2627fbada20b35af35663e6ca33237cfe1ff
|
7
|
+
data.tar.gz: 642e6babffd923a6426d0bc4bb85d64608b45e372f8bb3d30de755488737d8c0d4d25eb0266a66ad226c2b9c506115b24d2d07bd08f4032f9c5d49ef33f9e200
|
data/.travis.yml
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
rvm:
|
2
|
-
- 1.9.3
|
3
|
-
- 2.0.0
|
4
2
|
- 2.1
|
5
3
|
- 2.2.4
|
6
4
|
- 2.3.1
|
5
|
+
- 2.4.0
|
7
6
|
- ruby-head
|
8
7
|
|
9
8
|
gemfile:
|
10
9
|
- Gemfile
|
11
|
-
- Gemfile.v0.12
|
12
10
|
|
13
11
|
services:
|
14
12
|
- mongodb
|
@@ -22,10 +20,4 @@ script: bundle exec rake test
|
|
22
20
|
|
23
21
|
matrix:
|
24
22
|
allow_failures:
|
25
|
-
- rvm: 1.9.3
|
26
23
|
- rvm: ruby-head
|
27
|
-
exclude:
|
28
|
-
- rvm: 1.9.3
|
29
|
-
gemfile: Gemfile
|
30
|
-
- rvm: 2.0.0
|
31
|
-
gemfile: Gemfile
|
data/ChangeLog
CHANGED
@@ -1,14 +1,3 @@
|
|
1
|
-
Release 0.8.1 - 2017/03/23
|
2
|
-
|
3
|
-
* Add connection_string parameter for MongDB URI
|
4
|
-
* out_mongo_replset: Add nodes parameter
|
5
|
-
|
6
|
-
|
7
|
-
Release 0.8.0 - 2017/02/10
|
8
|
-
|
9
|
-
* Update mongo gem dependency to v2.0 or upper
|
10
|
-
|
11
|
-
|
12
1
|
Release 0.7.16 - 2016/10/05
|
13
2
|
|
14
3
|
* out_mongo: Log warn / deprecated message for invalid record handling
|
data/README.rdoc
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
|
3
3
|
fluent-plugin-mongo provides input and output plugins for {Fluentd}[http://fluentd.org] ({GitHub}[http://github.com/fluent/fluentd])
|
4
4
|
|
5
|
+
= Requirements
|
6
|
+
|
7
|
+
|fluent-plugin-mongo| fluentd | ruby |
|
8
|
+
|-------------------|------------|--------|
|
9
|
+
| >= 1.0.0 | >= 0.14.12 | >= 2.1 |
|
10
|
+
| < 1.0.0 | ~> 0.12.0 | >= 1.9 |
|
11
|
+
|
5
12
|
= Installation
|
6
13
|
|
7
14
|
== Gems
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
1.0.0.rc1
|
data/fluent-plugin-mongo.gemspec
CHANGED
@@ -1,23 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# coding: utf-8
|
2
|
+
require 'mongo'
|
3
|
+
require 'bson'
|
4
|
+
require 'fluent/plugin/input'
|
5
|
+
require 'fluent/plugin/mongo_auth'
|
6
|
+
require 'fluent/plugin/logger_support'
|
7
|
+
|
8
|
+
module Fluent::Plugin
|
4
9
|
class MongoTailInput < Input
|
5
|
-
Plugin.register_input('mongo_tail', self)
|
6
|
-
|
7
|
-
unless method_defined?(:log)
|
8
|
-
define_method(:log) { $log }
|
9
|
-
end
|
10
|
+
Fluent::Plugin.register_input('mongo_tail', self)
|
10
11
|
|
11
|
-
|
12
|
-
unless method_defined?(:router)
|
13
|
-
define_method("router") { ::Fluent::Engine }
|
14
|
-
end
|
12
|
+
helpers :timer
|
15
13
|
|
16
|
-
|
17
|
-
include
|
18
|
-
include
|
19
|
-
require 'fluent/plugin/logger_support'
|
20
|
-
include LoggerSupport
|
14
|
+
include Fluent::MongoAuthParams
|
15
|
+
include Fluent::MongoAuth
|
16
|
+
include Fluent::LoggerSupport
|
21
17
|
|
22
18
|
desc "MongoDB database"
|
23
19
|
config_param :database, :string, default: nil
|
@@ -50,8 +46,6 @@ module Fluent
|
|
50
46
|
|
51
47
|
def initialize
|
52
48
|
super
|
53
|
-
require 'mongo'
|
54
|
-
require 'bson'
|
55
49
|
|
56
50
|
@client_options = {}
|
57
51
|
@connection_options = {}
|
@@ -61,15 +55,15 @@ module Fluent
|
|
61
55
|
super
|
62
56
|
|
63
57
|
if !@tag and !@tag_key
|
64
|
-
raise ConfigError, "'tag' or 'tag_key' option is required on mongo_tail input"
|
58
|
+
raise Fluent::ConfigError, "'tag' or 'tag_key' option is required on mongo_tail input"
|
65
59
|
end
|
66
60
|
|
67
61
|
if @database && @url
|
68
|
-
raise ConfigError, "Both 'database' and 'url' can not be set"
|
62
|
+
raise Fluent::ConfigError, "Both 'database' and 'url' can not be set"
|
69
63
|
end
|
70
64
|
|
71
65
|
if !@database && !@url
|
72
|
-
raise ConfigError, "One of 'database' or 'url' must be specified"
|
66
|
+
raise Fluent::ConfigError, "One of 'database' or 'url' must be specified"
|
73
67
|
end
|
74
68
|
|
75
69
|
@last_id = @id_store_file ? get_last_id : nil
|
@@ -86,7 +80,7 @@ module Fluent
|
|
86
80
|
# Resume tailing from last inserted id.
|
87
81
|
# Because tailable option is obsoleted since mongo driver 2.0.
|
88
82
|
@last_id = get_last_inserted_id if !@id_store_file and get_last_inserted_id
|
89
|
-
@
|
83
|
+
timer_execute(:in_mongo_tail_watcher, @wait_time, &method(:run))
|
90
84
|
end
|
91
85
|
|
92
86
|
def shutdown
|
@@ -95,32 +89,22 @@ module Fluent
|
|
95
89
|
@file.close
|
96
90
|
end
|
97
91
|
|
98
|
-
@stop = true
|
99
|
-
@thread.join
|
100
92
|
@client.close
|
101
93
|
|
102
94
|
super
|
103
95
|
end
|
104
96
|
|
105
97
|
def run
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
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)
|
116
|
-
else
|
117
|
-
sleep @wait_time
|
118
|
-
end
|
119
|
-
}
|
120
|
-
rescue
|
121
|
-
# ignore Exceptions
|
98
|
+
option = {}
|
99
|
+
begin
|
100
|
+
option['_id'] = {'$gt' => BSON::ObjectId(@last_id)} if @last_id
|
101
|
+
documents = @collection.find(option)
|
102
|
+
if documents.count >= 1
|
103
|
+
process_documents(documents)
|
122
104
|
end
|
123
|
-
|
105
|
+
rescue
|
106
|
+
# ignore Exceptions
|
107
|
+
end
|
124
108
|
end
|
125
109
|
|
126
110
|
private
|
@@ -148,13 +132,13 @@ module Fluent
|
|
148
132
|
end
|
149
133
|
|
150
134
|
def process_documents(documents)
|
151
|
-
es = MultiEventStream.new
|
135
|
+
es = Fluent::MultiEventStream.new
|
152
136
|
documents.each {|doc|
|
153
137
|
time = if @time_key
|
154
138
|
t = doc.delete(@time_key)
|
155
|
-
t.nil? ? Engine.now : t.to_i
|
139
|
+
t.nil? ? Fluent::Engine.now : t.to_i
|
156
140
|
else
|
157
|
-
Engine.now
|
141
|
+
Fluent::Engine.now
|
158
142
|
end
|
159
143
|
@tag = if @tag_key
|
160
144
|
t = doc.delete(@tag_key)
|
@@ -1,29 +1,26 @@
|
|
1
|
-
require '
|
1
|
+
require 'mongo'
|
2
|
+
require 'msgpack'
|
3
|
+
require 'fluent/plugin/output'
|
4
|
+
require 'fluent/plugin/mongo_auth'
|
5
|
+
require 'fluent/plugin/logger_support'
|
2
6
|
|
3
|
-
module Fluent
|
4
|
-
class MongoOutput <
|
5
|
-
Plugin.register_output('mongo', self)
|
7
|
+
module Fluent::Plugin
|
8
|
+
class MongoOutput < Output
|
9
|
+
Fluent::Plugin.register_output('mongo', self)
|
6
10
|
|
7
|
-
|
8
|
-
define_method(:log) { $log }
|
9
|
-
end
|
11
|
+
helpers :event_emitter, :inject, :compat_parameters
|
10
12
|
|
11
|
-
|
12
|
-
include
|
13
|
-
include
|
14
|
-
require 'fluent/plugin/logger_support'
|
15
|
-
include LoggerSupport
|
13
|
+
include Fluent::MongoAuthParams
|
14
|
+
include Fluent::MongoAuth
|
15
|
+
include Fluent::LoggerSupport
|
16
16
|
|
17
|
-
|
18
|
-
config_set_default :include_tag_key, false
|
17
|
+
DEFAULT_BUFFER_TYPE = "memory"
|
19
18
|
|
20
|
-
|
19
|
+
config_set_default :include_tag_key, false
|
21
20
|
config_set_default :include_time_key, true
|
22
21
|
|
23
|
-
desc "MongoDB connection string"
|
24
|
-
config_param :connection_string, :default => nil
|
25
22
|
desc "MongoDB database"
|
26
|
-
config_param :database, :string
|
23
|
+
config_param :database, :string
|
27
24
|
desc "MongoDB collection"
|
28
25
|
config_param :collection, :string, default: 'untagged'
|
29
26
|
desc "MongoDB host"
|
@@ -53,15 +50,16 @@ module Fluent
|
|
53
50
|
config_param :ssl_verify, :bool, default: false
|
54
51
|
config_param :ssl_ca_cert, :string, default: nil
|
55
52
|
|
53
|
+
config_section :buffer do
|
54
|
+
config_set_default :@type, DEFAULT_BUFFER_TYPE
|
55
|
+
config_set_default :chunk_keys, ['tag']
|
56
|
+
end
|
57
|
+
|
56
58
|
attr_reader :client_options, :collection_options
|
57
59
|
|
58
60
|
def initialize
|
59
61
|
super
|
60
62
|
|
61
|
-
require 'mongo'
|
62
|
-
require 'msgpack'
|
63
|
-
|
64
|
-
@nodes = nil
|
65
63
|
@client_options = {}
|
66
64
|
@collection_options = {capped: false}
|
67
65
|
end
|
@@ -72,10 +70,10 @@ module Fluent
|
|
72
70
|
|
73
71
|
def configure(conf)
|
74
72
|
if conf.has_key?('buffer_chunk_limit')
|
75
|
-
configured_chunk_limit_size = Config.size_value(conf['buffer_chunk_limit'])
|
73
|
+
configured_chunk_limit_size = Fluent::Config.size_value(conf['buffer_chunk_limit'])
|
76
74
|
estimated_limit_size = LIMIT_AFTER_v1_8
|
77
75
|
estimated_limit_size_conf = '8m'
|
78
|
-
if conf.has_key?('mongodb_smaller_bson_limit') && Config.bool_value(conf['mongodb_smaller_bson_limit'])
|
76
|
+
if conf.has_key?('mongodb_smaller_bson_limit') && Fluent::Config.bool_value(conf['mongodb_smaller_bson_limit'])
|
79
77
|
estimated_limit_size = LIMIT_BEFORE_v1_8
|
80
78
|
estimated_limit_size_conf = '2m'
|
81
79
|
end
|
@@ -84,33 +82,31 @@ module Fluent
|
|
84
82
|
conf['buffer_chunk_limit'] = estimated_limit_size_conf
|
85
83
|
end
|
86
84
|
else
|
87
|
-
if conf.has_key?('mongodb_smaller_bson_limit') && Config.bool_value(conf['mongodb_smaller_bson_limit'])
|
85
|
+
if conf.has_key?('mongodb_smaller_bson_limit') && Fluent::Config.bool_value(conf['mongodb_smaller_bson_limit'])
|
88
86
|
conf['buffer_chunk_limit'] = '2m'
|
89
87
|
else
|
90
88
|
conf['buffer_chunk_limit'] = '8m'
|
91
89
|
end
|
92
90
|
end
|
91
|
+
compat_parameters_convert(conf, :inject)
|
93
92
|
|
94
93
|
super
|
95
94
|
|
96
|
-
if @connection_string.nil? && @database.nil?
|
97
|
-
raise Fluent::ConfigError, "connection_string or database parameter is required"
|
98
|
-
end
|
99
|
-
|
100
95
|
unless @ignore_invalid_record
|
101
96
|
log.warn "Since v0.8, invalid record detection will be removed because mongo driver v2.x and API spec don't provide it. You may lose invalid records, so you should not send such records to mongo plugin"
|
102
97
|
end
|
103
98
|
|
104
99
|
if conf.has_key?('tag_mapped')
|
105
|
-
|
100
|
+
log.warn "'tag_mapped' feature is replaced with built-in config placeholder. Please consider to use 'collection ${tag}'."
|
101
|
+
@collection = '${tag}'
|
106
102
|
end
|
107
|
-
raise ConfigError, "normal mode requires collection parameter" if !@tag_mapped and !conf.has_key?('collection')
|
103
|
+
raise Fluent::ConfigError, "normal mode requires collection parameter" if !@tag_mapped and !conf.has_key?('collection')
|
108
104
|
|
109
105
|
if conf.has_key?('capped')
|
110
|
-
raise ConfigError, "'capped_size' parameter is required on <store> of Mongo output" unless conf.has_key?('capped_size')
|
106
|
+
raise Fluent::ConfigError, "'capped_size' parameter is required on <store> of Mongo output" unless conf.has_key?('capped_size')
|
111
107
|
@collection_options[:capped] = true
|
112
|
-
@collection_options[:size] = Config.size_value(conf['capped_size'])
|
113
|
-
@collection_options[:max] = Config.size_value(conf['capped_max']) if conf.has_key?('capped_max')
|
108
|
+
@collection_options[:size] = Fluent::Config.size_value(conf['capped_size'])
|
109
|
+
@collection_options[:max] = Fluent::Config.size_value(conf['capped_max']) if conf.has_key?('capped_max')
|
114
110
|
end
|
115
111
|
|
116
112
|
if remove_tag_prefix = conf['remove_tag_prefix']
|
@@ -128,12 +124,6 @@ module Fluent
|
|
128
124
|
@client_options[:ssl_verify] = @ssl_verify
|
129
125
|
@client_options[:ssl_ca_cert] = @ssl_ca_cert
|
130
126
|
end
|
131
|
-
@nodes = ["#{@host}:#{@port}"] if @nodes.nil?
|
132
|
-
|
133
|
-
# MongoDB uses BSON's Date for time.
|
134
|
-
def @timef.format_nocache(time)
|
135
|
-
time
|
136
|
-
end
|
137
127
|
|
138
128
|
configure_logger(@mongo_log_level)
|
139
129
|
|
@@ -163,28 +153,36 @@ module Fluent
|
|
163
153
|
[time, record].to_msgpack
|
164
154
|
end
|
165
155
|
|
156
|
+
def formatted_to_msgpack_binary
|
157
|
+
true
|
158
|
+
end
|
159
|
+
|
160
|
+
def multi_workers_ready?
|
161
|
+
true
|
162
|
+
end
|
163
|
+
|
166
164
|
def write(chunk)
|
167
|
-
collection_name = @
|
165
|
+
collection_name = extract_placeholders(@collection, chunk.metadata)
|
168
166
|
operate(format_collection_name(collection_name), collect_records(chunk))
|
169
167
|
end
|
170
168
|
|
171
169
|
private
|
172
170
|
|
173
171
|
def client
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
@client_options[:user] = @user if @user
|
179
|
-
@client_options[:password] = @password if @password
|
180
|
-
Mongo::Client.new(@nodes, @client_options)
|
181
|
-
end
|
172
|
+
@client_options[:database] = @database
|
173
|
+
@client_options[:user] = @user if @user
|
174
|
+
@client_options[:password] = @password if @password
|
175
|
+
Mongo::Client.new(["#{@host}:#{@port}"], @client_options)
|
182
176
|
end
|
183
177
|
|
184
178
|
def collect_records(chunk)
|
185
179
|
records = []
|
180
|
+
time_key = @inject_config.time_key
|
181
|
+
tag = chunk.metadata.tag
|
186
182
|
chunk.msgpack_each {|time, record|
|
187
|
-
record
|
183
|
+
record = inject_values_to_record(tag, time, record)
|
184
|
+
# MongoDB uses BSON's Date for time.
|
185
|
+
record[time_key] = Time.at(time || record[time_key]) if time_key
|
188
186
|
records << record
|
189
187
|
}
|
190
188
|
records
|
@@ -1,18 +1,12 @@
|
|
1
1
|
require 'fluent/plugin/out_mongo'
|
2
2
|
|
3
|
-
module Fluent
|
3
|
+
module Fluent::Plugin
|
4
4
|
class MongoOutputReplset < MongoOutput
|
5
|
-
Plugin.register_output('mongo_replset', self)
|
6
|
-
|
7
|
-
unless method_defined?(:log)
|
8
|
-
define_method(:log) { $log }
|
9
|
-
end
|
5
|
+
Fluent::Plugin.register_output('mongo_replset', self)
|
10
6
|
|
11
7
|
config_set_default :include_tag_key, false
|
12
8
|
config_set_default :include_time_key, true
|
13
9
|
|
14
|
-
desc "Nodes of replica set"
|
15
|
-
config_param :nodes, :array, value_type: :string, :default => nil
|
16
10
|
desc "Replica set name"
|
17
11
|
config_param :replica_set, :string
|
18
12
|
desc "Read from specified role"
|
@@ -20,10 +14,6 @@ module Fluent
|
|
20
14
|
desc "Retry number"
|
21
15
|
config_param :num_retries, :integer, :default => 60
|
22
16
|
|
23
|
-
unless method_defined?(:log)
|
24
|
-
define_method(:log) { $log }
|
25
|
-
end
|
26
|
-
|
27
17
|
def configure(conf)
|
28
18
|
super
|
29
19
|
|
@@ -37,6 +27,14 @@ module Fluent
|
|
37
27
|
log.debug "Setup replica set configuration: #{conf['replica_set']}"
|
38
28
|
end
|
39
29
|
|
30
|
+
def format(tag, time, record)
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
def write(chunk)
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
40
38
|
private
|
41
39
|
|
42
40
|
def operate(client, records)
|
@@ -1,4 +1,7 @@
|
|
1
1
|
require "helper"
|
2
|
+
require "fluent/test/driver/input"
|
3
|
+
require "fluent/test/helpers"
|
4
|
+
require "timecop"
|
2
5
|
|
3
6
|
class MongoTailInputTest < Test::Unit::TestCase
|
4
7
|
def setup
|
@@ -44,7 +47,7 @@ class MongoTailInputTest < Test::Unit::TestCase
|
|
44
47
|
end
|
45
48
|
|
46
49
|
def create_driver(conf=default_config)
|
47
|
-
Fluent::Test::
|
50
|
+
Fluent::Test::Driver::Input.new(Fluent::Plugin::MongoTailInput).configure(conf)
|
48
51
|
end
|
49
52
|
|
50
53
|
def test_configure
|
@@ -67,6 +70,78 @@ class MongoTailInputTest < Test::Unit::TestCase
|
|
67
70
|
assert_equal(expected, d.instance.mongo_log_level)
|
68
71
|
end
|
69
72
|
|
73
|
+
class TailInputTest < self
|
74
|
+
include Fluent::Test::Helpers
|
75
|
+
|
76
|
+
def setup_mongod
|
77
|
+
options = {}
|
78
|
+
options[:database] = database_name
|
79
|
+
@client = ::Mongo::Client.new(["localhost:#{port}"], options)
|
80
|
+
@time = Time.now
|
81
|
+
Timecop.freeze(@time)
|
82
|
+
end
|
83
|
+
|
84
|
+
def teardown_mongod
|
85
|
+
@client[collection_name].drop
|
86
|
+
Timecop.return
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_emit
|
90
|
+
d = create_driver(%[
|
91
|
+
@type mongo_tail
|
92
|
+
database #{database_name}
|
93
|
+
collection #{collection_name}
|
94
|
+
tag input.mongo
|
95
|
+
time_key time
|
96
|
+
])
|
97
|
+
d.run(expect_records: 1, timeout: 5) do
|
98
|
+
@client[collection_name].insert_one({message: "test"})
|
99
|
+
end
|
100
|
+
events = d.events
|
101
|
+
assert_equal "input.mongo", events[0][0]
|
102
|
+
assert_equal event_time(@time.to_s), events[0][1]
|
103
|
+
assert_equal "test", events[0][2]["message"]
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_emit_with_tag_time_keys
|
107
|
+
d = create_driver(%[
|
108
|
+
@type mongo_tail
|
109
|
+
database #{database_name}
|
110
|
+
collection #{collection_name}
|
111
|
+
tag input.mongo
|
112
|
+
tag_key tag
|
113
|
+
time_key time
|
114
|
+
])
|
115
|
+
d.run(expect_records: 1, timeout: 5) do
|
116
|
+
@client[collection_name].insert_one({message: "test", tag: "user.defined", time: Fluent::Engine.now})
|
117
|
+
end
|
118
|
+
events = d.events
|
119
|
+
assert_equal "user.defined", events[0][0]
|
120
|
+
assert_equal event_time(@time.to_s), events[0][1]
|
121
|
+
assert_equal "test", events[0][2]["message"]
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_emit_after_last_id
|
125
|
+
d = create_driver(%[
|
126
|
+
@type mongo_tail
|
127
|
+
database #{database_name}
|
128
|
+
collection #{collection_name}
|
129
|
+
tag input.mongo.last_id
|
130
|
+
time_key time
|
131
|
+
])
|
132
|
+
@client[collection_name].insert_one({message: "can't obtain"})
|
133
|
+
|
134
|
+
d.run(expect_records: 1, timeout: 5) do
|
135
|
+
@client[collection_name].insert_one({message: "can obtain"})
|
136
|
+
end
|
137
|
+
events = d.events
|
138
|
+
assert_equal 1, events.size
|
139
|
+
assert_equal "input.mongo.last_id", events[0][0]
|
140
|
+
assert_equal event_time(@time.to_s), events[0][1]
|
141
|
+
assert_equal "can obtain", events[0][2]["message"]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
70
145
|
class MongoAuthenticateTest < self
|
71
146
|
require 'fluent/plugin/mongo_auth'
|
72
147
|
include ::Fluent::MongoAuth
|
@@ -1,7 +1,11 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
require "helper"
|
3
|
+
require "fluent/test/driver/output"
|
4
|
+
require "fluent/test/helpers"
|
3
5
|
|
4
6
|
class MongoOutputTest < ::Test::Unit::TestCase
|
7
|
+
include Fluent::Test::Helpers
|
8
|
+
|
5
9
|
def setup
|
6
10
|
Fluent::Test.setup
|
7
11
|
setup_mongod
|
@@ -38,17 +42,17 @@ class MongoOutputTest < ::Test::Unit::TestCase
|
|
38
42
|
@client = ::Mongo::Client.new(["localhost:#{port}"], options)
|
39
43
|
end
|
40
44
|
|
41
|
-
def teardown_mongod
|
42
|
-
@client[
|
45
|
+
def teardown_mongod(collection = collection_name)
|
46
|
+
@client[collection].drop
|
43
47
|
end
|
44
48
|
|
45
|
-
def create_driver(conf=default_config
|
46
|
-
Fluent::Test::
|
49
|
+
def create_driver(conf=default_config)
|
50
|
+
Fluent::Test::Driver::Output.new(Fluent::Plugin::MongoOutput).configure(conf)
|
47
51
|
end
|
48
52
|
|
49
53
|
def test_configure
|
50
54
|
d = create_driver(%[
|
51
|
-
|
55
|
+
type mongo
|
52
56
|
database fluent_test
|
53
57
|
collection test_collection
|
54
58
|
|
@@ -62,30 +66,6 @@ class MongoOutputTest < ::Test::Unit::TestCase
|
|
62
66
|
assert_equal(port, d.instance.port)
|
63
67
|
assert_equal({capped: true, size: 100}, d.instance.collection_options)
|
64
68
|
assert_equal({ssl: false, write: {j: false}}, d.instance.client_options)
|
65
|
-
assert_nil d.instance.connection_string
|
66
|
-
end
|
67
|
-
|
68
|
-
def test_configure_with_connection_string
|
69
|
-
d = create_driver(%[
|
70
|
-
@type mongo
|
71
|
-
connection_string mongodb://localhost/fluent_test
|
72
|
-
collection test_collection
|
73
|
-
capped
|
74
|
-
capped_size 100
|
75
|
-
])
|
76
|
-
assert_equal('mongodb://localhost/fluent_test', d.instance.connection_string)
|
77
|
-
assert_nil d.instance.database
|
78
|
-
end
|
79
|
-
|
80
|
-
def test_configure_without_connection_string_or_database
|
81
|
-
assert_raise Fluent::ConfigError do
|
82
|
-
d = create_driver(%[
|
83
|
-
@type mongo
|
84
|
-
collection test_collection
|
85
|
-
capped
|
86
|
-
capped_size 100
|
87
|
-
])
|
88
|
-
end
|
89
69
|
end
|
90
70
|
|
91
71
|
def test_configure_with_ssl
|
@@ -115,6 +95,7 @@ class MongoOutputTest < ::Test::Unit::TestCase
|
|
115
95
|
d = create_driver(conf)
|
116
96
|
assert_true(d.instance.tag_mapped)
|
117
97
|
assert_equal(/^raw\./, d.instance.remove_tag_prefix)
|
98
|
+
assert_equal('${tag}', d.instance.collection)
|
118
99
|
end
|
119
100
|
|
120
101
|
def test_configure_with_write_concern
|
@@ -155,61 +136,88 @@ class MongoOutputTest < ::Test::Unit::TestCase
|
|
155
136
|
assert_equal(expected, d.instance.mongo_log_level)
|
156
137
|
end
|
157
138
|
|
158
|
-
def get_documents
|
159
|
-
@client[
|
139
|
+
def get_documents(collection = collection_name)
|
140
|
+
@client[collection].find.to_a.map {|e| e.delete('_id'); e}
|
160
141
|
end
|
161
142
|
|
162
143
|
def emit_documents(d)
|
163
|
-
time =
|
164
|
-
d.
|
165
|
-
d.
|
144
|
+
time = event_time("2011-01-02 13:14:15 UTC")
|
145
|
+
d.feed(time, {'a' => 1})
|
146
|
+
d.feed(time, {'a' => 2})
|
166
147
|
time
|
167
148
|
end
|
168
149
|
|
169
150
|
def test_format
|
170
151
|
d = create_driver
|
171
152
|
|
172
|
-
time =
|
173
|
-
d.
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
d.
|
178
|
-
|
179
|
-
|
180
|
-
assert_equal(2, documents.size)
|
153
|
+
time = event_time("2011-01-02 13:14:15 UTC")
|
154
|
+
d.run(default_tag: 'test') do
|
155
|
+
d.feed(time, {'a' => 1})
|
156
|
+
d.feed(time, {'a' => 2})
|
157
|
+
end
|
158
|
+
assert_equal([time, {'a' => 1}].to_msgpack, d.formatted[0])
|
159
|
+
assert_equal([time, {'a' => 2}].to_msgpack, d.formatted[1])
|
160
|
+
assert_equal(2, d.formatted.size)
|
181
161
|
end
|
182
162
|
|
183
163
|
def test_write
|
184
164
|
d = create_driver
|
185
|
-
|
186
|
-
|
187
|
-
|
165
|
+
d.run(default_tag: 'test') do
|
166
|
+
emit_documents(d)
|
167
|
+
end
|
188
168
|
actual_documents = get_documents
|
189
|
-
time =
|
190
|
-
expected = [{'a' => 1, d.instance.time_key => time},
|
191
|
-
{'a' => 2, d.instance.time_key => time}]
|
169
|
+
time = event_time("2011-01-02 13:14:15 UTC")
|
170
|
+
expected = [{'a' => 1, d.instance.inject_config.time_key => Time.at(time).localtime},
|
171
|
+
{'a' => 2, d.instance.inject_config.time_key => Time.at(time).localtime}]
|
192
172
|
assert_equal(expected, actual_documents)
|
193
173
|
end
|
194
174
|
|
175
|
+
class WriteWithCollectionPlaceholder < self
|
176
|
+
def setup
|
177
|
+
@tag = 'custom'
|
178
|
+
setup_mongod
|
179
|
+
end
|
180
|
+
|
181
|
+
def teardown
|
182
|
+
teardown_mongod(@tag)
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_write_with_collection_placeholder
|
186
|
+
d = create_driver(%[
|
187
|
+
type mongo
|
188
|
+
database #{database_name}
|
189
|
+
collection ${tag}
|
190
|
+
include_time_key true
|
191
|
+
])
|
192
|
+
d.run(default_tag: @tag) do
|
193
|
+
emit_documents(d)
|
194
|
+
end
|
195
|
+
actual_documents = get_documents(@tag)
|
196
|
+
time = event_time("2011-01-02 13:14:15 UTC")
|
197
|
+
expected = [{'a' => 1, d.instance.inject_config.time_key => Time.at(time).localtime},
|
198
|
+
{'a' => 2, d.instance.inject_config.time_key => Time.at(time).localtime}]
|
199
|
+
assert_equal(expected, actual_documents)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
195
203
|
def test_write_at_enable_tag
|
196
204
|
d = create_driver(default_config + %[
|
197
205
|
include_tag_key true
|
198
206
|
include_time_key false
|
199
207
|
])
|
200
|
-
|
201
|
-
|
202
|
-
|
208
|
+
d.run(default_tag: 'test') do
|
209
|
+
emit_documents(d)
|
210
|
+
end
|
203
211
|
actual_documents = get_documents
|
204
|
-
expected = [{'a' => 1, d.instance.tag_key => 'test'},
|
205
|
-
{'a' => 2, d.instance.tag_key => 'test'}]
|
212
|
+
expected = [{'a' => 1, d.instance.inject_config.tag_key => 'test'},
|
213
|
+
{'a' => 2, d.instance.inject_config.tag_key => 'test'}]
|
206
214
|
assert_equal(expected, actual_documents)
|
207
215
|
end
|
208
216
|
|
209
217
|
def emit_invalid_documents(d)
|
210
|
-
time =
|
211
|
-
d.
|
212
|
-
d.
|
218
|
+
time = event_time("2011-01-02 13:14:15 UTC")
|
219
|
+
d.feed(time, {'a' => 3, 'b' => "c", '$last' => '石動'})
|
220
|
+
d.feed(time, {'a' => 4, 'b' => "d", 'first' => '菖蒲'.encode('EUC-JP').force_encoding('UTF-8')})
|
213
221
|
time
|
214
222
|
end
|
215
223
|
|
@@ -219,19 +227,19 @@ class MongoOutputTest < ::Test::Unit::TestCase
|
|
219
227
|
replace_dollar_in_key_with _dollar_
|
220
228
|
])
|
221
229
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
230
|
+
time = event_time("2011-01-02 13:14:15 UTC")
|
231
|
+
d.run(default_tag: 'test') do
|
232
|
+
d.feed(time, {
|
233
|
+
"foo.bar1" => {
|
234
|
+
"$foo$bar" => "baz"
|
235
|
+
},
|
236
|
+
"foo.bar2" => [
|
237
|
+
{
|
238
|
+
"$foo$bar" => "baz"
|
239
|
+
}
|
240
|
+
],
|
241
|
+
})
|
242
|
+
end
|
235
243
|
|
236
244
|
documents = get_documents
|
237
245
|
expected = {"foo_dot_bar1" => {
|
@@ -241,7 +249,7 @@ class MongoOutputTest < ::Test::Unit::TestCase
|
|
241
249
|
{
|
242
250
|
"_dollar_foo$bar"=>"baz"
|
243
251
|
},
|
244
|
-
], "time" => Time.
|
252
|
+
], "time" => Time.at(time).localtime
|
245
253
|
}
|
246
254
|
assert_equal(1, documents.size)
|
247
255
|
assert_equal(expected, documents[0])
|
@@ -266,13 +274,13 @@ class MongoOutputTest < ::Test::Unit::TestCase
|
|
266
274
|
user fluent
|
267
275
|
password password
|
268
276
|
])
|
269
|
-
|
270
|
-
|
271
|
-
|
277
|
+
d.run(default_tag: 'test') do
|
278
|
+
emit_documents(d)
|
279
|
+
end
|
272
280
|
actual_documents = get_documents
|
273
|
-
time =
|
274
|
-
expected = [{'a' => 1, d.instance.time_key => time},
|
275
|
-
{'a' => 2, d.instance.time_key => time}]
|
281
|
+
time = event_time("2011-01-02 13:14:15 UTC")
|
282
|
+
expected = [{'a' => 1, d.instance.inject_config.time_key => Time.at(time).localtime},
|
283
|
+
{'a' => 2, d.instance.inject_config.time_key => Time.at(time).localtime}]
|
276
284
|
assert_equal(expected, actual_documents)
|
277
285
|
end
|
278
286
|
end
|
@@ -1,6 +1,11 @@
|
|
1
1
|
require "helper"
|
2
|
+
require "fluent/test/driver/output"
|
3
|
+
require "fluent/test/helpers"
|
4
|
+
require 'fluent/mixin' # for TimeFormatter
|
2
5
|
|
3
6
|
class MongoReplsetOutputTest < ::Test::Unit::TestCase
|
7
|
+
include Fluent::Test::Helpers
|
8
|
+
|
4
9
|
def setup
|
5
10
|
Fluent::Test.setup
|
6
11
|
end
|
@@ -16,18 +21,14 @@ class MongoReplsetOutputTest < ::Test::Unit::TestCase
|
|
16
21
|
'fluent_test'
|
17
22
|
end
|
18
23
|
|
19
|
-
def nodes
|
20
|
-
["localhost:#{port}"]
|
21
|
-
end
|
22
|
-
|
23
24
|
def port
|
24
25
|
27018
|
25
26
|
end
|
26
27
|
|
27
28
|
def default_config
|
28
29
|
%[
|
29
|
-
|
30
|
-
|
30
|
+
type mongo
|
31
|
+
port 27018
|
31
32
|
database #{database_name}
|
32
33
|
collection #{collection_name}
|
33
34
|
include_time_key true
|
@@ -35,39 +36,24 @@ class MongoReplsetOutputTest < ::Test::Unit::TestCase
|
|
35
36
|
]
|
36
37
|
end
|
37
38
|
|
38
|
-
def create_driver(conf=default_config
|
39
|
-
Fluent::Test::
|
39
|
+
def create_driver(conf=default_config)
|
40
|
+
Fluent::Test::Driver::Output.new(Fluent::Plugin::MongoOutputReplset).configure(conf)
|
40
41
|
end
|
41
42
|
|
42
43
|
def test_configure
|
43
44
|
d = create_driver(%[
|
44
|
-
|
45
|
+
type mongo
|
45
46
|
port 27018
|
46
47
|
database fluent_test
|
47
48
|
collection test_collection
|
48
|
-
replica_set rs0
|
49
|
-
])
|
50
49
|
|
51
|
-
assert_equal('fluent_test', d.instance.database)
|
52
|
-
assert_equal('test_collection', d.instance.collection)
|
53
|
-
assert_equal('localhost', d.instance.host)
|
54
|
-
assert_equal(27018, d.instance.port)
|
55
|
-
assert_equal({replica_set: 'rs0', :ssl=>false, :write=>{:j=>false}},
|
56
|
-
d.instance.client_options)
|
57
|
-
end
|
58
|
-
|
59
|
-
def test_configure_with_nodes
|
60
|
-
d = create_driver(%[
|
61
|
-
@type mongo_replset
|
62
|
-
nodes localhost:27018,localhost:27019
|
63
|
-
database fluent_test
|
64
|
-
collection test_collection
|
65
50
|
replica_set rs0
|
66
51
|
])
|
67
52
|
|
68
53
|
assert_equal('fluent_test', d.instance.database)
|
69
54
|
assert_equal('test_collection', d.instance.collection)
|
70
|
-
assert_equal(
|
55
|
+
assert_equal('localhost', d.instance.host)
|
56
|
+
assert_equal(port, d.instance.port)
|
71
57
|
assert_equal({replica_set: 'rs0', :ssl=>false, :write=>{:j=>false}},
|
72
58
|
d.instance.client_options)
|
73
59
|
end
|
@@ -97,7 +83,7 @@ class MongoReplsetOutputTest < ::Test::Unit::TestCase
|
|
97
83
|
def setup_mongod
|
98
84
|
options = {}
|
99
85
|
options[:database] = database_name
|
100
|
-
@client = ::Mongo::Client.new(
|
86
|
+
@client = ::Mongo::Client.new(["localhost:#{port}"], options)
|
101
87
|
end
|
102
88
|
|
103
89
|
def teardown_mongod
|
@@ -109,35 +95,34 @@ class MongoReplsetOutputTest < ::Test::Unit::TestCase
|
|
109
95
|
end
|
110
96
|
|
111
97
|
def emit_documents(d)
|
112
|
-
time =
|
113
|
-
d.
|
114
|
-
d.
|
98
|
+
time = event_time("2011-01-02 13:14:15 UTC")
|
99
|
+
d.feed(time, {'a' => 1})
|
100
|
+
d.feed(time, {'a' => 2})
|
115
101
|
time
|
116
102
|
end
|
117
103
|
|
118
104
|
def test_format
|
119
105
|
d = create_driver
|
120
106
|
|
121
|
-
time =
|
122
|
-
d.
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
d.
|
127
|
-
|
128
|
-
|
129
|
-
assert_equal(2, documents.size)
|
107
|
+
time = event_time("2011-01-02 13:14:15 UTC")
|
108
|
+
d.run(default_tag: 'test') do
|
109
|
+
d.feed(time, {'a' => 1})
|
110
|
+
d.feed(time, {'a' => 2})
|
111
|
+
end
|
112
|
+
assert_equal([time, {'a' => 1}].to_msgpack, d.formatted[0])
|
113
|
+
assert_equal([time, {'a' => 2}].to_msgpack, d.formatted[1])
|
114
|
+
assert_equal(2, d.formatted.size)
|
130
115
|
end
|
131
116
|
|
132
117
|
def test_write
|
133
118
|
d = create_driver
|
134
|
-
|
135
|
-
|
136
|
-
|
119
|
+
d.run(default_tag: 'test') do
|
120
|
+
emit_documents(d)
|
121
|
+
end
|
137
122
|
actual_documents = get_documents
|
138
|
-
time =
|
139
|
-
expected = [{'a' => 1, d.instance.time_key => time},
|
140
|
-
{'a' => 2, d.instance.time_key => time}]
|
123
|
+
time = event_time("2011-01-02 13:14:15 UTC")
|
124
|
+
expected = [{'a' => 1, d.instance.inject_config.time_key => Time.at(time).localtime},
|
125
|
+
{'a' => 2, d.instance.inject_config.time_key => Time.at(time).localtime}]
|
141
126
|
assert_equal(expected, actual_documents)
|
142
127
|
end
|
143
128
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-mongo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masahiro Nakagawa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -100,6 +100,20 @@ dependencies:
|
|
100
100
|
- - ">="
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: 3.0.0
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: timecop
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.8.0
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 0.8.0
|
103
117
|
description: MongoDB plugin for Fluentd
|
104
118
|
email: repeatedly@gmail.com
|
105
119
|
executables:
|
@@ -112,7 +126,6 @@ files:
|
|
112
126
|
- AUTHORS
|
113
127
|
- ChangeLog
|
114
128
|
- Gemfile
|
115
|
-
- Gemfile.v0.12
|
116
129
|
- README.rdoc
|
117
130
|
- Rakefile
|
118
131
|
- VERSION
|
@@ -142,9 +155,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
142
155
|
version: '0'
|
143
156
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
157
|
requirements:
|
145
|
-
- - "
|
158
|
+
- - ">"
|
146
159
|
- !ruby/object:Gem::Version
|
147
|
-
version:
|
160
|
+
version: 1.3.1
|
148
161
|
requirements: []
|
149
162
|
rubyforge_project:
|
150
163
|
rubygems_version: 2.5.2
|