fluentd 0.12.20 → 0.12.21

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.

Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +23 -0
  3. data/Rakefile +2 -2
  4. data/bin/fluent-debug +0 -1
  5. data/lib/fluent/agent.rb +12 -9
  6. data/lib/fluent/buffer.rb +9 -3
  7. data/lib/fluent/command/bundler_injection.rb +2 -0
  8. data/lib/fluent/command/cat.rb +1 -1
  9. data/lib/fluent/command/debug.rb +3 -2
  10. data/lib/fluent/command/fluentd.rb +3 -1
  11. data/lib/fluent/config.rb +4 -5
  12. data/lib/fluent/config/basic_parser.rb +3 -4
  13. data/lib/fluent/config/configure_proxy.rb +2 -0
  14. data/lib/fluent/config/dsl.rb +3 -0
  15. data/lib/fluent/config/element.rb +3 -2
  16. data/lib/fluent/config/literal_parser.rb +8 -5
  17. data/lib/fluent/config/parser.rb +5 -3
  18. data/lib/fluent/config/section.rb +3 -3
  19. data/lib/fluent/config/types.rb +44 -50
  20. data/lib/fluent/config/v1_parser.rb +8 -6
  21. data/lib/fluent/configurable.rb +8 -6
  22. data/lib/fluent/engine.rb +23 -11
  23. data/lib/fluent/event.rb +2 -0
  24. data/lib/fluent/event_router.rb +4 -2
  25. data/lib/fluent/filter.rb +6 -0
  26. data/lib/fluent/formatter.rb +27 -25
  27. data/lib/fluent/input.rb +5 -0
  28. data/lib/fluent/label.rb +2 -2
  29. data/lib/fluent/log.rb +5 -2
  30. data/lib/fluent/mixin.rb +4 -2
  31. data/lib/fluent/output.rb +45 -31
  32. data/lib/fluent/parser.rb +35 -25
  33. data/lib/fluent/plugin.rb +4 -0
  34. data/lib/fluent/plugin/buf_file.rb +9 -2
  35. data/lib/fluent/plugin/buf_memory.rb +7 -1
  36. data/lib/fluent/plugin/exec_util.rb +7 -2
  37. data/lib/fluent/plugin/filter_grep.rb +6 -3
  38. data/lib/fluent/plugin/filter_record_transformer.rb +52 -51
  39. data/lib/fluent/plugin/filter_stdout.rb +4 -1
  40. data/lib/fluent/plugin/in_debug_agent.rb +7 -5
  41. data/lib/fluent/plugin/in_dummy.rb +8 -3
  42. data/lib/fluent/plugin/in_exec.rb +16 -10
  43. data/lib/fluent/plugin/in_forward.rb +18 -11
  44. data/lib/fluent/plugin/in_gc_stat.rb +6 -2
  45. data/lib/fluent/plugin/in_http.rb +23 -14
  46. data/lib/fluent/plugin/in_monitor_agent.rb +24 -17
  47. data/lib/fluent/plugin/in_object_space.rb +9 -4
  48. data/lib/fluent/plugin/in_stream.rb +15 -6
  49. data/lib/fluent/plugin/in_syslog.rb +18 -12
  50. data/lib/fluent/plugin/in_tail.rb +61 -40
  51. data/lib/fluent/plugin/in_tcp.rb +3 -1
  52. data/lib/fluent/plugin/in_udp.rb +1 -1
  53. data/lib/fluent/plugin/out_copy.rb +5 -1
  54. data/lib/fluent/plugin/out_exec.rb +9 -6
  55. data/lib/fluent/plugin/out_exec_filter.rb +32 -25
  56. data/lib/fluent/plugin/out_file.rb +11 -5
  57. data/lib/fluent/plugin/out_forward.rb +30 -24
  58. data/lib/fluent/plugin/out_null.rb +2 -0
  59. data/lib/fluent/plugin/out_relabel.rb +2 -0
  60. data/lib/fluent/plugin/out_roundrobin.rb +3 -0
  61. data/lib/fluent/plugin/out_stdout.rb +3 -1
  62. data/lib/fluent/plugin/out_stream.rb +8 -8
  63. data/lib/fluent/plugin/socket_util.rb +12 -10
  64. data/lib/fluent/process.rb +14 -8
  65. data/lib/fluent/registry.rb +2 -2
  66. data/lib/fluent/root_agent.rb +16 -12
  67. data/lib/fluent/rpc.rb +7 -7
  68. data/lib/fluent/supervisor.rb +35 -69
  69. data/lib/fluent/system_config.rb +98 -0
  70. data/lib/fluent/test.rb +1 -1
  71. data/lib/fluent/test/base.rb +6 -1
  72. data/lib/fluent/test/filter_test.rb +4 -0
  73. data/lib/fluent/test/formatter_test.rb +3 -2
  74. data/lib/fluent/test/input_test.rb +6 -0
  75. data/lib/fluent/test/output_test.rb +4 -0
  76. data/lib/fluent/test/parser_test.rb +3 -2
  77. data/lib/fluent/timezone.rb +2 -0
  78. data/lib/fluent/version.rb +1 -1
  79. data/test/config/test_configurable.rb +11 -11
  80. data/test/config/test_configure_proxy.rb +1 -1
  81. data/test/config/test_system_config.rb +5 -5
  82. data/test/config/test_types.rb +70 -0
  83. data/test/plugin/test_filter_record_transformer.rb +72 -55
  84. data/test/plugin/test_in_forward.rb +4 -0
  85. data/test/plugin/test_in_tail.rb +73 -2
  86. data/test/test_config.rb +2 -2
  87. data/test/test_event_router.rb +1 -0
  88. data/test/test_output.rb +27 -3
  89. data/test/test_plugin_classes.rb +3 -0
  90. data/test/test_process.rb +1 -0
  91. data/test/test_root_agent.rb +5 -3
  92. metadata +3 -2
