fluentd 0.12.27 → 0.12.28

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of fluentd might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f6f3ea036e68e5a0a46afbe518b05590fec7addf
4
- data.tar.gz: 1e73ba803fdbceec16d3e7d39f80744b696d271b
3
+ metadata.gz: 648289c24c5bb2d91083867a5e1bfb4199988800
4
+ data.tar.gz: 3415cae010e8d511e7b9ff3ec42cbc1bf2a57729
5
5
  SHA512:
6
- metadata.gz: 8ea885c9bbd62870782c04c8da7e3a29e78fa28c2ecc944d57454cc271238dc11b7d0a9de56c77aaa922871151eba2520133399c48826711d6a2b6d3154c4910
7
- data.tar.gz: 189f245592e68f78d61cda44c7253d7e5ec90a01369adf90e05a463a2a2461e6f26f838635d939b626f317af864d9c13e421db3a3190b6f2d59efd86c9a11567
6
+ metadata.gz: 89a9aab0f91f45d2eee9f6ed210a2788cbbddeb5ca357224f8d357e361ef960b8eaef45ed4f6fcd3b3772306129363698fc734c3fdff76b889a754b02bec4fe8
7
+ data.tar.gz: 5ca47b0c94fd74e29e4f81c7a7f21952c8aa058de62ea6ceb7fe9f4676483ef4e6fb0b7473ce1d018dedf18dec591e7508c5383ee8a6037ad8b495ad1554a8cb
data/ChangeLog CHANGED
@@ -1,5 +1,17 @@
1
1
  # v0.12
2
2
 
3
+ ## Release 0.12.28 - 2016/08/14
4
+
5
+ ### New features / Enhancement
6
+
7
+ * in_forward: Add source_hostname_key parameter
8
+ https://github.com/fluent/fluentd/pull/807
9
+
10
+ ### Bug fixes
11
+
12
+ * parser: Ensure strict mode is used for Oj parser
13
+ https://github.com/fluent/fluentd/pull/1147
14
+
3
15
  ## Release 0.12.27 - 2016/08/03
4
16
 
5
17
  ### New features / Enhancement
@@ -260,7 +260,7 @@ module Fluent
260
260
  begin
261
261
  raise LoadError unless @json_parser == 'oj'
262
262
  require 'oj'
263
- Oj.default_options = {bigdecimal_load: :float}
263
+ Oj.default_options = {bigdecimal_load: :float, mode: :strict}
264
264
  @load_proc = Oj.method(:load)
265
265
  @error_class = Oj::ParseError
266
266
  rescue LoadError
@@ -47,6 +47,8 @@ module Fluent
47
47
  config_param :chunk_size_limit, :size, default: nil
48
48
  desc 'Skip an event if incoming event is invalid.'
49
49
  config_param :skip_invalid_event, :bool, default: false
50
+ desc "The field name of the client's hostname."
51
+ config_param :source_hostname_key, :string, default: nil
50
52
 
51
53
  def configure(conf)
52
54
  super
@@ -133,7 +135,7 @@ module Fluent
133
135
  # 3: object record
134
136
  # 4: object option (optional)
135
137
  # }
136
- def on_message(msg, chunk_size, source)
138
+ def on_message(msg, chunk_size, peeraddr)
137
139
  if msg.nil?
138
140
  # for future TCP heartbeat_request
139
141
  return
@@ -141,7 +143,7 @@ module Fluent
141
143
 
142
144
  # TODO: raise an exception if broken chunk is generated by recoverable situation
143
145
  unless msg.is_a?(Array)
144
- log.warn "incoming chunk is broken:", source: source, msg: msg
146
+ log.warn "incoming chunk is broken:", source: source_message(peeraddr), msg: msg
145
147
  return
146
148
  end
147
149
 
@@ -149,23 +151,24 @@ module Fluent
149
151
  entries = msg[1]
150
152
 
151
153
  if @chunk_size_limit && (chunk_size > @chunk_size_limit)
152
- log.warn "Input chunk size is larger than 'chunk_size_limit', dropped:", tag: tag, source: source, limit: @chunk_size_limit, size: chunk_size
154
+ log.warn "Input chunk size is larger than 'chunk_size_limit', dropped:", tag: tag, source: source_message(peeraddr), limit: @chunk_size_limit, size: chunk_size
153
155
  return
154
156
  elsif @chunk_size_warn_limit && (chunk_size > @chunk_size_warn_limit)
155
- log.warn "Input chunk size is larger than 'chunk_size_warn_limit':", tag: tag, source: source, limit: @chunk_size_warn_limit, size: chunk_size
157
+ log.warn "Input chunk size is larger than 'chunk_size_warn_limit':", tag: tag, source: source_message(peeraddr), limit: @chunk_size_warn_limit, size: chunk_size
156
158
  end
157
159
 
