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
@@ -0,0 +1,63 @@
1
+ require 'helper'
2
+ require 'fluent/config/types'
3
+
4
+ class TestConfigTypes < ::Test::Unit::TestCase
5
+ include Fluent
6
+
7
+ sub_test_case 'Config.size_value' do
8
+ test 'normal case' do
9
+ assert_equal(2048, Config.size_value("2k"))
10
+ assert_equal(2048, Config.size_value("2K"))
11
+ assert_equal(3145728, Config.size_value("3m"))
12
+ assert_equal(3145728, Config.size_value("3M"))
13
+ assert_equal(4294967296, Config.size_value("4g"))
14
+ assert_equal(4294967296, Config.size_value("4G"))
15
+ assert_equal(5497558138880, Config.size_value("5t"))
16
+ assert_equal(5497558138880, Config.size_value("5T"))
17
+ assert_equal(6, Config.size_value("6"))
18
+ end
19
+
20
+ test 'not assumed case' do
21
+ assert_equal(6, Config.size_value(6))
22
+ assert_equal(0, Config.size_value("hoge"))
23
+ assert_equal(0, Config.size_value(""))
24
+ assert_equal(0, Config.size_value(nil))
25
+ end
26
+ end
27
+
28
+ sub_test_case 'Config.time_value' do
29
+ test 'normal case' do
30
+ assert_equal(10, Config.time_value("10s"))
31
+ assert_equal(10, Config.time_value("10sec"))
32
+ assert_equal(120, Config.time_value("2m"))
33
+ assert_equal(10800, Config.time_value("3h"))
34
+ assert_equal(345600, Config.time_value("4d"))
35
+ end
36
+
37
+ test 'not assumed case' do
38
+ assert_equal(4.0, Config.time_value(4))
39
+ assert_equal(0.4, Config.time_value(0.4))
40
+ assert_equal(0.0, Config.time_value("hoge"))
41
+ assert_equal(0.0, Config.time_value(""))
42
+ assert_equal(0.0, Config.time_value(nil))
43
+ end
44
+ end
45
+
46
+ sub_test_case 'Config.bool_value' do
47
+ test 'normal case' do
48
+ assert_true Config.bool_value("true")
49
+ assert_true Config.bool_value("yes")
50
+ assert_true Config.bool_value("")
51
+ assert_false Config.bool_value("false")
52
+ assert_false Config.bool_value("no")
53
+ end
54
+
55
+ test 'not assumed case' do
56
+ assert_true Config.bool_value(true)
57
+ assert_false Config.bool_value(false)
58
+ assert_nil Config.bool_value("hoge")
59
+ assert_nil Config.bool_value(nil)
60
+ assert_nil Config.bool_value(10)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,95 @@
1
+ require_relative '../helper'
2
+ require 'fluent/test'
3
+
4
+ class DummyTest < Test::Unit::TestCase
5
+ def setup
6
+ Fluent::Test.setup
7
+ end
8
+
9
+ def create_driver(conf)
10
+ Fluent::Test::InputTestDriver.new(Fluent::DummyInput).configure(conf)
11
+ end
12
+
13
+ sub_test_case 'configure' do
14
+ test 'required parameters' do
15
+ assert_raise_message("'tag' parameter is required") do
16
+ create_driver('')
17
+ end
18
+ end
19
+
20
+ test 'tag' do
21
+ d = create_driver(%[
22
+ tag dummy
23
+ ])
24
+ assert_equal "dummy", d.instance.tag
25
+ end
26
+
27
+ config = %[
28
+ tag dummy
29
+ ]
30
+
31
+ test 'auto_increment_key' do
32
+ d = create_driver(config + %[
33
+ auto_increment_key id
34
+ ])
35
+ assert_equal "id", d.instance.auto_increment_key
36
+ end
37
+
38
+ test 'rate' do
39
+ d = create_driver(config + %[
40
+ rate 10
41
+ ])
42
+ assert_equal 10, d.instance.rate
43
+ end
44
+
45
+ test 'dummy' do
46
+ # hash is okay
47
+ d = create_driver(config + %[dummy {"foo":"bar"}])
48
+ assert_equal [{"foo"=>"bar"}], d.instance.dummy
49
+
50
+ # array of hash is okay
51
+ d = create_driver(config + %[dummy [{"foo":"bar"}]])
52
+ assert_equal [{"foo"=>"bar"}], d.instance.dummy
53
+
54
+ assert_raise_message(/JSON::ParserError|got incomplete JSON/) do
55
+ create_driver(config + %[dummy "foo"])
56
+ end
57
+
58
+ assert_raise_message(/is not a hash/) do
59
+ create_driver(config + %[dummy ["foo"]])
60
+ end
61
+ end
62
+ end
63
+
64
+ sub_test_case "emit" do
65
+ config = %[
66
+ tag dummy
67
+ rate 10
68
+ dummy {"foo":"bar"}
69
+ ]
70
+
71
+ test 'simple' do
72
+ d = create_driver(config)
73
+ d.run {
74
+ # d.run sleeps 0.5 sec
75
+ }
76
+ emits = d.emits
77
+ emits.each do |tag, time, record|
78
+ assert_equal("dummy", tag)
79
+ assert_equal({"foo"=>"bar"}, record)
80
+ end
81
+ end
82
+
83
+ test 'with auto_increment_key' do
84
+ d = create_driver(config + %[auto_increment_key id])
85
+ d.run {
86
+ # d.run sleeps 0.5 sec
87
+ }
88
+ emits = d.emits
89
+ emits.each_with_index do |(tag, time, record), i|
90
+ assert_equal("dummy", tag)
91
+ assert_equal({"foo"=>"bar", "id"=>i}, record)
92
+ end
93
+ end
94
+ end
95
+ end
@@ -1,4 +1,4 @@
1
- require 'fluent/test'
1
+ require_relative '../helper'
2
2
  require 'net/http'
