fluent-logger 0.8.0 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: eb07188f881f645087ed46e08dcb033abd3e78f3
4
- data.tar.gz: c5e7715e87ebf4bb7ca5f5a0afb6297d4772011b
2
+ SHA256:
3
+ metadata.gz: 7be5ae39c39ebb27bdeeaa66b1d103cb6e7d8f7d6f0f5073ff5320c333345c37
4
+ data.tar.gz: 6f226c613086aff26729786e088a2923552fd02a8e28ebe88654d1dda068b98f
5
5
  SHA512:
6
- metadata.gz: 44b031f5063e83cac44e704f8a3fe95d1fa8bdf732f68dad096bd6da73b41c31c480412c00c1fe006f9b2bd6285e626f6ab6bc3096115ac559c3961ffd3c9a59
7
- data.tar.gz: d3929bbf74cc3e77fc76149f98a0cd001f34213a715c807290cdc7bdc88df35d4d11d07d963a6a765ad144552ee99fb8cb191d7dce8f28e91e4e4c5c053ef37c
6
+ metadata.gz: 53da0192645010cd5fe3ddc739ff4a6c5784ceb5ddbb8216b25ccd562a176606abfeeb5a9e164d0734e53467b69de749075136c07aebfa02e1da9babfb3f5e1b
7
+ data.tar.gz: db4c2283dc26641cdf4ac727ebb8815fa0e9ce3c0672b0e5bb98030aa83538005d653547551fa1ac954e591013ff1aaefbf1556905e5e4445479492e5b07b6a0
data/ChangeLog CHANGED
@@ -1,3 +1,12 @@
1
+ Release 0.8.2 - 2019/08/21
2
+
3
+ * Block timeout during IO#write to avoid writing invalid bytes
4
+ * Fluent::Logger::EventTime#to_json returns String
5
+
6
+ Release 0.8.1 - 2019/05/30
7
+
8
+ * Improve non-blocking write handling
9
+
1
10
  Release 0.8.0 - 2019/01/25
2
11
 
3
12
  * Add use_nonblock and wait_writeable parameters
@@ -130,4 +139,3 @@ Release 0.2.0 - 2011/08/05
130
139
  Release 0.1.0 - 2011/08/04
131
140
 
132
141
  * First release
133
-
data/README.md CHANGED
@@ -4,6 +4,22 @@
4
4
 
5
5
  A structured event logger
6
6
 
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'fluent-logger'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install fluent-logger
22
+
7
23
  ## Examples
8
24
 
9
25
  ### Simple
@@ -27,6 +43,7 @@ require 'fluent-logger'
27
43
 
28
44
  log = Fluent::Logger::FluentLogger.new(nil, :socket_path => "/tmp/fluent.sock")
29
45
  unless log.post("myapp.access", {"agent" => "foo"})
46
+ # Passed records are stored into logger's internal buffer so don't re-post same event.
30
47
  p log.last_error # You can get last error object via last_error method
31
48
  end
32
49
 
@@ -49,10 +66,17 @@ log.post("access", {"agent" => "foo"})
49
66
  require 'fluent-logger'
50
67
 
51
68
  log = Fluent::Logger::FluentLogger.new(nil, :host => 'localhost', :port => 24224, :use_nonblock => true, :wait_writeable => false)
69
+ # When wait_writeable is false
52
70
  begin
53
71
  log.post("myapp.access", {"agent" => "foo"})
54
72
  rescue IO::EAGAINWaitWritable => e
55
73
  # wait code for avoding "Resource temporarily unavailable"
74
+ # Passed records are stored into logger's internal buffer so don't re-post same event.
75
+ end
76
+
77
+ # When wait_writeable is true
78
+ unless log.post("myapp.access", {"agent" => "foo"})
79
+ # same as other example
56
80
  end
57
81
 
58
82
  # output: myapp.access {"agent":"foo"}
@@ -88,11 +112,11 @@ Use nano second event time instead of epoch. See also "Tips" section.
88
112
 
89
113
  #### use_nonblock (Bool)
90
114
 
91
- Use nonblocking write(`IO#write_nonblock`) instead of normal write(`IO#write`). If `Logger#post` stuck on your environment, specify `true`.
115
+ Use nonblocking write(`IO#write_nonblock`) instead of normal write(`IO#write`). If `Logger#post` stuck on your environment, specify `true`. Default: `false`
92
116
 
93
117
  #### wait_writeable (Bool)
94
118
 
95
- If `true`, `Logger#post` raises an error when nonblocking write gets `EAGAIN`.
119
+ If `false`, `Logger#post` raises an error when nonblocking write gets `EAGAIN` (i.e. `use_nonblock` must be `true`, otherwise this will have no effect). Default: `true`
96
120
 
97
121
  #### buffer_overflow_handler (Proc)
98
122
 
@@ -15,6 +15,7 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
  #
18
+ require 'timeout'
18
19
  require 'msgpack'
19
20
  require 'socket'
20
21
  require 'monitor'
@@ -44,7 +45,7 @@ module Fluent
44
45
  end
45
46
 
46
47
  def to_json(*args)
47
- @sec
48
+ @sec.to_s
48
49
  end
49
50
  end
50
51
 
@@ -126,7 +127,6 @@ module Fluent
126
127
  end
127
128
 
128
129
  attr_accessor :limit, :logger, :log_reconnect_error_threshold
129
- attr_reader :last_error
130
130
 
131
131
  def last_error
132
132
  @last_error[Thread.current.object_id]
@@ -230,7 +230,11 @@ module Fluent
230
230
  end
231
231
 
232
232
  begin