@@ -14,10 +14,19 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
+ require 'fileutils'
18
+ require 'socket'
19
+
20
+ require 'cool.io'
21
+ require 'yajl'
22
+
23
+ require 'fluent/input'
24
+ require 'fluent/event'
25
+
17
26
  module Fluent
18
27
  # obsolete
19
28
  class StreamInput < Input
20
- config_param :blocking_timeout, :time, :default => 0.5
29
+ config_param :blocking_timeout, :time, default: 0.5
21
30
 
22
31
  def initialize
23
32
  require 'socket'
@@ -45,7 +54,7 @@ module Fluent
45
54
  def run
46
55
  @loop.run(@blocking_timeout)
47
56
  rescue
48
- log.error "unexpected error", :error=>$!.to_s
57
+ log.error "unexpected error", error: $!.to_s
49
58
  log.error_backtrace
50
59
  end
51
60
 
@@ -142,7 +151,7 @@ module Fluent
142
151
  def on_read_json(data)
143
152
  @y << data
144
153
  rescue
145
- @log.error "unexpected error", :error=>$!.to_s
154
+ @log.error "unexpected error", error: $!.to_s
146
155
  @log.error_backtrace
147
156
  close
148
157
  end
@@ -150,7 +159,7 @@ module Fluent
150
159
  def on_read_msgpack(data)
151
160
  @u.feed_each(data, &@on_message)
152
161
  rescue
153
- @log.error "unexpected error", :error=>$!.to_s
162
+ @log.error "unexpected error", error: $!.to_s
154
163
  @log.error_backtrace
155
164
  close
156
165
  end
@@ -165,9 +174,9 @@ module Fluent
165
174
  Plugin.register_input('unix', self)
166
175
 
167
176
  desc 'The path to your Unix Domain Socket.'
168
- config_param :path, :string, :default => DEFAULT_SOCKET_PATH
177
+ config_param :path, :string, default: DEFAULT_SOCKET_PATH
169
178
  desc 'The backlog of Unix Domain Socket.'
170
- config_param :backlog, :integer, :default => nil
179
+ config_param :backlog, :integer, default: nil
171
180
 
172
181
  def configure(conf)
173
182
  super