158
160
  if entries.class == String
159
161
  # PackedForward
160
162
  es = MessagePackEventStream.new(entries)
161
- es = check_and_skip_invalid_event(tag, es, source) if @skip_invalid_event
163
+ es = check_and_skip_invalid_event(tag, es, peeraddr) if @skip_invalid_event
164
+ es = add_source_host(es, peeraddr[2]) if @source_hostname_key
162
165
  router.emit_stream(tag, es)
163
166
  option = msg[2]
164
167
 
165
168
  elsif entries.class == Array
166
169
  # Forward
167
170
  es = if @skip_invalid_event
168
- check_and_skip_invalid_event(tag, entries, source)
171
+ check_and_skip_invalid_event(tag, entries, peeraddr)
169
172
  else
170
173
  es = MultiEventStream.new
171
174
  entries.each { |e|
@@ -177,6 +180,7 @@ module Fluent
177
180
  }
178
181
  es
179
182
  end
183
+ es = add_source_host(es, peeraddr[2]) if @source_hostname_key
180
184
  router.emit_stream(tag, es)
181
185
  option = msg[2]
182
186
 
@@ -185,11 +189,12 @@ module Fluent
185
189
  time = msg[1]
186
190
  record = msg[2]
187
191
  if @skip_invalid_event && invalid_event?(tag, time, record)
188
- log.warn "got invalid event and drop it:", source: source, tag: tag, time: time, record: record
192
+ log.warn "got invalid event and drop it:", source: source_message(peeraddr), tag: tag, time: time, record: record
189
193
  return msg[3] # retry never succeeded so return ack and drop incoming event.
190
194
  end
191
195
  return if record.nil?
192
196
  time = Engine.now if time == 0
197
+ record[@source_hostname_key] = peeraddr[2] if @source_hostname_key
193
198
  router.emit(tag, time, record)
194
199
  option = msg[3]
195
200
  end
@@ -202,11 +207,11 @@ module Fluent
202
207
  !(time.is_a?(Integer) && record.is_a?(Hash) && tag.is_a?(String))
203
208
  end
204
209
 
205
- def check_and_skip_invalid_event(tag, es, source)
210
+ def check_and_skip_invalid_event(tag, es, peeraddr)
206
211
  new_es = MultiEventStream.new
207
212
  es.each { |time, record|
208
213
  if invalid_event?(tag, time, record)
209
- log.warn "skip invalid event:", source: source, tag: tag, time: time, record: record
214
+ log.warn "skip invalid event:", source: source_message(peeraddr), tag: tag, time: time, record: record
210
215
  next
211
216
  end
212
217
  new_es.add(time, record)
@@ -214,16 +219,29 @@ module Fluent
214
219
  new_es
215
220
  end
216
221
 
222
+ def add_source_host(es, host)
223
+ new_es = MultiEventStream.new
224
+ es.each { |time, record|
225
+ record[@source_hostname_key] = host
226
+ new_es.add(time, record)
227
+ }
228
+ new_es
229
+ end
230
+
231
+ def source_message(peeraddr)
232
+ _, port, host, addr = peeraddr
233
+ "host: #{host}, addr: #{addr}, port: #{port}"
234
+ end
235
+
217
236
  class Handler < Coolio::Socket
218
237
  PEERADDR_FAILED = ["?", "?", "name resolusion failed", "?"]
219
238
 
220
239
  def initialize(io, linger_timeout, log, on_message)
221
240
  super(io)
222
241
 
242
+ @peeraddr = nil
223
243
  if io.is_a?(TCPSocket) # for unix domain socket support in the future
224
- proto, port, host, addr = ( io.peeraddr rescue PEERADDR_FAILED )
225
- @source = "host: #{host}, addr: #{addr}, port: #{port}"
226
-
244
+ @peeraddr = (io.peeraddr rescue PEERADDR_FAILED)
227
245
  opt = [1, linger_timeout].pack('I!I!') # { int l_onoff; int l_linger; }
228
246
  io.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, opt)
229
247
  end
@@ -252,7 +270,7 @@ module Fluent
252
270
  @serializer = :to_json.to_proc
253
271
  @y = Yajl::Parser.new
254
272
  @y.on_parse_complete = lambda { |obj|
255
- option = @on_message.call(obj, @chunk_counter, @source)
273
+ option = @on_message.call(obj, @chunk_counter, @peeraddr)
256
274
  respond option if option
257
275
  @chunk_counter = 0
258
276
  }
@@ -280,7 +298,7 @@ module Fluent
280
298
  def on_read_msgpack(data)
281
299
  @chunk_counter += data.bytesize
282
300
  @u.feed_each(data) do |obj|
283
- option = @on_message.call(obj, @chunk_counter, @source)
301
+ option = @on_message.call(obj, @chunk_counter, @peeraddr)
284
302
  respond option if option
