fluentd 1.13.3 → 1.16.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/{bug_report.yaml → bug_report.yml} +2 -0
  3. data/.github/ISSUE_TEMPLATE/config.yml +2 -2
  4. data/.github/ISSUE_TEMPLATE/{feature_request.yaml → feature_request.yml} +1 -0
  5. data/.github/workflows/stale-actions.yml +11 -9
  6. data/.github/workflows/test.yml +32 -0
  7. data/CHANGELOG.md +490 -10
  8. data/CONTRIBUTING.md +2 -2
  9. data/MAINTAINERS.md +7 -5
  10. data/README.md +3 -23
  11. data/Rakefile +1 -1
  12. data/SECURITY.md +14 -0
  13. data/fluentd.gemspec +7 -8
  14. data/lib/fluent/command/cat.rb +13 -3
  15. data/lib/fluent/command/ctl.rb +6 -3
  16. data/lib/fluent/command/fluentd.rb +73 -65
  17. data/lib/fluent/command/plugin_config_formatter.rb +1 -1
  18. data/lib/fluent/compat/output.rb +9 -6
  19. data/lib/fluent/config/dsl.rb +1 -1
  20. data/lib/fluent/config/error.rb +12 -0
  21. data/lib/fluent/config/literal_parser.rb +2 -2
  22. data/lib/fluent/config/parser.rb +1 -1
  23. data/lib/fluent/config/v1_parser.rb +3 -3
  24. data/lib/fluent/config/yaml_parser/fluent_value.rb +47 -0
  25. data/lib/fluent/config/yaml_parser/loader.rb +108 -0
  26. data/lib/fluent/config/yaml_parser/parser.rb +166 -0
  27. data/lib/fluent/config/yaml_parser/section_builder.rb +107 -0
  28. data/lib/fluent/config/yaml_parser.rb +56 -0
  29. data/lib/fluent/config.rb +14 -1
  30. data/lib/fluent/counter/server.rb +1 -1
  31. data/lib/fluent/counter/validator.rb +3 -3
  32. data/lib/fluent/daemon.rb +2 -4
  33. data/lib/fluent/engine.rb +1 -1
  34. data/lib/fluent/env.rb +4 -0
  35. data/lib/fluent/error.rb +3 -0
  36. data/lib/fluent/event.rb +8 -4
  37. data/lib/fluent/event_router.rb +47 -2
  38. data/lib/fluent/file_wrapper.rb +137 -0
  39. data/lib/fluent/log/console_adapter.rb +66 -0
  40. data/lib/fluent/log.rb +44 -5
  41. data/lib/fluent/match.rb +1 -1
  42. data/lib/fluent/msgpack_factory.rb +6 -1
  43. data/lib/fluent/oj_options.rb +1 -2
  44. data/lib/fluent/plugin/bare_output.rb +49 -8
  45. data/lib/fluent/plugin/base.rb +26 -9
  46. data/lib/fluent/plugin/buf_file.rb +34 -5
  47. data/lib/fluent/plugin/buf_file_single.rb +32 -3
  48. data/lib/fluent/plugin/buffer/file_chunk.rb +1 -1
  49. data/lib/fluent/plugin/buffer.rb +216 -70
  50. data/lib/fluent/plugin/filter.rb +35 -1
  51. data/lib/fluent/plugin/filter_record_transformer.rb +1 -1
  52. data/lib/fluent/plugin/in_forward.rb +2 -2
  53. data/lib/fluent/plugin/in_http.rb +39 -10
  54. data/lib/fluent/plugin/in_monitor_agent.rb +4 -2
  55. data/lib/fluent/plugin/in_sample.rb +1 -1
  56. data/lib/fluent/plugin/in_syslog.rb +13 -1
  57. data/lib/fluent/plugin/in_tail/group_watch.rb +204 -0
  58. data/lib/fluent/plugin/in_tail/position_file.rb +33 -33
  59. data/lib/fluent/plugin/in_tail.rb +216 -84
  60. data/lib/fluent/plugin/in_tcp.rb +47 -2
  61. data/lib/fluent/plugin/input.rb +39 -1
  62. data/lib/fluent/plugin/metrics.rb +119 -0
  63. data/lib/fluent/plugin/metrics_local.rb +96 -0
  64. data/lib/fluent/plugin/multi_output.rb +43 -6
  65. data/lib/fluent/plugin/out_copy.rb +1 -1
  66. data/lib/fluent/plugin/out_exec_filter.rb +2 -2
  67. data/lib/fluent/plugin/out_file.rb +20 -2
  68. data/lib/fluent/plugin/out_forward/ack_handler.rb +19 -4
  69. data/lib/fluent/plugin/out_forward/socket_cache.rb +2 -0
  70. data/lib/fluent/plugin/out_forward.rb +17 -9
  71. data/lib/fluent/plugin/out_secondary_file.rb +39 -22
  72. data/lib/fluent/plugin/output.rb +167 -78
  73. data/lib/fluent/plugin/parser.rb +3 -4
  74. data/lib/fluent/plugin/parser_apache2.rb +1 -1
  75. data/lib/fluent/plugin/parser_json.rb +1 -1
  76. data/lib/fluent/plugin/parser_syslog.rb +1 -1
  77. data/lib/fluent/plugin/storage_local.rb +3 -5
  78. data/lib/fluent/plugin.rb +10 -1
  79. data/lib/fluent/plugin_helper/child_process.rb +3 -0
  80. data/lib/fluent/plugin_helper/event_emitter.rb +8 -1
  81. data/lib/fluent/plugin_helper/event_loop.rb +2 -2
  82. data/lib/fluent/plugin_helper/http_server/server.rb +2 -1
  83. data/lib/fluent/plugin_helper/metrics.rb +129 -0
  84. data/lib/fluent/plugin_helper/record_accessor.rb +1 -1
  85. data/lib/fluent/plugin_helper/retry_state.rb +14 -4
  86. data/lib/fluent/plugin_helper/server.rb +35 -6
  87. data/lib/fluent/plugin_helper/service_discovery.rb +2 -2
  88. data/lib/fluent/plugin_helper/socket.rb +13 -2
  89. data/lib/fluent/plugin_helper/thread.rb +3 -3
  90. data/lib/fluent/plugin_helper.rb +1 -0
  91. data/lib/fluent/plugin_id.rb +3 -2
  92. data/lib/fluent/registry.rb +2 -1
  93. data/lib/fluent/root_agent.rb +6 -0
  94. data/lib/fluent/rpc.rb +4 -3
  95. data/lib/fluent/supervisor.rb +283 -259
  96. data/lib/fluent/system_config.rb +13 -3
  97. data/lib/fluent/test/driver/base.rb +11 -5
  98. data/lib/fluent/test/driver/filter.rb +4 -0
  99. data/lib/fluent/test/startup_shutdown.rb +6 -8
  100. data/lib/fluent/time.rb +21 -20
  101. data/lib/fluent/version.rb +1 -1
  102. data/lib/fluent/win32api.rb +38 -0
  103. data/lib/fluent/winsvc.rb +5 -8
  104. data/templates/new_gem/test/helper.rb.erb +0 -1
  105. data/test/command/test_cat.rb +31 -2
  106. data/test/command/test_ctl.rb +1 -2
  107. data/test/command/test_fluentd.rb +209 -24
  108. data/test/command/test_plugin_config_formatter.rb +0 -1
  109. data/test/compat/test_parser.rb +6 -6
  110. data/test/config/test_system_config.rb +13 -11
  111. data/test/config/test_types.rb +1 -1
  112. data/test/log/test_console_adapter.rb +110 -0
  113. data/test/plugin/in_tail/test_io_handler.rb +26 -8
  114. data/test/plugin/in_tail/test_position_file.rb +48 -59
  115. data/test/plugin/out_forward/test_ack_handler.rb +39 -0
  116. data/test/plugin/out_forward/test_socket_cache.rb +26 -1
  117. data/test/plugin/test_bare_output.rb +14 -1
  118. data/test/plugin/test_base.rb +133 -1
  119. data/test/plugin/test_buf_file.rb +62 -23
  120. data/test/plugin/test_buf_file_single.rb +65 -0
  121. data/test/plugin/test_buffer.rb +267 -3
  122. data/test/plugin/test_buffer_chunk.rb +11 -0
  123. data/test/plugin/test_filter.rb +12 -1
  124. data/test/plugin/test_filter_parser.rb +1 -1
  125. data/test/plugin/test_filter_stdout.rb +2 -2
  126. data/test/plugin/test_in_forward.rb +9 -11
  127. data/test/plugin/test_in_http.rb +65 -3
  128. data/test/plugin/test_in_monitor_agent.rb +216 -11
  129. data/test/plugin/test_in_object_space.rb +9 -3
  130. data/test/plugin/test_in_syslog.rb +35 -0
  131. data/test/plugin/test_in_tail.rb +1393 -385
  132. data/test/plugin/test_in_tcp.rb +87 -2
  133. data/test/plugin/test_in_udp.rb +28 -0
  134. data/test/plugin/test_in_unix.rb +2 -2
  135. data/test/plugin/test_input.rb +12 -1
  136. data/test/plugin/test_metrics.rb +294 -0
  137. data/test/plugin/test_metrics_local.rb +96 -0
  138. data/test/plugin/test_multi_output.rb +25 -1
  139. data/test/plugin/test_out_exec.rb +6 -4
  140. data/test/plugin/test_out_exec_filter.rb +6 -2
  141. data/test/plugin/test_out_file.rb +34 -17
  142. data/test/plugin/test_out_forward.rb +78 -77
  143. data/test/plugin/test_out_http.rb +1 -0
  144. data/test/plugin/test_out_stdout.rb +2 -2
  145. data/test/plugin/test_output.rb +297 -12
  146. data/test/plugin/test_output_as_buffered.rb +44 -44
  147. data/test/plugin/test_output_as_buffered_compress.rb +32 -18
  148. data/test/plugin/test_output_as_buffered_retries.rb +54 -7
  149. data/test/plugin/test_output_as_buffered_secondary.rb +4 -4
  150. data/test/plugin/test_parser_regexp.rb +1 -6
  151. data/test/plugin/test_parser_syslog.rb +1 -1
  152. data/test/plugin_helper/test_cert_option.rb +1 -1
  153. data/test/plugin_helper/test_child_process.rb +38 -16
  154. data/test/plugin_helper/test_event_emitter.rb +29 -0
  155. data/test/plugin_helper/test_http_server_helper.rb +1 -1
  156. data/test/plugin_helper/test_metrics.rb +137 -0
  157. data/test/plugin_helper/test_retry_state.rb +602 -38
  158. data/test/plugin_helper/test_server.rb +78 -6
  159. data/test/plugin_helper/test_timer.rb +2 -2
  160. data/test/test_config.rb +191 -24
  161. data/test/test_event_router.rb +17 -0
  162. data/test/test_file_wrapper.rb +53 -0
  163. data/test/test_formatter.rb +24 -21
  164. data/test/test_log.rb +122 -40
  165. data/test/test_msgpack_factory.rb +32 -0
  166. data/test/test_plugin_classes.rb +102 -0
  167. data/test/test_root_agent.rb +30 -1
  168. data/test/test_supervisor.rb +477 -257
  169. data/test/test_time_parser.rb +22 -0
  170. metadata +55 -34
  171. data/.drone.yml +0 -35
  172. data/.github/workflows/issue-auto-closer.yml +0 -12
  173. data/.github/workflows/linux-test.yaml +0 -36
  174. data/.github/workflows/macos-test.yaml +0 -30
  175. data/.github/workflows/windows-test.yaml +0 -46
  176. data/.gitlab-ci.yml +0 -103
  177. data/lib/fluent/plugin/file_wrapper.rb +0 -187
  178. data/test/plugin/test_file_wrapper.rb +0 -126
  179. data/test/test_logger_initializer.rb +0 -46
