fluentd 0.14.2 → 0.14.5

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +77 -1131
  3. data/Rakefile +15 -0
  4. data/appveyor.yml +2 -2
  5. data/example/in_forward.conf +3 -0
  6. data/example/in_forward_client.conf +37 -0
  7. data/example/in_forward_shared_key.conf +15 -0
  8. data/example/in_forward_users.conf +24 -0
  9. data/example/multi_filters.conf +61 -0
  10. data/example/out_forward.conf +13 -13
  11. data/example/out_forward_client.conf +109 -0
  12. data/example/out_forward_shared_key.conf +36 -0
  13. data/example/out_forward_users.conf +65 -0
  14. data/example/{out_buffered_null.conf → out_null.conf} +10 -6
  15. data/example/secondary_file.conf +41 -0
  16. data/fluentd.gemspec +19 -16
  17. data/lib/fluent/agent.rb +5 -0
  18. data/lib/fluent/command/debug.rb +4 -4
  19. data/lib/fluent/compat/handle_tag_and_time_mixin.rb +2 -0
  20. data/lib/fluent/compat/output.rb +5 -2
  21. data/lib/fluent/config/configure_proxy.rb +26 -5
  22. data/lib/fluent/config/error.rb +3 -0
  23. data/lib/fluent/config/section.rb +15 -0
  24. data/lib/fluent/event_router.rb +77 -4
  25. data/lib/fluent/plugin/base.rb +12 -3
  26. data/lib/fluent/plugin/buffer.rb +5 -1
  27. data/lib/fluent/plugin/filter.rb +48 -6
  28. data/lib/fluent/plugin/filter_record_transformer.rb +3 -1
  29. data/lib/fluent/plugin/filter_stdout.rb +0 -4
  30. data/lib/fluent/plugin/in_debug_agent.rb +5 -5
  31. data/lib/fluent/plugin/in_dummy.rb +9 -1
  32. data/lib/fluent/plugin/in_forward.rb +330 -62
  33. data/lib/fluent/plugin/in_monitor_agent.rb +31 -77
  34. data/lib/fluent/plugin/in_tail.rb +76 -92
  35. data/lib/fluent/plugin/multi_output.rb +4 -0
  36. data/lib/fluent/plugin/out_forward.rb +328 -222
  37. data/lib/fluent/plugin/out_null.rb +37 -0
  38. data/lib/fluent/plugin/out_secondary_file.rb +128 -0
  39. data/lib/fluent/plugin/out_stdout.rb +38 -2
  40. data/lib/fluent/plugin/output.rb +29 -6
  41. data/lib/fluent/plugin/storage_local.rb +16 -0
  42. data/lib/fluent/plugin_helper/timer.rb +6 -1
  43. data/lib/fluent/root_agent.rb +4 -1
  44. data/lib/fluent/supervisor.rb +62 -9
  45. data/lib/fluent/test/base.rb +3 -0
  46. data/lib/fluent/test/driver/base.rb +5 -0
  47. data/lib/fluent/test/formatter_test.rb +2 -0
  48. data/lib/fluent/test/parser_test.rb +2 -0
  49. data/lib/fluent/test/startup_shutdown.rb +33 -0
  50. data/lib/fluent/version.rb +1 -1
  51. data/lib/fluent/winsvc.rb +1 -2
  52. data/test/compat/test_calls_super.rb +2 -0
  53. data/test/config/test_configurable.rb +88 -0
  54. data/test/config/test_types.rb +7 -3
  55. data/test/plugin/test_filter.rb +121 -23
  56. data/test/plugin/test_filter_record_transformer.rb +22 -6
  57. data/test/plugin/test_in_debug_agent.rb +2 -2
  58. data/test/plugin/test_in_forward.rb +920 -407
  59. data/test/plugin/test_in_monitor_agent.rb +333 -0
  60. data/test/plugin/test_in_tail.rb +686 -595
  61. data/test/plugin/test_out_forward.rb +150 -207
  62. data/test/plugin/test_out_null.rb +85 -9
  63. data/test/plugin/test_out_secondary_file.rb +432 -0
  64. data/test/plugin/test_out_stdout.rb +143 -45
  65. data/test/plugin/test_output.rb +53 -0
  66. data/test/plugin/test_output_as_buffered.rb +13 -0
  67. data/test/plugin/test_output_as_buffered_overflow.rb +3 -0
  68. data/test/plugin/test_output_as_buffered_retries.rb +11 -0
  69. data/test/plugin/test_output_as_buffered_secondary.rb +12 -0
  70. data/test/plugin/test_output_as_standard.rb +12 -0
  71. data/test/plugin_helper/test_compat_parameters.rb +2 -0
  72. data/test/plugin_helper/test_timer.rb +31 -0
  73. data/test/test_event_router.rb +87 -0
  74. data/test/test_filter.rb +48 -6
  75. data/test/test_log.rb +5 -2
  76. data/test/test_output.rb +41 -1
  77. data/test/test_plugin_classes.rb +17 -9
  78. data/test/test_root_agent.rb +188 -0
  79. metadata +62 -68
  80. data/lib/fluent/plugin/out_buffered_null.rb +0 -59
  81. data/lib/fluent/plugin/out_buffered_stdout.rb +0 -70
  82. data/test/plugin/test_out_buffered_null.rb +0 -79
  83. data/test/plugin/test_out_buffered_stdout.rb +0 -122