3
3
 
4
4
  class ExecInputTest < Test::Unit::TestCase
@@ -1,5 +1,4 @@
1
- require 'fluent/test'
2
- require 'helper'
1
+ require_relative '../helper'
3
2
 
4
3
  class ForwardInputTest < Test::Unit::TestCase
5
4
  def setup
@@ -1,4 +1,4 @@
1
- require 'fluent/test'
1
+ require_relative '../helper'
2
2
 
3
3
  class GCStatInputTest < Test::Unit::TestCase
4
4
  def setup
@@ -1,5 +1,4 @@
1
- require 'fluent/test'
2
- require 'helper'
1
+ require_relative '../helper'
3
2
  require 'net/http'
4
3
 
5
4
  class HttpInputTest < Test::Unit::TestCase
@@ -13,6 +12,7 @@ class HttpInputTest < Test::Unit::TestCase
13
12
  bind "127.0.0.1"
14
13
  body_size_limit 10m
15
14
  keepalive_timeout 5
15
+ respond_with_empty_img true
16
16
  ]
17
17
 
18
18
  def create_driver(conf=CONFIG)
@@ -199,6 +199,81 @@ class HttpInputTest < Test::Unit::TestCase
199
199
  end
200
200
  end
201
201
 
202
+ def test_resonse_with_empty_img
203
+ d = create_driver(CONFIG + "respond_with_empty_img true")
204
+ assert_equal true, d.instance.respond_with_empty_img
205
+
206
+ time = Time.parse("2011-01-02 13:14:15 UTC").to_i
207
+
208
+ d.expect_emit "tag1", time, {"a"=>1}
209
+ d.expect_emit "tag2", time, {"a"=>2}
210
+
211
+ d.run do
212
+ d.expected_emits.each {|tag,time,record|
213
+ res = post("/#{tag}", {"json"=>record.to_json, "time"=>time.to_s})
214
+ assert_equal "200", res.code
215
+ # Ruby returns ASCII-8 encoded string for GIF.
216
+ assert_equal Fluent::HttpInput::EMPTY_GIF_IMAGE, res.body.force_encoding("UTF-8")
217
+ }
218
+ end
219
+ end
220
+
221
+ def test_if_content_type_is_initialized_properly
222
+ # This test is to check if Fluent::HttpInput::Handler's @content_type is initialized properly.
223
+ # Especially when in Keep-Alive and the second request has no 'Content-Type'.
224
+ #
225
+ # Actually, in the current implementation of in_http, we can't test it directly.
226
+ # So we replace Fluent::HttpInput::Handler temporally with the extended Handler
227
+ # in order to collect @content_type(s) per request.
228
+ # Finally, we check those collected @content_type(s).
229
+
230
+ # Save the original Handler
231
+ orig_handler = Fluent::HttpInput::Handler
232
+
233
+ begin
234
+ # Create the extended Handler which can store @content_type per request
235
+ ext_handler = Class.new(Fluent::HttpInput::Handler) do
236
+ @@content_types = []
237
+
238
+ def self.content_types
239
+ @@content_types
240
+ end
241
+
242
+ def on_message_complete
243
+ @@content_types << @content_type
244
+ super
245
+ end
246
+ end
247
+
248
+ # Replace the original Handler temporally with the extended one
249
+ Fluent::HttpInput.module_eval do
250
+ remove_const(:Handler) if const_defined?(:Handler)
251
+ const_set(:Handler, ext_handler)
252
+ end
253
+
254
+ d = create_driver
255
+
256
+ d.run do
257
+ # Send two requests the second one has no Content-Type in Keep-Alive
258
+ Net::HTTP.start("127.0.0.1", PORT) do |http|
259
+ req = Net::HTTP::Post.new("/foodb/bartbl", {"connection" => "keepalive", "content-type" => "application/json"})
260
+ res = http.request(req)
261
+
262
+ req = Net::HTTP::Get.new("/foodb/bartbl", {"connection" => "keepalive"})
263
+ res = http.request(req)
264
+ end
265
+
266
+ assert_equal(['application/json', ''], ext_handler.content_types)
267
+ end
268
+ ensure
269
+ # Revert the original Handler
270
+ Fluent::HttpInput.module_eval do
271
+ remove_const(:Handler) if const_defined?(:Handler)
272
+ const_set(:Handler, orig_handler)
273
+ end
274
+ end
275
+ end
276
+
202
277
  def post(path, params, header = {})
203
278
  http = Net::HTTP.new("127.0.0.1", PORT)
204
279
  req = Net::HTTP::Post.new(path, header)
@@ -1,4 +1,4 @@
1
- require 'fluent/test'
1
+ require_relative '../helper'
2
2
 
3
3
  class ObjectSpaceInputTest < Test::Unit::TestCase
4
4
  class FailObject
@@ -1,4 +1,4 @@
1
- require 'fluent/test'
1
+ require_relative '../helper'
2
2
 
3
3
  class StatusInputTest < Test::Unit::TestCase
4
4
  def setup
@@ -1,5 +1,4 @@
1
- require 'fluent/test'
2
- require 'helper'
1
+ require_relative '../helper'
3
2
 
4
3
  module StreamInputTest
5
4
  def setup
@@ -1,5 +1,4 @@
1
- require 'fluent/test'
2
- require 'helper'
1
+ require_relative '../helper'
3
2
 
4
3
  class SyslogInputTest < Test::Unit::TestCase
5
4
  def setup
@@ -1,4 +1,4 @@
1
- require 'fluent/test'
1
+ require_relative '../helper'
2
2
  require 'net/http'
3
3
  require 'flexmock'
4
4
 
@@ -1,5 +1,4 @@
1
- require 'fluent/test'
2
- require 'helper'
1
+ require_relative '../helper'
3
2
 
4
3
  class TcpInputTest < Test::Unit::TestCase
5
4
  def setup
@@ -1,5 +1,4 @@
1
- require 'fluent/test'
2
- require 'helper'
1
+ require_relative '../helper'
3
2
 
4
3
  class UdpInputTest < Test::Unit::TestCase
5
4
  def setup
@@ -1,6 +1,17 @@
1
- require 'fluent/test'
1
+ require_relative '../helper'
2
2
 
3
3
  class CopyOutputTest < Test::Unit::TestCase
4
+ class << self
5
+ def startup
6
+ $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', 'scripts'))
7
+ require 'fluent/plugin/out_test'
8
+ end
9
+
10
+ def shutdown
11
+ $LOAD_PATH.shift
12
+ end
13
+ end
14
+
4
15
  def setup
5
16
  Fluent::Test.setup
6
17
  end
@@ -1,4 +1,4 @@
1
- require 'fluent/test'
1
+ require_relative '../helper'
2
2
  require 'fileutils'
3
3
 
4
4
  class ExecOutputTest < Test::Unit::TestCase
@@ -1,4 +1,4 @@
1
- require 'fluent/test'
1
+ require_relative '../helper'
2
2
  require 'fileutils'
3
3
 
4
4
  class ExecFilterOutputTest < Test::Unit::TestCase
@@ -1,3 +1,4 @@
1
+ require_relative '../helper'
1
2
  require 'fluent/test'
2
3
  require 'fileutils'
3
4
  require 'time'
@@ -125,7 +126,7 @@ class FileOutputTest < Test::Unit::TestCase
125
126
 
126
127
  # FileOutput#write returns path
127
128
  path = d.run
128
- expect_path = "#{TMP_DIR}/out_file_test._0.log.gz"
129
+ expect_path = "#{TMP_DIR}/out_file_test.20110102_0.log.gz"
129
130
  assert_equal expect_path, path
130
131
 
131
132
  check_gzipped_result(path, %[2011-01-02T13:14:15Z\ttest\t{"a":1}\n] + %[2011-01-02T13:14:15Z\ttest\t{"a":2}\n])
@@ -177,13 +178,13 @@ class FileOutputTest < Test::Unit::TestCase
177
178
 
178
179
  # FileOutput#write returns path
179
180
  path = d.run
180
- assert_equal "#{TMP_DIR}/out_file_test._0.log.gz", path
181
+ assert_equal "#{TMP_DIR}/out_file_test.20110102_0.log.gz", path
181
182
  check_gzipped_result(path, formatted_lines)
182
183
  path = d.run
183
- assert_equal "#{TMP_DIR}/out_file_test._1.log.gz", path
184
+ assert_equal "#{TMP_DIR}/out_file_test.20110102_1.log.gz", path
184
185
  check_gzipped_result(path, formatted_lines)
185
186
  path = d.run
186
- assert_equal "#{TMP_DIR}/out_file_test._2.log.gz", path
187
+ assert_equal "#{TMP_DIR}/out_file_test.20110102_2.log.gz", path
187
188
  check_gzipped_result(path, formatted_lines)
188
189
  end
189
190
 
@@ -202,13 +203,13 @@ class FileOutputTest < Test::Unit::TestCase
202
203
 
203
204
  # FileOutput#write returns path
204
205
  path = d.run
205
- assert_equal "#{TMP_DIR}/out_file_test..log.gz", path
206
+ assert_equal "#{TMP_DIR}/out_file_test.20110102.log.gz", path
206
207
  check_gzipped_result(path, formatted_lines)
207
208
  path = d.run
208
- assert_equal "#{TMP_DIR}/out_file_test..log.gz", path
209
+ assert_equal "#{TMP_DIR}/out_file_test.20110102.log.gz", path
209
210
  check_gzipped_result(path, formatted_lines * 2)
210
211
  path = d.run
211
- assert_equal "#{TMP_DIR}/out_file_test..log.gz", path
212
+ assert_equal "#{TMP_DIR}/out_file_test.20110102.log.gz", path
212
213
  check_gzipped_result(path, formatted_lines * 3)
213
214
  end
214
215
 
@@ -240,5 +241,58 @@ class FileOutputTest < Test::Unit::TestCase
240
241
  FileUtils.rm_rf(symlink_path)
241
242
  end
242
243
  end
244
+
245
+ sub_test_case 'path' do
246
+ test 'normal' do
247
+ d = create_driver(%[
248
+ path #{TMP_DIR}/out_file_test
249
+ time_slice_format %Y-%m-%d-%H
250
+ utc true
251
+ ])
252
+ time = Time.parse("2011-01-02 13:14:15 UTC").to_i
253
+ d.emit({"a"=>1}, time)
254
+ # FileOutput#write returns path
255
+ path = d.run
256
+ assert_equal "#{TMP_DIR}/out_file_test.2011-01-02-13_0.log", path
257
+ end
258
+
259
+ test 'normal with append' do
260
+ d = create_driver(%[
261
+ path #{TMP_DIR}/out_file_test
262
+ time_slice_format %Y-%m-%d-%H
263
+ utc true
264
+ append true
265
+ ])
266
+ time = Time.parse("2011-01-02 13:14:15 UTC").to_i
267
+ d.emit({"a"=>1}, time)
268
+ path = d.run
269
+ assert_equal "#{TMP_DIR}/out_file_test.2011-01-02-13.log", path
270
+ end
271
+
272
+ test '*' do
273
+ d = create_driver(%[
274
+ path #{TMP_DIR}/out_file_test.*.txt
275
+ time_slice_format %Y-%m-%d-%H
276
+ utc true
277
+ ])
278
+ time = Time.parse("2011-01-02 13:14:15 UTC").to_i
279
+ d.emit({"a"=>1}, time)
280
+ path = d.run
281
+ assert_equal "#{TMP_DIR}/out_file_test.2011-01-02-13_0.txt", path
282
+ end
283
+
284
+ test '* with append' do
285
+ d = create_driver(%[
286
+ path #{TMP_DIR}/out_file_test.*.txt
287
+ time_slice_format %Y-%m-%d-%H
288
+ utc true
289
+ append true
290
+ ])
291
+ time = Time.parse("2011-01-02 13:14:15 UTC").to_i
292
+ d.emit({"a"=>1}, time)
293
+ path = d.run
294
+ assert_equal "#{TMP_DIR}/out_file_test.2011-01-02-13.txt", path
295
+ end
296
+ end
243
297
  end
244
298