@@ -16,14 +16,20 @@ class ServerPluginHelperTest < Test::Unit::TestCase
16
16
 
17
17
  setup do
18
18
  @port = unused_port
19
- @socket_manager_path = ServerEngine::SocketManager::Server.generate_path
20
- if @socket_manager_path.is_a?(String) && File.exist?(@socket_manager_path)
21
- FileUtils.rm_f @socket_manager_path
19
+ if Fluent.windows?
20
+ @socket_manager_server = ServerEngine::SocketManager::Server.open
21
+ @socket_manager_path = @socket_manager_server.path
22
+ else
23
+ @socket_manager_path = ServerEngine::SocketManager::Server.generate_path
24
+ if @socket_manager_path.is_a?(String) && File.exist?(@socket_manager_path)
25
+ FileUtils.rm_f @socket_manager_path
26
+ end
27
+ @socket_manager_server = ServerEngine::SocketManager::Server.open(@socket_manager_path)
22
28
  end
23
- @socket_manager_server = ServerEngine::SocketManager::Server.open(@socket_manager_path)
24
29
  ENV['SERVERENGINE_SOCKETMANAGER_PATH'] = @socket_manager_path.to_s
25
30
 
26
31
  @d = Dummy.new
32
+ @d.under_plugin_development = true
27
33
  @d.start