data/test/test_filter.rb CHANGED
@@ -23,17 +23,57 @@ class FilterTest < Test::Unit::TestCase
23
23
  end
24
24
 
25
25
  sub_test_case 'configure' do
26
- test 'check default' do
27
- assert_nothing_raised { create_driver }
26
+ test 'check to implement `filter` method' do
27
+ klass = Class.new(Fluent::Filter) do |c|
28
+ def filter(tag, time, record); end
29
+ end
30
+
31
+ assert_nothing_raised do
32
+ klass.new
33
+ end
34
+ end
35
+
36
+ test 'check to implement `filter_with_time` method' do
37
+ klass = Class.new(Fluent::Filter) do |c|
38
+ def filter_with_time(tag, time, record); end
39
+ end
40
+
41
+ assert_nothing_raised do
42
+ klass.new
43
+ end
44
+ end
45
+
46
+ test 'DO NOT check when implement `filter_stream`' do
47
+ klass = Class.new(Fluent::Filter) do |c|
48
+ def filter_stream(tag, es); end
49
+ end
50
+
51
+ assert_nothing_raised do
52
+ klass.new
53
+ end
28
54
  end
29
- end
30
55
 
31
- sub_test_case 'filter' do
32
56
  test 'NotImplementedError' do
33
- not_implemented_filter = Class.new(Fluent::Filter)
34
- assert_raise(NotImplementedError) { emit(not_implemented_filter, ['foo']) }
57
+ klass = Class.new(Fluent::Filter)
58
+
59
+ assert_raise NotImplementedError do
60
+ klass.new
61
+ end
62
+ end
63
+
64
+ test 'duplicated method implementation' do
65
+ klass = Class.new(Fluent::Filter) do |c|
66
+ def filter(tag, time, record); end
67
+ def filter_with_time(tag, time, record); end
68
+ end
69
+
70
+ assert_raise do
71
+ klass.new
72
+ end
35
73
  end
74
+ end
36
75
 
76
+ sub_test_case 'filter' do
37
77
  test 'null filter' do
38
78
  null_filter = Class.new(Fluent::Filter) do |c|
39
79
  def filter(tag, time, record)
@@ -61,6 +101,7 @@ class FilterTest < Test::Unit::TestCase
61
101
  def filter_stream(tag, es)
62
102
  MultiEventStream.new
63
103
  end
104
+ def filter(tag, time, record); record; end
64
105
  end
65
106
  es = emit(null_filter, ['foo'])
66
107
  assert_equal(0, es.instance_variable_get(:@record_array).size)
@@ -71,6 +112,7 @@ class FilterTest < Test::Unit::TestCase
71
112
  def filter_stream(tag, es)