233
- send_data(@pending)
233
+ written = send_data(@pending)
234
+ if @pending.bytesize != written
235
+ raise "Actual written data size(#{written} bytes) is different from the received data size(#{@pending.bytesize} bytes)."
236
+ end
237
+
234
238
  @pending = nil
235
239
  true
236
240
  rescue => e
@@ -255,9 +259,13 @@ module Fluent
255
259
  connect!
256
260
  end
257
261
  if @use_nonblock
258
- @con.write_nonblock data
262
+ send_data_nonblock(data)
259
263
  else
260
- @con.write data
264
+ _, ws = IO.select([], [@con])
265
+ Thread.handle_interrupt(::Timeout::Error => :never) do
266
+ # block timeout error during IO#write
267
+ ws.first.write(data)
268
+ end
261
269
  end
262
270
  #while true
263
271
  # puts "sending #{data.length} bytes"
@@ -272,7 +280,19 @@ module Fluent
272
280
  # end
273
281
  # data = data[n..-1]
274
282
  #end
275
- true
283
+ end
284
+
285
+ def send_data_nonblock(data)
286
+ written = @con.write_nonblock(data)
287
+ remaining = data.bytesize - written
288
+
289
+ while remaining > 0
290
+ len = @con.write_nonblock(data.byteslice(written, remaining))
291
+ remaining -= len
292
+ written += len
293
+ end
294
+
295
+ written
276
296
  end
277
297
 
278
298
  def connect!
@@ -1,5 +1,5 @@
1
1
  module Fluent
2
2
  module Logger
3
- VERSION = '0.8.0'
3
+ VERSION = '0.8.2'
4
4
  end
5
5
  end
@@ -58,6 +58,57 @@ describe Fluent::Logger::FluentLogger do
58
58
  @serverengine.shutdown
59
59
  end
60
60
 
61
+ describe('testing interaction of use_nonblock and wait_writeable') do
62
+ before(:example) do
63
+ allow_any_instance_of(TCPSocket).to receive(:write_nonblock).and_raise(IO::EAGAINWaitWritable)
64
+ allow_any_instance_of(TCPSocket).to receive(:write) { |_, buf| buf.size }
65
+ end
66
+
67
+ context('use_nonblock is false') do
68
+ let(:block_config) { logger_config.merge(use_nonblock: false) }
69
+
70
+ it('post returns true when wait_writeable is false') {
71
+ cfg = block_config.merge(wait_writeable: false)
72
+ l = Fluent::Logger::FluentLogger.new('logger-test', cfg)
73
+ expect(l.post('hello', foo: 'bar')).to eq true
74
+ }
75
+
76
+ it('post returns true when wait_writeable is true') {
77
+ cfg = block_config.merge(wait_writeable: true)
78
+ l = Fluent::Logger::FluentLogger.new('logger-test', cfg)
79
+ expect(l.post('hello', {foo: 'bar'})).to eq true
80
+ }
81
+ end
82
+
83
+ context('use_nonblock is true') do
84
+ let(:nonblock_config) { logger_config.merge(use_nonblock: true) }
85
+
86
+ it('post raises IO::EAGAINWaitWritable when wait_writeable is false') {
87
+ cfg = nonblock_config.merge(wait_writeable: false)
88
+ l = Fluent::Logger::FluentLogger.new('logger-test', cfg)
89
+ expect { l.post('hello', foo: 'bar') }.to raise_error(IO::EAGAINWaitWritable)
90
+ }
91
+
92
+ it('post returns false when wait_writeable is true') {
93
+ cfg = nonblock_config.merge(wait_writeable: true)
94
+ l = Fluent::Logger::FluentLogger.new('logger-test', cfg)
95
+ expect(l.post('hello', {foo: 'bar'})).to eq false
96
+ }
97
+
98
+ context 'when write_nonblock returns the size less than received data' do
99
+ before do
100
+ allow_any_instance_of(TCPSocket).to receive(:write_nonblock).and_return(1) # write 1 bytes per call
101
+ end
102
+
103
+ it 'buffering data and flush at closed time' do
104
+ logger = Fluent::Logger::FluentLogger.new('logger-test', nonblock_config)
105
+ expect(logger.post('hello', foo: 'bar')).to eq(true)
106
+ expect(logger.pending_bytesize).to eq(0)
107
+ end
108
+ end
109
+ end
110
+ end
111
+
61
112
  context('Post by CUI') do
62
113
  it('post') {
63
114
  args = %W(-h localhost -p #{fluentd.port} -t logger-test.tag -v a=b -v foo=bar)
@@ -86,6 +137,16 @@ describe Fluent::Logger::FluentLogger do
86
137
  }
87
138
  end
88
139
 
140
+ context 'when the message has object which does not have #to_msgpack method' do
141
+ it 'success with nanosecond' do
142
+ expect(logger_with_nanosec.pending_bytesize).to eq(0)
143
+ expect(logger_with_nanosec.post('tag', 'a' => Errno::ETIMEDOUT)).to eq(true)
144
+ fluentd.wait_transfer
145
+ expect(fluentd.queue.last).to eq(['logger-test.tag', { 'a' => 'Errno::ETIMEDOUT' }])
146
+ expect(logger_with_nanosec.pending_bytesize).to eq(0)
147
+ end
148
+ end
149
+
89
150
  it ('close after post') {
90
151
  expect(logger).to be_connect
91
152
  logger.close
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.8.0
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-25 00:00:00.000000000 Z
11
+ date: 2019-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -161,8 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
161
161
  - !ruby/object:Gem::Version
162
162
  version: '0'
163
163
  requirements: []
164
- rubyforge_project:
165
- rubygems_version: 2.6.14.1
164
+ rubygems_version: 3.0.3
166
165
  signing_key:
167
166
  specification_version: 4
168
167
  summary: fluent logger for ruby