28
34
  @d.after_start
29
35
  end
@@ -37,7 +43,7 @@ class ServerPluginHelperTest < Test::Unit::TestCase
37
43
  (@d.terminated? || @d.terminate) rescue nil
38
44
 
39
45
  @socket_manager_server.close
40
- if @socket_manager_server.is_a?(String) && File.exist?(@socket_manager_path)
46
+ if @socket_manager_path.is_a?(String) && File.exist?(@socket_manager_path)
41
47
  FileUtils.rm_f @socket_manager_path
42
48
  end
43
49
  end
@@ -64,6 +70,24 @@ class ServerPluginHelperTest < Test::Unit::TestCase
64
70
  end
65
71
  assert d.plugin_id
66
72
  assert d.log
73
+ assert_equal 0, d.transport_config.linger_timeout
74
+ end
75
+
76
+ test 'can change linger_timeout option' do
77
+ d = Dummy.new
78
+
79
+ transport_opts = {
80
+ 'linger_timeout' => 1,
81
+ }
82
+ transport_conf = config_element('transport', 'tcp', transport_opts)
83
+ conf = config_element('source', 'tag.*', {}, [transport_conf])
84
+
85
+ assert_nothing_raised do
86
+ d.configure(conf)
87
+ end
88
+ assert d.plugin_id
89
+ assert d.log
90
+ assert_equal 1, d.transport_config.linger_timeout
67
91
  end
