fluentd 0.10.30 → 0.10.31

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.

data/ChangeLog CHANGED
@@ -1,4 +1,12 @@
1
1
 
2
+ Release 0.10.31 - 2013/01/31
3
+
4
+ * out_forward: supports TCP heartbeat
5
+ * in_tail reads rotated files from its head rather than its end when pos_file option is set
6
+ * out_/in_ forward set O_NONBLOCK flag to the UDP heartbeat socket
7
+ * Improved match cache expiration algorithm
8
+
9
+
2
10
  Release 0.10.30 - 2012/12/06
3
11
 
4
12
  * Shows configuration file at start time
@@ -52,7 +52,7 @@ An event consists of *tag*, *time* and *record*. Tag is a string separated with
52
52
  == Meta
53
53
 
54
54
  Web site:: http://fluentd.org/
55
- Documents:: http://fluentd.org/doc/
55
+ Documents:: http://docs.fluentd.org/
56
56
  Source repository:: http://github.com/fluent
57
57
  Discussion:: http://groups.google.com/group/fluentd
58
58
  Author:: Sadayuki Furuhashi
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.10.30
1
+ 0.10.31
@@ -23,10 +23,13 @@ class EngineClass
23
23
  @matches = []
24
24
  @sources = []
25
25
  @match_cache = {}
26
+ @match_cache_keys = []
26
27
  @started = []
27
28
  @default_loop = nil
28
29
  end
29
30
 
31
+ MATCH_CACHE_SIZE = 1024
32
+
30
33
  attr_reader :matches, :sources
31
34
 
32
35
  def init
@@ -106,9 +109,13 @@ class EngineClass
106
109
  target = @match_cache[tag]
107
110
  unless target
108
111
  target = match(tag) || NoMatchMatch.new
109
- if @match_cache.size < 1024 # TODO size limit
110
- @match_cache[tag] = target
112
+ # this is not thread-safe but inconsistency doesn't
113
+ # cause serious problems while locking causes.
114
+ if @match_cache_keys.size >= MATCH_CACHE_SIZE
115
+ @match_cache_keys.delete @match_cache_keys.shift
111
116
  end
117
+ @match_cache[tag] = target
118
+ @match_cache_keys << tag
112
119
  end
113
120
  target.emit(tag, es)
114
121
  rescue
@@ -65,7 +65,7 @@ class ArrayEventStream < EventStream
65
65
  end
66
66
 
67
67
  def empty?
68
- @time_array.empty?
68
+ @entries.empty?
69
69
  end
70
70
 
71
71
  def each(&block)
@@ -1,5 +1,6 @@
1
1
  require 'thread'
2
2
  require 'socket'
3
+ require 'fcntl'
3
4
  require 'time'
4
5
  require 'monitor'
5
6
  require 'stringio'
@@ -141,19 +141,8 @@ class OutputThread
141
141
  }
142
142
  end
143
143
 
144
- if ConditionVariable.new.method(:wait).arity == 1
145
- $log.warn "WARNING: Running on Ruby 1.8. Ruby 1.9 is recommended."
146
- require 'timeout'
147
- def cond_wait(sec)
148
- Timeout.timeout(sec) {
149
- @cond.wait(@mutex)
150
- }
151
- rescue Timeout::Error
152
- end
153
- else
154
- def cond_wait(sec)
155
- @cond.wait(@mutex, sec)
156
- end
144
+ def cond_wait(sec)
145
+ @cond.wait(@mutex, sec)
157
146
  end
158
147
  end
159
148
 
@@ -213,7 +213,7 @@ class TextParser
213
213
  regexp = regexp_or_proc
214
214
  factory = Proc.new { RegexpParser.new(regexp, {'time_format'=>time_format}) }
215
215
  else
216
- factory = Proc.new { regexp_or_proc }
216
+ factory = regexp_or_proc
217
217
  end
218
218
 
219
219
  TEMPLATE_FACTORIES[name] = factory
@@ -41,6 +41,7 @@ class ForwardInput < Input
41
41
 
42
42
  @usock = SocketUtil.create_udp_socket(@bind)
43
43
  @usock.bind(@bind, @port)
44
+ @usock.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
44
45
  @hbr = HeartbeatRequestHandler.new(@usock, method(:on_heartbeat_request))
45
46
  @loop.attach(@hbr)
46
47
 
@@ -102,6 +103,11 @@ class ForwardInput < Input
102
103
  # 3: object record
103
104
  # }
104
105
  def on_message(msg)
106
+ if msg.nil?
107
+ # for future TCP heartbeat_request
108
+ return
109
+ end
110
+
105
111
  # TODO format error
106
112
  tag = msg[0].to_s
107
113
  entries = msg[1]
@@ -191,7 +197,11 @@ class ForwardInput < Input
191
197
  end
192
198
 
193
199
  def on_readable
