fluentd 1.10.1-x86-mingw32 → 1.11.1-x86-mingw32

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +112 -1
  3. data/CONTRIBUTING.md +1 -1
  4. data/lib/fluent/command/debug.rb +1 -0
  5. data/lib/fluent/command/fluentd.rb +12 -1
  6. data/lib/fluent/config.rb +1 -0
  7. data/lib/fluent/log.rb +45 -6
  8. data/lib/fluent/match.rb +1 -1
  9. data/lib/fluent/plugin/in_dummy.rb +2 -2
  10. data/lib/fluent/plugin/in_forward.rb +2 -2
  11. data/lib/fluent/plugin/in_gc_stat.rb +16 -0
  12. data/lib/fluent/plugin/in_http.rb +146 -75
  13. data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
  14. data/lib/fluent/plugin/in_syslog.rb +4 -4
  15. data/lib/fluent/plugin/in_tail.rb +4 -4
  16. data/lib/fluent/plugin/in_unix.rb +77 -77
  17. data/lib/fluent/plugin/out_copy.rb +1 -1
  18. data/lib/fluent/plugin/out_file.rb +1 -1
  19. data/lib/fluent/plugin/out_forward.rb +23 -18
  20. data/lib/fluent/plugin/out_forward/load_balancer.rb +1 -1
  21. data/lib/fluent/plugin/out_http.rb +15 -2
  22. data/lib/fluent/plugin/parser_multiline.rb +1 -1
  23. data/lib/fluent/plugin/parser_syslog.rb +215 -54
  24. data/lib/fluent/plugin_helper/child_process.rb +3 -2
  25. data/lib/fluent/plugin_helper/record_accessor.rb +14 -0
  26. data/lib/fluent/plugin_helper/service_discovery.rb +7 -0
  27. data/lib/fluent/plugin_helper/service_discovery/manager.rb +8 -0
  28. data/lib/fluent/plugin_helper/socket.rb +20 -2
  29. data/lib/fluent/plugin_helper/socket_option.rb +2 -2
  30. data/lib/fluent/supervisor.rb +21 -9
  31. data/lib/fluent/system_config.rb +2 -1
  32. data/lib/fluent/test/filter_test.rb +2 -2
  33. data/lib/fluent/test/output_test.rb +3 -3
  34. data/lib/fluent/version.rb +1 -1
  35. data/test/command/test_fluentd.rb +57 -10
  36. data/test/config/test_system_config.rb +2 -0
  37. data/test/plugin/out_forward/test_load_balancer.rb +46 -0
  38. data/test/plugin/test_in_gc_stat.rb +24 -1
  39. data/test/plugin/test_in_http.rb +57 -0
  40. data/test/plugin/test_in_syslog.rb +1 -1
  41. data/test/plugin/test_in_tail.rb +20 -16
  42. data/test/plugin/test_in_unix.rb +128 -73
  43. data/test/plugin/test_out_forward.rb +11 -2
  44. data/test/plugin/test_out_http.rb +38 -0
  45. data/test/plugin/test_out_null.rb +1 -1
  46. data/test/plugin/test_output_as_buffered_retries.rb +12 -4
  47. data/test/plugin/test_parser_syslog.rb +66 -29
  48. data/test/plugin_helper/data/cert/cert_chains/ca-cert-key.pem +27 -0
  49. data/test/plugin_helper/data/cert/cert_chains/ca-cert.pem +20 -0
  50. data/test/plugin_helper/data/cert/cert_chains/cert-key.pem +27 -0
  51. data/test/plugin_helper/data/cert/cert_chains/cert.pem +40 -0
  52. data/test/plugin_helper/data/cert/generate_cert.rb +38 -0
  53. data/test/plugin_helper/http_server/test_app.rb +1 -1
  54. data/test/plugin_helper/http_server/test_route.rb +1 -1
  55. data/test/plugin_helper/test_child_process.rb +15 -0
  56. data/test/plugin_helper/test_http_server_helper.rb +2 -2
  57. data/test/plugin_helper/test_record_accessor.rb +41 -0
  58. data/test/plugin_helper/test_server.rb +1 -1
  59. data/test/plugin_helper/test_service_discovery.rb +37 -4
  60. data/test/plugin_helper/test_socket.rb +131 -0
  61. data/test/test_log.rb +44 -0
  62. metadata +12 -2