68
92
  end
69
93
 
@@ -771,6 +795,50 @@ class ServerPluginHelperTest < Test::Unit::TestCase
771
795
  end
772
796
  end
773
797
  end
798
+
799
+ sub_test_case 'over max_bytes' do
800
+ data("cut off on Non-Windows", { max_bytes: 32, records: ["a" * 40], expected: ["a" * 32] }, keep: true) unless Fluent.windows?
801
+ data("drop on Windows", { max_bytes: 32, records: ["a" * 40], expected: [] }, keep: true) if Fluent.windows?
802
+ test 'with sock' do |data|
803
+ max_bytes, records, expected = data.values
804
+
805
+ actual_records = []
806
+ @d.server_create_udp(:myserver, @port, max_bytes: max_bytes) do |data, sock|
807
+ actual_records << data
808
+ end
809
+
810
+ open_client(:udp, "127.0.0.1", @port) do |sock|
811
+ records.each do |record|
812
+ sock.send(record, 0)
813
+ end
814
+ end
815
+
816
+ waiting(10) { sleep 0.1 until actual_records.size >= expected.size }
817
+ sleep 1 if expected.size == 0 # To confirm no record recieved.
818
+
819
+ assert_equal expected, actual_records
820
+ end
821
+
822
+ test 'without sock' do |data|
823
+ max_bytes, records, expected = data.values
824
+
825
+ actual_records = []
826
+ @d.server_create_udp(:myserver, @port, max_bytes: max_bytes) do |data|
827
+ actual_records << data
828
+ end
829
+
830
+ open_client(:udp, "127.0.0.1", @port) do |sock|
831
+ records.each do |record|
832
+ sock.send(record, 0)
833
+ end
834
+ end
835
+
836
+ waiting(10) { sleep 0.1 until actual_records.size >= expected.size }
837
+ sleep 1 if expected.size == 0 # To confirm no record recieved.
838
+
839
+ assert_equal expected, actual_records
840
+ end
841
+ end
774
842
  end
775
843
 
776
844
  module CertUtil
@@ -1261,7 +1329,7 @@ class ServerPluginHelperTest < Test::Unit::TestCase
1261
1329
  # OpenSSL 1.1.1: "TLSv1.2"
1262
1330
  if tls_version == "TLSv1/SSLv3" || tls_version == "TLSv1.2"
1263
1331
  matched = true