285
303
  @chunk_counter = 0
286
304
  end
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Fluent
18
18
 
19
- VERSION = '0.12.27'
19
+ VERSION = '0.12.28'
20
20
 
21
21
  end
@@ -17,6 +17,7 @@ class ForwardInputTest < Test::Unit::TestCase
17
17
  port #{PORT}
18
18
  bind 127.0.0.1
19
19
  ]
20
+ PEERADDR = ['?', '0000', '127.0.0.1', '127.0.0.1']
20
21
 
21
22
  def create_driver(conf=CONFIG)
22
23
  Fluent::Test::InputTestDriver.new(Fluent::ForwardInput).configure(conf)
@@ -197,7 +198,7 @@ class ForwardInputTest < Test::Unit::TestCase
197
198
 
198
199
  d.run do
199
200
  Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
200
- d.instance.send(:on_message, obj, chunk.size, "host: 127.0.0.1, addr: 127.0.0.1, port: 0000")
201
+ d.instance.send(:on_message, obj, chunk.size, PEERADDR)
201
202
  end
202
203
  end
203
204
 
@@ -226,7 +227,7 @@ class ForwardInputTest < Test::Unit::TestCase
226
227
 
227
228
  d.run do
228
229
  Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
229
- d.instance.send(:on_message, obj, chunk.size, "host: 127.0.0.1, addr: 127.0.0.1, port: 0000")
230
+ d.instance.send(:on_message, obj, chunk.size, PEERADDR)
230
231
  end
231
232
  end
232
233
 
@@ -253,7 +254,7 @@ class ForwardInputTest < Test::Unit::TestCase
253
254
  # d.run => send_data
254
255
  d.run do
255
256
  Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
256
- d.instance.send(:on_message, obj, chunk.size, "host: 127.0.0.1, addr: 127.0.0.1, port: 0000")
257
+ d.instance.send(:on_message, obj, chunk.size, PEERADDR)
257
258
  end
258
259
  end
259
260
 
@@ -275,7 +276,7 @@ class ForwardInputTest < Test::Unit::TestCase
275
276
 
276
277
  # d.run => send_data
277
278
  d.run do
278
- d.instance.send(:on_message, data, 1000000000, "host: 127.0.0.1, addr: 127.0.0.1, port: 0000")
279
+ d.instance.send(:on_message, data, 1000000000, PEERADDR)
279
280
  end
280
281
 
281
282
  # check emitted data
@@ -391,7 +392,6 @@ class ForwardInputTest < Test::Unit::TestCase
391
392
 
392
393
  assert_equal events, d.emits
393
394
  assert_equal expected_acks, @responses.map { |res| JSON.parse(res)['ack'] }
394
-
395
395
  end
396
396
 
397
397
  def test_not_respond_to_message_not_requiring_ack
@@ -498,5 +498,53 @@ class ForwardInputTest < Test::Unit::TestCase
498
498
  @responses << res if try_to_receive_response
499
499
  end
500
500
 
501
+ # TODO: Use sub_test_case. Currently Errno::EADDRINUSE happens inside sub_test_case
502
+ test 'message protocol with source_hostname_key' do
503
+ execute_test { |events|
504
+ events.each { |tag, time, record|
505
+ send_data [tag, time, record].to_msgpack
506
+ }
507
+ }
508
+ end
509
+
510
+ test 'forward protocol with source_hostname_key' do
511
+ execute_test { |events|
512
+ entries = []
513
+ events.each {|tag,time,record|
514
+ entries << [time, record]
515
+ }
516
+ send_data ['tag1', entries].to_msgpack
517
+ }
518
+ end
519
+
520
+ test 'packed forward protocol with source_hostname_key' do
521
+ execute_test { |events|
522
+ entries = ''
523
+ events.each { |tag, time, record|
524
+ Fluent::Engine.msgpack_factory.packer(entries).write([time, record]).flush
525
+ }
526
+ send_data Fluent::Engine.msgpack_factory.packer.write(["tag1", entries]).to_s
527
+ }
528
+ end
529
+
530
+ def execute_test(&block)
531
+ d = create_driver(CONFIG + 'source_hostname_key source')
532
+
533
+ time = Time.parse("2011-01-02 13:14:15 UTC").to_i
534
+ events = [
535
+ ["tag1", time, {"a"=>1}],
536
+ ["tag1", time, {"a"=>2}]
537
+ ]
538
+ d.expected_emits_length = events.length
539
+
540
+ d.run do
541
+ block.call(events)
542
+ end
543
+
544
+ d.emits.each { |tag, _time, record|
545
+ assert_true record.has_key?('source')
546
+ }
547
+ end
548
+
501
549
  # TODO heartbeat
502
550
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluentd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.27
4
+ version: 0.12.28
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-03 00:00:00.000000000 Z
11
+ date: 2016-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack