fluentd 0.10.57 → 0.10.58

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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/ChangeLog +18 -0
  4. data/fluent.conf +26 -16
  5. data/fluentd.gemspec +1 -1
  6. data/lib/fluent/config.rb +1 -8
  7. data/lib/fluent/config/basic_parser.rb +1 -0
  8. data/lib/fluent/config/configure_proxy.rb +7 -7
  9. data/lib/fluent/config/types.rb +1 -0
  10. data/lib/fluent/config/v1_parser.rb +2 -1
  11. data/lib/fluent/engine.rb +0 -26
  12. data/lib/fluent/env.rb +1 -0
  13. data/lib/fluent/formatter.rb +96 -26
  14. data/lib/fluent/input.rb +4 -0
  15. data/lib/fluent/output.rb +7 -2
  16. data/lib/fluent/parser.rb +82 -88
  17. data/lib/fluent/plugin.rb +18 -0
  18. data/lib/fluent/plugin/buf_file.rb +3 -3
  19. data/lib/fluent/plugin/in_dummy.rb +103 -0
  20. data/lib/fluent/plugin/in_exec.rb +1 -1
  21. data/lib/fluent/plugin/in_forward.rb +3 -3
  22. data/lib/fluent/plugin/in_gc_stat.rb +1 -1
  23. data/lib/fluent/plugin/in_http.rb +49 -17
  24. data/lib/fluent/plugin/in_monitor_agent.rb +41 -10
  25. data/lib/fluent/plugin/in_object_space.rb +1 -1
  26. data/lib/fluent/plugin/in_status.rb +1 -1
  27. data/lib/fluent/plugin/in_stream.rb +3 -3
  28. data/lib/fluent/plugin/in_syslog.rb +5 -5
  29. data/lib/fluent/plugin/in_tail.rb +6 -6
  30. data/lib/fluent/plugin/out_copy.rb +1 -1
  31. data/lib/fluent/plugin/out_exec_filter.rb +1 -1
  32. data/lib/fluent/plugin/out_file.rb +3 -3
  33. data/lib/fluent/plugin/out_roundrobin.rb +1 -1
  34. data/lib/fluent/plugin/socket_util.rb +2 -2
  35. data/lib/fluent/supervisor.rb +21 -24
  36. data/lib/fluent/test/base.rb +14 -0
  37. data/lib/fluent/test/output_test.rb +7 -1
  38. data/lib/fluent/version.rb +1 -1
  39. data/test/config/test_config_parser.rb +6 -2
  40. data/test/config/test_configurable.rb +1 -1
  41. data/test/config/test_configure_proxy.rb +1 -1
  42. data/test/config/test_dsl.rb +1 -1
  43. data/test/config/test_literal_parser.rb +2 -2
  44. data/test/config/test_section.rb +1 -1
  45. data/test/config/test_system_config.rb +65 -15
  46. data/test/config/test_types.rb +63 -0
  47. data/test/plugin/test_in_dummy.rb +95 -0
  48. data/test/plugin/test_in_exec.rb +1 -1
  49. data/test/plugin/test_in_forward.rb +1 -2
  50. data/test/plugin/test_in_gc_stat.rb +1 -1
  51. data/test/plugin/test_in_http.rb +77 -2
  52. data/test/plugin/test_in_object_space.rb +1 -1
  53. data/test/plugin/test_in_status.rb +1 -1
  54. data/test/plugin/test_in_stream.rb +1 -2
  55. data/test/plugin/test_in_syslog.rb +1 -2
  56. data/test/plugin/test_in_tail.rb +1 -1
  57. data/test/plugin/test_in_tcp.rb +1 -2
  58. data/test/plugin/test_in_udp.rb +1 -2
  59. data/test/plugin/test_out_copy.rb +12 -1
  60. data/test/plugin/test_out_exec.rb +1 -1
  61. data/test/plugin/test_out_exec_filter.rb +1 -1
  62. data/test/plugin/test_out_file.rb +61 -7
  63. data/test/plugin/test_out_forward.rb +1 -2
  64. data/test/plugin/test_out_roundrobin.rb +12 -1
  65. data/test/plugin/test_out_stdout.rb +1 -1
  66. data/test/plugin/test_out_stream.rb +1 -2
  67. data/test/scripts/fluent/plugin/formatter_known.rb +4 -1
  68. data/{lib → test/scripts}/fluent/plugin/out_test.rb +0 -0
  69. data/test/scripts/fluent/plugin/parser_known.rb +2 -1
  70. data/test/test_config.rb +1 -1
  71. data/test/test_configdsl.rb +1 -2
  72. data/test/test_formatter.rb +172 -3
  73. data/test/test_input.rb +21 -0
  74. data/test/test_match.rb +1 -2
  75. data/test/test_mixin.rb +1 -1
  76. data/test/test_output.rb +25 -1
  77. data/test/test_parser.rb +124 -78
  78. metadata +12 -4
@@ -21,12 +21,16 @@ module Fluent
21
21
  include PluginId
22
22
  include PluginLoggerMixin
23
23
 
24
+ attr_accessor :router
25
+
24
26
  def initialize
25
27
  super
26
28
  end
27
29
 
28
30
  def configure(conf)
29
31
  super
32
+
33
+ @router = Engine
30
34
  end
31
35
 
32
36
  def start
@@ -61,12 +61,16 @@ module Fluent
61
61
  include PluginId
62
62
  include PluginLoggerMixin
63
63
 
64
+ attr_accessor :router
65
+
64
66
  def initialize
65
67
  super
66
68
  end
67
69
 
68
70
  def configure(conf)
69
71
  super
72
+
73
+ @router = Engine
70
74
  end
71
75
 
72
76
  def start
@@ -202,7 +206,7 @@ module Fluent
202
206
  }
203
207
 
204
208
  if sconf = conf.elements.select {|e| e.name == 'secondary' }.first
205
- type = sconf['type'] || conf['type']
209
+ type = sconf['@type'] || conf['@type'] || sconf['type'] || conf['type']
206
210
  @secondary = Plugin.new_output(type)
207
211
  @secondary.configure(sconf)
208
212
 
@@ -395,7 +399,7 @@ module Fluent
395
399
  # secondary retry
396
400
  @retry_wait * (2 ** (@num_errors - 2 - @retry_limit))
397
401
  end
398
- retry_wait = wait + (rand * (wait / 4.0) - (wait / 8.0))
402
+ retry_wait = wait.finite? ? wait + (rand * (wait / 4.0) - (wait / 8.0)) : wait
399
403
  @max_retry_wait ? [retry_wait, @max_retry_wait].min : retry_wait
400
404
  end
401
405
 
@@ -469,6 +473,7 @@ module Fluent
469
473
  config_set_default :flush_interval, nil
470
474
 
471
475
  attr_accessor :localtime
476
+ attr_reader :time_slicer # for test
472
477
 
473
478
  def configure(conf)
474
479
  super
@@ -18,9 +18,38 @@
18
18
  module Fluent
19
19
  require 'fluent/registry'
20
20
 
21
- class TextParser
22
- class ParserError < StandardError
21
+ class ParserError < StandardError
22
+ end
23
+
24
+ class Parser
25
+ include Configurable
26
+
27
+ # SET false BEFORE CONFIGURE, to return nil when time not parsed
28
+ # 'configure()' may raise errors for unexpected configurations
29
+ attr_accessor :estimate_current_event
30
+
31
+ def initialize
32
+ super
33
+ @estimate_current_event = true
34
+ end
35
+
36
+ def configure(conf)
37
+ super
38
+ end
39
+
40
+ def parse(text)
41
+ raise NotImplementedError, "Implement this method in child class"
42
+ end
43
+
44
+ # Keep backward compatibility for existing plugins
45
+ def call(*a, &b)
46
+ parse(*a, &b)
23
47
  end
48
+ end
49
+
50
+ class TextParser
51
+ # Keep backward compatibility for existing plugins
52
+ ParserError = ::Fluent::ParserError
24
53
 
25
54
  class TimeParser
26
55
  def initialize(time_format)
@@ -129,16 +158,11 @@ module Fluent
129
158
  end
130
159
  end
131
160
 
132
- class RegexpParser
133
- include Configurable
161
+ class RegexpParser < Parser
134
162
  include TypeConverter
135
163
 
136
164
  config_param :time_format, :string, :default => nil
137
165
 
138
- # SET false BEFORE CONFIGURE, to return nil when time not parsed
139
- # 'configure()' may raise errors for unexpected configurations
140
- attr_accessor :estimate_current_event
141
-
142
166
  def initialize(regexp, conf={})
143
167
  super()
144
168
  @regexp = regexp
@@ -147,7 +171,6 @@ module Fluent
147
171
  end
148
172
 
149
173
  @time_parser = TimeParser.new(@time_format)
150
- @estimate_current_event = true
151
174
  @mutex = Mutex.new
152
175
  end
153
176
 
@@ -160,7 +183,7 @@ module Fluent
160
183
  {'format' => @regexp, 'time_format' => @time_format}
161
184
  end
162
185
 
163
- def call(text)
186
+ def parse(text)
164
187
  m = @regexp.match(text)
165
188
  unless m
166
189
  if block_given?
@@ -201,21 +224,10 @@ module Fluent
201
224
  end
202
225
  end
203
226
 
204
- class JSONParser
205
- include Configurable
206
-
227
+ class JSONParser < Parser
207
228
  config_param :time_key, :string, :default => 'time'
208
229
  config_param :time_format, :string, :default => nil
209
230
 
210
- # SET false BEFORE CONFIGURE, to return nil when time not parsed
211
- # 'configure()' may raise errors for unexpected configurations
212
- attr_accessor :estimate_current_event
213
-
214
- def initialize
215
- super
216
- @estimate_current_event = true
217
- end
218
-
219
231
  def configure(conf)
220
232
  super
221
233
 
@@ -225,7 +237,7 @@ module Fluent
225
237
  end
226
238
  end
227
239
 
228
- def call(text)
240
+ def parse(text)
229
241
  record = Yajl.load(text)
230
242
 
231
243
  if value = record.delete(@time_key)
@@ -260,21 +272,13 @@ module Fluent
260
272
  end
261
273
  end
262
274
 
263
- class ValuesParser
264
- include Configurable
275
+ class ValuesParser < Parser
265
276
  include TypeConverter
266
277
 
267
278
  config_param :keys, :string
268
279
  config_param :time_key, :string, :default => nil
269
280
  config_param :time_format, :string, :default => nil
270
281
 
271
- attr_accessor :estimate_current_event
272
-
273
- def initialize
274
- super
275
- @estimate_current_event = true
276
- end
277
-
278
282
  def configure(conf)
279
283
  super
280
284
 
@@ -331,11 +335,16 @@ module Fluent
331
335
  class TSVParser < ValuesParser
332
336
  config_param :delimiter, :string, :default => "\t"
333
337
 
334
- def call(text)
338
+ def configure(conf)
339
+ super
340
+ @key_num = @keys.length
341
+ end
342
+
343
+ def parse(text)
335
344
  if block_given?
336
- yield values_map(text.split(@delimiter))
345
+ yield values_map(text.split(@delimiter, @key_num))
337
346
  else
338
- return values_map(text.split(@delimiter))
347
+ return values_map(text.split(@delimiter, @key_num))
339
348
  end
340
349
  end
341
350
  end
@@ -350,7 +359,7 @@ module Fluent
350
359
  super(conf)
351
360
  end
352
361
 
353
- def call(text)
362
+ def parse(text)
354
363
  @keys = []
355
364
  values = []
356
365
 
@@ -374,7 +383,7 @@ module Fluent
374
383
  require 'csv'
375
384
  end
376
385
 
377
- def call(text)
386
+ def parse(text)
378
387
  if block_given?
379
388
  yield values_map(CSV.parse_line(text))
380
389
  else
@@ -383,19 +392,10 @@ module Fluent
383
392
  end
384
393
  end
385
394
 
386
- class NoneParser
387
- include Configurable
388
-
395
+ class NoneParser < Parser
389
396
  config_param :message_key, :string, :default => 'message'
390
397
 
391
- attr_accessor :estimate_current_event
392
-
393
- def initialize
394
- super
395
- @estimate_current_event = true
396
- end
397
-
398
- def call(text)
398
+ def parse(text)
399
399
  record = {}
