fluentd 0.14.0 → 0.14.1

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 (105) hide show
  1. checksums.yaml +4 -4
  2. data/example/copy_roundrobin.conf +39 -0
  3. data/example/filter_stdout.conf +5 -5
  4. data/example/in_forward.conf +2 -2
  5. data/example/in_http.conf +2 -2
  6. data/example/in_syslog.conf +2 -2
  7. data/example/in_tail.conf +2 -2
  8. data/example/in_tcp.conf +2 -2
  9. data/example/in_udp.conf +2 -2
  10. data/example/out_buffered_null.conf +32 -0
  11. data/example/out_copy.conf +4 -4
  12. data/example/out_file.conf +2 -2
  13. data/example/out_forward.conf +2 -2
  14. data/example/v0_12_filter.conf +8 -8
  15. data/fluentd.gemspec +1 -1
  16. data/lib/fluent/command/fluentd.rb +6 -1
  17. data/lib/fluent/compat/handle_tag_name_mixin.rb +53 -0
  18. data/lib/fluent/compat/input.rb +1 -0
  19. data/lib/fluent/compat/output.rb +1 -0
  20. data/lib/fluent/compat/record_filter_mixin.rb +34 -0
  21. data/lib/fluent/compat/set_tag_key_mixin.rb +50 -0
  22. data/lib/fluent/compat/set_time_key_mixin.rb +69 -0
  23. data/lib/fluent/compat/type_converter.rb +90 -0
  24. data/lib/fluent/config/configure_proxy.rb +24 -4
  25. data/lib/fluent/config/dsl.rb +18 -1
  26. data/lib/fluent/config/v1_parser.rb +3 -2
  27. data/lib/fluent/configurable.rb +1 -1
  28. data/lib/fluent/event.rb +37 -9
  29. data/lib/fluent/mixin.rb +12 -286
  30. data/lib/fluent/plugin/buffer.rb +2 -2
  31. data/lib/fluent/plugin/in_dummy.rb +5 -1
  32. data/lib/fluent/plugin/in_gc_stat.rb +7 -37
  33. data/lib/fluent/plugin/in_http.rb +2 -0
  34. data/lib/fluent/plugin/{in_stream.rb → in_unix.rb} +0 -0
  35. data/lib/fluent/plugin/out_buffered_stdout.rb +60 -0
  36. data/lib/fluent/plugin/out_copy.rb +8 -51
  37. data/lib/fluent/plugin/out_null.rb +5 -5
  38. data/lib/fluent/plugin/out_relabel.rb +5 -5
  39. data/lib/fluent/plugin/out_roundrobin.rb +13 -40
  40. data/lib/fluent/plugin/output.rb +9 -0
  41. data/lib/fluent/plugin_helper.rb +2 -0
  42. data/lib/fluent/plugin_helper/formatter.rb +138 -0
  43. data/lib/fluent/plugin_helper/inject.rb +112 -0
  44. data/lib/fluent/plugin_helper/parser.rb +138 -0
  45. data/lib/fluent/plugin_helper/storage.rb +64 -50
  46. data/lib/fluent/process.rb +6 -1
  47. data/lib/fluent/registry.rb +1 -1
  48. data/lib/fluent/supervisor.rb +20 -2
  49. data/lib/fluent/test.rb +30 -5
  50. data/lib/fluent/test/base.rb +2 -66
  51. data/lib/fluent/test/driver/base.rb +3 -0
  52. data/lib/fluent/test/driver/base_owned.rb +106 -0
  53. data/lib/fluent/test/driver/formatter.rb +30 -0
  54. data/lib/fluent/test/driver/multi_output.rb +52 -0
  55. data/lib/fluent/test/driver/owner.rb +32 -0
  56. data/lib/fluent/test/driver/parser.rb +30 -0
  57. data/lib/fluent/test/helpers.rb +54 -0
  58. data/lib/fluent/test/log.rb +73 -0
  59. data/lib/fluent/time.rb +71 -0
  60. data/lib/fluent/version.rb +1 -1
  61. data/test/compat/test_parser.rb +82 -0
  62. data/test/config/test_configure_proxy.rb +15 -0
  63. data/test/config/test_dsl.rb +180 -2
  64. data/test/helper.rb +2 -24
  65. data/test/plugin/test_in_gc_stat.rb +6 -6
  66. data/test/plugin/test_in_http.rb +49 -32
  67. data/test/plugin/{test_in_stream.rb → test_in_unix.rb} +1 -1
  68. data/test/plugin/test_out_buffered_stdout.rb +108 -0
  69. data/test/plugin/test_out_copy.rb +88 -127
  70. data/test/plugin/test_out_null.rb +29 -0
  71. data/test/plugin/test_out_relabel.rb +28 -0
  72. data/test/plugin/test_out_roundrobin.rb +35 -29
  73. data/test/plugin/test_out_stdout.rb +4 -4
  74. data/test/plugin/test_output_as_buffered.rb +51 -0
  75. data/test/plugin/test_output_as_buffered_secondary.rb +13 -0
  76. data/test/plugin/test_parser_apache.rb +38 -0
  77. data/test/plugin/test_parser_apache2.rb +38 -0
  78. data/test/plugin/test_parser_apache_error.rb +40 -0
  79. data/test/plugin/test_parser_base.rb +32 -0
  80. data/test/plugin/test_parser_csv.rb +94 -0
  81. data/test/plugin/test_parser_json.rb +107 -0
  82. data/test/plugin/test_parser_labeled_tsv.rb +129 -0
  83. data/test/plugin/test_parser_multiline.rb +100 -0
  84. data/test/plugin/test_parser_nginx.rb +42 -0
  85. data/test/plugin/test_parser_none.rb +53 -0
  86. data/test/plugin/test_parser_regexp.rb +110 -0
  87. data/test/plugin/test_parser_syslog.rb +66 -0
  88. data/test/plugin/test_parser_time.rb +46 -0
  89. data/test/plugin/test_parser_tsv.rb +125 -0
  90. data/test/plugin_helper/test_child_process.rb +11 -2
  91. data/test/plugin_helper/test_formatter.rb +212 -0
  92. data/test/plugin_helper/test_inject.rb +388 -0
  93. data/test/plugin_helper/test_parser.rb +223 -0
  94. data/test/plugin_helper/test_retry_state.rb +40 -40
  95. data/test/plugin_helper/test_storage.rb +77 -10
  96. data/test/scripts/fluent/plugin/out_test.rb +22 -17
  97. data/test/scripts/fluent/plugin/out_test2.rb +80 -0
  98. data/test/test_event.rb +57 -0
  99. data/test/test_formatter.rb +0 -178
  100. data/test/test_output.rb +2 -152
  101. data/test/test_root_agent.rb +3 -2
  102. data/test/test_supervisor.rb +93 -26
  103. data/test/test_time_formatter.rb +186 -0
  104. metadata +69 -7
  105. data/test/test_parser.rb +0 -1087
@@ -413,8 +413,8 @@ module Fluent
413
413
  write_step_by_step(metadata, data, data.size / 3, &block)
414
414
  end
415
415
  rescue ShouldRetry
416
- enqueue_list.each do |metadata|
417
- enqueue_chunk(metadata)
416
+ enqueue_list.each do |m|
417
+ enqueue_chunk(m)
418
418
  end
419
419
  retry
420
420
  end
@@ -89,7 +89,11 @@ module Fluent::Plugin
89
89
  end
90
90
 
91
91
  def emit(num)
92
- num.times { router.emit(@tag, Fluent::Engine.now, generate()) }
92
+ begin
93
+ num.times { router.emit(@tag, Fluent::Engine.now, generate()) }
94
+ rescue => _
95
+ # ignore all errors not to stop emits by emit errors
96
+ end
93
97
  end
94
98
 
95
99
  def generate
@@ -14,13 +14,13 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'cool.io'
17
+ require 'fluent/plugin/input'
18
18
 
19
- require 'fluent/input'
19
+ module Fluent::Plugin
20
+ class GCStatInput < Fluent::Plugin::Input
21
+ Fluent::Plugin.register_input('gc_stat', self)
20
22
 
21
- module Fluent
22
- class GCStatInput < Input
23
- Plugin.register_input('gc_stat', self)
23
+ helpers :timer
24
24
 