@@ -14,6 +14,13 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
+ require 'cool.io'
18
+ require 'yajl'
19
+
20
+ require 'fluent/input'
21
+ require 'fluent/config/error'
22
+ require 'fluent/parser'
23
+
17
24
  module Fluent
18
25
  class SyslogInput < Input
19
26
  Plugin.register_input('syslog', self)
@@ -60,18 +67,17 @@ module Fluent
60
67
 
61
68
  def initialize
62
69
  super
63
- require 'cool.io'
64
70
  require 'fluent/plugin/socket_util'
65
71
  end
66
72
 
67
73
  desc 'The port to listen to.'
68
- config_param :port, :integer, :default => 5140
74
+ config_param :port, :integer, default: 5140
69
75
  desc 'The bind address to listen to.'
70
- config_param :bind, :string, :default => '0.0.0.0'
76
+ config_param :bind, :string, default: '0.0.0.0'
71
77
  desc 'The prefix of the tag. The tag itself is generated by the tag prefix, facility level, and priority.'
72
78
  config_param :tag, :string
73
79
  desc 'The transport protocol used to receive logs.(udp, tcp)'
74
- config_param :protocol_type, :default => :udp do |val|
80
+ config_param :protocol_type, default: :udp do |val|
75
81
  case val.downcase
76
82
  when 'tcp'
77
83
  :tcp
@@ -82,10 +88,10 @@ module Fluent
82
88
  end
83
89
  end
84
90
  desc 'If true, add source host to event record.'
85
- config_param :include_source_host, :bool, :default => false
91
+ config_param :include_source_host, :bool, default: false
86
92
  desc 'Specify key of source host when include_source_host is true.'
87
- config_param :source_host_key, :string, :default => 'source_host'.freeze
88
- config_param :blocking_timeout, :time, :default => 0.5
93
+ config_param :source_host_key, :string, default: 'source_host'.freeze
94
+ config_param :blocking_timeout, :time, default: 0.5
89
95
 
90
96
  def configure(conf)
91
97
  super
@@ -125,7 +131,7 @@ module Fluent
125
131
  def run
126
132
  @loop.run(@blocking_timeout)
127
133
  rescue
128
- log.error "unexpected error", :error=>$!.to_s
134
+ log.error "unexpected error", error: $!.to_s
129
135
  log.error_backtrace
130
136
  end
131
137
 
@@ -150,14 +156,14 @@ module Fluent
150
156
  emit(pri, time, record)
151
157
  }
152
158
  rescue => e
153
- log.error data.dump, :error => e.to_s
159
+ log.error data.dump, error: e.to_s
154
160
  log.error_backtrace
155
161
  end
156
162
 
157
163
  def receive_data(data, addr)
158
164
  @parser.parse(data) { |time, record|
159
165
  unless time && record
160
- log.warn "invalid syslog message", :data => data
166
+ log.warn "invalid syslog message", data: data
161
167
  return
162
168
  end
163
169
 
@@ -166,7 +172,7 @@ module Fluent
166
172
  emit(pri, time, record)
167
173
  }
168
174
  rescue => e
169
- log.error data.dump, :error => e.to_s
175
+ log.error data.dump, error: e.to_s
170
176
  log.error_backtrace
171
177
  end
172
178
 
@@ -192,7 +198,7 @@ module Fluent
192
198
 
193
199
  router.emit(tag, time, record)
194
200
  rescue => e
195
- log.error "syslog failed to emit", :error => e.to_s, :error_class => e.class.to_s, :tag => tag, :record => Yajl.dump(record)
201
+ log.error "syslog failed to emit", error: e.to_s, error_class: e.class.to_s, tag: tag, record: Yajl.dump(record)
196
202
  end
197
203
  end
198
204
  end
@@ -14,6 +14,12 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
+ require 'cool.io'
18
+
19
+ require 'fluent/input'
20
+ require 'fluent/config/error'
21
+ require 'fluent/event'
22
+
17
23
  module Fluent
18
24
  class NewTailInput < Input
19
25
  Plugin.register_input('tail', self)
