fluent-logger 0.8.0 → 0.8.2

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 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