@@ -22,9 +22,14 @@ class GCStatInputTest < Test::Unit::TestCase
22
22
  assert_equal("t1", d.instance.tag)
23
23
  end
24
24
 
25
- def test_emit
25
+ def setup_gc_stat
26
26
  stat = GC.stat
27
27
  stub(GC).stat { stat }
28
+ stat
29
+ end
30
+
31
+ def test_emit
32
+ stat = setup_gc_stat
28
33
 
29
34
  d = create_driver
30
35
  d.run(expect_emits: 2)
@@ -36,4 +41,22 @@ class GCStatInputTest < Test::Unit::TestCase
36
41
  assert(events[i][1].is_a?(Fluent::EventTime))
37
42
  }
38
43
  end
44
+
45
+ def test_emit_with_use_symbol_keys_false
46
+ stat = setup_gc_stat
47
+ result = {}
48
+ stat.each_pair { |k, v|
49
+ result[k.to_s] = v
50
+ }
51
+
52
+ d = create_driver(CONFIG + "use_symbol_keys false")
53
+ d.run(expect_emits: 2)
54
+
55
+ events = d.events
56
+ assert(events.length > 0)
57
+ events.each_index {|i|
58
+ assert_equal(result, events[i][2])
59
+ assert(events[i][1].is_a?(Fluent::EventTime))
60
+ }
61
+ end
39
62
  end
@@ -116,6 +116,36 @@ class HttpInputTest < Test::Unit::TestCase
116
116
  assert_equal_event_time time, d.events[1][1]
117
117
  end
118
118
 
119
+ data('json' => ['json', :to_json],
120
+ 'msgpack' => ['msgpack', :to_msgpack])
121
+ def test_default_with_time_format(data)
122
+ param, method_name = data
123
+ d = create_driver(CONFIG + %[
124
+ <parse>
125
+ keep_time_key
126
+ time_format %iso8601
127
+ </parse>
128
+ ])
129
+
130
+ time = event_time("2020-06-10T01:14:27+00:00")
131
+ events = [
132
+ ["tag1", time, {"a" => 1, "time" => '2020-06-10T01:14:27+00:00'}],
133
+ ["tag2", time, {"a" => 2, "time" => '2020-06-10T01:14:27+00:00'}],
134
+ ]
135
+ res_codes = []
136
+
137
+ d.run(expect_records: 2) do
138
+ events.each do |tag, t, record|
139
+ res = post("/#{tag}", {param => record.__send__(method_name)})
140
+ res_codes << res.code
141
+ end
142
+ end
143
+ assert_equal ["200", "200"], res_codes
144
+ assert_equal events, d.events
145
+ assert_equal_event_time time, d.events[0][1]
146
+ assert_equal_event_time time, d.events[1][1]
147
+ end
148
+
119
149
  def test_multi_json
120
150
  d = create_driver
121
151
  time = event_time("2011-01-02 13:14:15 UTC")
@@ -163,6 +193,33 @@ class HttpInputTest < Test::Unit::TestCase
163
193
  assert_equal_event_time time, d.events[1][1]
164
194
  end
165
195
 
196
+ data('json' => ['json', :to_json],
197
+ 'msgpack' => ['msgpack', :to_msgpack])
198
+ def test_default_multi_with_time_format(data)
199
+ param, method_name = data
200
+ d = create_driver(CONFIG + %[
201
+ <parse>
202
+ keep_time_key
203
+ time_format %iso8601
204
+ </parse>
205
+ ])
206
+ time = event_time("2020-06-10T01:14:27+00:00")
207
+ events = [
208
+ ["tag1", time, {'a' => 1, 'time' => "2020-06-10T01:14:27+00:00"}],
209
+ ["tag1", time, {'a' => 2, 'time' => "2020-06-10T01:14:27+00:00"}],
210
+ ]
211
+ tag = "tag1"
212
+ res_codes = []
213
+ d.run(expect_records: 2, timeout: 5) do
214
+ res = post("/#{tag}", {param => events.map { |e| e[2] }.__send__(method_name)})
215
+ res_codes << res.code
216
+ end
217
+ assert_equal ["200"], res_codes
218
+ assert_equal events, d.events
219
+ assert_equal_event_time time, d.events[0][1]
220
+ assert_equal_event_time time, d.events[1][1]
221
+ end
222
+
166
223
  def test_multi_json_with_nonexistent_time_key