72
113
  es
73
114
  end
115
+ def filter(tag, time, record); record; end
74
116
  end
75
117
  es = emit(pass_filter, ['foo'])
76
118
  assert_equal(1, es.instance_variable_get(:@record_array).size)
data/test/test_log.rb CHANGED
@@ -1,17 +1,19 @@
1
1
  require_relative 'helper'
2
2
  require 'fluent/engine'
3
3
  require 'fluent/log'
4
+ require 'timecop'
4
5
 
5
6
  class LogTest < Test::Unit::TestCase
6
7
  def setup
7
8
  @log_device = Fluent::Test::DummyLogDevice.new
8
9
  @timestamp = Time.parse("2016-04-21 11:58:41 +0900")
9
10
  @timestamp_str = @timestamp.strftime("%Y-%m-%d %H:%M:%S %z")
10
- stub(Time).now { @timestamp }
11
+ Timecop.freeze(@timestamp)
11
12
  end
12
13
 
13
14
  def teardown
14
15
  @log_device.reset
16
+ Timecop.return
15
17
  Thread.current[:last_repeated_stacktrace] = nil
16
18
  end
17
19
 
@@ -409,7 +411,7 @@ class PluginLoggerTest < Test::Unit::TestCase
409
411
  @log_device = Fluent::Test::DummyLogDevice.new
410
412
  @timestamp = Time.parse("2016-04-21 11:58:41 +0900")
411
413
  @timestamp_str = @timestamp.strftime("%Y-%m-%d %H:%M:%S %z")
412
- stub(Time).now { @timestamp }
414
+ Timecop.freeze(@timestamp)
413
415
  dl_opts = {}
414
416
  dl_opts[:log_level] = ServerEngine::DaemonLogger::TRACE
415
417
  logdev = @log_device
@@ -419,6 +421,7 @@ class PluginLoggerTest < Test::Unit::TestCase
419
421
 
420
422
  def teardown
421
423
  @log_device.reset
424
+ Timecop.return
422
425
  Thread.current[:last_repeated_stacktrace] = nil
423
426
  end
424
427
 
data/test/test_output.rb CHANGED
@@ -65,6 +65,20 @@ module FluentOutputTest
65
65
  # assert_equal Float, d.instance.retry_wait.class
66
66
  end
67
67
 
68
+ class FormatterInjectTestOutput < Fluent::Output
69
+ def initialize
70
+ super
71
+ @formatter = nil
72
+ end
73
+ end
74
+ def test_start
75
+ i = FormatterInjectTestOutput.new
76
+ i.configure(config_element('ROOT', '', {}, [config_element('inject', '', {'hostname_key' => "host"})]))
77
+ assert_nothing_raised do
78
+ i.start
79
+ end
80
+ end
81
+
68
82
  def create_mock_driver(conf=CONFIG)
69
83
  Fluent::Test::BufferedOutputTestDriver.new(Fluent::BufferedOutput) do
70
84
  attr_accessor :submit_flush_threads
@@ -95,12 +109,37 @@ module FluentOutputTest
95
109
  end
96
110
 
97
111
  def test_secondary