194
- msg, addr = @io.recvfrom(1024)
200
+ begin
201
+ msg, addr = @io.recvfrom(1024)
202
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINTR
203
+ return
204
+ end
195
205
  host = addr[3]
196
206
  port = addr[1]
197
207
  @callback.call(host, port, msg)
@@ -202,7 +212,10 @@ class ForwardInput < Input
202
212
 
203
213
  def on_heartbeat_request(host, port, msg)
204
214
  #$log.trace "heartbeat request from #{host}:#{port}"
205
- @usock.send "\0", 0, host, port
215
+ begin
216
+ @usock.send "\0", 0, host, port
217
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINTR
218
+ end
206
219
  end
207
220
  end
208
221
 
@@ -77,7 +77,6 @@ class SyslogInput < Input
77
77
 
78
78
  parser = TextParser.new
79
79
  if parser.configure(conf, false)
80
- parser.use_template('syslog')
81
80
  @parser = parser
82
81
  else
83
82
  @parser = nil
@@ -191,12 +191,22 @@ class TailInput < Input
191
191
  stat = io.stat
192
192
  fsize = stat.size
193
193
  inode = stat.ino
194
- if inode == @pe.read_inode
194
+
195
+ last_inode = @pe.read_inode
196
+ if inode == last_inode
195
197
  # seek to the saved position
196
198
  pos = @pe.read_pos
199
+ elsif last_inode != 0
200
+ # this is FilePositionEntry and fluentd once started.
201
+ # read data from the head of the rotated file.
202
+ # logs never duplicate because this file is a rotated new file.
203
+ pos = 0
204
+ @pe.update(inode, pos)
197
205
  else
198
- # seek to the end of the file.
199
- # logs never duplicate but may be lost if fluentd is down.
206
+ # this is MemoryPositionEntry or this is the first time fluentd started.
207
+ # seek to the end of the any files.
208
+ # logs may duplicate without this seek because it's not sure the file is
209
+ # existent file or rotated new file.
200
210
  pos = fsize
201
211
  @pe.update(inode, pos)
202
212
  end
@@ -30,6 +30,16 @@ class ForwardOutput < ObjectBufferedOutput
30
30
  end
31
31
 
32
32
  config_param :send_timeout, :time, :default => 60
33
+ config_param :heartbeat_type, :default => :udp do |val|
34
+ case val.downcase
35
+ when 'tcp'
36
+ :tcp
37
+ when 'udp'
38
+ :udp
39
+ else
40
+ raise ConfigError, "forward output heartbeat type should be 'tcp' or 'udp'"
41
+ end
42
+ end
33
43
  config_param :heartbeat_interval, :time, :default => 1
34
44
  config_param :recover_wait, :time, :default => 10
35
45
  config_param :hard_timeout, :time, :default => 60
@@ -89,10 +99,13 @@ class ForwardOutput < ObjectBufferedOutput
89
99
 
90
100
  @loop = Coolio::Loop.new
91
101
 
92
- # Assume all hosts are same protocol.
93
- @usock = SocketUtil.create_udp_socket(@nodes.first.host)
94
- @hb = HeartbeatHandler.new(@usock, method(:on_heartbeat))
95
- @loop.attach(@hb)
102
+ if @heartbeat_type == :udp
103
+ # assuming all hosts use udp
104
+ @usock = SocketUtil.create_udp_socket(@nodes.first.host)
105
+ @usock.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
106
+ @hb = HeartbeatHandler.new(@usock, method(:on_heartbeat))
107
+ @loop.attach(@hb)
108
+ end
96
109
 
97
110
  @timer = HeartbeatRequestTimer.new(@heartbeat_interval, method(:on_timer))
98
111
  @loop.attach(@timer)
@@ -105,7 +118,7 @@ class ForwardOutput < ObjectBufferedOutput
105
118
  @loop.watchers.each {|w| w.detach }
106
119
  @loop.stop
107
120
  @thread.join
108
- @usock.close
121
+ @usock.close if @usock
109
122
  end
110
123
 
111
124
  def run
@@ -196,6 +209,22 @@ class ForwardOutput < ObjectBufferedOutput
196
209
  # MessagePack FixArray length = 2
197
210
  FORWARD_HEADER = [0x92].pack('C')
198
211
 
212
+ #FORWARD_TCP_HEARTBEAT_DATA = FORWARD_HEADER + ''.to_msgpack + [].to_msgpack
213
+ def send_heartbeat_tcp(node)
214
+ sock = connect(node)
215
+ begin
216
+ opt = [1, @send_timeout.to_i].pack('I!I!') # { int l_onoff; int l_linger; }
217
+ sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, opt)
218
+ opt = [@send_timeout.to_i, 0].pack('L!L!') # struct timeval
219
+ # don't send any data to not cause a compatibility problem
220
+ #sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, opt)
221
+ #sock.write FORWARD_TCP_HEARTBEAT_DATA
222
+ node.heartbeat(true)
223
+ ensure
224
+ sock.close
225
+ end
226
+ end
227
+
199
228
  def send_data(node, tag, es)