25
25
  def initialize
26
26
  super
@@ -29,22 +29,6 @@ module Fluent
29
29
  config_param :emit_interval, :time, default: 60
30
30
  config_param :tag, :string
31
31
 
32
- class TimerWatcher < Coolio::TimerWatcher
33
- def initialize(interval, repeat, log, &callback)
34
- @callback = callback
35
- @log = log
36
- super(interval, repeat)
37
- end
38
-
39
- def on_timer
40
- @callback.call
41
- rescue
42
- # TODO log?
43
- @log.error $!.to_s
44
- @log.error_backtrace
45
- end
46
- end
47
-
48
32
  def configure(conf)
49
33
  super
50
34
  end
@@ -52,29 +36,15 @@ module Fluent
52
36
  def start
53
37
  super
54
38
 
55
- @loop = Coolio::Loop.new
56
- @timer = TimerWatcher.new(@emit_interval, true, log, &method(:on_timer))
57
- @loop.attach(@timer)
58
- @thread = Thread.new(&method(:run))
39
+ timer_execute(:in_gc_stat, @emit_interval, &method(:on_timer))
59
40
  end
60
41
 
61
42
  def shutdown
62
- @loop.watchers.each {|w| w.detach }
63
- @loop.stop
64
- @thread.join
65
-
66
43
  super
67
44
  end
68
45
 
69
- def run
70
- @loop.run
71
- rescue
72
- log.error "unexpected error", error: $!.to_s
73
- log.error_backtrace
74
- end
75
-
76
46
  def on_timer
77
- now = Engine.now
47
+ now = Fluent::EventTime.now
78
48
  record = GC.stat
79
49
  router.emit(@tag, now, record)
80
50
  end
@@ -309,6 +309,8 @@ module Fluent
309
309
  end
310
310
  when /Origin/i
311
311
  @origin = v
312
+ when /X-Forwarded-For/i
313
+ @remote_addr = v.split(",").first
312
314
  end
313
315
  }
314
316
  if expect
@@ -0,0 +1,60 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'fluent/plugin/output'
18
+
19
+ module Fluent::Plugin
20
+ class BufferedStdoutOutput < Output
21
+ Fluent::Plugin.register_output('buffered_stdout', self)
22
+
23
+ desc 'Output format.(json,hash)'
24
+ config_param :output_type, default: 'json'
25
+ config_section :buffer do
26
+ config_set_default :chunk_keys, ['tag']
27
+ config_set_default :flush_at_shutdown, true
28
+ config_set_default :chunk_limit_size, 10 * 1024
29
+ end
30
+
31
+ attr_accessor :delayed
32
+
33
+ def initialize
34
+ super
35
+ @delayed = false
36
+ end
37
+
38
+ def prefer_delayed_commit
39
+ @delayed
40
+ end
41
+
42
+ def configure(conf)
43
+ super
44
+ @formatter = Fluent::Plugin.new_formatter(@output_type, parent: self)
45
+ @formatter.configure(conf)
46
+ end
47
+
48
+ def write(chunk)
49
+ chunk.write_to($log)
50
+ end
51
+
52
+ def try_write(chunk)
53
+ chunk.write_to($log)
54
+ end
55
+
56
+ def format(tag, time, record)
57
+ "#{Time.at(time).localtime} #{tag}: #{@formatter.format(tag, time, record).chomp}\n"
58
+ end
59
+ end
60
+ end
@@ -14,72 +14,29 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'fluent/output'
17
+ require 'fluent/plugin/multi_output'
18
18
  require 'fluent/config/error'
19
19
  require 'fluent/event'
20
20
 
21
- module Fluent
21
+ module Fluent::Plugin
22
22
  class CopyOutput < MultiOutput
23
- Plugin.register_output('copy', self)
23
+ Fluent::Plugin.register_output('copy', self)
24
24
 
25
25
  desc 'If true, pass different record to each `store` plugin.'
26
26
  config_param :deep_copy, :bool, default: false
27
27
 
28
- def initialize
29
- super
30
- @outputs = []
31
- end
32
-
33
- attr_reader :outputs
34
-
35
- def configure(conf)
36
- super
37
- conf.elements.select {|e|
38
- e.name == 'store'
39
- }.each {|e|
40
- type = e['@type']
41
- unless type
42
- raise ConfigError, "Missing 'type' parameter on <store> directive"
43
- end
44
- log.debug "adding store type=#{type.dump}"
45
-
46
- output = Plugin.new_output(type)
47
- output.router = router
48
- output.configure(e)
49
- @outputs << output
50
- }
51
- end
52
-
53
- def start
54
- super
55
-
56
- @outputs.each do |o|
57
- o.start unless o.started?
58
- end
59
- end
60
-
61
- def shutdown
62
- @outputs.each do |o|
63
- o.shutdown unless o.shutdown?
64
- end
65
-
66
- super
67
- end
68
-
69
- def emit(tag, es, chain)
28
+ def process(tag, es)
70
29
  unless es.repeatable?
71
- m = MultiEventStream.new
30
+ m = Fluent::MultiEventStream.new
72
31
  es.each {|time,record|
73
32
  m.add(time, record)
74
33
  }
75
34
  es = m
76
35
  end
77
- if @deep_copy
78
- chain = CopyOutputChain.new(@outputs, tag, es, chain)
79
- else
80
- chain = OutputChain.new(@outputs, tag, es, chain)
36
+
37
+ outputs.each do |output|
38
+ output.emit_events(tag, @deep_copy ? es.dup : es)
81
39
  end
82
- chain.next
83
40
  end
84
41
  end
85
42
  end
@@ -14,14 +14,14 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'fluent/output'
17
+ require 'fluent/plugin/output'
18
18
 
19
- module Fluent
19
+ module Fluent::Plugin
20
20
  class NullOutput < Output
21
- Plugin.register_output('null', self)
21
+ Fluent::Plugin.register_output('null', self)
22
22
 
23
- def emit(tag, es, chain)
24
- chain.next
23
+ def process(tag, es)
24
+ # Do nothing
25
25
  end
26
26
  end
27
27
  end
@@ -14,15 +14,15 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'fluent/output'
17
+ require 'fluent/plugin/output'
18
18
 
19
- module Fluent
19
+ module Fluent::Plugin
20
20
  class RelabelOutput < Output
21
- Plugin.register_output('relabel', self)
21
+ Fluent::Plugin.register_output('relabel', self)
22
+ helpers :event_emitter
22
23
 
23
- def emit(tag, es, chain)
24
+ def process(tag, es)
24
25
  router.emit_stream(tag, es)
25
- chain.next
26
26
  end
27
27
  end
28
28
  end
@@ -14,68 +14,41 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'fluent/output'
17
+ require 'fluent/plugin/multi_output'
18
18
  require 'fluent/config/error'
19
19
 
20
- module Fluent
20
+ module Fluent::Plugin
21
21
  class RoundRobinOutput < MultiOutput
22
- Plugin.register_output('roundrobin', self)
22
+ Fluent::Plugin.register_output('roundrobin', self)
23
+
24
+ config_section :store do
25
+ config_param :weight, :integer, default: 1
26
+ end
23
27
 
24
28
  def initialize
25
29
  super
26
-
27
- @outputs = []
28
30
  @weights = []
29
31
  end
30
32
 
31
- attr_reader :outputs, :weights
32
- attr_accessor :rand_seed
33
+ attr_reader :weights
33
34
 
34
35
  def configure(conf)
35
36
  super
36
37
 
37
- conf.elements.select {|e|
38
- e.name == 'store'
39
- }.each {|e|
40
- type = e['@type']
41
- unless type
42
- raise ConfigError, "Missing 'type' parameter on <store> directive"
43
- end
44
-
45
- weight = e['weight']
46
- weight = weight ? weight.to_i : 1
47
- log.debug "adding store type=#{type.dump}, weight=#{weight}"
48
-
49
- output = Plugin.new_output(type)
50
- output.router = router
51
- output.configure(e)
52
- @outputs << output
53
- @weights << weight
54
- }
38
+ @stores.each do |store|
39
+ @weights << store.weight
40
+ end
55
41
  @rr = -1 # starts from @output[0]
56
42
  @rand_seed = Random.new.seed
57
43
  end
58
44
 
59
45
  def start
60
46
  super
61
-
62
47
  rebuild_weight_array
63
-
64
- @outputs.each do |o|
65
- o.start unless o.started?
66
- end
67
- end
68
-
69
- def shutdown
70
- @outputs.each do |o|
71
- o.shutdown unless o.shutdown?
72
- end
73
-
74
- super
75
48
  end
76
49
 
77
- def emit(tag, es, chain)
78
- next_output.emit(tag, es, chain)
50
+ def process(tag, es)
51
+ next_output.emit_events(tag, es)
79
52
  end
80
53
 
81
54
  private
@@ -37,6 +37,8 @@ module Fluent
37
37
  CHUNK_KEY_PATTERN = /^[-_.@a-zA-Z0-9]+$/
38
38
  CHUNK_KEY_PLACEHOLDER_PATTERN = /\$\{[-_.@a-zA-Z0-9]+\}/
39
39
 
40
+ CHUNKING_FIELD_WARN_NUM = 4
41
+
40
42
  config_param :time_as_integer, :bool, default: false
41
43
 
42
44
  # `<buffer>` and `<secondary>` sections are available only when '#format' and '#write' are implemented
@@ -253,6 +255,10 @@ module Fluent
253
255
  @output_time_formatter_cache = {}
254
256
  end
255
257
 
258
+ if (@chunk_key_tag ? 1 : 0) + @chunk_keys.size >= CHUNKING_FIELD_WARN_NUM
259
+ log.warn "many chunk keys specified, and it may cause too many chunks on your system."
260
+ end
261
+
256
262
  # no chunk keys or only tags (chunking can be done without iterating event stream)
257
263
  @simple_chunking = !@chunk_key_time && @chunk_keys.empty?
258
264
 
@@ -287,6 +293,9 @@ module Fluent
287
293
  raise Fluent::ConfigError, "<secondary> section and 'retry_forever' are exclusive" if @buffer_config.retry_forever
288
294
 
289
295
  secondary_type = @secondary_config[:@type]
296
+ unless secondary_type
297
+ secondary_type = conf['@type'] # primary plugin type
298
+ end
290
299
  secondary_conf = conf.elements(name: 'secondary').first
291
300
  @secondary = Plugin.new_output(secondary_type)
292
301
  @secondary.acts_as_secondary(self)
@@ -20,6 +20,8 @@ require 'fluent/plugin_helper/event_loop'
20
20
  require 'fluent/plugin_helper/timer'
21
21
  require 'fluent/plugin_helper/child_process'
22
22
  require 'fluent/plugin_helper/storage'
23
+ require 'fluent/plugin_helper/parser'
24
+ require 'fluent/plugin_helper/formatter'
23
25
  require 'fluent/plugin_helper/retry_state'
24
26
  require 'fluent/plugin_helper/compat_parameters'