@@ -29,19 +35,21 @@ module Fluent
29
35
  desc 'The tag of the event.'
30
36
  config_param :tag, :string
31
37
  desc 'The paths to exclude the files from watcher list.'
32
- config_param :exclude_path, :array, :default => []
38
+ config_param :exclude_path, :array, default: []
33
39
  desc 'Specify interval to keep reference to old file when rotate a file.'
34
- config_param :rotate_wait, :time, :default => 5
40
+ config_param :rotate_wait, :time, default: 5
35
41
  desc 'Fluentd will record the position it last read into this file.'
36
- config_param :pos_file, :string, :default => nil
42
+ config_param :pos_file, :string, default: nil
37
43
  desc 'Start to read the logs from the head of file, not bottom.'
38
- config_param :read_from_head, :bool, :default => false
44
+ config_param :read_from_head, :bool, default: false
39
45
  desc 'The interval of refreshing the list of watch file.'
40
- config_param :refresh_interval, :time, :default => 60
46
+ config_param :refresh_interval, :time, default: 60
41
47
  desc 'The number of reading lines at each IO.'
42
- config_param :read_lines_limit, :integer, :default => 1000
48
+ config_param :read_lines_limit, :integer, default: 1000
43
49
  desc 'The interval of flushing the buffer for multiline format'
44
- config_param :multiline_flush_interval, :time, :default => nil
50
+ config_param :multiline_flush_interval, :time, default: nil
51
+ desc 'Enable the additional watch timer.'
52
+ config_param :enable_watch_timer, :bool, default: true
45
53
 
46
54
  attr_reader :paths
47
55
 
@@ -150,7 +158,7 @@ module Fluent
150
158
 
151
159
  def setup_watcher(path, pe)
152
160
  line_buffer_timer_flusher = (@multiline_mode && @multiline_flush_interval) ? TailWatcher::LineBufferTimerFlusher.new(log, @multiline_flush_interval, &method(:flush_buffer)) : nil
153
- tw = TailWatcher.new(path, @rotate_wait, pe, log, @read_from_head, @read_lines_limit, method(:update_watcher), line_buffer_timer_flusher, &method(:receive_lines))
161
+ tw = TailWatcher.new(path, @rotate_wait, pe, log, @read_from_head, @enable_watch_timer, @read_lines_limit, method(:update_watcher), line_buffer_timer_flusher, &method(:receive_lines))
154
162
  tw.attach(@loop)
155
163
  tw
156
164
  end
@@ -232,10 +240,11 @@ module Fluent
232
240
  def run
233
241
  @loop.run
234
242
  rescue
235
- log.error "unexpected error", :error=>$!.to_s
243
+ log.error "unexpected error", error: $!.to_s
236
244
  log.error_backtrace
237
245
  end
238
246
 
247
+ # @return true if no error or unrecoverable error happens in emit action. false if got BufferQueueLimitError
239
248
  def receive_lines(lines, tail_watcher)
240
249
  es = @receive_handler.call(lines, tail_watcher)
241
250
  unless es.empty?
@@ -246,10 +255,15 @@ module Fluent
246
255
  end
247
256
  begin
248
257
  router.emit_stream(tag, es)
258
+ rescue BufferQueueLimitError
259
+ return false
249
260
  rescue
250
- # ignore errors. Engine shows logs and backtraces.
261
+ # ignore non BufferQueueLimitError errors because in_tail can't recover. Engine shows logs and backtraces.
262
+ return true
251
263
  end
252
264
  end
265
+
266
+ return true
253
267
  end
254
268
 
255
269
  def convert_line_to_event(line, es)
@@ -263,7 +277,7 @@ module Fluent
263
277
  end
264
278
  }
265
279
  rescue => e
266
- log.warn line.dump, :error => e.to_s
280
+ log.warn line.dump, error: e.to_s
267
281
  log.debug_backtrace(e.backtrace)
268
282
  end
269
283
  end
@@ -312,16 +326,18 @@ module Fluent
312
326
  end
313
327
 
314
328
  class TailWatcher