167
224
  d = create_driver(CONFIG + %[
168
225
  <parse>
@@ -375,7 +375,7 @@ EOS
375
375
  ]
376
376
  msgs.each { |msg|
377
377
  m = msg['msg']
378
- msg['msg'] = "#{m.size + 1} #{m}"
378
+ msg['msg'] = "#{m.size} #{m}"
379
379
  }
380
380
  msgs
381
381
  end
@@ -23,9 +23,6 @@ class TailInputTest < Test::Unit::TestCase
23
23
  def cleanup_directory(path)
24
24
  FileUtils.rm_rf(path, secure: true)
25
25
  if File.exist?(path)
26
- # ensure files are closed for Windows, on which deleted files
27
- # are still visible from filesystem
28
- GC.start(full_mark: true, immediate_mark: true, immediate_sweep: true)
29
26
  FileUtils.remove_entry_secure(path, true)
30
27
  end
31
28
  FileUtils.mkdir_p(path)
@@ -105,6 +102,12 @@ class TailInputTest < Test::Unit::TestCase
105
102
  assert_equal ["tail.txt", "test2", "tmp,dev"], d.instance.paths
106
103
  end
107
104
 
105
+ test "multi paths with same path configured twice" do
106
+ c = config_element("ROOT", "", { "path" => "test1.txt,test2.txt,test1.txt", "tag" => "t1", "path_delimiter" => "," })
107
+ d = create_driver(c + PARSE_SINGLE_LINE_CONFIG, false)
108
+ assert_equal ["test2.txt","test1.txt"].sort, d.instance.paths.sort
109
+ end
110
+
108
111
  test "multi paths with invaid path_delimiter" do
109
112
  c = config_element("ROOT", "", { "path" => "tail.txt|test2|tmp,dev", "tag" => "t1", "path_delimiter" => "*" })
110
113
  assert_raise(Fluent::ConfigError) do
@@ -1025,6 +1028,17 @@ class TailInputTest < Test::Unit::TestCase
1025
1028
  assert_equal EX_PATHS - [EX_PATHS.last], plugin.expand_paths.sort
1026
1029
  end
1027
1030
 
1031
+ def test_expand_paths_with_duplicate_configuration
1032
+ expanded_paths = [
1033
+ 'test/plugin/data/log/foo/bar.log',
1034
+ 'test/plugin/data/log/test.log'
1035
+ ]
1036
+ duplicate_config = EX_CONFIG.dup
1037
+ duplicate_config["path"]="test/plugin/data/log/**/*.log, test/plugin/data/log/**/*.log"
1038
+ plugin = create_driver(EX_CONFIG, false).instance
1039
+ assert_equal expanded_paths, plugin.expand_paths.sort
1040
+ end
1041
+
1028
1042
  def test_expand_paths_with_timezone
1029
1043
  ['Asia/Taipei', '+08'].each do |tz_type|
1030
1044
  taipei_config = EX_CONFIG + config_element("", "", {"path_timezone" => tz_type})
@@ -1065,9 +1079,6 @@ class TailInputTest < Test::Unit::TestCase
1065
1079
  assert_equal expected_files, plugin.expand_paths.sort
1066
1080
  end
1067
1081
 
1068
- # For https://github.com/fluent/fluentd/issues/1455
1069
- # This test is fragile because test content depends on internal implementation.
1070
- # So if you modify in_tail internal, this test may break.
1071
1082
  def test_unwatched_files_should_be_removed
1072
1083
  config = config_element("", "", {
1073
1084
  "tag" => "tail",
@@ -1079,22 +1090,15 @@ class TailInputTest < Test::Unit::TestCase
1079
1090
  })
1080
1091
  d = create_driver(config, false)
1081
1092
  d.end_if { d.instance.instance_variable_get(:@tails).keys.size >= 1 }
1082
- d.run(expect_emits: 1, shutdown: false, timeout: 1) do
1093
+ d.run(expect_emits: 1, shutdown: false) do
1083
1094
  File.open("#{TMP_DIR}/tail.txt", "ab") { |f| f.puts "test3\n" }
1084
1095
  end
1085
1096
 
1086
1097
  cleanup_directory(TMP_DIR)
1087
1098
  waiting(20) { sleep 0.1 until Dir.glob("#{TMP_DIR}/*.txt").size == 0 } # Ensure file is deleted on Windows
1088
- waiting(5) { sleep 0.1 until d.instance.instance_variable_get(:@tails).keys.size == 0 }
1099
+ waiting(5) { sleep 0.1 until d.instance.instance_variable_get(:@tails).keys.size <= 0 }
1089
1100
 
1090
- # Previous implementation has an infinite watcher creation bug.
1091
- # Following code checks such unexpected bug by counting actual object allocation.
1092
- base_num = count_timer_object
1093
- 2.times {
1094
- sleep 1
1095
- num = count_timer_object
1096
- assert_equal base_num, num
1097
- }
1101
+ assert_equal 0, d.instance.instance_variable_get(:@tails).keys.size
1098
1102
 
1099
1103
  d.instance_shutdown
1100
1104
  end
@@ -1,126 +1,181 @@
1
1
  require_relative '../helper'
2
- require 'fluent/test'
2
+ require 'fluent/test/driver/input'
3
3
  require 'fluent/plugin/in_unix'
4
4
 
5
- module StreamInputTest
5
+ class UnixInputTest < Test::Unit::TestCase
6
6
  def setup
7
7
  Fluent::Test.setup
8
+ @d = nil
8
9
  end
9
10
 
10
- def test_time
11
- d = create_driver
11
+ def teardown
12
+ @d.instance_shutdown if @d
13
+ end
12
14
 
13
- time = Fluent::EventTime.parse("2011-01-02 13:14:15 UTC")
14
- Fluent::Engine.now = time
15
+ TMP_DIR = File.dirname(__FILE__) + "/../tmp/in_unix#{ENV['TEST_ENV_NUMBER']}"
16
+ CONFIG = %[
17
+ path #{TMP_DIR}/unix
18
+ backlog 1000
19
+ ]
20
+
21
+ def create_driver(conf = CONFIG)
22
+ Fluent::Test::Driver::Input.new(Fluent::Plugin::UnixInput).configure(conf)
23
+ end
15
24
 
16
- d.expect_emit "tag1", time, {"a"=>1}
17
- d.expect_emit "tag2", time, {"a"=>2}
25
+ def packer(*args)
26
+ Fluent::MessagePackFactory.msgpack_packer(*args)
27
+ end
18
28
 
19
- d.run do
20
- d.expected_emits.each {|tag,_time,record|
21
- send_data Fluent::MessagePackFactory.msgpack_packer.write([tag, 0, record]).to_s
29
+ def unpacker
30
+ Fluent::MessagePackFactory.msgpack_unpacker
31
+ end
32
+
33
+ def send_data(data)
34
+ io = UNIXSocket.new("#{TMP_DIR}/unix")
35
+ begin
36
+ io.write data
37
+ ensure
38
+ io.close
39
+ end
40
+ end
41
+
42
+ def test_configure
43
+ @d = create_driver
44
+ assert_equal "#{TMP_DIR}/unix", @d.instance.path
45
+ assert_equal 1000, @d.instance.backlog
46
+ end
47
+
48
+ def test_time
49
+ @d = create_driver
50
+
51
+ time = Fluent::EventTime.now
52
+ records = [
53
+ ["tag1", 0, {"a" => 1}],
54
+ ["tag2", nil, {"a" => 2}],
55
+ ]
56
+
57
+ @d.run(expect_records: records.length, timeout: 5) do
58
+ records.each {|tag, _time, record|
59
+ send_data packer.write([tag, _time, record]).to_s
22
60
  }
23
61
  end
62
+
63
+ @d.events.each_with_index { |e, i|
64
+ orig = records[i]
65
+ assert_equal(orig[0], e[0])
66
+ assert_true(time <= e[1])
67
+ assert_equal(orig[2], e[2])
68
+ }
24
69
  end
25
70
 
26
71
  def test_message
27
- d = create_driver
72
+ @d = create_driver
28
73
 
29
- time = Fluent::EventTime.parse("2011-01-02 13:14:15 UTC")
30
-
31
- d.expect_emit "tag1", time, {"a"=>1}
32
- d.expect_emit "tag2", time, {"a"=>2}
74
+ time = Fluent::EventTime.now
75
+ records = [
76
+ ["tag1", time, {"a" => 1}],
77
+ ["tag2", time, {"a" => 2}],
78
+ ]
33
79
 
34
- d.run do
35
- d.expected_emits.each {|tag,_time,record|
36
- send_data Fluent::MessagePackFactory.msgpack_packer.write([tag, _time, record]).to_s
80
+ @d.run(expect_records: records.length, timeout: 5) do
81
+ records.each {|tag, _time, record|
82
+ send_data packer.write([tag, _time, record]).to_s
37
83
  }
38
84
  end
85
+
86
+ assert_equal(records, @d.events)
39
87
  end
40
88
 
41
89
  def test_forward
42
- d = create_driver
90
+ @d = create_driver
43
91
 
44
92
  time = Fluent::EventTime.parse("2011-01-02 13:14:15 UTC")
93
+ records = [
94
+ ["tag1", time, {"a" => 1}],
95
+ ["tag1", time, {"a" => 2}]
96
+ ]
45
97
 
46
- d.expect_emit "tag1", time, {"a"=>1}
47
- d.expect_emit "tag1", time, {"a"=>2}
48
-
49
- d.run do
98
+ @d.run(expect_records: records.length, timeout: 20) do
50
99
  entries = []
51
- d.expected_emits.each {|tag,_time,record|
100
+ records.each {|tag, _time, record|
52
101
  entries << [_time, record]
53
102
  }
54
- send_data Fluent::MessagePackFactory.msgpack_packer.write(["tag1", entries]).to_s
103
+ send_data packer.write(["tag1", entries]).to_s
55
104
  end
105
+ assert_equal(records, @d.events)
56
106
  end
57
107
 
58
108
  def test_packed_forward
59
- d = create_driver
109
+ @d = create_driver
60
110
 
61
- time = Fluent::EventTime.parse("2011-01-02 13:14:15 UTC")
62
-
63
- d.expect_emit "tag1", time, {"a"=>1}
64
- d.expect_emit "tag1", time, {"a"=>2}
111
+ time = Fluent::EventTime.now
112
+ records = [
113
+ ["tag1", time, {"a" => 1}],
114
+ ["tag1", time, {"a" => 2}],
115
+ ]
65
116
 
66
- d.run do
117
+ @d.run(expect_records: records.length, timeout: 20) do
67
118
  entries = ''
68
- d.expected_emits.each {|tag,_time,record|
69
- Fluent::MessagePackFactory.msgpack_packer(entries).write([_time, record]).flush
119
+ records.each {|_tag, _time, record|
120
+ packer(entries).write([_time, record]).flush
70
121
  }
71
- send_data Fluent::MessagePackFactory.msgpack_packer.write(["tag1", entries]).to_s
122
+ send_data packer.write(["tag1", entries]).to_s
72
123
  end
124
+ assert_equal(records, @d.events)
73
125
  end
74
126
 
75
127
  def test_message_json
76
- d = create_driver
128
+ @d = create_driver
129
+
130
+ time = Fluent::EventTime.now
131
+ records = [
132
+ ["tag1", time, {"a" => 1}],
133
+ ["tag2", time, {"a" => 2}],
134
+ ]
135
+
136
+ @d.run(expect_records: records.length, timeout: 5) do
137
+ tag, _time, record = records[0]
138
+ send_data [tag, _time.to_i, record].to_json
139
+ tag, _time, record = records[1]
140
+ send_data [tag, _time.to_f, record].to_json
141
+ end
77
142
 
78
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
143
+ assert_equal(records, @d.events)
144
+ end
145
+
146
+ def test_message_with_tag
147
+ @d = create_driver(CONFIG + "tag new_tag")
79
148
 
80
- d.expect_emit "tag1", time, {"a"=>1}
81
- d.expect_emit "tag2", time, {"a"=>2}
149
+ time = Fluent::EventTime.now
150
+ records = [
151
+ ["tag1", time, {"a" => 1}],
152
+ ["tag2", time, {"a" => 2}],
153
+ ]
82
154
 
83
- d.run do
84
- d.expected_emits.each {|tag,_time,record|
85
- send_data [tag, time, record].to_json
155
+ @d.run(expect_records: records.length, timeout: 5) do
156
+ records.each {|tag, _time, record|
157
+ send_data packer.write([tag, _time, record]).to_s
86
158
  }
87
159
  end
88
- end
89
160
 
90
- def create_driver(klass, conf)
91
- Fluent::Test::InputTestDriver.new(klass).configure(conf)
161
+ @d.events.each { |event|
162
+ assert_equal("new_tag", event[0])
163
+ }
92
164
  end
93
165
 
94
- def send_data(data)
95
- io = connect
96
- begin
97
- io.write data
98
- ensure
99
- io.close
166
+ data('string chunk' => 'broken string',
167
+ 'integer chunk' => 10)
168
+ def test_broken_message(data)
169
+ @d = create_driver
170
+ @d.run(shutdown: false, timeout: 5) do
171
+ @d.instance.__send__(:on_message, data)
100
172
  end
101
- end
102
- end
103
-
104
- class UnixInputTest < Test::Unit::TestCase
105
- include StreamInputTest
106
-
107
- TMP_DIR = File.dirname(__FILE__) + "/../tmp/in_unix#{ENV['TEST_ENV_NUMBER']}"
108
- CONFIG = %[
109
- path #{TMP_DIR}/unix
110
- backlog 1000
111
- ]
112
173
 
113
- def create_driver(conf=CONFIG)
114
- super(Fluent::UnixInput, conf)
115
- end
116
-
117
- def test_configure
118
- d = create_driver
119
- assert_equal "#{TMP_DIR}/unix", d.instance.path
120
- assert_equal 1000, d.instance.backlog
121
- end
174
+ assert_equal 0, @d.events.size
122
175
 
123
- def connect
124
- UNIXSocket.new("#{TMP_DIR}/unix")
176
+ logs = @d.instance.log.logs
177
+ assert_equal 1, logs.select { |line|
178
+ line =~ / \[warn\]: incoming data is broken: msg=#{data.inspect}/
179
+ }.size, "should not accept broken chunk"
125
180
  end
126
181
  end unless Fluent.windows?
@@ -1056,7 +1056,7 @@ EOL
1056
1056
  e = assert_raise Fluent::UnrecoverableError do
1057
1057
  d.instance_start
1058
1058
  end
1059
- assert_match(/Failed to establish connection/, e.message)
1059
+ assert_match(/failed to establish connection/, e.message)
1060
1060
  end
1061
1061
  end
1062
1062
 
@@ -1092,7 +1092,7 @@ EOL
1092
1092
  d.instance_start
1093
1093
  end
1094
1094
 
1095
- assert_match(/Failed to establish connection/, e.message)
1095
+ assert_match(/failed to establish connection/, e.message)
1096
1096
  end
1097
1097
  end
1098
1098
 
@@ -1200,6 +1200,15 @@ EOL
1200
1200
  end
1201
1201
  end
1202
1202
 
1203
+ test 'create timer of purging obsolete sockets' do
1204
+ output_conf = CONFIG + %[keepalive true]
1205
+ d = create_driver(output_conf)
1206
+
1207
+ mock(d.instance).timer_execute(:out_forward_heartbeat_request, 1).once
1208
+ mock(d.instance).timer_execute(:out_forward_keep_alived_socket_watcher, 5).once
1209
+ d.instance_start
1210
+ end
1211
+
1203
1212
  sub_test_case 'with require_ack_response' do
1204
1213
  test 'Create connection per send_data' do
1205
1214
  target_input_driver = create_target_input_driver(conf: TARGET_CONFIG)