98
- d = create_driver(CONFIG + %[
112
+ d = Fluent::Test::BufferedOutputTestDriver.new(Fluent::BufferedOutput) do
113
+ def write(chunk)
114
+ chunk.read
115
+ end
116
+ end
117
+
118
+ mock(d.instance.log).warn("secondary type should be same with primary one",
119
+ { primary: d.instance.class.to_s, secondary: "Fluent::Plugin::Test2Output" })
120
+ d.configure(CONFIG + %[
99
121
  <secondary>
100
122
  type test2
101
123
  name c0
102
124
  </secondary>
103
125
  ])
126
+
127
+ assert_not_nil d.instance.instance_variable_get(:@secondary).router
128
+ end
129
+
130
+ def test_secondary_with_no_warn_log
131
+ # ObjectBufferedOutput doesn't implemnt `custom_filter`
132
+ d = Fluent::Test::BufferedOutputTestDriver.new(Fluent::ObjectBufferedOutput)
133
+
134
+ mock(d.instance.log).warn("secondary type should be same with primary one",
135
+ { primary: d.instance.class.to_s, secondary: "Fluent::Plugin::Test2Output" }).never
136
+ d.configure(CONFIG + %[
137
+ <secondary>
138
+ type test2
139
+ name c0
140
+ </secondary>
141
+ ])
142
+
104
143
  assert_not_nil d.instance.instance_variable_get(:@secondary).router
105
144
  end
106
145
  end
@@ -165,6 +204,7 @@ module FluentOutputTest
165
204
  test "emit with invalid event" do
166
205
  d = create_driver
167
206
  d.instance.start
207
+ d.instance.after_start
168
208
  assert_raise ArgumentError, "time must be a Fluent::EventTime (or Integer)" do
169
209
  d.instance.emit_events('test', OneEventStream.new('string', 10))
170
210
  end
@@ -1,24 +1,26 @@
1
1
  require_relative 'helper'
2
- require 'fluent/input'
3
- require 'fluent/output'
4
- require 'fluent/filter'
2
+ require 'fluent/plugin/input'
3
+ require 'fluent/plugin/output'
4
+ require 'fluent/plugin/filter'
5
5
 
6
6
  module FluentTest
7
- class FluentTestInput < ::Fluent::Input
7
+ class FluentTestInput < ::Fluent::Plugin::Input
8
8
  ::Fluent::Plugin.register_input('test_in', self)
9
9
 
10
10
  attr_reader :started
11
11
 
12
12
  def start
13
+ super
13
14
  @started = true
14
15
  end
15
16
 
16
17
  def shutdown
17
18
  @started = false
19
+ super
18
20
  end
19
21
  end
20
22
 
21
- class FluentTestOutput < ::Fluent::Output
23
+ class FluentTestOutput < ::Fluent::Plugin::Output
22
24
  ::Fluent::Plugin.register_output('test_out', self)
23
25
 
24
26
  def initialize
@@ -30,21 +32,23 @@ module FluentTest
30
32
  attr_reader :started
31
33
 
32
34
  def start
35
+ super
33
36
  @started = true
34
37
  end
35
38
 
36
39
  def shutdown
37
40
  @started = false
41
+ super
38
42
  end
39
43
 
40
- def emit(tag, es, chain)
41
- es.each { |time, record|
44
+ def process(tag, es)
45
+ es.each do |time, record|
42
46
  @events[tag] << record
43
- }
47
+ end
44
48
  end
45
49
  end
46
50
 
47
- class FluentTestErrorOutput < ::Fluent::BufferedOutput
51
+ class FluentTestErrorOutput < ::Fluent::Plugin::Output
48
52
  ::Fluent::Plugin.register_output('test_out_error', self)
49
53
 
50
54
  def format(tag, time, record)
@@ -69,11 +73,13 @@ module FluentTest
69
73
  attr_reader :started
70
74
 
71
75
  def start
76
+ super
72
77
  @started = true
73
78
  end
74
79
 
75
80
  def shutdown
76
81
  @started = false
82
+ super
77
83
  end
78
84
 
79
85
  def filter(tag, time, record)
@@ -96,11 +102,13 @@ module FluentTest
96
102
  attr_reader :started
97
103
 
98
104
  def start
105
+ super
99
106
  @started = true
100
107
  end
101
108
 
102
109
  def shutdown
103
110
  @started = false
111
+ super
104
112
  end
105
113
 
106
114
  def filter(tag, time, record)
@@ -47,6 +47,48 @@ class RootAgentTest < ::Test::Unit::TestCase
47
47
  assert_nil ra.error_collector
48
48
  end
49
49
 
50
+ test 'raises configuration error for missing type of source' do
51
+ conf = <<-EOC
52
+ <source>
53
+ </source>
54
+ EOC
55
+ errmsg = "Missing '@type' parameter on <source> directive"
56
+ assert_raise Fluent::ConfigError.new(errmsg) do
57
+ configure_ra(conf)
58
+ end
59
+ end
60
+
61
+ test 'raises configuration error for missing type of match' do
62
+ conf = <<-EOC
63
+ <source>
64
+ @type test_in
65
+ </source>
66
+ <match *.**>
67
+ </match>
68
+ EOC
69
+ errmsg = "Missing '@type' parameter on <match> directive"
70
+ assert_raise Fluent::ConfigError.new(errmsg) do
71
+ configure_ra(conf)
72
+ end
73
+ end
74
+
75
+ test 'raises configuration error for missing type of filter' do
76
+ conf = <<-EOC
77
+ <source>
78
+ @type test_in
79
+ </source>
80
+ <filter *.**>
81
+ </filter>
82
+ <match *.**>
83
+ @type test_out
84
+ </match>
85
+ EOC
86
+ errmsg = "Missing '@type' parameter on <filter> directive"
87
+ assert_raise Fluent::ConfigError.new(errmsg) do
88
+ configure_ra(conf)
89
+ end
90
+ end
91
+
50
92
  test 'with plugins' do
51
93
  # check @type and type in one configuration
52
94
  conf = <<-EOC
@@ -129,4 +171,150 @@ EOC
129
171
  assert_false @ra.outputs.first.started
130
172
  end
131
173
  end
174
+
175
+ sub_test_case 'configured with MultiOutput plugins' do
176
+ setup do
177
+ @ra = RootAgent.new(log: $log)
178
+ stub(Engine).root_agent { @ra }
179
+ @ra.configure(Config.parse(<<-EOC, "(test)", "(test_dir)", true))
180
+ <source>
181
+ @type test_in
182
+ @id test_in
183
+ </source>
184
+ <filter>
185
+ @type test_filter
186
+ @id test_filter
187
+ </filter>
188
+ <match **>
189
+ @type copy
190
+ @id test_copy
191
+ <store>
192
+ @type test_out
193
+ @id test_out1
194
+ </store>
195
+ <store>
196
+ @type test_out
197
+ @id test_out2
198
+ </store>
199
+ </match>
200
+ EOC
201
+ @ra
202
+ end
203
+
204
+ test 'plugin status with multi output' do
205
+ assert_equal 1, @ra.inputs.size
206
+ assert_equal 1, @ra.filters.size
207
+ assert_equal 3, @ra.outputs.size
208
+
209
+ @ra.start
210
+ assert_equal [true], @ra.inputs.map{|i| i.started? }
211
+ assert_equal [true], @ra.filters.map{|i| i.started? }
212
+ assert_equal [true, true, true], @ra.outputs.map{|i| i.started? }
213
+
214
+ assert_equal [true], @ra.inputs.map{|i| i.after_started? }
215
+ assert_equal [true], @ra.filters.map{|i| i.after_started? }
216
+ assert_equal [true, true, true], @ra.outputs.map{|i| i.after_started? }
217
+
218
+ @ra.shutdown
219
+ assert_equal [true], @ra.inputs.map{|i| i.stopped? }
220
+ assert_equal [true], @ra.filters.map{|i| i.stopped? }
221
+ assert_equal [true, true, true], @ra.outputs.map{|i| i.stopped? }
222
+
223
+ assert_equal [true], @ra.inputs.map{|i| i.before_shutdown? }
224
+ assert_equal [true], @ra.filters.map{|i| i.before_shutdown? }
225
+ assert_equal [true, true, true], @ra.outputs.map{|i| i.before_shutdown? }
226
+
227
+ assert_equal [true], @ra.inputs.map{|i| i.shutdown? }
228
+ assert_equal [true], @ra.filters.map{|i| i.shutdown? }
229
+ assert_equal [true, true, true], @ra.outputs.map{|i| i.shutdown? }
230
+
231
+ assert_equal [true], @ra.inputs.map{|i| i.after_shutdown? }
232
+ assert_equal [true], @ra.filters.map{|i| i.after_shutdown? }
233
+ assert_equal [true, true, true], @ra.outputs.map{|i| i.after_shutdown? }
234
+
235
+ assert_equal [true], @ra.inputs.map{|i| i.closed? }
236
+ assert_equal [true], @ra.filters.map{|i| i.closed? }
237
+ assert_equal [true, true, true], @ra.outputs.map{|i| i.closed? }
238
+
239
+ assert_equal [true], @ra.inputs.map{|i| i.terminated? }
240
+ assert_equal [true], @ra.filters.map{|i| i.terminated? }
241
+ assert_equal [true, true, true], @ra.outputs.map{|i| i.terminated? }
242
+ end
243
+ end
244
+
245
+ sub_test_case 'configured with MultiOutput plugins and labels' do
246
+ setup do
247
+ @ra = RootAgent.new(log: $log)
248
+ stub(Engine).root_agent { @ra }
249
+ @ra.configure(Config.parse(<<-EOC, "(test)", "(test_dir)", true))
250
+ <source>
251
+ @type test_in
252
+ @id test_in
253
+ @label @testing
254
+ </source>
255
+ <label @testing>
256
+ <filter>
257
+ @type test_filter
258
+ @id test_filter
259
+ </filter>
260
+ <match **>
261
+ @type copy
262
+ @id test_copy
263
+ <store>
264
+ @type test_out
265
+ @id test_out1
266
+ </store>
267
+ <store>
268
+ @type test_out
269
+ @id test_out2
270
+ </store>
271
+ </match>
272
+ </label>
273
+ EOC
274
+ @ra
275
+ end
276
+
277
+ test 'plugin status with multi output' do
278
+ assert_equal 1, @ra.inputs.size
279
+ assert_equal 0, @ra.filters.size
280
+ assert_equal 0, @ra.outputs.size
281
+ assert_equal 1, @ra.labels.size
282
+ assert_equal '@testing', @ra.labels.keys.first
283
+ assert_equal 1, @ra.labels.values.first.filters.size
284
+ assert_equal 3, @ra.labels.values.first.outputs.size
285
+
286
+ label_filters = @ra.labels.values.first.filters
287
+ label_outputs = @ra.labels.values.first.outputs
288
+
289
+ @ra.start
290
+ assert_equal [true], @ra.inputs.map{|i| i.started? }
291
+ assert_equal [true], label_filters.map{|i| i.started? }
292
+ assert_equal [true, true, true], label_outputs.map{|i| i.started? }
293
+
294
+ @ra.shutdown
295
+ assert_equal [true], @ra.inputs.map{|i| i.stopped? }
296
+ assert_equal [true], label_filters.map{|i| i.stopped? }
297
+ assert_equal [true, true, true], label_outputs.map{|i| i.stopped? }
298
+
299
+ assert_equal [true], @ra.inputs.map{|i| i.before_shutdown? }
300
+ assert_equal [true], label_filters.map{|i| i.before_shutdown? }
301
+ assert_equal [true, true, true], label_outputs.map{|i| i.before_shutdown? }
302
+
303
+ assert_equal [true], @ra.inputs.map{|i| i.shutdown? }
304
+ assert_equal [true], label_filters.map{|i| i.shutdown? }
305
+ assert_equal [true, true, true], label_outputs.map{|i| i.shutdown? }
306
+
307
+ assert_equal [true], @ra.inputs.map{|i| i.after_shutdown? }
308
+ assert_equal [true], label_filters.map{|i| i.after_shutdown? }
309
+ assert_equal [true, true, true], label_outputs.map{|i| i.after_shutdown? }
310
+
311
+ assert_equal [true], @ra.inputs.map{|i| i.closed? }
312
+ assert_equal [true], label_filters.map{|i| i.closed? }
313
+ assert_equal [true, true, true], label_outputs.map{|i| i.closed? }
314
+
315
+ assert_equal [true], @ra.inputs.map{|i| i.terminated? }
316
+ assert_equal [true], label_filters.map{|i| i.terminated? }
317
+ assert_equal [true, true, true], label_outputs.map{|i| i.terminated? }
318
+ end
319
+ end
132
320
  end