315
- def initialize(path, rotate_wait, pe, log, read_from_head, read_lines_limit, update_watcher, line_buffer_timer_flusher, &receive_lines)
329
+ def initialize(path, rotate_wait, pe, log, read_from_head, enable_watch_timer, read_lines_limit, update_watcher, line_buffer_timer_flusher, &receive_lines)
316
330
  @path = path
317
331
  @rotate_wait = rotate_wait
318
332
  @pe = pe || MemoryPositionEntry.new
319
333
  @read_from_head = read_from_head
334
+ @enable_watch_timer = enable_watch_timer
320
335
  @read_lines_limit = read_lines_limit
321
336
  @receive_lines = receive_lines
322
337
  @update_watcher = update_watcher
323
338
 
324
- @timer_trigger = TimerWatcher.new(1, true, log, &method(:on_notify))
339
+ @timer_trigger = TimerWatcher.new(1, true, log, &method(:on_notify)) if @enable_watch_timer
340
+
325
341
  @stat_trigger = StatWatcher.new(path, log, &method(:on_notify))
326
342
 
327
343
  @rotate_handler = RotateHandler.new(path, log, &method(:on_rotate))
@@ -344,13 +360,13 @@ module Fluent
344
360
  end
345
361
 
346
362
  def attach(loop)
347
- @timer_trigger.attach(loop)
363
+ @timer_trigger.attach(loop) if @enable_watch_timer
348
364
  @stat_trigger.attach(loop)
349
365
  on_notify
350
366
  end
351
367
 
352
368
  def detach
353
- @timer_trigger.detach if @timer_trigger.attached?
369
+ @timer_trigger.detach if @enable_watch_timer && @timer_trigger.attached?
354
370
  @stat_trigger.detach if @stat_trigger.attached?
355
371
  end
356
372
 
@@ -503,6 +519,7 @@ module Fluent
503
519
  @receive_lines = receive_lines
504
520
  @buffer = ''.force_encoding('ASCII-8BIT')
505
521
  @iobuf = ''.force_encoding('ASCII-8BIT')
522
+ @lines = []
506
523
  end
507
524
 
508
525
  attr_reader :io
@@ -510,31 +527,36 @@ module Fluent
510
527
 
511
528
  def on_notify
512
529
  begin
513
- lines = []
514
530
  read_more = false
515
531
 
516
- begin
517
- while true
518
- if @buffer.empty?
519
- @io.read_nonblock(2048, @buffer)
520
- else
521
- @buffer << @io.read_nonblock(2048, @iobuf)
522
- end
523
- while line = @buffer.slice!(/.*?\n/m)
524
- lines << line
525
- end
526
- if lines.size >= @read_lines_limit
527
- # not to use too much memory in case the file is very large
528
- read_more = true
529
- break
532
+ if @lines.empty?
533
+ begin
534
+ while true
535
+ if @buffer.empty?
536
+ @io.readpartial(2048, @buffer)
537
+ else
538
+ @buffer << @io.readpartial(2048, @iobuf)
539
+ end
540
+ while line = @buffer.slice!(/.*?\n/m)
541
+ @lines << line
542
+ end
543
+ if @lines.size >= @read_lines_limit
544
+ # not to use too much memory in case the file is very large
545
+ read_more = true
546
+ break
547
+ end
530
548
  end
549
+ rescue EOFError
531
550
  end
532
- rescue EOFError
533
551
  end
534
552
 
535
- unless lines.empty?
536
- @receive_lines.call(lines)
537
- @pe.update_pos(@io.pos - @buffer.bytesize)
553
+ unless @lines.empty?
554
+ if @receive_lines.call(@lines)
555
+ @pe.update_pos(@io.pos - @buffer.bytesize)
556
+ @lines.clear
557
+ else
558
+ read_more = false
559
+ end
538
560
  end
539
561
  end while read_more
540
562
 
@@ -574,8 +596,7 @@ module Fluent
574
596
 
575
597
  def on_notify
576
598
  begin
577
- io = File.open(@path)
578
- stat = io.stat
599
+ stat = File.stat(@path)
579
600
  inode = stat.ino
580
601
  fsize = stat.size