200
229
  sock = connect(node)
201
230
  begin
@@ -258,9 +287,13 @@ class ForwardOutput < ObjectBufferedOutput
258
287
  rebuild_weight_array
259
288
  end
260
289
  begin
261
- #$log.trace "sending heartbeat #{n.host}:#{n.port}"
262
- @usock.send "\0", 0, Socket.pack_sockaddr_in(n.port, n.resolved_host)
263
- rescue
290
+ #$log.trace "sending heartbeat #{n.host}:#{n.port} on #{@heartbeat_type}"
291
+ if @heartbeat_type == :tcp
292
+ send_heartbeat_tcp(n)
293
+ else
294
+ @usock.send "\0", 0, Socket.pack_sockaddr_in(n.port, n.resolved_host)
295
+ end
296
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINTR
264
297
  # TODO log
265
298
  $log.debug "failed to send heartbeat packet to #{n.host}:#{n.port}", :error=>$!.to_s
266
299
  end
@@ -275,7 +308,11 @@ class ForwardOutput < ObjectBufferedOutput
275
308
  end
276
309
 
277
310
  def on_readable
278
- msg, addr = @io.recvfrom(1024)
311
+ begin
312
+ msg, addr = @io.recvfrom(1024)
313
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINTR
314
+ return
315
+ end
279
316
  host = addr[3]
280
317
  port = addr[1]
281
318
  sockaddr = Socket.pack_sockaddr_in(port, host)
@@ -496,4 +533,3 @@ end
496
533
 
497
534
 
498
535
  end
499
-
@@ -1,5 +1,5 @@
1
1
  module Fluent
2
2
 
3
- VERSION = '0.10.30'
3
+ VERSION = '0.10.31'
4
4
 
5
5
  end
@@ -7,5 +7,15 @@ class Test::Unit::TestCase
7
7
  include RR::Adapters::TestUnit
8
8
  end
9
9
 
10
- $log = Fluent::Log.new(STDOUT, Fluent::Log::LEVEL_WARN)
10
+ def ipv6_enabled?
11
+ require 'socket'
12
+
13
+ begin
14
+ TCPServer.open("::1", 0)
15
+ true
16
+ rescue
17
+ false
18
+ end
19
+ end
11
20
 
21
+ $log = Fluent::Log.new(STDOUT, Fluent::Log::LEVEL_WARN)
@@ -1,4 +1,5 @@
1
1
  require 'fluent/test'
2
+ require 'helper'
2
3
 
3
4
  class SyslogInputTest < Test::Unit::TestCase
4
5
  def setup
@@ -23,7 +24,10 @@ class SyslogInputTest < Test::Unit::TestCase
23
24
  end
24
25
 
25
26
  def test_configure
26
- {'127.0.0.1' => CONFIG, '::1' => IPv6_CONFIG}.each_pair { |k, v|
27
+ configs = {'127.0.0.1' => CONFIG}
28
+ configs.merge!('::1' => IPv6_CONFIG) if ipv6_enabled?
29
+
30
+ configs.each_pair { |k, v|
27
31
  d = create_driver(v)
28
32
  assert_equal 9911, d.instance.port
29
33
  assert_equal k, d.instance.bind
@@ -31,7 +35,10 @@ class SyslogInputTest < Test::Unit::TestCase
31
35
  end
32
36
 
33
37
  def test_time_format
34
- {'127.0.0.1' => CONFIG, '::1' => IPv6_CONFIG}.each_pair { |k, v|
38
+ configs = {'127.0.0.1' => CONFIG}
39
+ configs.merge!('::1' => IPv6_CONFIG) if ipv6_enabled?
40
+
41
+ configs.each_pair { |k, v|
35
42
  d = create_driver(v)
36
43
 
37
44
  tests = [
@@ -26,10 +26,16 @@ class ForwardOutputTest < Test::Unit::TestCase
26
26
  d = create_driver
27
27
  nodes = d.instance.nodes
28
28
  assert_equal 51, d.instance.send_timeout
29
+ assert_equal :udp, d.instance.heartbeat_type
29
30
  assert_equal 1, nodes.length
30
31
  node = nodes.first
31
32
  assert_equal "test", node.name
32
33
  assert_equal '127.0.0.1', node.host
33
34
  assert_equal 13999, node.port
34
35
  end
36
+
37
+ def test_configure_tcp_heartbeat
38
+ d = create_driver(CONFIG + "\nheartbeat_type tcp")
39
+ assert_equal :tcp, d.instance.heartbeat_type
40
+ end
35
41
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluentd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.30
4
+ version: 0.10.31
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-06 00:00:00.000000000 Z
12
+ date: 2013-01-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: msgpack