jmoses_fluent-logger 0.4.8
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.gitmodules +3 -0
- data/.rspec +1 -0
- data/.travis.yml +15 -0
- data/AUTHORS +1 -0
- data/COPYING +14 -0
- data/ChangeLog +81 -0
- data/Gemfile +11 -0
- data/README.md +63 -0
- data/Rakefile +18 -0
- data/VERSION +1 -0
- data/bin/fluent-post +11 -0
- data/fluent-logger.gemspec +44 -0
- data/lib/fluent/logger/console_logger.rb +57 -0
- data/lib/fluent/logger/fluent_logger/cui.rb +46 -0
- data/lib/fluent/logger/fluent_logger.rb +298 -0
- data/lib/fluent/logger/logger_base.rb +39 -0
- data/lib/fluent/logger/null_logger.rb +28 -0
- data/lib/fluent/logger/test_logger.rb +51 -0
- data/lib/fluent/logger/text_logger.rb +39 -0
- data/lib/fluent/logger/version.rb +7 -0
- data/lib/fluent/logger.rb +69 -0
- data/lib/fluent-logger.rb +1 -0
- data/spec/console_logger_spec.rb +69 -0
- data/spec/fluent_logger_spec.rb +297 -0
- data/spec/logger_base_spec.rb +11 -0
- data/spec/logger_spec.rb +42 -0
- data/spec/null_logger_spec.rb +15 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/support/timecop.rb +8 -0
- data/spec/test_logger_spec.rb +37 -0
- metadata +217 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
#
|
2
|
+
# Fluent
|
3
|
+
#
|
4
|
+
# Copyright (C) 2011 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
module Fluent
|
19
|
+
module Logger
|
20
|
+
|
21
|
+
class LoggerBase
|
22
|
+
def self.open(*args, &block)
|
23
|
+
Fluent::Logger.open(self, *args, &block)
|
24
|
+
end
|
25
|
+
|
26
|
+
def post(tag, map)
|
27
|
+
raise ArgumentError.new("Second argument should kind of Hash (tag: #{map})") unless map.kind_of? Hash
|
28
|
+
post_with_time(tag, map, Time.now)
|
29
|
+
end
|
30
|
+
|
31
|
+
#def post_with_time(tag, map)
|
32
|
+
#end
|
33
|
+
|
34
|
+
def close
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#
|
2
|
+
# Fluent
|
3
|
+
#
|
4
|
+
# Copyright (C) 2011 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
module Fluent
|
19
|
+
module Logger
|
20
|
+
|
21
|
+
class NullLogger < LoggerBase
|
22
|
+
def post_with_time(tag, map, time)
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#
|
2
|
+
# Fluent
|
3
|
+
#
|
4
|
+
# Copyright (C) 2011 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
module Fluent
|
19
|
+
module Logger
|
20
|
+
|
21
|
+
class TestLogger < LoggerBase
|
22
|
+
def initialize(queue=[])
|
23
|
+
@queue = queue
|
24
|
+
@max = 1024
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_accessor :max
|
28
|
+
attr_reader :queue
|
29
|
+
|
30
|
+
def post_with_time(tag, map, time)
|
31
|
+
while @queue.size > @max-1
|
32
|
+
@queue.shift
|
33
|
+
end
|
34
|
+
(class<<map;self;end).module_eval do
|
35
|
+
define_method(:tag) { tag }
|
36
|
+
define_method(:time) { time }
|
37
|
+
end
|
38
|
+
@queue << map
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
def tag_queue(tag)
|
43
|
+
@queue.find_all {|map| map.tag == tag }
|
44
|
+
end
|
45
|
+
|
46
|
+
def close
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#
|
2
|
+
# Fluent
|
3
|
+
#
|
4
|
+
# Copyright (C) 2011 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
module Fluent
|
19
|
+
module Logger
|
20
|
+
|
21
|
+
class TextLogger < LoggerBase
|
22
|
+
def initialize
|
23
|
+
require 'yajl'
|
24
|
+
@time_format = "%b %e %H:%M:%S"
|
25
|
+
end
|
26
|
+
|
27
|
+
def post_with_time(tag, map, time)
|
28
|
+
a = [time.strftime(@time_format), " ", tag, ":"]
|
29
|
+
map.each_pair {|k,v|
|
30
|
+
a << " #{k}="
|
31
|
+
a << Yajl::Encoder.encode(v)
|
32
|
+
}
|
33
|
+
post_text a.join
|
34
|
+
true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#
|
2
|
+
# Fluent
|
3
|
+
#
|
4
|
+
# Copyright (C) 2011 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
module Fluent
|
19
|
+
|
20
|
+
module Logger
|
21
|
+
autoload :ConsoleLogger , 'fluent/logger/console_logger'
|
22
|
+
autoload :FluentLogger , 'fluent/logger/fluent_logger'
|
23
|
+
autoload :LoggerBase , 'fluent/logger/logger_base'
|
24
|
+
autoload :TestLogger , 'fluent/logger/test_logger'
|
25
|
+
autoload :TextLogger , 'fluent/logger/text_logger'
|
26
|
+
autoload :NullLogger , 'fluent/logger/null_logger'
|
27
|
+
autoload :VERSION , 'fluent/logger/version'
|
28
|
+
|
29
|
+
@@default_logger = nil
|
30
|
+
|
31
|
+
def self.new(*args)
|
32
|
+
if args.first.is_a?(Class) && args.first.ancestors.include?(LoggerBase)
|
33
|
+
type = args.shift
|
34
|
+
else
|
35
|
+
type = FluentLogger
|
36
|
+
end
|
37
|
+
type.new(*args)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.open(*args)
|
41
|
+
close
|
42
|
+
@@default_logger = new(*args)
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.close
|
46
|
+
if @@default_logger
|
47
|
+
@@default_logger.close
|
48
|
+
@@default_logger = nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.post(tag, map)
|
53
|
+
@@default_logger.post(tag, map)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.post_with_time(tag, map, time)
|
57
|
+
@@default_logger.post_with_time(tag, map, time)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.default
|
61
|
+
@@default_logger ||= ConsoleLogger.new(STDOUT)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.default=(logger)
|
65
|
+
@@default_logger = logger
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'fluent', 'logger')
|
@@ -0,0 +1,69 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'stringio'
|
4
|
+
require 'tempfile'
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
describe Fluent::Logger::ConsoleLogger do
|
8
|
+
before(:each) {
|
9
|
+
Timecop.freeze Time.local(2008, 9, 1, 10, 5, 0)
|
10
|
+
}
|
11
|
+
after(:each) {
|
12
|
+
Timecop.return
|
13
|
+
}
|
14
|
+
|
15
|
+
context "IO output" do
|
16
|
+
let(:io) { StringIO.new }
|
17
|
+
let(:logger) { Fluent::Logger::ConsoleLogger.new(io) }
|
18
|
+
|
19
|
+
subject {
|
20
|
+
io
|
21
|
+
}
|
22
|
+
|
23
|
+
context "post and read" do
|
24
|
+
before do
|
25
|
+
logger.post('example', {:foo => :bar})
|
26
|
+
io.rewind
|
27
|
+
end
|
28
|
+
its(:read) { should eq %Q!Sep 1 10:05:00 example: foo="bar"\n! }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "Filename output" do
|
33
|
+
let(:path) {
|
34
|
+
@tmp = Tempfile.new('fluent-logger') # ref instance var because Tempfile.close(true) check GC
|
35
|
+
filename = @tmp.path
|
36
|
+
@tmp.close(true)
|
37
|
+
Pathname.new(filename)
|
38
|
+
}
|
39
|
+
let(:logger) { Fluent::Logger::ConsoleLogger.new(path.to_s) }
|
40
|
+
|
41
|
+
subject { path }
|
42
|
+
after { path.unlink }
|
43
|
+
|
44
|
+
context "post and read" do
|
45
|
+
before do
|
46
|
+
logger.post('example', {:foo => :bar})
|
47
|
+
logger.close
|
48
|
+
end
|
49
|
+
its(:read) { should eq %Q!Sep 1 10:05:00 example: foo="bar"\n! }
|
50
|
+
end
|
51
|
+
|
52
|
+
context "reopen" do
|
53
|
+
before do
|
54
|
+
logger.post('example', {:foo => :baz})
|
55
|
+
logger.close
|
56
|
+
logger.reopen!
|
57
|
+
end
|
58
|
+
its(:read) { should eq %Q!Sep 1 10:05:00 example: foo="baz"\n! }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "Invalid output" do
|
63
|
+
it {
|
64
|
+
expect {
|
65
|
+
Fluent::Logger::ConsoleLogger.new(nil)
|
66
|
+
}.to raise_error
|
67
|
+
}
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,297 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
if RUBY_VERSION < "1.9.2"
|
4
|
+
|
5
|
+
describe Fluent::Logger::FluentLogger do
|
6
|
+
pending "fluentd don't work RUBY < 1.9.2"
|
7
|
+
end
|
8
|
+
|
9
|
+
else
|
10
|
+
|
11
|
+
require 'fluent/load'
|
12
|
+
require 'tempfile'
|
13
|
+
require 'logger'
|
14
|
+
require 'socket'
|
15
|
+
require 'stringio'
|
16
|
+
require 'fluent/logger/fluent_logger/cui'
|
17
|
+
|
18
|
+
$log = Fluent::Log.new(StringIO.new) # XXX should remove $log from fluentd
|
19
|
+
|
20
|
+
describe Fluent::Logger::FluentLogger do
|
21
|
+
WAIT = ENV['WAIT'] ? ENV['WAIT'].to_f : 0.1
|
22
|
+
|
23
|
+
let(:fluentd_port) {
|
24
|
+
port = 60001
|
25
|
+
loop do
|
26
|
+
begin
|
27
|
+
TCPServer.open('localhost', port).close
|
28
|
+
break
|
29
|
+
rescue Errno::EADDRINUSE
|
30
|
+
port += 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
port
|
34
|
+
}
|
35
|
+
|
36
|
+
let(:logger) {
|
37
|
+
@logger_io = StringIO.new
|
38
|
+
logger = ::Logger.new(@logger_io)
|
39
|
+
Fluent::Logger::FluentLogger.new('logger-test', {
|
40
|
+
:host => 'localhost',
|
41
|
+
:port => fluentd_port,
|
42
|
+
:logger => logger,
|
43
|
+
})
|
44
|
+
}
|
45
|
+
|
46
|
+
let(:logger_io) {
|
47
|
+
@logger_io
|
48
|
+
}
|
49
|
+
|
50
|
+
let(:output) {
|
51
|
+
sleep 0.0001 # next tick
|
52
|
+
Fluent::Engine.match('logger-test').output
|
53
|
+
}
|
54
|
+
|
55
|
+
let(:queue) {
|
56
|
+
queue = []
|
57
|
+
output.emits.each {|tag, time, record|
|
58
|
+
queue << [tag, record]
|
59
|
+
}
|
60
|
+
queue
|
61
|
+
}
|
62
|
+
|
63
|
+
let(:queue_with_time) {
|
64
|
+
queue = []
|
65
|
+
output.emits.each {|tag, time, record|
|
66
|
+
queue << [tag, time, record]
|
67
|
+
}
|
68
|
+
queue
|
69
|
+
}
|
70
|
+
|
71
|
+
after(:each) do
|
72
|
+
output.emits.clear rescue nil
|
73
|
+
end
|
74
|
+
|
75
|
+
def wait_transfer
|
76
|
+
sleep WAIT
|
77
|
+
end
|
78
|
+
|
79
|
+
context "running fluentd" do
|
80
|
+
before(:each) do
|
81
|
+
tmp = Tempfile.new('fluent-logger-config')
|
82
|
+
tmp.close(false)
|
83
|
+
|
84
|
+
File.open(tmp.path, 'w') {|f|
|
85
|
+
f.puts <<EOF
|
86
|
+
<source>
|
87
|
+
type tcp
|
88
|
+
port #{fluentd_port}
|
89
|
+
</source>
|
90
|
+
<match logger-test.**>
|
91
|
+
type test
|
92
|
+
</match>
|
93
|
+
EOF
|
94
|
+
}
|
95
|
+
Fluent::Test.setup
|
96
|
+
Fluent::Engine.read_config(tmp.path)
|
97
|
+
@coolio_default_loop = nil
|
98
|
+
@thread = Thread.new {
|
99
|
+
@coolio_default_loop = Coolio::Loop.default
|
100
|
+
Fluent::Engine.run
|
101
|
+
}
|
102
|
+
wait_transfer
|
103
|
+
end
|
104
|
+
|
105
|
+
after(:each) do
|
106
|
+
@coolio_default_loop.stop
|
107
|
+
Fluent::Engine.send :shutdown
|
108
|
+
@thread.join
|
109
|
+
end
|
110
|
+
|
111
|
+
context('Post by CUI') do
|
112
|
+
it('post') {
|
113
|
+
args = %W(-h localhost -p #{fluentd_port} -t logger-test.tag -v a=b -v foo=bar)
|
114
|
+
Fluent::Logger::FluentLogger::CUI.post(args)
|
115
|
+
wait_transfer
|
116
|
+
queue.last.should == ['logger-test.tag', {'a' => 'b', 'foo' => 'bar'}]
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
context('post') do
|
121
|
+
it ('success') {
|
122
|
+
logger.post('tag', {'a' => 'b'}).should be_true
|
123
|
+
wait_transfer
|
124
|
+
queue.last.should == ['logger-test.tag', {'a' => 'b'}]
|
125
|
+
}
|
126
|
+
|
127
|
+
it ('close after post') {
|
128
|
+
logger.should be_connect
|
129
|
+
logger.close
|
130
|
+
logger.should_not be_connect
|
131
|
+
|
132
|
+
logger.post('tag', {'b' => 'c'})
|
133
|
+
logger.should be_connect
|
134
|
+
wait_transfer
|
135
|
+
queue.last.should == ['logger-test.tag', {'b' => 'c'}]
|
136
|
+
}
|
137
|
+
|
138
|
+
it ('large data') {
|
139
|
+
data = {'a' => ('b' * 1000000)}
|
140
|
+
logger.post('tag', data)
|
141
|
+
wait_transfer
|
142
|
+
queue.last.should == ['logger-test.tag', data]
|
143
|
+
}
|
144
|
+
|
145
|
+
it ('msgpack unsupport data') {
|
146
|
+
data = {
|
147
|
+
'time' => Time.utc(2008, 9, 1, 10, 5, 0),
|
148
|
+
'object' => Object.new,
|
149
|
+
'proc' => proc { 1 },
|
150
|
+
}
|
151
|
+
logger.post('tag', data)
|
152
|
+
wait_transfer
|
153
|
+
logger_data = queue.last.last
|
154
|
+
logger_data['time'].should == '2008-09-01 10:05:00 UTC'
|
155
|
+
logger_data['proc'].should be
|
156
|
+
logger_data['object'].should be
|
157
|
+
}
|
158
|
+
|
159
|
+
it ('msgpack and JSON unsupport data') {
|
160
|
+
data = {
|
161
|
+
'time' => Time.utc(2008, 9, 1, 10, 5, 0),
|
162
|
+
'object' => Object.new,
|
163
|
+
'proc' => proc { 1 },
|
164
|
+
'NaN' => (0.0/0.0) # JSON don't convert
|
165
|
+
}
|
166
|
+
logger.post('tag', data)
|
167
|
+
wait_transfer
|
168
|
+
queue.last.should be_nil
|
169
|
+
logger_io.rewind
|
170
|
+
logger_io.read =~ /FluentLogger: Can't convert to msgpack:/
|
171
|
+
}
|
172
|
+
|
173
|
+
it ('batch post') {
|
174
|
+
messages = [
|
175
|
+
['logger-test.tag1', 'message 1', Time.utc(2008, 9, 1, 10, 5, 0)],
|
176
|
+
['logger-test.tag2', 'message 2', Time.utc(2008, 9, 1, 10, 6, 0)],
|
177
|
+
]
|
178
|
+
|
179
|
+
logger.batch_post_with_time(messages)
|
180
|
+
wait_transfer
|
181
|
+
|
182
|
+
queue_with_time.should have(2).items
|
183
|
+
queue_with_time.first[0].should eq('logger-test.tag1')
|
184
|
+
queue_with_time.first[1].should eq(1220263500)
|
185
|
+
queue_with_time.first[2].should eq('message 1')
|
186
|
+
queue_with_time.last[0].should eq('logger-test.tag2')
|
187
|
+
queue_with_time.last[1].should eq(1220263560)
|
188
|
+
queue_with_time.last[2].should eq('message 2')
|
189
|
+
}
|
190
|
+
|
191
|
+
it ('batches faster than single') {
|
192
|
+
require 'benchmark'
|
193
|
+
require 'digest/md5'
|
194
|
+
|
195
|
+
messages = 1000.times.map do |id|
|
196
|
+
['logger-test.tag', Digest::MD5.hexdigest(id.to_s), Time.now]
|
197
|
+
end
|
198
|
+
|
199
|
+
single = Benchmark.realtime do
|
200
|
+
output.emits.clear
|
201
|
+
messages.each {|m| logger.post_with_time *m }
|
202
|
+
wait_transfer
|
203
|
+
queue.should have(1000).items
|
204
|
+
end
|
205
|
+
|
206
|
+
batch = Benchmark.realtime do
|
207
|
+
output.emits.clear
|
208
|
+
logger.batch_post_with_time messages
|
209
|
+
wait_transfer
|
210
|
+
queue.should have(1000).items
|
211
|
+
end
|
212
|
+
|
213
|
+
batch.should be < single
|
214
|
+
}
|
215
|
+
|
216
|
+
it ('should raise an error when second argument is non hash object') {
|
217
|
+
data = 'FooBar'
|
218
|
+
expect {
|
219
|
+
logger.post('tag', data)
|
220
|
+
}.to raise_error(ArgumentError)
|
221
|
+
|
222
|
+
data = nil
|
223
|
+
expect {
|
224
|
+
logger.post('tag', data)
|
225
|
+
}.to raise_error(ArgumentError)
|
226
|
+
}
|
227
|
+
end
|
228
|
+
|
229
|
+
context "initializer" do
|
230
|
+
it "backward compatible" do
|
231
|
+
port = fluentd_port
|
232
|
+
fluent_logger = Fluent::Logger::FluentLogger.new('logger-test', 'localhost', port)
|
233
|
+
fluent_logger.method_missing(:instance_eval) { # fluent_logger is delegetor
|
234
|
+
@host.should == 'localhost'
|
235
|
+
@port.should == port
|
236
|
+
}
|
237
|
+
end
|
238
|
+
|
239
|
+
it "hash argument" do
|
240
|
+
port = fluentd_port
|
241
|
+
fluent_logger = Fluent::Logger::FluentLogger.new('logger-test', {
|
242
|
+
:host => 'localhost',
|
243
|
+
:port => port
|
244
|
+
})
|
245
|
+
fluent_logger.method_missing(:instance_eval) { # fluent_logger is delegetor
|
246
|
+
@host.should == 'localhost'
|
247
|
+
@port.should == port
|
248
|
+
}
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
context "not running fluentd" do
|
254
|
+
context('fluent logger interface') do
|
255
|
+
it ('post & close') {
|
256
|
+
logger.post('tag', {'a' => 'b'}).should be_false
|
257
|
+
wait_transfer # even if wait
|
258
|
+
queue.last.should be_nil
|
259
|
+
logger.close
|
260
|
+
logger_io.rewind
|
261
|
+
log = logger_io.read
|
262
|
+
log.should =~ /Failed to connect/
|
263
|
+
log.should =~ /Can't send logs to/
|
264
|
+
}
|
265
|
+
|
266
|
+
it ('post limit over') do
|
267
|
+
logger.limit = 100
|
268
|
+
logger.post('tag', {'a' => 'b'})
|
269
|
+
wait_transfer # even if wait
|
270
|
+
queue.last.should be_nil
|
271
|
+
|
272
|
+
logger_io.rewind
|
273
|
+
logger_io.read.should_not =~ /Can't send logs to/
|
274
|
+
|
275
|
+
logger.post('tag', {'a' => ('c' * 1000)})
|
276
|
+
logger_io.rewind
|
277
|
+
logger_io.read.should =~ /Can't send logs to/
|
278
|
+
end
|
279
|
+
|
280
|
+
it ('log connect error once') do
|
281
|
+
Fluent::Logger::FluentLogger.any_instance.stub(:suppress_sec).and_return(-1)
|
282
|
+
logger.log_reconnect_error_threshold = 1
|
283
|
+
Fluent::Logger::FluentLogger.any_instance.should_receive(:log_reconnect_error).once.and_call_original
|
284
|
+
|
285
|
+
logger.post('tag', {'a' => 'b'})
|
286
|
+
wait_transfer # even if wait
|
287
|
+
logger.post('tag', {'a' => 'b'})
|
288
|
+
wait_transfer # even if wait
|
289
|
+
logger_io.rewind
|
290
|
+
logger_io.read.should =~ /Failed to connect/
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
end
|
296
|
+
|
297
|
+
end
|
data/spec/logger_spec.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
describe Fluent::Logger do
|
6
|
+
context "default logger" do
|
7
|
+
let(:test_logger) {
|
8
|
+
Fluent::Logger::TestLogger.new
|
9
|
+
}
|
10
|
+
before(:each) do
|
11
|
+
Fluent::Logger.default = test_logger
|
12
|
+
end
|
13
|
+
|
14
|
+
it('post') {
|
15
|
+
test_logger.should_receive(:post).with('tag1', {:foo => :bar})
|
16
|
+
Fluent::Logger.post('tag1', {:foo => :bar})
|
17
|
+
}
|
18
|
+
|
19
|
+
it('close') {
|
20
|
+
test_logger.should_receive(:close)
|
21
|
+
Fluent::Logger.close
|
22
|
+
}
|
23
|
+
|
24
|
+
it('open') {
|
25
|
+
test_logger.should_receive(:close)
|
26
|
+
klass = Class.new(Fluent::Logger::LoggerBase)
|
27
|
+
fluent_logger_logger_io = StringIO.new
|
28
|
+
Fluent::Logger.open('tag-prefix', {
|
29
|
+
:logger => ::Logger.new(fluent_logger_logger_io)
|
30
|
+
})
|
31
|
+
# Fluent::Logger::FluentLogger is delegator
|
32
|
+
Fluent::Logger.default.method_missing(:kind_of?, Fluent::Logger::FluentLogger).should be_true
|
33
|
+
}
|
34
|
+
|
35
|
+
it('open with BaseLogger class') {
|
36
|
+
test_logger.should_receive(:close)
|
37
|
+
klass = Class.new(Fluent::Logger::LoggerBase)
|
38
|
+
Fluent::Logger.open(klass)
|
39
|
+
Fluent::Logger.default.class.should == klass
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Fluent::Logger::NullLogger do
|
5
|
+
context "logger method" do
|
6
|
+
let(:logger) { Fluent::Logger::NullLogger.new }
|
7
|
+
|
8
|
+
context "post" do
|
9
|
+
it('false') {
|
10
|
+
logger.post('tag1', {:foo => :bar}).should == false
|
11
|
+
logger.post('tag2', {:foo => :baz}).should == false
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|