581
602
  rescue Errno::ENOENT
@@ -587,14 +608,14 @@ module Fluent
587
608
  begin
588
609
  if @inode != inode || fsize < @fsize
589
610
  # rotated or truncated
611
+ begin
612
+ io = File.open(@path)
613
+ rescue Errno::ENOENT
614
+ end
590
615
  @on_rotate.call(io)
591
- io = nil
592
616
  end
593
-
594
617
  @inode = inode
595
618
  @fsize = fsize
596
- ensure
597
- io.close if io
598
619
  end
599
620
 
600
621
  rescue
@@ -14,6 +14,8 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
+ require 'cool.io'
18
+
17
19
  require 'fluent/plugin/socket_util'
18
20
 
19
21
  module Fluent
@@ -22,7 +24,7 @@ module Fluent
22
24
 
23
25
  config_set_default :port, 5170
24
26
  desc 'The payload is read up to this character.'
25
- config_param :delimiter, :string, :default => "\n" # syslog family add "\n" to each message and this seems only way to split messages in tcp stream
27
+ config_param :delimiter, :string, default: "\n" # syslog family add "\n" to each message and this seems only way to split messages in tcp stream
26
28
 
27
29
  def listen(callback)
28
30
  log.info "listening tcp socket on #{@bind}:#{@port}"
@@ -21,7 +21,7 @@ module Fluent
21
21
  Plugin.register_input('udp', self)
22
22
 
23
23
  config_set_default :port, 5160
24
- config_param :body_size_limit, :size, :default => 4096
24
+ config_param :body_size_limit, :size, default: 4096
25
25
 
26
26
  def listen(callback)
27
27
  log.info "listening udp socket on #{@bind}:#{@port}"
@@ -14,12 +14,16 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
+ require 'fluent/output'
18
+ require 'fluent/config/error'
19
+ require 'fluent/event'
20
+
17
21
  module Fluent
18
22
  class CopyOutput < MultiOutput
19
23
  Plugin.register_output('copy', self)
20
24
 
21
25
  desc 'If true, pass different record to each `store` plugin.'
22
- config_param :deep_copy, :bool, :default => false
26
+ config_param :deep_copy, :bool, default: false
23
27
 
24
28
  def initialize
25
29
  super
@@ -14,6 +14,10 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
+ require 'tempfile'
18
+
19
+ require 'fluent/output'
20
+ require 'fluent/config/error'
17
21
  require 'fluent/plugin/exec_util'
18
22
 
19
23
  module Fluent
@@ -22,24 +26,23 @@ module Fluent
22
26
 
23
27
  def initialize
24
28
  super
25
- require 'tempfile'
26
29
  @localtime = false
27
30
  end
28
31
 
29
32
  desc 'The command (program) to execute. The exec plugin passes the path of a TSV file as the last argumen'
30
33
  config_param :command, :string
31
34
  desc 'Specify the comma-separated keys when using the tsv format.'
32
- config_param :keys, :default => [] do |val|
35
+ config_param :keys, default: [] do |val|
33
36
  val.split(',')
34
37
  end
35
38
  desc 'The name of the key to use as the event tag. This replaces the value in the event record.'
36
- config_param :tag_key, :string, :default => nil
39
+ config_param :tag_key, :string, default: nil
37
40
  desc 'The name of the key to use as the event time. This replaces the the value in the event record.'
38
- config_param :time_key, :string, :default => nil
41
+ config_param :time_key, :string, default: nil
39
42
  desc 'The format for event time used when the time_key parameter is specified. The default is UNIX time (integer).'
40
- config_param :time_format, :string, :default => nil
43
+ config_param :time_format, :string, default: nil
41
44
  desc "The format used to map the incoming events to the program input. (#{ExecUtil::SUPPORTED_FORMAT.keys.join(',')})"
42
- config_param :format, :default => :tsv do |val|
45
+ config_param :format, default: :tsv do |val|
43
46
  f = ExecUtil::SUPPORTED_FORMAT[val]
44
47
  raise ConfigError, "Unsupported format '#{val}'" unless f
45
48
  f