25
27
 
@@ -0,0 +1,138 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'fluent/plugin'
18
+ require 'fluent/plugin/formatter'
19
+ require 'fluent/config/element'
20
+
21
+ module Fluent
22
+ module PluginHelper
23
+ module Formatter
24
+ def formatter_create(usage: '', type: nil, conf: nil)
25
+ formatter = @_formatters[usage]
26
+ return formatter if formatter
27
+
28
+ if !type
29
+ raise ArgumentError, "BUG: both type and conf are not specified" unless conf
30
+ raise Fluent::ConfigError, "@type is required in <format>" unless conf['@type']
31
+ type = conf['@type']
32
+ end
33
+ formatter = Fluent::Plugin.new_formatter(type, parent: self)
34
+ config = case conf
35
+ when Fluent::Config::Element
36
+ conf
37
+ when Hash
38
+ # in code, programmer may use symbols as keys, but Element needs strings
39
+ conf = Hash[conf.map{|k,v| [k.to_s, v]}]
40
+ Fluent::Config::Element.new('format', usage, conf, [])
41
+ when nil
42
+ Fluent::Config::Element.new('format', usage, {}, [])
43
+ else
44
+ raise ArgumentError, "BUG: conf must be a Element, Hash (or unspecified), but '#{conf.class}'"
45
+ end
46
+ formatter.configure(config)
47
+ if @_formatters_started
48
+ formatter.start
49
+ end
50
+
51
+ @_formatters[usage] = formatter
52
+ formatter
53
+ end
54
+
55
+ def self.included(mod)
56
+ mod.instance_eval do
57
+ # minimum section definition to instantiate formatter plugin instances
58
+ config_section :format, required: false, multi: true, param_name: :formatter_configs do
59
+ config_argument :usage, :string, default: ''
60
+ config_param :@type, :string
61
+ end
62
+ end
63
+ end
64
+
65
+ attr_reader :_formatters # for tests
66
+
67
+ def initialize
68
+ super
69
+ @_formatters_started = false
70
+ @_formatters = {} # usage => formatter
71
+ end
72
+
73
+ def configure(conf)
74
+ super
75
+
76
+ @formatter_configs.each do |section|
77
+ if @_formatters[section.usage]
78
+ raise Fluent::ConfigError, "duplicated formatter configured: #{section.usage}"
79
+ end
80
+ formatter = Plugin.new_formatter(section[:@type], parent: self)
81
+ formatter.configure(section.corresponding_config_element)
82
+ @_formatters[section.usage] = formatter
83
+ end
84
+ end
85
+
86
+ def start
87
+ super
88
+ @_formatters_started = true
89
+ @_formatters.each_pair do |usage, formatter|
90
+ formatter.start
91
+ end
92
+ end
93
+
94
+ def formatter_operate(method_name, &block)
95
+ @_formatters.each_pair do |usage, formatter|
96
+ begin
97
+ formatter.send(method_name)
98
+ block.call(formatter) if block_given?
99
+ rescue => e
100
+ log.error "unexpected error while #{method_name}", usage: usage, formatter: formatter, error: e
101
+ end
102
+ end
103
+ end
104
+
105
+ def stop
106
+ super
107
+ formatter_operate(:stop)
108
+ end
109
+
110
+ def before_shutdown
111
+ formatter_operate(:before_shutdown)
112
+ super
113
+ end
114
+
115
+ def shutdown
116
+ formatter_operate(:shutdown)
117
+ super
118
+ end
119
+
120
+ def after_shutdown
121
+ formatter_operate(:after_shutdown)
122
+ super
123
+ end
124
+
125
+ def close
126
+ formatter_operate(:close)
127
+ super
128
+ end
129
+
130
+ def terminate
131
+ formatter_operate(:terminate)
132
+ @_formatters_started = false
133
+ @_formatters = {}
134
+ super
135
+ end
136
+ end
137
+ end
138
+ end