1264
- unless cipher_name.match(/#{conf.ciphers}/)
1332
+ unless cipher_name.match?(/#{conf.ciphers}/)
1265
1333
  matched = false
1266
1334
  break
1267
1335
  end
@@ -1552,6 +1620,10 @@ class ServerPluginHelperTest < Test::Unit::TestCase
1552
1620
 
1553
1621
  def open_client(proto, addr, port)
1554
1622
  client = case proto
1623
+ when :udp
1624
+ c = UDPSocket.open
1625
+ c.connect(addr, port)
1626
+ c
1555
1627
  when :tcp
1556
1628
  TCPSocket.open(addr, port)
1557
1629
  when :tls
@@ -90,8 +90,8 @@ class TimerTest < Test::Unit::TestCase
90
90
  assert{ counter1 >= 4 && counter1 <= 5 }
91
91
  assert{ counter2 == 2 }
92
92
  msg = "Unexpected error raised. Stopping the timer. title=:t2"
93
- assert{ d1.log.out.logs.any?{|line| line.include?("[error]:") && line.include?(msg) && line.include?("abort!!!!!!") } }
94
- assert{ d1.log.out.logs.any?{|line| line.include?("[error]:") && line.include?("Timer detached. title=:t2") } }
93
+ assert(d1.log.out.logs.any?{|line| line.include?("[error]:") && line.include?(msg) && line.include?("abort!!!!!!") })
94
+ assert(d1.log.out.logs.any?{|line| line.include?("[error]:") && line.include?("Timer detached. title=:t2") })
95
95
 
96
96
  d1.shutdown; d1.close; d1.terminate
97
97
  end
data/test/test_config.rb CHANGED
@@ -10,11 +10,18 @@ class ConfigTest < Test::Unit::TestCase
10
10
 
11
11
  TMP_DIR = File.dirname(__FILE__) + "/tmp/config#{ENV['TEST_ENV_NUMBER']}"
12
12
 
13
- def read_config(path)
13
+ def read_config(path, use_yaml: false)
14
14
  path = File.expand_path(path)
15
- File.open(path) { |io|
16
- Fluent::Config::Parser.parse(io, File.basename(path), File.dirname(path))
17
- }
15
+ if use_yaml
16
+ context = Kernel.binding
17
+
18
+ s = Fluent::Config::YamlParser::Loader.new(context).load(Pathname.new(path))
19
+ Fluent::Config::YamlParser::Parser.new(s).build.to_element
20
+ else
21
+ File.open(path) { |io|
22
+ Fluent::Config::Parser.parse(io, File.basename(path), File.dirname(path))
23
+ }
24
+ end
18
25
  end
19
26
 
20
27
  def prepare_config
@@ -151,30 +158,190 @@ class ConfigTest < Test::Unit::TestCase
151
158
  assert_equal before_size, match_conf.unused.size
152
159
  end
153
160
 
154
- def write_config(path, data, encoding: 'utf-8')
155
- FileUtils.mkdir_p(File.dirname(path))
156
- File.open(path, "w:#{encoding}:utf-8") {|f| f.write data }
157
- end
161
+ sub_test_case "yaml config" do
162
+ def test_included
163
+ write_config "#{TMP_DIR}/config_test_not_fetched.yaml", <<-EOS
164
+ config:
165
+ - source:
166
+ $type: dummy
167
+ tag: tag.dummy
168
+ - source:
169
+ $type: tcp
170
+ tag: tag.tcp
171
+ parse:
172
+ $arg:
173
+ - why.parse.section.doesnot.have.arg
174
+ - huh
175
+ $type: none
176
+ - match:
177
+ $tag: tag.*
178
+ $type: stdout
179
+ buffer:
180
+ $type: memory
181
+ flush_interval: 1s
182
+ - !include fluent-included.yaml
183
+ EOS
184
+ write_config "#{TMP_DIR}/fluent-included.yaml", <<-EOS
185
+ - label:
186
+ $name: '@FLUENT_LOG'
187
+ config:
188
+ - match:
189
+ $type: "null"
190
+ $tag: "**"
191
+ buffer:
192
+ $type: memory
193
+ flush_mode: interval
194
+ flush_interval: 1s
195
+ EOS
196
+ root_conf = read_config("#{TMP_DIR}/config_test_not_fetched.yaml", use_yaml: true)
197
+ dummy_source_conf = root_conf.elements.first
198
+ tcp_source_conf = root_conf.elements[1]
199
+ parse_tcp_conf = tcp_source_conf.elements.first
200
+ match_conf = root_conf.elements[2]
201
+ label_conf = root_conf.elements[3]
202
+ fluent_log_conf = label_conf.elements.first
203
+ fluent_log_buffer_conf = fluent_log_conf.elements.first
158
204
 
159
- def test_inline
160
- prepare_config
161
- opts = {
162
- :config_path => "#{TMP_DIR}/config_test_1.conf",
163
- :inline_config => "<source>\n type http\n port 2222\n </source>",
164
- :use_v1_config => false
165
- }
166
- assert_nothing_raised do
167
- Fluent::Supervisor.new(opts)
205
+ assert_equal(
206
+ [
207
+ 'dummy',
208
+ 'tag.dummy',
209
+ 'tcp',
210
+ 'tag.tcp',
211
+ 'none',
212
+ 'why.parse.section.doesnot.have.arg,huh',
213
+ 'stdout',
214
+ 'tag.*',
215
+ 'null',
216
+ '**',
217
+ '@FLUENT_LOG',
218
+ 'memory',
219
+ 'interval',
220
+ '1s',
221
+ ],
222
+ [
223
+ dummy_source_conf['@type'],
224
+ dummy_source_conf['tag'],
225
+ tcp_source_conf['@type'],
226
+ tcp_source_conf['tag'],
227
+ parse_tcp_conf['@type'],
228
+ parse_tcp_conf.arg,
229
+ match_conf['@type'],
230
+ match_conf.arg,
231
+ fluent_log_conf['@type'],
232
+ fluent_log_conf.arg,
233
+ label_conf.arg,
234
+ fluent_log_buffer_conf['@type'],
235
+ fluent_log_buffer_conf['flush_mode'],
236
+ fluent_log_buffer_conf['flush_interval'],
237
+ ])
238
+ end
239
+
240
+ def test_included_glob
241
+ write_config "#{TMP_DIR}/config.yaml", <<-EOS
242
+ config:
243
+ - !include "include/*.yaml"
244
+ EOS
245
+ write_config "#{TMP_DIR}/include/02_source2.yaml", <<-EOS
246
+ - source:
247
+ $type: dummy
248
+ tag: tag.dummy
249
+ EOS
250
+ write_config "#{TMP_DIR}/include/01_source1.yaml", <<-EOS
251
+ - source:
252
+ $type: tcp
253
+ tag: tag.tcp
254
+ parse:
255
+ $arg:
256
+ - why.parse.section.doesnot.have.arg
257
+ - huh
258
+ $type: none
259
+ EOS
260
+ write_config "#{TMP_DIR}/include/03_match1.yaml", <<-EOS
261
+ - match:
262
+ $tag: tag.*
263
+ $type: stdout
264
+ buffer:
265
+ $type: memory
266
+ flush_interval: 1s
267
+ EOS
268
+ root_conf = read_config("#{TMP_DIR}/config.yaml", use_yaml: true)
269
+ tcp_source_conf = root_conf.elements.first
270
+ dummy_source_conf = root_conf.elements[1]
271
+ parse_tcp_conf = tcp_source_conf.elements.first
272
+ match_conf = root_conf.elements[2]
273
+
274
+ assert_equal(
275
+ [
276
+ 'tcp',
277
+ 'tag.tcp',
278
+ 'none',
279
+ 'why.parse.section.doesnot.have.arg,huh',
280
+ 'dummy',
281
+ 'tag.dummy',
282
+ 'stdout',
283
+ 'tag.*',
284
+ ],
285
+ [
286
+ tcp_source_conf['@type'],
287
+ tcp_source_conf['tag'],
288
+ parse_tcp_conf['@type'],
289
+ parse_tcp_conf.arg,
290
+ dummy_source_conf['@type'],
291
+ dummy_source_conf['tag'],
292
+ match_conf['@type'],
293
+ match_conf.arg,
294
+ ])
295
+ end
296
+
297
+ def test_check_not_fetchd
298
+ write_config "#{TMP_DIR}/config_test_not_fetched.yaml", <<-EOS
299
+ config:
300
+ - match:
301
+ $arg: dummy
302
+ $type: rewrite
303
+ add_prefix: filtered
304
+ rule:
305
+ key: path
306
+ pattern: "^[A-Z]+"
307
+ replace: true
308
+ EOS
309
+ root_conf = read_config("#{TMP_DIR}/config_test_not_fetched.yaml", use_yaml: true)
310
+ match_conf = root_conf.elements.first
311
+ rule_conf = match_conf.elements.first
312
+
313
+ not_fetched = []; root_conf.check_not_fetched {|key, e| not_fetched << key }
314
+ assert_equal %w[@type $arg add_prefix key pattern replace], not_fetched
315
+
316
+ not_fetched = []; match_conf.check_not_fetched {|key, e| not_fetched << key }
317
+ assert_equal %w[@type $arg add_prefix key pattern replace], not_fetched
318
+
319
+ not_fetched = []; rule_conf.check_not_fetched {|key, e| not_fetched << key }
320
+ assert_equal %w[key pattern replace], not_fetched
321
+
322
+ # accessing should delete
323
+ match_conf['type']
324
+ rule_conf['key']
325
+
326
+ not_fetched = []; root_conf.check_not_fetched {|key, e| not_fetched << key }
327
+ assert_equal %w[@type $arg add_prefix pattern replace], not_fetched
328
+
329
+ not_fetched = []; match_conf.check_not_fetched {|key, e| not_fetched << key }
330
+ assert_equal %w[@type $arg add_prefix pattern replace], not_fetched
331
+
332
+ not_fetched = []; rule_conf.check_not_fetched {|key, e| not_fetched << key }
333
+ assert_equal %w[pattern replace], not_fetched
334
+
335
+ # repeatedly accessing should not grow memory usage
336
+ before_size = match_conf.unused.size
337
+ 10.times { match_conf['type'] }
338
+ assert_equal before_size, match_conf.unused.size
168
339
  end
169
- create_warn_dummy_logger
170
340
  end
171
341
 
172
- def create_warn_dummy_logger
173
- dl_opts = {}
174
- dl_opts[:log_level] = ServerEngine::DaemonLogger::WARN
175
- logdev = Fluent::Test::DummyLogDevice.new
176
- logger = ServerEngine::DaemonLogger.new(logdev, dl_opts)
177
- $log = Fluent::Log.new(logger)
342
+ def write_config(path, data, encoding: 'utf-8')
343
+ FileUtils.mkdir_p(File.dirname(path))
344
+ File.open(path, "w:#{encoding}:utf-8") {|f| f.write data }
178
345
  end
179
346
 
180
347
  sub_test_case '.build' do
@@ -326,6 +326,23 @@ class EventRouterTest < ::Test::Unit::TestCase
326
326
  event_router.emit('test', Engine.now, 'k' => 'v')
327
327
  end
328
328
  end
329
+
330
+ test 'can pass records modified by filters to handle_emits_error' do
331
+ filter = Class.new(FluentTestFilter) {
332
+ def filter_stream(_tag, es); end
333
+ }.new
334
+ event_router.add_rule('test', filter)
335
+ event_router.add_rule('test', error_output)
336
+
337
+ time = Engine.now
338
+ modified_es = OneEventStream.new(time, 'modified_label' => 'modified_value')
339
+
340
+ assert_rr do
341
+ stub(filter).filter_stream { modified_es }
342
+ mock(emit_handler).handle_emits_error('test', modified_es, is_a(RuntimeError))
343
+ event_router.emit('test', time, 'pre_label' => 'pre_value')
344
+ end
345
+ end
329
346
  end
330
347
  end
331
348
  end
@@ -0,0 +1,53 @@
1
+ require_relative 'helper'
2
+ require 'fluent/file_wrapper'
3
+
4
+ class FileWrapperTest < Test::Unit::TestCase
5
+ TMP_DIR = File.dirname(__FILE__) + "/../tmp/file_wrapper#{ENV['TEST_ENV_NUMBER']}"
6
+
7
+ def setup
8
+ FileUtils.mkdir_p(TMP_DIR)
9
+ end
10
+
11
+ def teardown
12
+ FileUtils.rm_rf(TMP_DIR)
13
+ end
14
+
15
+ sub_test_case 'WindowsFile exceptions' do
16
+ test 'nothing raised' do
17
+ begin
18
+ path = "#{TMP_DIR}/test_windows_file.txt"
19
+ file1 = file2 = nil
20
+ file1 = File.open(path, "wb") do |f|
21
+ end
22
+ assert_nothing_raised do
23
+ file2 = Fluent::WindowsFile.new(path)
24
+ ensure
25
+ file2.close
26
+ end
27
+ ensure
28
+ file1.close if file1
29
+ end
30
+ end
31
+
32
+ test 'Errno::ENOENT raised' do
33
+ path = "#{TMP_DIR}/nofile.txt"
34
+ file = nil
35
+ assert_raise(Errno::ENOENT) do
36
+ file = Fluent::WindowsFile.new(path)
37
+ ensure
38
+ file.close if file
39
+ end
40
+ end
41
+
42
+ test 'Errno::ENOENT raised on DeletePending' do
43
+ path = "#{TMP_DIR}/deletepending.txt"
44
+ file = Fluent::WindowsFile.new(path, mode='w')
45
+ File.delete(path)
46
+ assert_raise(Errno::ENOENT) do
47
+ file.stat
48
+ ensure
49
+ file.close if file
50
+ end
51
+ end
52
+ end
53
+ end if Fluent.windows?
@@ -18,7 +18,7 @@ module FormatterTest
18
18
 
19
19
  def test_call
20
20
  formatter = Formatter.new
21
- formatter.configure({})
21
+ formatter.configure(config_element())
22
22
  assert_raise NotImplementedError do
23
23
  formatter.format('tag', Engine.now, {})
24
24
  end
@@ -130,7 +130,7 @@ module FormatterTest
130
130
  include FormatterTest
131
131
 
132
132
  def setup
133
- @formatter = TextFormatter::MessagePackFormatter.new
133
+ @formatter = Fluent::Test::FormatterTestDriver.new(TextFormatter::MessagePackFormatter)
134
134
  @time = Engine.now
135
135
  end
136
136
 
@@ -146,7 +146,7 @@ module FormatterTest
146
146
  include FormatterTest
147
147
 
148
148
  def setup
149
- @formatter = TextFormatter::LabeledTSVFormatter.new
149
+ @formatter = Fluent::Test::FormatterTestDriver.new(TextFormatter::LabeledTSVFormatter)
150
150
  @time = Engine.now
151
151
  @newline = if Fluent.windows?
152
152
  "\r\n"
@@ -156,16 +156,16 @@ module FormatterTest
156
156
  end
157
157
 
158
158
  def test_config_params
159
- assert_equal "\t", @formatter.delimiter
160
- assert_equal ":", @formatter.label_delimiter
159
+ assert_equal "\t", @formatter.instance.delimiter
160
+ assert_equal ":", @formatter.instance.label_delimiter
161
161
 
162
162
  @formatter.configure(
163
163
  'delimiter' => ',',
164
164
  'label_delimiter' => '=',
165
165
  )
166
166
 
167
- assert_equal ",", @formatter.delimiter
168
- assert_equal "=", @formatter.label_delimiter
167
+ assert_equal ",", @formatter.instance.delimiter
168
+ assert_equal "=", @formatter.instance.label_delimiter
169
169
  end
170
170
 
171
171
  def test_format
@@ -220,14 +220,14 @@ module FormatterTest
220
220
  include FormatterTest
221
221
 
222
222
  def setup
223
- @formatter = TextFormatter::CsvFormatter.new
223
+ @formatter = Fluent::Test::FormatterTestDriver.new(TextFormatter::CsvFormatter)
224
224
  @time = Engine.now
225
225
  end
226
226
 
227
227
  def test_config_params
228
- assert_equal ',', @formatter.delimiter
229
- assert_equal true, @formatter.force_quotes
230
- assert_nil @formatter.fields
228
+ assert_equal ',', @formatter.instance.delimiter
229
+ assert_equal true, @formatter.instance.force_quotes
230
+ assert_nil @formatter.instance.fields
231
231
  end
232
232
 
233
233
  data(
@@ -237,8 +237,8 @@ module FormatterTest
237
237
  def test_config_params_with_customized_delimiters(data)
238
238
  expected, target = data
239
239
  @formatter.configure('delimiter' => target, 'fields' => 'a,b,c')
240
- assert_equal expected, @formatter.delimiter
241
- assert_equal ['a', 'b', 'c'], @formatter.fields
240
+ assert_equal expected, @formatter.instance.delimiter
241
+ assert_equal ['a', 'b', 'c'], @formatter.instance.fields
242
242
  end
243
243
 
244
244
  def test_format
@@ -299,7 +299,7 @@ module FormatterTest
299
299
  'blank' => 'one,,two,three')
300
300
  def test_config_params_with_fields(data)
301
301
  @formatter.configure('fields' => data)
302
- assert_equal %w(one two three), @formatter.fields
302
+ assert_equal %w(one two three), @formatter.instance.fields
303
303
  end
304
304
  end
305
305
 
@@ -313,31 +313,34 @@ module FormatterTest
313
313
  end
314
314
  end
315
315
 
316
+ def create_driver(klass_or_str)
317
+ Fluent::Test::FormatterTestDriver.new(klass_or_str)
318
+ end
316
319
 
317
320
  def test_config_params
318
- formatter = TextFormatter::SingleValueFormatter.new
319
- assert_equal "message", formatter.message_key
321
+ formatter = create_driver(TextFormatter::SingleValueFormatter)
322
+ assert_equal "message", formatter.instance.message_key
320
323
 
321
324
  formatter.configure('message_key' => 'foobar')
322
- assert_equal "foobar", formatter.message_key
325
+ assert_equal "foobar", formatter.instance.message_key
323
326
  end
324
327
 
325
328
  def test_format
326
- formatter = Fluent::Plugin.new_formatter('single_value')
329
+ formatter = create_driver('single_value')
327
330
  formatter.configure({})
328
331
  formatted = formatter.format('tag', Engine.now, {'message' => 'awesome'})
329
332
  assert_equal("awesome#{@newline}", formatted)
330
333
  end
331
334
 
332
335
  def test_format_without_newline
333
- formatter = Fluent::Plugin.new_formatter('single_value')
336
+ formatter = create_driver('single_value')
334
337
  formatter.configure('add_newline' => 'false')
335
338
  formatted = formatter.format('tag', Engine.now, {'message' => 'awesome'})
336
339
  assert_equal("awesome", formatted)
337
340
  end
338
341
 
339
342
  def test_format_with_message_key
340
- formatter = TextFormatter::SingleValueFormatter.new
343
+ formatter = create_driver(TextFormatter::SingleValueFormatter)
341
344
  formatter.configure('message_key' => 'foobar')
342
345
  formatted = formatter.format('tag', Engine.now, {'foobar' => 'foo'})
343
346
 
@@ -349,7 +352,7 @@ module FormatterTest
349
352
  include FormatterTest
350
353
 
351
354
  def test_unknown_format
352
- assert_raise ConfigError do
355
+ assert_raise NotFoundPluginError do
353
356
  Fluent::Plugin.new_formatter('unknown')
354
357
  end
355
358
  end