fluent-logger 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +0 -6
- data/ChangeLog +6 -0
- data/README.md +29 -0
- data/VERSION +1 -1
- data/lib/fluent/logger/fluent_logger.rb +13 -1
- data/lib/fluent/logger/logger_base.rb +1 -1
- data/lib/fluent/logger/version.rb +1 -1
- data/spec/fluent_logger_spec.rb +83 -37
- data/spec/logger_base_spec.rb +16 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3cc43a68a8c73c0232044f58faae75f84eb2fc3
|
4
|
+
data.tar.gz: 43ed7af93c1e1e0976a813b89daedba55f88ff66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 607a3d6c81390b225efba3a1fff812f233d53ff6e7521aa1b95fbf0cfdc052f55961c908455b477b2511dda86c9830bdbabb372c0952589fd37390949414127e
|
7
|
+
data.tar.gz: a7f32f72c5411e264463a451f830228f7a15d943445ec0b5058ab1c3aee811252dc879822c3f7f7adba94a790c74be6970235ff05503d3bb9b931f3e090477ac
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/ChangeLog
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
Release 0.5.1 - 2015/11/24
|
2
|
+
|
3
|
+
* Allow injection of buffer overflow handler
|
4
|
+
* tag_prefix now default to nil
|
5
|
+
* LoggerBase.open follows README
|
6
|
+
|
1
7
|
Release 0.5.0 - 2015/01/25
|
2
8
|
|
3
9
|
* Use json instead of yajl. If you pass an invalid string to post, you may get 'invalid byte sequence' error.
|
data/README.md
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
# Fluent logger
|
2
|
+
|
3
|
+
[](https://travis-ci.org/fluent/fluent-logger-ruby)
|
4
|
+
|
2
5
|
A structured event logger
|
3
6
|
|
4
7
|
## Examples
|
@@ -53,6 +56,32 @@ Fluent::Logger::ConsoleLogger.open(io)
|
|
53
56
|
Fluent::Logger::NullLogger.open
|
54
57
|
```
|
55
58
|
|
59
|
+
## Buffer overflow
|
60
|
+
|
61
|
+
You can inject your own custom proc to handle buffer overflow in the event of connection failure. This will mitigate the loss of data instead of simply throwing data away.
|
62
|
+
|
63
|
+
Your proc must accept a single argument, which will be the internal buffer of messages from the logger. A typical use-case for this would be writing to disk or possibly writing to Redis.
|
64
|
+
|
65
|
+
##### Example
|
66
|
+
```
|
67
|
+
class BufferOverflowHandler
|
68
|
+
attr_accessor :buffer
|
69
|
+
|
70
|
+
def flush(messages)
|
71
|
+
@buffer ||= []
|
72
|
+
MessagePack::Unpacker.new.feed_each(messages) do |msg|
|
73
|
+
@buffer << msg
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
handler = Proc.new { |messages| BufferOverflowHandler.new.flush(messages) }
|
79
|
+
|
80
|
+
Fluent::Logger::FluentLogger.new(nil,
|
81
|
+
:host => 'localhost', :port => 24224,
|
82
|
+
:buffer_overflow_handler => handler)
|
83
|
+
```
|
84
|
+
|
56
85
|
|name|description|
|
57
86
|
|---|---|
|
58
87
|
|Web site|http://fluentd.org/|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.1
|
@@ -34,7 +34,7 @@ module Fluent
|
|
34
34
|
r / RECONNECT_WAIT_INCR_RATE
|
35
35
|
}
|
36
36
|
|
37
|
-
def initialize(tag_prefix =
|
37
|
+
def initialize(tag_prefix = nil, *args)
|
38
38
|
super()
|
39
39
|
|
40
40
|
options = {
|
@@ -62,6 +62,8 @@ module Fluent
|
|
62
62
|
@limit = options[:buffer_limit] || BUFFER_LIMIT
|
63
63
|
@log_reconnect_error_threshold = options[:log_reconnect_error_threshold] || RECONNECT_WAIT_MAX_COUNT
|
64
64
|
|
65
|
+
@buffer_overflow_handler = options[:buffer_overflow_handler]
|
66
|
+
|
65
67
|
if logger = options[:logger]
|
66
68
|
@logger = logger
|
67
69
|
else
|
@@ -107,6 +109,7 @@ module Fluent
|
|
107
109
|
rescue => e
|
108
110
|
set_last_error(e)
|
109
111
|
@logger.error("FluentLogger: Can't send logs to #{@host}:#{@port}: #{$!}")
|
112
|
+
call_buffer_overflow_handler(@pending)
|
110
113
|
end
|
111
114
|
end
|
112
115
|
@con.close if connect?
|
@@ -168,6 +171,7 @@ module Fluent
|
|
168
171
|
set_last_error(e)
|
169
172
|
if @pending.bytesize > @limit
|
170
173
|
@logger.error("FluentLogger: Can't send logs to #{@host}:#{@port}: #{$!}")
|
174
|
+
call_buffer_overflow_handler(@pending)
|
171
175
|
@pending = nil
|
172
176
|
end
|
173
177
|
@con.close if connect?
|
@@ -217,6 +221,14 @@ module Fluent
|
|
217
221
|
raise e
|
218
222
|
end
|
219
223
|
|
224
|
+
def call_buffer_overflow_handler(pending)
|
225
|
+
if @buffer_overflow_handler
|
226
|
+
@buffer_overflow_handler.call(pending)
|
227
|
+
end
|
228
|
+
rescue Exception => e
|
229
|
+
@logger.error("FluentLogger: Can't call buffer overflow handler: #{$!}")
|
230
|
+
end
|
231
|
+
|
220
232
|
def log_reconnect_error
|
221
233
|
@logger.error("FluentLogger: Can't connect to #{@host}:#{@port}(#{@connect_error_history.size} retried): #{$!}")
|
222
234
|
end
|
data/spec/fluent_logger_spec.rb
CHANGED
@@ -10,7 +10,7 @@ require 'stringio'
|
|
10
10
|
require 'fluent/logger/fluent_logger/cui'
|
11
11
|
require 'plugin/out_test'
|
12
12
|
|
13
|
-
$log = Fluent::Log.new(StringIO.new) # XXX should remove $log from fluentd
|
13
|
+
$log = Fluent::Log.new(StringIO.new) # XXX should remove $log from fluentd
|
14
14
|
|
15
15
|
describe Fluent::Logger::FluentLogger do
|
16
16
|
WAIT = ENV['WAIT'] ? ENV['WAIT'].to_f : 0.1
|
@@ -32,19 +32,26 @@ describe Fluent::Logger::FluentLogger do
|
|
32
32
|
@logger_io = StringIO.new
|
33
33
|
logger = ::Logger.new(@logger_io)
|
34
34
|
Fluent::Logger::FluentLogger.new('logger-test', {
|
35
|
-
:host => 'localhost',
|
35
|
+
:host => 'localhost',
|
36
36
|
:port => fluentd_port,
|
37
37
|
:logger => logger,
|
38
|
+
:buffer_overflow_handler => buffer_overflow_handler
|
38
39
|
})
|
39
40
|
}
|
40
41
|
|
42
|
+
let(:buffer_overflow_handler) { nil }
|
43
|
+
|
41
44
|
let(:logger_io) {
|
42
45
|
@logger_io
|
43
46
|
}
|
44
47
|
|
45
48
|
let(:output) {
|
46
49
|
sleep 0.0001 # next tick
|
47
|
-
Fluent::Engine.match
|
50
|
+
if Fluent::Engine.respond_to?(:match)
|
51
|
+
Fluent::Engine.match('logger-test').output
|
52
|
+
else
|
53
|
+
Fluent::Engine.root_agent.event_router.match('logger-test')
|
54
|
+
end
|
48
55
|
}
|
49
56
|
|
50
57
|
let(:queue) {
|
@@ -95,33 +102,33 @@ EOF
|
|
95
102
|
args = %W(-h localhost -p #{fluentd_port} -t logger-test.tag -v a=b -v foo=bar)
|
96
103
|
Fluent::Logger::FluentLogger::CUI.post(args)
|
97
104
|
wait_transfer
|
98
|
-
queue.last.
|
105
|
+
expect(queue.last).to eq ['logger-test.tag', {'a' => 'b', 'foo' => 'bar'}]
|
99
106
|
}
|
100
107
|
end
|
101
108
|
|
102
109
|
context('post') do
|
103
|
-
it ('success') {
|
110
|
+
it ('success') {
|
104
111
|
expect(logger.post('tag', {'a' => 'b'})).to be true
|
105
112
|
wait_transfer
|
106
|
-
queue.last.
|
113
|
+
expect(queue.last).to eq ['logger-test.tag', {'a' => 'b'}]
|
107
114
|
}
|
108
115
|
|
109
116
|
it ('close after post') {
|
110
|
-
logger.
|
117
|
+
expect(logger).to be_connect
|
111
118
|
logger.close
|
112
|
-
logger.
|
119
|
+
expect(logger).not_to be_connect
|
113
120
|
|
114
121
|
logger.post('tag', {'b' => 'c'})
|
115
|
-
logger.
|
122
|
+
expect(logger).to be_connect
|
116
123
|
wait_transfer
|
117
|
-
queue.last.
|
124
|
+
expect(queue.last).to eq ['logger-test.tag', {'b' => 'c'}]
|
118
125
|
}
|
119
126
|
|
120
127
|
it ('large data') {
|
121
128
|
data = {'a' => ('b' * 1000000)}
|
122
129
|
logger.post('tag', data)
|
123
130
|
wait_transfer
|
124
|
-
queue.last.
|
131
|
+
expect(queue.last).to eq ['logger-test.tag', data]
|
125
132
|
}
|
126
133
|
|
127
134
|
it ('msgpack unsupport data') {
|
@@ -133,9 +140,9 @@ EOF
|
|
133
140
|
logger.post('tag', data)
|
134
141
|
wait_transfer
|
135
142
|
logger_data = queue.last.last
|
136
|
-
logger_data['time'].
|
137
|
-
logger_data['proc'].
|
138
|
-
logger_data['object'].
|
143
|
+
expect(logger_data['time']).to eq '2008-09-01 10:05:00 UTC'
|
144
|
+
expect(logger_data['proc']).to be_truthy
|
145
|
+
expect(logger_data['object']).to be_truthy
|
139
146
|
}
|
140
147
|
|
141
148
|
it ('msgpack and JSON unsupport data') {
|
@@ -147,7 +154,7 @@ EOF
|
|
147
154
|
}
|
148
155
|
logger.post('tag', data)
|
149
156
|
wait_transfer
|
150
|
-
queue.last.
|
157
|
+
expect(queue.last).to be_nil
|
151
158
|
logger_io.rewind
|
152
159
|
logger_io.read =~ /FluentLogger: Can't convert to msgpack:/
|
153
160
|
}
|
@@ -167,66 +174,105 @@ EOF
|
|
167
174
|
|
168
175
|
context "initializer" do
|
169
176
|
it "backward compatible" do
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
@port.should == port
|
175
|
-
}
|
177
|
+
fluent_logger = Fluent::Logger::FluentLogger.new('logger-test', 'localhost', fluentd_port)
|
178
|
+
host, port = fluent_logger.instance_eval { [@host, @port] }
|
179
|
+
expect(host).to eq 'localhost'
|
180
|
+
expect(port).to eq fluentd_port
|
176
181
|
end
|
177
182
|
|
178
183
|
it "hash argument" do
|
179
|
-
port = fluentd_port
|
180
184
|
fluent_logger = Fluent::Logger::FluentLogger.new('logger-test', {
|
181
185
|
:host => 'localhost',
|
182
|
-
:port =>
|
186
|
+
:port => fluentd_port
|
183
187
|
})
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
+
|
189
|
+
host, port = fluent_logger.instance_eval { [@host, @port] }
|
190
|
+
expect(host).to eq 'localhost'
|
191
|
+
expect(port).to eq fluentd_port
|
188
192
|
end
|
189
193
|
end
|
190
194
|
end
|
191
|
-
|
195
|
+
|
192
196
|
context "not running fluentd" do
|
193
197
|
context('fluent logger interface') do
|
194
198
|
it ('post & close') {
|
195
199
|
expect(logger.post('tag', {'a' => 'b'})).to be false
|
196
200
|
wait_transfer # even if wait
|
197
|
-
queue.last.
|
201
|
+
expect(queue.last).to be_nil
|
198
202
|
logger.close
|
199
203
|
logger_io.rewind
|
200
204
|
log = logger_io.read
|
201
|
-
log.
|
202
|
-
log.
|
205
|
+
expect(log).to match /Failed to connect/
|
206
|
+
expect(log).to match /Can't send logs to/
|
203
207
|
}
|
204
208
|
|
205
209
|
it ('post limit over') do
|
206
210
|
logger.limit = 100
|
207
211
|
logger.post('tag', {'a' => 'b'})
|
208
212
|
wait_transfer # even if wait
|
209
|
-
queue.last.
|
213
|
+
expect(queue.last).to be_nil
|
210
214
|
|
211
215
|
logger_io.rewind
|
212
|
-
logger_io.read.
|
216
|
+
expect(logger_io.read).not_to match /Can't send logs to/
|
213
217
|
|
214
218
|
logger.post('tag', {'a' => ('c' * 1000)})
|
215
219
|
logger_io.rewind
|
216
|
-
logger_io.read.
|
220
|
+
expect(logger_io.read).to match /Can't send logs to/
|
217
221
|
end
|
218
222
|
|
219
223
|
it ('log connect error once') do
|
220
|
-
Fluent::Logger::FluentLogger.
|
224
|
+
allow_any_instance_of(Fluent::Logger::FluentLogger).to receive(:suppress_sec).and_return(-1)
|
221
225
|
logger.log_reconnect_error_threshold = 1
|
222
|
-
Fluent::Logger::FluentLogger.
|
226
|
+
expect_any_instance_of(Fluent::Logger::FluentLogger).to receive(:log_reconnect_error).once.and_call_original
|
223
227
|
|
224
228
|
logger.post('tag', {'a' => 'b'})
|
225
229
|
wait_transfer # even if wait
|
226
230
|
logger.post('tag', {'a' => 'b'})
|
227
231
|
wait_transfer # even if wait
|
228
232
|
logger_io.rewind
|
229
|
-
logger_io.read.
|
233
|
+
expect(logger_io.read).to match /Failed to connect/
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
context "when a buffer overflow handler is provided" do
|
238
|
+
class BufferOverflowHandler
|
239
|
+
attr_accessor :buffer
|
240
|
+
|
241
|
+
def flush(messages)
|
242
|
+
@buffer ||= []
|
243
|
+
MessagePack::Unpacker.new.feed_each(messages) do |msg|
|
244
|
+
@buffer << msg
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
let(:handler) { BufferOverflowHandler.new }
|
250
|
+
let(:buffer_overflow_handler) { Proc.new { |messages| handler.flush(messages) } }
|
251
|
+
|
252
|
+
it ('post limit over') do
|
253
|
+
logger.limit = 100
|
254
|
+
event_1 = {'a' => 'b'}
|
255
|
+
logger.post('tag', event_1)
|
256
|
+
wait_transfer # even if wait
|
257
|
+
queue.last.should be_nil
|
258
|
+
|
259
|
+
logger_io.rewind
|
260
|
+
logger_io.read.should_not =~ /Can't send logs to/
|
261
|
+
|
262
|
+
event_2 = {'a' => ('c' * 1000)}
|
263
|
+
logger.post('tag', event_2)
|
264
|
+
logger_io.rewind
|
265
|
+
logger_io.read.should =~ /Can't send logs to/
|
266
|
+
|
267
|
+
buffer = handler.buffer
|
268
|
+
|
269
|
+
buffer[0][0].should == 'logger-test.tag'
|
270
|
+
buffer[0][1].should.to_s =~ /\d{10}/
|
271
|
+
buffer[0][2].should == event_1
|
272
|
+
|
273
|
+
buffer[1][0].should == 'logger-test.tag'
|
274
|
+
buffer[1][1].should.to_s =~ /\d{10}/
|
275
|
+
buffer[1][2].should == event_2
|
230
276
|
end
|
231
277
|
end
|
232
278
|
end
|
data/spec/logger_base_spec.rb
CHANGED
@@ -3,9 +3,21 @@ require 'spec_helper'
|
|
3
3
|
|
4
4
|
describe Fluent::Logger::LoggerBase do
|
5
5
|
context "subclass" do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
let(:subclass) { Class.new(Fluent::Logger::LoggerBase) }
|
7
|
+
let(:other_subclass) { Class.new(Fluent::Logger::LoggerBase) }
|
8
|
+
|
9
|
+
describe ".open" do
|
10
|
+
subject(:open) { subclass.open }
|
11
|
+
|
12
|
+
it { should be_kind_of(Fluent::Logger::LoggerBase) }
|
13
|
+
|
14
|
+
it "changes Fluent::Logger.default" do
|
15
|
+
subclass.open
|
16
|
+
expect(Fluent::Logger.default).to be_kind_of(subclass)
|
17
|
+
|
18
|
+
other_subclass.open
|
19
|
+
expect(Fluent::Logger.default).to be_kind_of(other_subclass)
|
20
|
+
end
|
21
|
+
end
|
10
22
|
end
|
11
23
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-logger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-11-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -181,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
181
181
|
version: '0'
|
182
182
|
requirements: []
|
183
183
|
rubyforge_project:
|
184
|
-
rubygems_version: 2.4.5
|
184
|
+
rubygems_version: 2.4.5.1
|
185
185
|
signing_key:
|
186
186
|
specification_version: 4
|
187
187
|
summary: fluent logger for ruby
|