400
400
  record[@message_key] = text
401
401
  time = @estimate_current_event ? Engine.now : nil
@@ -407,13 +407,12 @@ module Fluent
407
407
  end
408
408
  end
409
409
 
410
- class ApacheParser
411
- include Configurable
412
-
410
+ class ApacheParser < Parser
413
411
  REGEXP = /^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$/
414
412
  TIME_FORMAT = "%d/%b/%Y:%H:%M:%S %z"
415
413
 
416
414
  def initialize
415
+ super
417
416
  @time_parser = TimeParser.new(TIME_FORMAT)
418
417
  @mutex = Mutex.new
419
418
  end
@@ -422,7 +421,7 @@ module Fluent
422
421
  {'format' => REGEXP, 'time_format' => TIME_FORMAT}
423
422
  end
424
423
 
425
- def call(text)
424
+ def parse(text)
426
425
  m = REGEXP.match(text)
427
426
  unless m
428
427
  if block_given?
@@ -476,9 +475,7 @@ module Fluent
476
475
  end
477
476
  end
478
477
 
479
- class SyslogParser
480
- include Configurable
481
-
478
+ class SyslogParser < Parser
482
479
  # From existence TextParser pattern
483
480
  REGEXP = /^(?<time>[^ ]*\s*[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
484
481
  # From in_syslog default pattern
@@ -487,11 +484,8 @@ module Fluent
487
484
  config_param :time_format, :string, :default => "%b %d %H:%M:%S"
488
485
  config_param :with_priority, :bool, :default => false
489
486
 
490
- attr_accessor :estimate_current_event
491
-
492
487
  def initialize
493
488
  super
494
- @estimate_current_event = true
495
489
  @mutex = Mutex.new
496
490
  end
497
491
 
@@ -506,7 +500,7 @@ module Fluent
506
500
  {'format' => @regexp, 'time_format' => @time_format}
507
501
  end
508
502
 
509
- def call(text)
503
+ def parse(text)
510
504
  m = @regexp.match(text)
511
505
  unless m
512
506
  if block_given?
@@ -545,9 +539,7 @@ module Fluent
545
539
  end
546
540
  end
547
541
 
548
- class MultilineParser
549
- include Configurable
550
-
542
+ class MultilineParser < Parser
551
543
  config_param :format_firstline, :string, :default => nil
552
544
 
553
545
  FORMAT_MAX_NUM = 20
@@ -572,7 +564,7 @@ module Fluent
572
564
  end
573
565
  end
574
566
 
575
- def call(text, &block)
567
+ def parse(text, &block)
576
568
  if block
577
569
  @parser.call(text, &block)
578
570
  else
@@ -648,7 +640,9 @@ module Fluent
648
640
  }
649
641
 
650
642
  def self.register_template(name, regexp_or_proc, time_format=nil)
651
- if regexp_or_proc.is_a?(Regexp)
643
+ if regexp_or_proc.is_a?(Class)
644
+ factory = Proc.new { regexp_or_proc.new }
645
+ elsif regexp_or_proc.is_a?(Regexp)
652
646
  regexp = regexp_or_proc
653
647
  factory = Proc.new { RegexpParser.new(regexp, {'time_format'=>time_format}) }
654
648
  else
@@ -658,26 +652,9 @@ module Fluent
658
652
  TEMPLATE_REGISTRY.register(name, factory)
659
653
  end
660
654
 
661
- def initialize
662
- @parser = nil
663
- @estimate_current_event = nil
664
- end
665
-
666
- attr_reader :parser
667
-
668
- # SET false BEFORE CONFIGURE, to return nil when time not parsed
669
- # 'configure()' may raise errors for unexpected configurations
670
- attr_accessor :estimate_current_event
671
-
672
- def configure(conf, required=true)
673
- format = conf['format']
674
-
675
- if format == nil
676
- if required
677
- raise ConfigError, "'format' parameter is required"
678
- else
679
- return nil
680
- end
655
+ def self.lookup(format)
656
+ if format.nil?
657
+ raise ConfigError, "'format' parameter is required"
681
658
  end
682
659
 
683
660
  if format[0] == ?/ && format[format.length-1] == ?/
@@ -691,7 +668,7 @@ module Fluent
691
668
  raise ConfigError, "Invalid regexp '#{format[1..-2]}': #{$!}"
692
669
  end
693
670
 
694
- @parser = RegexpParser.new(regexp, conf)
671
+ RegexpParser.new(regexp)
695
672
  else
696
673
  # built-in template
697
674
  begin
@@ -699,9 +676,26 @@ module Fluent
699
676
  rescue ConfigError => e # keep same error message
700
677
  raise ConfigError, "Unknown format template '#{format}'"
701
678
  end
702
- @parser = factory.call
679
+
680
+ factory.call
703
681
  end
682
+ end
683
+
684
+ def initialize
685
+ @parser = nil
686
+ @estimate_current_event = nil
687
+ end
688
+
689
+ attr_reader :parser
690
+
691
+ # SET false BEFORE CONFIGURE, to return nil when time not parsed
692
+ # 'configure()' may raise errors for unexpected configurations
693
+ attr_accessor :estimate_current_event
694
+
695
+ def configure(conf, required=true)
696
+ format = conf['format']
704
697
 
698
+ @parser = TextParser.lookup(format)
705
699
  if ! @estimate_current_event.nil? && @parser.respond_to?(:'estimate_current_event=')
706
700
  @parser.estimate_current_event = @estimate_current_event
707
701
  end
@@ -715,9 +709,9 @@ module Fluent
715
709
 
716
710
  def parse(text, &block)
717
711
  if block
718
- @parser.call(text, &block)
712
+ @parser.parse(text, &block)
719
713
  else # keep backward compatibility. Will be removed at v1
720
- return @parser.call(text)
714
+ return @parser.parse(text)
721
715
  end
722
716
  end
723
717
  end
@@ -17,6 +17,8 @@
17
17
  #
18
18
  module Fluent
19
19
  class PluginClass
20
+ # This class is refactored using Fluent::Registry at v0.14
21
+
20
22
  def initialize
21
23
  @input = {}
22
24
  @output = {}
@@ -35,6 +37,14 @@ module Fluent
35
37
  register_impl('buffer', @buffer, type, klass)
36
38
  end
37
39
 
40
+ def register_parser(type, klass)
41
+ TextParser.register_template(type, klass)
42
+ end
43
+
44
+ def register_formatter(type, klass)
45
+ TextFormatter.register_template(type, klass)
46
+ end
47
+
38
48
  def new_input(type)
39
49
  new_impl('input', @input, type)
40
50
  end
@@ -47,6 +57,14 @@ module Fluent
47
57
  new_impl('buffer', @buffer, type)
48
58
  end
49
59
 
60
+ def new_parser(type)
61
+ TextParser.lookup(type)
62
+ end
63
+
64
+ def new_formatter(type)
65
+ TextFormatter.lookup(type)
66
+ end
67
+
50
68
  def load_plugins
51
69
  dir = File.join(File.dirname(__FILE__), "plugin")
52
70
  load_plugin_dir(dir)
@@ -91,9 +91,9 @@ module Fluent
91
91
  super
92
92
 
93
93
  if @@buffer_paths.has_key?(@buffer_path)
94
- raise ConfigError, "Other '#{@@buffer_paths[@buffer_path]}' plugin already use same buffer_path: type = #{conf['type']}, buffer_path = #{@buffer_path}"
94
+ raise ConfigError, "Other '#{@@buffer_paths[@buffer_path]}' plugin already use same buffer_path: type = #{conf['@type'] || conf['type']}, buffer_path = #{@buffer_path}"
95
95
  else
96
- @@buffer_paths[@buffer_path] = conf['type']
96
+ @@buffer_paths[@buffer_path] = conf['@type'] || conf['type']
97
97
  end
98
98
 
99
99
  if pos = @buffer_path.index('*')
@@ -112,7 +112,7 @@ module Fluent
112
112
  end
113
113
 
114
114
  def start
115
- FileUtils.mkdir_p File.dirname(@buffer_path_prefix+"path")
115
+ FileUtils.mkdir_p File.dirname(@buffer_path_prefix + "path"), :mode => DEFAULT_DIR_PERMISSION
116
116
  super
117
117
  end
118
118