fluentd 0.12.40 → 1.6.2

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 (428) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
  4. data/.github/ISSUE_TEMPLATE.md +17 -0
  5. data/.github/PULL_REQUEST_TEMPLATE.md +13 -0
  6. data/.gitignore +5 -0
  7. data/.gitlab/cicd-template.yaml +10 -0
  8. data/.gitlab-ci.yml +147 -0
  9. data/.travis.yml +56 -20
  10. data/ADOPTERS.md +5 -0
  11. data/CHANGELOG.md +1369 -0
  12. data/CONTRIBUTING.md +16 -5
  13. data/GOVERNANCE.md +55 -0
  14. data/Gemfile +5 -0
  15. data/GithubWorkflow.md +78 -0
  16. data/LICENSE +202 -0
  17. data/MAINTAINERS.md +7 -0
  18. data/README.md +23 -11
  19. data/Rakefile +48 -2
  20. data/Vagrantfile +17 -0
  21. data/appveyor.yml +37 -0
  22. data/bin/fluent-binlog-reader +7 -0
  23. data/bin/fluent-ca-generate +6 -0
  24. data/bin/fluent-plugin-config-format +5 -0
  25. data/bin/fluent-plugin-generate +5 -0
  26. data/bin/fluentd +3 -0
  27. data/code-of-conduct.md +3 -0
  28. data/example/copy_roundrobin.conf +39 -0
  29. data/example/counter.conf +18 -0
  30. data/example/in_dummy_blocks.conf +17 -0
  31. data/example/in_dummy_with_compression.conf +23 -0
  32. data/example/in_forward.conf +7 -0
  33. data/example/in_forward_client.conf +37 -0
  34. data/example/in_forward_shared_key.conf +15 -0
  35. data/example/in_forward_tls.conf +14 -0
  36. data/example/in_forward_users.conf +24 -0
  37. data/example/in_forward_workers.conf +21 -0
  38. data/example/in_http.conf +3 -1
  39. data/example/in_out_forward.conf +17 -0
  40. data/example/logevents.conf +25 -0
  41. data/example/multi_filters.conf +61 -0
  42. data/example/out_exec_filter.conf +42 -0
  43. data/example/out_forward.conf +13 -13
  44. data/example/out_forward_buf_file.conf +23 -0
  45. data/example/out_forward_client.conf +109 -0
  46. data/example/out_forward_heartbeat_none.conf +16 -0
  47. data/example/out_forward_shared_key.conf +36 -0
  48. data/example/out_forward_tls.conf +18 -0
  49. data/example/out_forward_users.conf +65 -0
  50. data/example/out_null.conf +36 -0
  51. data/example/secondary_file.conf +42 -0
  52. data/example/suppress_config_dump.conf +7 -0
  53. data/example/worker_section.conf +36 -0
  54. data/fluent.conf +29 -0
  55. data/fluentd.gemspec +21 -11
  56. data/lib/fluent/agent.rb +67 -90
  57. data/lib/fluent/clock.rb +62 -0
  58. data/lib/fluent/command/binlog_reader.rb +244 -0
  59. data/lib/fluent/command/ca_generate.rb +181 -0
  60. data/lib/fluent/command/cat.rb +42 -18
  61. data/lib/fluent/command/debug.rb +12 -10
  62. data/lib/fluent/command/fluentd.rb +153 -5
  63. data/lib/fluent/command/plugin_config_formatter.rb +292 -0
  64. data/lib/fluent/command/plugin_generator.rb +324 -0
  65. data/lib/fluent/compat/call_super_mixin.rb +67 -0
  66. data/lib/fluent/compat/detach_process_mixin.rb +33 -0
  67. data/lib/fluent/compat/exec_util.rb +129 -0
  68. data/lib/fluent/compat/file_util.rb +54 -0
  69. data/lib/fluent/compat/filter.rb +68 -0
  70. data/lib/fluent/compat/formatter.rb +111 -0
  71. data/lib/fluent/compat/formatter_utils.rb +85 -0
  72. data/lib/fluent/compat/handle_tag_and_time_mixin.rb +62 -0
  73. data/lib/fluent/compat/handle_tag_name_mixin.rb +53 -0
  74. data/lib/fluent/compat/input.rb +49 -0
  75. data/lib/fluent/compat/output.rb +718 -0
  76. data/lib/fluent/compat/output_chain.rb +60 -0
  77. data/lib/fluent/compat/parser.rb +310 -0
  78. data/lib/fluent/compat/parser_utils.rb +40 -0
  79. data/lib/fluent/compat/propagate_default.rb +62 -0
  80. data/lib/fluent/compat/record_filter_mixin.rb +34 -0
  81. data/lib/fluent/compat/set_tag_key_mixin.rb +50 -0
  82. data/lib/fluent/compat/set_time_key_mixin.rb +69 -0
  83. data/lib/fluent/compat/socket_util.rb +165 -0
  84. data/lib/fluent/compat/string_util.rb +34 -0
  85. data/lib/fluent/compat/structured_format_mixin.rb +26 -0
  86. data/lib/fluent/compat/type_converter.rb +90 -0
  87. data/lib/fluent/config/configure_proxy.rb +210 -62
  88. data/lib/fluent/config/dsl.rb +12 -5
  89. data/lib/fluent/config/element.rb +107 -9
  90. data/lib/fluent/config/literal_parser.rb +9 -3
  91. data/lib/fluent/config/parser.rb +4 -4
  92. data/lib/fluent/config/section.rb +51 -14
  93. data/lib/fluent/config/types.rb +28 -13
  94. data/lib/fluent/config/v1_parser.rb +3 -5
  95. data/lib/fluent/config.rb +23 -20
  96. data/lib/fluent/configurable.rb +79 -21
  97. data/lib/fluent/counter/base_socket.rb +46 -0
  98. data/lib/fluent/counter/client.rb +297 -0
  99. data/lib/fluent/counter/error.rb +86 -0
  100. data/lib/fluent/counter/mutex_hash.rb +163 -0
  101. data/lib/fluent/counter/server.rb +273 -0
  102. data/lib/fluent/counter/store.rb +205 -0
  103. data/lib/fluent/counter/validator.rb +145 -0
  104. data/lib/fluent/counter.rb +23 -0
  105. data/lib/fluent/daemon.rb +15 -0
  106. data/lib/fluent/engine.rb +102 -65
  107. data/lib/fluent/env.rb +7 -3
  108. data/lib/fluent/error.rb +30 -0
  109. data/lib/fluent/event.rb +197 -21
  110. data/lib/fluent/event_router.rb +93 -10
  111. data/lib/fluent/filter.rb +2 -50
  112. data/lib/fluent/formatter.rb +4 -293
  113. data/lib/fluent/input.rb +2 -32
  114. data/lib/fluent/label.rb +10 -2
  115. data/lib/fluent/load.rb +3 -3
  116. data/lib/fluent/log.rb +348 -81
  117. data/lib/fluent/match.rb +37 -36
  118. data/lib/fluent/mixin.rb +12 -176
  119. data/lib/fluent/msgpack_factory.rb +62 -0
  120. data/lib/fluent/output.rb +10 -612
  121. data/lib/fluent/output_chain.rb +23 -0
  122. data/lib/fluent/parser.rb +4 -800
  123. data/lib/fluent/plugin/bare_output.rb +63 -0
  124. data/lib/fluent/plugin/base.rb +192 -0
  125. data/lib/fluent/plugin/buf_file.rb +128 -174
  126. data/lib/fluent/plugin/buf_memory.rb +9 -92
  127. data/lib/fluent/plugin/buffer/chunk.rb +221 -0
  128. data/lib/fluent/plugin/buffer/file_chunk.rb +383 -0
  129. data/lib/fluent/plugin/buffer/memory_chunk.rb +90 -0
  130. data/lib/fluent/plugin/buffer.rb +779 -0
  131. data/lib/fluent/plugin/compressable.rb +92 -0
  132. data/lib/fluent/plugin/exec_util.rb +3 -108
  133. data/lib/fluent/plugin/file_util.rb +4 -34
  134. data/lib/fluent/plugin/file_wrapper.rb +120 -0
  135. data/lib/fluent/plugin/filter.rb +93 -0
  136. data/lib/fluent/plugin/filter_grep.rb +117 -34
  137. data/lib/fluent/plugin/filter_parser.rb +85 -62
  138. data/lib/fluent/plugin/filter_record_transformer.rb +27 -39
  139. data/lib/fluent/plugin/filter_stdout.rb +15 -12
  140. data/lib/fluent/plugin/formatter.rb +50 -0
  141. data/lib/fluent/plugin/formatter_csv.rb +52 -0
  142. data/lib/fluent/plugin/formatter_hash.rb +33 -0
  143. data/lib/fluent/plugin/formatter_json.rb +55 -0
  144. data/lib/fluent/plugin/formatter_ltsv.rb +42 -0
  145. data/lib/fluent/plugin/formatter_msgpack.rb +33 -0
  146. data/lib/fluent/plugin/formatter_out_file.rb +51 -0
  147. data/lib/fluent/plugin/formatter_single_value.rb +34 -0
  148. data/lib/fluent/plugin/formatter_stdout.rb +76 -0
  149. data/lib/fluent/plugin/formatter_tsv.rb +38 -0
  150. data/lib/fluent/plugin/in_debug_agent.rb +17 -6
  151. data/lib/fluent/plugin/in_dummy.rb +47 -20
  152. data/lib/fluent/plugin/in_exec.rb +55 -123
  153. data/lib/fluent/plugin/in_forward.rb +299 -216
  154. data/lib/fluent/plugin/in_gc_stat.rb +14 -36
  155. data/lib/fluent/plugin/in_http.rb +204 -91
  156. data/lib/fluent/plugin/in_monitor_agent.rb +186 -258
  157. data/lib/fluent/plugin/in_object_space.rb +13 -41
  158. data/lib/fluent/plugin/in_syslog.rb +112 -134
  159. data/lib/fluent/plugin/in_tail.rb +408 -745
  160. data/lib/fluent/plugin/in_tcp.rb +66 -9
  161. data/lib/fluent/plugin/in_udp.rb +60 -11
  162. data/lib/fluent/plugin/{in_stream.rb → in_unix.rb} +8 -4
  163. data/lib/fluent/plugin/input.rb +37 -0
  164. data/lib/fluent/plugin/multi_output.rb +158 -0
  165. data/lib/fluent/plugin/out_copy.rb +23 -35
  166. data/lib/fluent/plugin/out_exec.rb +67 -70
  167. data/lib/fluent/plugin/out_exec_filter.rb +204 -271
  168. data/lib/fluent/plugin/out_file.rb +267 -73
  169. data/lib/fluent/plugin/out_forward.rb +854 -325
  170. data/lib/fluent/plugin/out_null.rb +42 -9
  171. data/lib/fluent/plugin/out_relabel.rb +9 -5
  172. data/lib/fluent/plugin/out_roundrobin.rb +18 -37
  173. data/lib/fluent/plugin/out_secondary_file.rb +133 -0
  174. data/lib/fluent/plugin/out_stdout.rb +43 -10
  175. data/lib/fluent/plugin/out_stream.rb +7 -2
  176. data/lib/fluent/plugin/output.rb +1498 -0
  177. data/lib/fluent/plugin/owned_by_mixin.rb +42 -0
  178. data/lib/fluent/plugin/parser.rb +191 -0
  179. data/lib/fluent/plugin/parser_apache.rb +28 -0
  180. data/lib/fluent/plugin/parser_apache2.rb +88 -0
  181. data/lib/fluent/plugin/parser_apache_error.rb +26 -0
  182. data/lib/fluent/plugin/parser_csv.rb +39 -0
  183. data/lib/fluent/plugin/parser_json.rb +94 -0
  184. data/lib/fluent/plugin/parser_ltsv.rb +49 -0
  185. data/lib/fluent/plugin/parser_msgpack.rb +50 -0
  186. data/lib/fluent/plugin/parser_multiline.rb +106 -0
  187. data/lib/fluent/plugin/parser_nginx.rb +28 -0
  188. data/lib/fluent/plugin/parser_none.rb +36 -0
  189. data/lib/fluent/plugin/parser_regexp.rb +68 -0
  190. data/lib/fluent/plugin/parser_syslog.rb +142 -0
  191. data/lib/fluent/plugin/parser_tsv.rb +42 -0
  192. data/lib/fluent/plugin/socket_util.rb +3 -143
  193. data/lib/fluent/plugin/storage.rb +84 -0
  194. data/lib/fluent/plugin/storage_local.rb +164 -0
  195. data/lib/fluent/plugin/string_util.rb +3 -15
  196. data/lib/fluent/plugin.rb +122 -121
  197. data/lib/fluent/plugin_helper/cert_option.rb +178 -0
  198. data/lib/fluent/plugin_helper/child_process.rb +364 -0
  199. data/lib/fluent/plugin_helper/compat_parameters.rb +333 -0
  200. data/lib/fluent/plugin_helper/counter.rb +51 -0
  201. data/lib/fluent/plugin_helper/event_emitter.rb +93 -0
  202. data/lib/fluent/plugin_helper/event_loop.rb +170 -0
  203. data/lib/fluent/plugin_helper/extract.rb +104 -0
  204. data/lib/fluent/plugin_helper/formatter.rb +147 -0
  205. data/lib/fluent/plugin_helper/http_server/app.rb +79 -0
  206. data/lib/fluent/plugin_helper/http_server/compat/server.rb +81 -0
  207. data/lib/fluent/plugin_helper/http_server/compat/webrick_handler.rb +58 -0
  208. data/lib/fluent/plugin_helper/http_server/methods.rb +35 -0
  209. data/lib/fluent/plugin_helper/http_server/request.rb +42 -0
  210. data/lib/fluent/plugin_helper/http_server/router.rb +54 -0
  211. data/lib/fluent/plugin_helper/http_server/server.rb +87 -0
  212. data/lib/fluent/plugin_helper/http_server.rb +76 -0
  213. data/lib/fluent/plugin_helper/inject.rb +151 -0
  214. data/lib/fluent/plugin_helper/parser.rb +147 -0
  215. data/lib/fluent/plugin_helper/record_accessor.rb +210 -0
  216. data/lib/fluent/plugin_helper/retry_state.rb +205 -0
  217. data/lib/fluent/plugin_helper/server.rb +807 -0
  218. data/lib/fluent/plugin_helper/socket.rb +250 -0
  219. data/lib/fluent/plugin_helper/socket_option.rb +80 -0
  220. data/lib/fluent/plugin_helper/storage.rb +349 -0
  221. data/lib/fluent/plugin_helper/thread.rb +179 -0
  222. data/lib/fluent/plugin_helper/timer.rb +92 -0
  223. data/lib/fluent/plugin_helper.rb +73 -0
  224. data/lib/fluent/plugin_id.rb +80 -0
  225. data/lib/fluent/process.rb +3 -489
  226. data/lib/fluent/registry.rb +52 -10
  227. data/lib/fluent/root_agent.rb +204 -42
  228. data/lib/fluent/supervisor.rb +597 -359
  229. data/lib/fluent/system_config.rb +131 -42
  230. data/lib/fluent/test/base.rb +6 -54
  231. data/lib/fluent/test/driver/base.rb +224 -0
  232. data/lib/fluent/test/driver/base_owned.rb +70 -0
  233. data/lib/fluent/test/driver/base_owner.rb +135 -0
  234. data/lib/fluent/test/driver/event_feeder.rb +98 -0
  235. data/lib/fluent/test/driver/filter.rb +57 -0
  236. data/lib/fluent/test/driver/formatter.rb +30 -0
  237. data/lib/fluent/test/driver/input.rb +31 -0
  238. data/lib/fluent/test/driver/multi_output.rb +53 -0
  239. data/lib/fluent/test/driver/output.rb +102 -0
  240. data/lib/fluent/test/driver/parser.rb +30 -0
  241. data/lib/fluent/test/driver/test_event_router.rb +45 -0
  242. data/lib/fluent/test/filter_test.rb +0 -1
  243. data/lib/fluent/test/formatter_test.rb +4 -1
  244. data/lib/fluent/test/helpers.rb +58 -10
  245. data/lib/fluent/test/input_test.rb +27 -19
  246. data/lib/fluent/test/log.rb +79 -0
  247. data/lib/fluent/test/output_test.rb +28 -39
  248. data/lib/fluent/test/parser_test.rb +3 -1
  249. data/lib/fluent/test/startup_shutdown.rb +46 -0
  250. data/lib/fluent/test.rb +33 -1
  251. data/lib/fluent/time.rb +450 -1
  252. data/lib/fluent/timezone.rb +27 -3
  253. data/lib/fluent/{status.rb → unique_id.rb} +15 -24
  254. data/lib/fluent/version.rb +1 -1
  255. data/lib/fluent/winsvc.rb +85 -0
  256. data/templates/new_gem/Gemfile +3 -0
  257. data/templates/new_gem/README.md.erb +43 -0
  258. data/templates/new_gem/Rakefile +13 -0
  259. data/templates/new_gem/fluent-plugin.gemspec.erb +27 -0
  260. data/templates/new_gem/lib/fluent/plugin/filter.rb.erb +14 -0
  261. data/templates/new_gem/lib/fluent/plugin/formatter.rb.erb +14 -0
  262. data/templates/new_gem/lib/fluent/plugin/input.rb.erb +11 -0
  263. data/templates/new_gem/lib/fluent/plugin/output.rb.erb +11 -0
  264. data/templates/new_gem/lib/fluent/plugin/parser.rb.erb +15 -0
  265. data/templates/new_gem/test/helper.rb.erb +8 -0
  266. data/templates/new_gem/test/plugin/test_filter.rb.erb +18 -0
  267. data/templates/new_gem/test/plugin/test_formatter.rb.erb +18 -0
  268. data/templates/new_gem/test/plugin/test_input.rb.erb +18 -0
  269. data/templates/new_gem/test/plugin/test_output.rb.erb +18 -0
  270. data/templates/new_gem/test/plugin/test_parser.rb.erb +18 -0
  271. data/templates/plugin_config_formatter/param.md-compact.erb +25 -0
  272. data/templates/plugin_config_formatter/param.md.erb +34 -0
  273. data/templates/plugin_config_formatter/section.md.erb +12 -0
  274. data/test/command/test_binlog_reader.rb +346 -0
  275. data/test/command/test_ca_generate.rb +70 -0
  276. data/test/command/test_fluentd.rb +901 -0
  277. data/test/command/test_plugin_config_formatter.rb +276 -0
  278. data/test/command/test_plugin_generator.rb +92 -0
  279. data/test/compat/test_calls_super.rb +166 -0
  280. data/test/compat/test_parser.rb +92 -0
  281. data/test/config/test_config_parser.rb +126 -2
  282. data/test/config/test_configurable.rb +946 -187
  283. data/test/config/test_configure_proxy.rb +424 -74
  284. data/test/config/test_dsl.rb +11 -11
  285. data/test/config/test_element.rb +500 -0
  286. data/test/config/test_literal_parser.rb +8 -0
  287. data/test/config/test_plugin_configuration.rb +56 -0
  288. data/test/config/test_section.rb +79 -7
  289. data/test/config/test_system_config.rb +122 -35
  290. data/test/config/test_types.rb +38 -0
  291. data/test/counter/test_client.rb +559 -0
  292. data/test/counter/test_error.rb +44 -0
  293. data/test/counter/test_mutex_hash.rb +179 -0
  294. data/test/counter/test_server.rb +589 -0
  295. data/test/counter/test_store.rb +258 -0
  296. data/test/counter/test_validator.rb +137 -0
  297. data/test/helper.rb +89 -6
  298. data/test/helpers/fuzzy_assert.rb +89 -0
  299. data/test/plugin/test_bare_output.rb +118 -0
  300. data/test/plugin/test_base.rb +115 -0
  301. data/test/plugin/test_buf_file.rb +823 -460
  302. data/test/plugin/test_buf_memory.rb +32 -194
  303. data/test/plugin/test_buffer.rb +1233 -0
  304. data/test/plugin/test_buffer_chunk.rb +198 -0
  305. data/test/plugin/test_buffer_file_chunk.rb +844 -0
  306. data/test/plugin/test_buffer_memory_chunk.rb +338 -0
  307. data/test/plugin/test_compressable.rb +84 -0
  308. data/test/plugin/test_filter.rb +357 -0
  309. data/test/plugin/test_filter_grep.rb +540 -29
  310. data/test/plugin/test_filter_parser.rb +439 -452
  311. data/test/plugin/test_filter_record_transformer.rb +123 -166
  312. data/test/plugin/test_filter_stdout.rb +160 -72
  313. data/test/plugin/test_formatter_csv.rb +111 -0
  314. data/test/plugin/test_formatter_hash.rb +35 -0
  315. data/test/plugin/test_formatter_json.rb +51 -0
  316. data/test/plugin/test_formatter_ltsv.rb +62 -0
  317. data/test/plugin/test_formatter_msgpack.rb +28 -0
  318. data/test/plugin/test_formatter_out_file.rb +95 -0
  319. data/test/plugin/test_formatter_single_value.rb +38 -0
  320. data/test/plugin/test_formatter_tsv.rb +68 -0
  321. data/test/plugin/test_in_debug_agent.rb +24 -1
  322. data/test/plugin/test_in_dummy.rb +111 -18
  323. data/test/plugin/test_in_exec.rb +200 -113
  324. data/test/plugin/test_in_forward.rb +990 -387
  325. data/test/plugin/test_in_gc_stat.rb +10 -8
  326. data/test/plugin/test_in_http.rb +600 -224
  327. data/test/plugin/test_in_monitor_agent.rb +690 -0
  328. data/test/plugin/test_in_object_space.rb +24 -8
  329. data/test/plugin/test_in_syslog.rb +154 -215
  330. data/test/plugin/test_in_tail.rb +1006 -707
  331. data/test/plugin/test_in_tcp.rb +125 -48
  332. data/test/plugin/test_in_udp.rb +204 -63
  333. data/test/plugin/{test_in_stream.rb → test_in_unix.rb} +14 -13
  334. data/test/plugin/test_input.rb +126 -0
  335. data/test/plugin/test_metadata.rb +89 -0
  336. data/test/plugin/test_multi_output.rb +180 -0
  337. data/test/plugin/test_out_copy.rb +117 -112
  338. data/test/plugin/test_out_exec.rb +258 -53
  339. data/test/plugin/test_out_exec_filter.rb +538 -115
  340. data/test/plugin/test_out_file.rb +865 -178
  341. data/test/plugin/test_out_forward.rb +998 -210
  342. data/test/plugin/test_out_null.rb +105 -0
  343. data/test/plugin/test_out_relabel.rb +28 -0
  344. data/test/plugin/test_out_roundrobin.rb +36 -29
  345. data/test/plugin/test_out_secondary_file.rb +458 -0
  346. data/test/plugin/test_out_stdout.rb +135 -37
  347. data/test/plugin/test_out_stream.rb +18 -0
  348. data/test/plugin/test_output.rb +984 -0
  349. data/test/plugin/test_output_as_buffered.rb +2021 -0
  350. data/test/plugin/test_output_as_buffered_backup.rb +312 -0
  351. data/test/plugin/test_output_as_buffered_compress.rb +165 -0
  352. data/test/plugin/test_output_as_buffered_overflow.rb +250 -0
  353. data/test/plugin/test_output_as_buffered_retries.rb +911 -0
  354. data/test/plugin/test_output_as_buffered_secondary.rb +874 -0
  355. data/test/plugin/test_output_as_standard.rb +374 -0
  356. data/test/plugin/test_owned_by.rb +35 -0
  357. data/test/plugin/test_parser.rb +359 -0
  358. data/test/plugin/test_parser_apache.rb +42 -0
  359. data/test/plugin/test_parser_apache2.rb +47 -0
  360. data/test/plugin/test_parser_apache_error.rb +45 -0
  361. data/test/plugin/test_parser_csv.rb +103 -0
  362. data/test/plugin/test_parser_json.rb +138 -0
  363. data/test/plugin/test_parser_labeled_tsv.rb +145 -0
  364. data/test/plugin/test_parser_multiline.rb +100 -0
  365. data/test/plugin/test_parser_nginx.rb +88 -0
  366. data/test/plugin/test_parser_none.rb +52 -0
  367. data/test/plugin/test_parser_regexp.rb +289 -0
  368. data/test/plugin/test_parser_syslog.rb +441 -0
  369. data/test/plugin/test_parser_tsv.rb +122 -0
  370. data/test/plugin/test_storage.rb +167 -0
  371. data/test/plugin/test_storage_local.rb +335 -0
  372. data/test/plugin_helper/data/cert/cert-key.pem +27 -0
  373. data/test/plugin_helper/data/cert/cert-with-no-newline.pem +19 -0
  374. data/test/plugin_helper/data/cert/cert.pem +19 -0
  375. data/test/plugin_helper/http_server/test_app.rb +65 -0
  376. data/test/plugin_helper/http_server/test_route.rb +32 -0
  377. data/test/plugin_helper/test_cert_option.rb +16 -0
  378. data/test/plugin_helper/test_child_process.rb +794 -0
  379. data/test/plugin_helper/test_compat_parameters.rb +353 -0
  380. data/test/plugin_helper/test_event_emitter.rb +51 -0
  381. data/test/plugin_helper/test_event_loop.rb +52 -0
  382. data/test/plugin_helper/test_extract.rb +194 -0
  383. data/test/plugin_helper/test_formatter.rb +255 -0
  384. data/test/plugin_helper/test_http_server_helper.rb +205 -0
  385. data/test/plugin_helper/test_inject.rb +519 -0
  386. data/test/plugin_helper/test_parser.rb +264 -0
  387. data/test/plugin_helper/test_record_accessor.rb +197 -0
  388. data/test/plugin_helper/test_retry_state.rb +442 -0
  389. data/test/plugin_helper/test_server.rb +1714 -0
  390. data/test/plugin_helper/test_storage.rb +542 -0
  391. data/test/plugin_helper/test_thread.rb +164 -0
  392. data/test/plugin_helper/test_timer.rb +132 -0
  393. data/test/scripts/exec_script.rb +0 -6
  394. data/test/scripts/fluent/plugin/formatter1/formatter_test1.rb +7 -0
  395. data/test/scripts/fluent/plugin/formatter2/formatter_test2.rb +7 -0
  396. data/test/scripts/fluent/plugin/out_test.rb +23 -15
  397. data/test/scripts/fluent/plugin/out_test2.rb +80 -0
  398. data/test/test_clock.rb +164 -0
  399. data/test/test_config.rb +16 -7
  400. data/test/test_configdsl.rb +2 -2
  401. data/test/test_event.rb +360 -13
  402. data/test/test_event_router.rb +108 -11
  403. data/test/test_event_time.rb +199 -0
  404. data/test/test_filter.rb +48 -6
  405. data/test/test_formatter.rb +11 -391
  406. data/test/test_input.rb +1 -1
  407. data/test/test_log.rb +591 -31
  408. data/test/test_mixin.rb +1 -1
  409. data/test/test_output.rb +121 -185
  410. data/test/test_plugin.rb +251 -0
  411. data/test/test_plugin_classes.rb +177 -10
  412. data/test/test_plugin_helper.rb +81 -0
  413. data/test/test_plugin_id.rb +101 -0
  414. data/test/test_process.rb +8 -42
  415. data/test/test_root_agent.rb +766 -21
  416. data/test/test_supervisor.rb +481 -0
  417. data/test/test_test_drivers.rb +135 -0
  418. data/test/test_time_formatter.rb +282 -0
  419. data/test/test_time_parser.rb +231 -0
  420. data/test/test_unique_id.rb +47 -0
  421. metadata +454 -60
  422. data/COPYING +0 -14
  423. data/ChangeLog +0 -666
  424. data/lib/fluent/buffer.rb +0 -365
  425. data/lib/fluent/plugin/in_status.rb +0 -76
  426. data/test/plugin/test_in_status.rb +0 -38
  427. data/test/test_buffer.rb +0 -624
  428. data/test/test_parser.rb +0 -1305
@@ -0,0 +1,874 @@
1
+ require_relative '../helper'
2
+ require 'fluent/plugin/output'
3
+ require 'fluent/plugin/buffer'
4
+ require 'fluent/event'
5
+
6
+ require 'json'
7
+ require 'time'
8
+ require 'timeout'
9
+ require 'timecop'
10
+
11
+ module FluentPluginOutputAsBufferedSecondaryTest
12
+ class DummyBareOutput < Fluent::Plugin::Output
13
+ def register(name, &block)
14
+ instance_variable_set("@#{name}", block)
15
+ end
16
+ end
17
+ class DummySyncOutput < DummyBareOutput
18
+ def initialize
19
+ super
20
+ @process = nil
21
+ end
22
+ def process(tag, es)
23
+ @process ? @process.call(tag, es) : nil
24
+ end
25
+ end
26
+ class DummyFullFeatureOutput < DummyBareOutput
27
+ def initialize
28
+ super
29
+ @prefer_buffered_processing = nil
30
+ @prefer_delayed_commit = nil
31
+ @process = nil
32
+ @format = nil
33
+ @write = nil
34
+ @try_write = nil
35
+ end
36
+ def prefer_buffered_processing
37
+ @prefer_buffered_processing ? @prefer_buffered_processing.call : false
38
+ end
39
+ def prefer_delayed_commit
40
+ @prefer_delayed_commit ? @prefer_delayed_commit.call : false
41
+ end
42
+ def process(tag, es)
43
+ @process ? @process.call(tag, es) : nil
44
+ end
45
+ def format(tag, time, record)
46
+ @format ? @format.call(tag, time, record) : [tag, time, record].to_json
47
+ end
48
+ def write(chunk)
49
+ @write ? @write.call(chunk) : nil
50
+ end
51
+ def try_write(chunk)
52
+ @try_write ? @try_write.call(chunk) : nil
53
+ end
54
+ end
55
+ class DummyFullFeatureOutput2 < DummyFullFeatureOutput
56
+ def prefer_buffered_processing; true; end
57
+ def prefer_delayed_commit; super; end
58
+ def format(tag, time, record); super; end
59
+ def write(chunk); super; end
60
+ def try_write(chunk); super; end
61
+ end
62
+ end
63
+
64
+ class BufferedOutputSecondaryTest < Test::Unit::TestCase
65
+ def create_output(type=:full)
66
+ case type
67
+ when :bare then FluentPluginOutputAsBufferedSecondaryTest::DummyBareOutput.new
68
+ when :sync then FluentPluginOutputAsBufferedSecondaryTest::DummySyncOutput.new
69
+ when :full then FluentPluginOutputAsBufferedSecondaryTest::DummyFullFeatureOutput.new
70
+ else
71
+ raise ArgumentError, "unknown type: #{type}"
72
+ end
73
+ end
74
+ def create_metadata(timekey: nil, tag: nil, variables: nil)
75
+ Fluent::Plugin::Buffer::Metadata.new(timekey, tag, variables)
76
+ end
77
+ def waiting(seconds)
78
+ begin
79
+ Timeout.timeout(seconds) do
80
+ yield
81
+ end
82
+ rescue Timeout::Error
83
+ STDERR.print(*@i.log.out.logs)
84
+ raise
85
+ end
86
+ end
87
+ def dummy_event_stream
88
+ Fluent::ArrayEventStream.new([
89
+ [ event_time('2016-04-13 18:33:00'), {"name" => "moris", "age" => 36, "message" => "data1"} ],
90
+ [ event_time('2016-04-13 18:33:13'), {"name" => "moris", "age" => 36, "message" => "data2"} ],
91
+ [ event_time('2016-04-13 18:33:32'), {"name" => "moris", "age" => 36, "message" => "data3"} ],
92
+ ])
93
+ end
94
+
95
+ setup do
96
+ @i = create_output
97
+ end
98
+
99
+ teardown do
100
+ if @i
101
+ @i.stop unless @i.stopped?
102
+ @i.before_shutdown unless @i.before_shutdown?
103
+ @i.shutdown unless @i.shutdown?
104
+ @i.after_shutdown unless @i.after_shutdown?
105
+ @i.close unless @i.closed?
106
+ @i.terminate unless @i.terminated?
107
+ end
108
+ Timecop.return
109
+ end
110
+
111
+ sub_test_case 'secondary plugin feature for buffered output with periodical retry' do
112
+ setup do
113
+ Fluent::Plugin.register_output('output_secondary_test', FluentPluginOutputAsBufferedSecondaryTest::DummyFullFeatureOutput)
114
+ Fluent::Plugin.register_output('output_secondary_test2', FluentPluginOutputAsBufferedSecondaryTest::DummyFullFeatureOutput2)
115
+ end
116
+
117
+ test 'raises configuration error if primary does not support buffering' do
118
+ i = create_output(:sync)
119
+ assert_raise Fluent::ConfigError do
120
+ i.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'output_secondary_test'})]))
121
+ end
122
+ end
123
+
124
+ test 'raises configuration error if <buffer>/<secondary> section is specified in <secondary> section' do
125
+ priconf = config_element('buffer','tag',{'flush_interval' => 1, 'retry_type' => :periodic, 'retry_wait' => 3, 'retry_timeout' => 30, 'retry_randomize' => false})
126
+ secconf1 = config_element('secondary','',{'@type' => 'output_secondary_test'},[config_element('buffer', 'time')])
127
+ secconf2 = config_element('secondary','',{'@type' => 'output_secondary_test'},[config_element('secondary', '')])
128
+ i = create_output()
129
+ assert_raise Fluent::ConfigError do
130
+ i.configure(config_element('ROOT','',{},[priconf,secconf1]))
131
+ end
132
+ assert_raise Fluent::ConfigError do
133
+ i.configure(config_element('ROOT','',{},[priconf,secconf2]))
134
+ end
135
+ end
136
+
137
+ test 'uses same plugin type with primary if @type is missing in secondary' do
138
+ bufconf = config_element('buffer','tag',{'flush_interval' => 1, 'retry_type' => :periodic, 'retry_wait' => 3, 'retry_timeout' => 30, 'retry_randomize' => false})
139
+ secconf = config_element('secondary','',{})
140
+ priconf = config_element('ROOT', '', {'@type' => 'output_secondary_test'}, [bufconf, secconf])
141
+ i = create_output()
142
+ assert_nothing_raised do
143
+ i.configure(priconf)
144
+ end
145
+ logs = i.log.out.logs
146
+ assert{ logs.empty? }
147
+ assert{ i.secondary.is_a? FluentPluginOutputAsBufferedSecondaryTest::DummyFullFeatureOutput }
148
+ end
149
+
150
+ test 'warns if secondary plugin is different type from primary one' do
151
+ priconf = config_element('buffer','tag',{'flush_interval' => 1, 'retry_type' => :periodic, 'retry_wait' => 3, 'retry_timeout' => 30, 'retry_randomize' => false})
152
+ secconf = config_element('secondary','',{'@type' => 'output_secondary_test2'})
153
+ i = create_output()
154
+ i.configure(config_element('ROOT','',{},[priconf,secconf]))
155
+ logs = i.log.out.logs
156
+ assert{ logs.any?{|l| l.include?("secondary type should be same with primary one") } }
157
+ end
158
+
159
+ test 'secondary plugin lifecycle is kicked by primary' do
160
+ priconf = config_element('buffer','tag',{'flush_interval' => 1, 'retry_type' => :periodic, 'retry_wait' => 3, 'retry_timeout' => 30, 'retry_randomize' => false})
161
+ secconf = config_element('secondary','',{'@type' => 'output_secondary_test2'})
162
+ i = create_output()
163
+ i.configure(config_element('ROOT','',{},[priconf,secconf]))
164
+ logs = i.log.out.logs
165
+ assert{ logs.any?{|l| l.include?("secondary type should be same with primary one") } }
166
+
167
+ assert i.secondary.configured?
168
+
169
+ assert !i.secondary.started?
170
+ i.start
171
+ assert i.secondary.started?
172
+
173
+ assert !i.secondary.after_started?
174
+ i.after_start
175
+ assert i.secondary.after_started?
176
+
177
+ assert !i.secondary.stopped?
178
+ i.stop
179
+ assert i.secondary.stopped?
180
+
181
+ assert !i.secondary.before_shutdown?
182
+ i.before_shutdown
183
+ assert i.secondary.before_shutdown?
184
+
185
+ assert !i.secondary.shutdown?
186
+ i.shutdown
187
+ assert i.secondary.shutdown?
188
+
189
+ assert !i.secondary.after_shutdown?
190
+ i.after_shutdown
191
+ assert i.secondary.after_shutdown?
192
+
193
+ assert !i.secondary.closed?
194
+ i.close
195
+ assert i.secondary.closed?
196
+
197
+ assert !i.secondary.terminated?
198
+ i.terminate
199
+ assert i.secondary.terminated?
200
+ end
201
+
202
+ test 'primary plugin will emit event streams to secondary after retries for time of retry_timeout * retry_secondary_threshold' do
203
+ written = []
204
+ priconf = config_element('buffer','tag',{'flush_interval' => 1, 'retry_type' => :periodic, 'retry_wait' => 3, 'retry_timeout' => 60, 'retry_randomize' => false})
205
+ secconf = config_element('secondary','',{'@type' => 'output_secondary_test2'})
206
+ @i.configure(config_element('ROOT','',{},[priconf,secconf]))
207
+ @i.register(:prefer_buffered_processing){ true }
208
+ @i.register(:prefer_delayed_commit){ false }
209
+ @i.register(:format){|tag,time,record| [tag,time.to_i,record].to_json + "\n" }
210
+ @i.register(:write){|chunk| raise "yay, your #write must fail" }
211
+ @i.secondary.register(:prefer_delayed_commit){ false }
212
+ @i.secondary.register(:write){|chunk| chunk.read.split("\n").each{|line| written << JSON.parse(line) } }
213
+ @i.start
214
+ @i.after_start
215
+
216
+ @i.interrupt_flushes
217
+
218
+ now = Time.parse('2016-04-13 18:33:30 -0700')
219
+ Timecop.freeze( now )
220
+
221
+ @i.emit_events("test.tag.1", dummy_event_stream())
222
+
223
+ now = Time.parse('2016-04-13 18:33:31 -0700')
224
+ Timecop.freeze( now )
225
+
226
+ @i.emit_events("test.tag.2", dummy_event_stream())
227
+
228
+ assert_equal 0, @i.write_count
229
+ assert_equal 0, @i.num_errors
230
+
231
+ @i.enqueue_thread_wait
232
+ @i.flush_thread_wakeup
233
+ waiting(4){ sleep 0.1 until @i.write_count > 0 && @i.num_errors > 0 }
234
+
235
+ assert{ @i.buffer.queue.size > 0 }
236
+ assert{ @i.buffer.queue.first.metadata.tag == 'test.tag.1' }
237
+
238
+ assert{ @i.write_count > 0 }
239
+ assert{ @i.num_errors > 0 }
240
+
241
+ prev_write_count = @i.write_count
242
+ prev_num_errors = @i.num_errors
243
+
244
+ first_failure = @i.retry.start
245
+
246
+ # retry_timeout == 60(sec), retry_secondary_threshold == 0.8
247
+ now = first_failure + 60 * 0.8 + 1 # to step from primary to secondary
248
+ Timecop.freeze( now )
249
+
250
+ unless @i.retry.secondary?
251
+ @i.enqueue_thread_wait
252
+ @i.flush_thread_wakeup
253
+ waiting(4){ sleep 0.1 until @i.write_count > prev_write_count }
254
+
255
+ prev_write_count = @i.write_count
256
+ prev_num_errors = @i.num_errors
257
+
258
+ # next step is on secondary
259
+ now = first_failure + 60 * 0.8 + 10
260
+ Timecop.freeze( now )
261
+ end
262
+
263
+ @i.enqueue_thread_wait
264
+ @i.flush_thread_wakeup
265
+ waiting(4){ sleep 0.1 until @i.write_count > prev_write_count }
266
+
267
+ current_write_count = @i.write_count
268
+ current_num_errors = @i.num_errors
269
+ assert{ current_write_count > prev_write_count }
270
+ assert{ current_num_errors == prev_num_errors }
271
+
272
+ assert_nil @i.retry
273
+
274
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:00').to_i, {"name" => "moris", "age" => 36, "message" => "data1"} ], written[0]
275
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:13').to_i, {"name" => "moris", "age" => 36, "message" => "data2"} ], written[1]
276
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:32').to_i, {"name" => "moris", "age" => 36, "message" => "data3"} ], written[2]
277
+
278
+ logs = @i.log.out.logs
279
+ waiting(4){ sleep 0.1 until logs.any?{|l| l.include?("[warn]: retry succeeded by secondary.") } }
280
+ assert{ logs.any?{|l| l.include?("[warn]: retry succeeded by secondary.") } }
281
+ end
282
+
283
+ test 'secondary can do non-delayed commit even if primary do delayed commit' do
284
+ written = []
285
+ priconf = config_element('buffer','tag',{'flush_interval' => 1, 'retry_type' => :periodic, 'retry_wait' => 3, 'retry_timeout' => 60, 'retry_randomize' => false})
286
+ secconf = config_element('secondary','',{'@type' => 'output_secondary_test2'})
287
+ @i.configure(config_element('ROOT','',{},[priconf,secconf]))
288
+ @i.register(:prefer_buffered_processing){ true }
289
+ @i.register(:prefer_delayed_commit){ true }
290
+ @i.register(:format){|tag,time,record| [tag,time.to_i,record].to_json + "\n" }
291
+ @i.register(:try_write){|chunk| raise "yay, your #write must fail" }
292
+ @i.secondary.register(:prefer_delayed_commit){ false }
293
+ @i.secondary.register(:write){|chunk| chunk.read.split("\n").each{|line| written << JSON.parse(line) } }
294
+ @i.start
295
+ @i.after_start
296
+
297
+ @i.interrupt_flushes
298
+
299
+ now = Time.parse('2016-04-13 18:33:30 -0700')
300
+ Timecop.freeze( now )
301
+
302
+ @i.emit_events("test.tag.1", dummy_event_stream())
303
+
304
+ now = Time.parse('2016-04-13 18:33:31 -0700')
305
+ Timecop.freeze( now )
306
+
307
+ @i.emit_events("test.tag.2", dummy_event_stream())
308
+
309
+ assert_equal 0, @i.write_count
310
+ assert_equal 0, @i.num_errors
311
+
312
+ @i.enqueue_thread_wait
313
+ @i.flush_thread_wakeup
314
+ waiting(4){ sleep 0.1 until @i.write_count > 0 && @i.num_errors > 0 }
315
+
316
+ assert{ @i.buffer.queue.size > 0 }
317
+ assert{ @i.buffer.queue.first.metadata.tag == 'test.tag.1' }
318
+
319
+ assert{ @i.write_count > 0 }
320
+ assert{ @i.num_errors > 0 }
321
+
322
+ prev_write_count = @i.write_count
323
+ prev_num_errors = @i.num_errors
324
+
325
+ first_failure = @i.retry.start
326
+
327
+ # retry_timeout == 60(sec), retry_secondary_threshold == 0.8
328
+ now = first_failure + 60 * 0.8 + 1 # to step from primary to secondary
329
+ Timecop.freeze( now )
330
+
331
+ unless @i.retry.secondary?
332
+ @i.enqueue_thread_wait
333
+ @i.flush_thread_wakeup
334
+ waiting(4){ sleep 0.1 until @i.write_count > prev_write_count }
335
+
336
+ prev_write_count = @i.write_count
337
+ prev_num_errors = @i.num_errors
338
+
339
+ # next step is on secondary
340
+ now = first_failure + 60 * 0.8 + 10
341
+ Timecop.freeze( now )
342
+ end
343
+
344
+ @i.enqueue_thread_wait
345
+ @i.flush_thread_wakeup
346
+ waiting(4){ sleep 0.1 until @i.write_count > prev_write_count }
347
+
348
+ assert{ @i.write_count > prev_write_count }
349
+ assert{ @i.num_errors == prev_num_errors }
350
+
351
+ assert_nil @i.retry
352
+
353
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:00').to_i, {"name" => "moris", "age" => 36, "message" => "data1"} ], written[0]
354
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:13').to_i, {"name" => "moris", "age" => 36, "message" => "data2"} ], written[1]
355
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:32').to_i, {"name" => "moris", "age" => 36, "message" => "data3"} ], written[2]
356
+
357
+ logs = @i.log.out.logs
358
+ waiting(4){ sleep 0.1 until logs.any?{|l| l.include?("[warn]: retry succeeded by secondary.") } }
359
+ assert{ logs.any?{|l| l.include?("[warn]: retry succeeded by secondary.") } }
360
+ end
361
+
362
+ test 'secondary plugin can do delayed commit if primary do it' do
363
+ written = []
364
+ chunks = []
365
+ priconf = config_element('buffer','tag',{'flush_interval' => 1, 'retry_type' => :periodic, 'retry_wait' => 3, 'retry_timeout' => 60, 'retry_randomize' => false})
366
+ secconf = config_element('secondary','',{'@type' => 'output_secondary_test2'})
367
+ @i.configure(config_element('ROOT','',{},[priconf,secconf]))
368
+ @i.register(:prefer_buffered_processing){ true }
369
+ @i.register(:prefer_delayed_commit){ true }
370
+ @i.register(:format){|tag,time,record| [tag,time.to_i,record].to_json + "\n" }
371
+ @i.register(:try_write){|chunk| raise "yay, your #write must fail" }
372
+ @i.secondary.register(:prefer_delayed_commit){ true }
373
+ @i.secondary.register(:try_write){|chunk| chunks << chunk; chunk.read.split("\n").each{|line| written << JSON.parse(line) } }
374
+ @i.start
375
+ @i.after_start
376
+
377
+ @i.interrupt_flushes
378
+
379
+ now = Time.parse('2016-04-13 18:33:30 -0700')
380
+ Timecop.freeze( now )
381
+
382
+ @i.emit_events("test.tag.1", dummy_event_stream())
383
+
384
+ now = Time.parse('2016-04-13 18:33:31 -0700')
385
+ Timecop.freeze( now )
386
+
387
+ @i.emit_events("test.tag.2", dummy_event_stream())
388
+
389
+ assert_equal 0, @i.write_count
390
+ assert_equal 0, @i.num_errors
391
+
392
+ @i.enqueue_thread_wait
393
+ @i.flush_thread_wakeup
394
+ waiting(4){ sleep 0.1 until @i.write_count > 0 && @i.num_errors > 0 }
395
+
396
+ assert{ @i.buffer.queue.size > 0 }
397
+ assert{ @i.buffer.queue.first.metadata.tag == 'test.tag.1' }
398
+
399
+ assert{ @i.write_count > 0 }
400
+ assert{ @i.num_errors > 0 }
401
+
402
+ prev_write_count = @i.write_count
403
+ prev_num_errors = @i.num_errors
404
+
405
+ first_failure = @i.retry.start
406
+
407
+ # retry_timeout == 60(sec), retry_secondary_threshold == 0.8
408
+ now = first_failure + 60 * 0.8 + 1 # to step from primary to secondary
409
+ Timecop.freeze( now )
410
+
411
+ unless @i.retry.secondary?
412
+ @i.enqueue_thread_wait
413
+ @i.flush_thread_wakeup
414
+ waiting(4){ sleep 0.1 until @i.write_count > prev_write_count }
415
+
416
+ prev_write_count = @i.write_count
417
+ prev_num_errors = @i.num_errors
418
+
419
+ # next step is on secondary
420
+ now = first_failure + 60 * 0.8 + 10
421
+ Timecop.freeze( now )
422
+ end
423
+
424
+ @i.enqueue_thread_wait
425
+ @i.flush_thread_wakeup
426
+ waiting(4){ sleep 0.1 until @i.write_count > prev_write_count }
427
+
428
+ assert{ @i.write_count > prev_write_count }
429
+ assert{ @i.num_errors == prev_num_errors }
430
+
431
+ assert @i.retry
432
+
433
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:00').to_i, {"name" => "moris", "age" => 36, "message" => "data1"} ], written[0]
434
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:13').to_i, {"name" => "moris", "age" => 36, "message" => "data2"} ], written[1]
435
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:32').to_i, {"name" => "moris", "age" => 36, "message" => "data3"} ], written[2]
436
+
437
+ assert{ @i.buffer.dequeued.size > 0 }
438
+ assert{ chunks.size > 0 }
439
+ assert{ !chunks.first.empty? }
440
+
441
+ @i.secondary.commit_write(chunks[0].unique_id)
442
+
443
+ assert{ @i.buffer.dequeued[chunks[0].unique_id].nil? }
444
+ assert{ chunks.first.empty? }
445
+
446
+ assert_nil @i.retry
447
+
448
+ logs = @i.log.out.logs
449
+ waiting(4){ sleep 0.1 until logs.any?{|l| l.include?("[warn]: retry succeeded by secondary.") } }
450
+ assert{ logs.any?{|l| l.include?("[warn]: retry succeeded by secondary.") } }
451
+ end
452
+
453
+ test 'secondary plugin can do delayed commit even if primary does not do it' do
454
+ written = []
455
+ chunks = []
456
+ priconf = config_element('buffer','tag',{'flush_interval' => 1, 'retry_type' => :periodic, 'retry_wait' => 3, 'retry_timeout' => 60, 'retry_randomize' => false})
457
+ secconf = config_element('secondary','',{'@type' => 'output_secondary_test2'})
458
+ @i.configure(config_element('ROOT','',{},[priconf,secconf]))
459
+ @i.register(:prefer_buffered_processing){ true }
460
+ @i.register(:prefer_delayed_commit){ false }
461
+ @i.register(:format){|tag,time,record| [tag,time.to_i,record].to_json + "\n" }
462
+ @i.register(:write){|chunk| raise "yay, your #write must fail" }
463
+ @i.secondary.register(:prefer_delayed_commit){ true }
464
+ @i.secondary.register(:try_write){|chunk| chunks << chunk; chunk.read.split("\n").each{|line| written << JSON.parse(line) } }
465
+ @i.start
466
+ @i.after_start
467
+
468
+ @i.interrupt_flushes
469
+
470
+ now = Time.parse('2016-04-13 18:33:30 -0700')
471
+ Timecop.freeze( now )
472
+
473
+ @i.emit_events("test.tag.1", dummy_event_stream())
474
+
475
+ now = Time.parse('2016-04-13 18:33:31 -0700')
476
+ Timecop.freeze( now )
477
+
478
+ @i.emit_events("test.tag.2", dummy_event_stream())
479
+
480
+ assert_equal 0, @i.write_count
481
+ assert_equal 0, @i.num_errors
482
+
483
+ @i.enqueue_thread_wait
484
+ @i.flush_thread_wakeup
485
+ waiting(4){ sleep 0.1 until @i.write_count > 0 && @i.num_errors > 0 }
486
+
487
+ assert{ @i.buffer.queue.size > 0 }
488
+ assert{ @i.buffer.queue.first.metadata.tag == 'test.tag.1' }
489
+
490
+ assert{ @i.write_count > 0 }
491
+ assert{ @i.num_errors > 0 }
492
+
493
+ prev_write_count = @i.write_count
494
+ prev_num_errors = @i.num_errors
495
+
496
+ first_failure = @i.retry.start
497
+
498
+ # retry_timeout == 60(sec), retry_secondary_threshold == 0.8
499
+ now = first_failure + 60 * 0.8 + 1 # to step from primary to secondary
500
+ Timecop.freeze( now )
501
+
502
+ unless @i.retry.secondary?
503
+ @i.enqueue_thread_wait
504
+ @i.flush_thread_wakeup
505
+ waiting(4){ sleep 0.1 until @i.write_count > prev_write_count }
506
+
507
+ prev_write_count = @i.write_count
508
+ prev_num_errors = @i.num_errors
509
+
510
+ # next step is on secondary
511
+ now = first_failure + 60 * 0.8 + 10
512
+ Timecop.freeze( now )
513
+ end
514
+
515
+ @i.enqueue_thread_wait
516
+ @i.flush_thread_wakeup
517
+ waiting(4){ sleep 0.1 until @i.write_count > prev_write_count }
518
+
519
+ assert{ @i.write_count > prev_write_count }
520
+ assert{ @i.num_errors == prev_num_errors }
521
+
522
+ assert @i.retry
523
+
524
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:00').to_i, {"name" => "moris", "age" => 36, "message" => "data1"} ], written[0]
525
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:13').to_i, {"name" => "moris", "age" => 36, "message" => "data2"} ], written[1]
526
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:32').to_i, {"name" => "moris", "age" => 36, "message" => "data3"} ], written[2]
527
+
528
+ assert{ @i.buffer.dequeued.size > 0 }
529
+ assert{ chunks.size > 0 }
530
+ assert{ !chunks.first.empty? }
531
+
532
+ @i.secondary.commit_write(chunks[0].unique_id)
533
+
534
+ assert{ @i.buffer.dequeued[chunks[0].unique_id].nil? }
535
+ assert{ chunks.first.empty? }
536
+
537
+ assert_nil @i.retry
538
+
539
+ logs = @i.log.out.logs
540
+ waiting(4){ sleep 0.1 until logs.any?{|l| l.include?("[warn]: retry succeeded by secondary.") } }
541
+ assert{ logs.any?{|l| l.include?("[warn]: retry succeeded by secondary.") } }
542
+ end
543
+
544
+ test 'secondary plugin can do delayed commit even if primary does not do it, and non-committed chunks will be rollbacked by primary' do
545
+ written = []
546
+ chunks = []
547
+ priconf = config_element('buffer','tag',{'flush_interval' => 1, 'retry_type' => :periodic, 'retry_wait' => 3, 'retry_timeout' => 60, 'delayed_commit_timeout' => 2, 'retry_randomize' => false, 'queued_chunks_limit_size' => 10})
548
+ secconf = config_element('secondary','',{'@type' => 'output_secondary_test2'})
549
+ @i.configure(config_element('ROOT','',{},[priconf,secconf]))
550
+ @i.register(:prefer_buffered_processing){ true }
551
+ @i.register(:prefer_delayed_commit){ false }
552
+ @i.register(:format){|tag,time,record| [tag,time.to_i,record].to_json + "\n" }
553
+ @i.register(:write){|chunk| raise "yay, your #write must fail" }
554
+ @i.secondary.register(:prefer_delayed_commit){ true }
555
+ @i.secondary.register(:try_write){|chunk| chunks << chunk; chunk.read.split("\n").each{|line| written << JSON.parse(line) } }
556
+ @i.secondary.register(:write){|chunk| raise "don't use this" }
557
+ @i.start
558
+ @i.after_start
559
+
560
+ @i.interrupt_flushes
561
+
562
+ now = Time.parse('2016-04-13 18:33:30 -0700')
563
+ Timecop.freeze( now )
564
+
565
+ @i.emit_events("test.tag.1", dummy_event_stream())
566
+ @i.emit_events("test.tag.2", dummy_event_stream())
567
+
568
+ now = Time.parse('2016-04-13 18:33:31 -0700')
569
+ Timecop.freeze( now )
570
+
571
+ assert_equal 0, @i.write_count
572
+ assert_equal 0, @i.num_errors
573
+
574
+ @i.enqueue_thread_wait
575
+ @i.flush_thread_wakeup
576
+ waiting(4){ sleep 0.1 until @i.write_count > 0 && @i.num_errors > 0 }
577
+
578
+ assert{ @i.buffer.queue.size == 2 }
579
+ assert{ @i.buffer.queue.first.metadata.tag == 'test.tag.1' }
580
+
581
+ assert{ @i.write_count > 0 }
582
+ assert{ @i.num_errors > 0 }
583
+
584
+ prev_write_count = @i.write_count
585
+ prev_num_errors = @i.num_errors
586
+
587
+ first_failure = @i.retry.start
588
+
589
+ # retry_timeout == 60(sec), retry_secondary_threshold == 0.8
590
+
591
+ now = first_failure + 60 * 0.8 + 1
592
+ Timecop.freeze( now )
593
+ @i.enqueue_thread_wait
594
+ @i.flush_thread_wakeup
595
+ now = first_failure + 60 * 0.8 + 2
596
+ Timecop.freeze( now )
597
+ @i.enqueue_thread_wait
598
+ @i.flush_thread_wakeup
599
+
600
+ waiting(4){ sleep 0.1 until chunks.size == 2 }
601
+
602
+ assert{ @i.write_count > prev_write_count }
603
+ assert{ @i.num_errors == prev_num_errors }
604
+
605
+ assert @i.retry
606
+
607
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:00').to_i, {"name" => "moris", "age" => 36, "message" => "data1"} ], written[0]
608
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:13').to_i, {"name" => "moris", "age" => 36, "message" => "data2"} ], written[1]
609
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:32').to_i, {"name" => "moris", "age" => 36, "message" => "data3"} ], written[2]
610
+ assert_equal [ 'test.tag.2', event_time('2016-04-13 18:33:00').to_i, {"name" => "moris", "age" => 36, "message" => "data1"} ], written[3]
611
+ assert_equal [ 'test.tag.2', event_time('2016-04-13 18:33:13').to_i, {"name" => "moris", "age" => 36, "message" => "data2"} ], written[4]
612
+ assert_equal [ 'test.tag.2', event_time('2016-04-13 18:33:32').to_i, {"name" => "moris", "age" => 36, "message" => "data3"} ], written[5]
613
+
614
+ assert{ @i.buffer.dequeued.size == 2 }
615
+ assert{ chunks.size == 2 }
616
+ assert{ !chunks[0].empty? }
617
+ assert{ !chunks[1].empty? }
618
+
619
+ 30.times do |i| # large enough
620
+ now = first_failure + 60 * 0.8 + 2 + i
621
+ Timecop.freeze( now )
622
+ @i.flush_thread_wakeup
623
+
624
+ break if @i.buffer.dequeued.size == 0
625
+ end
626
+
627
+ assert @i.retry
628
+ logs = @i.log.out.logs
629
+ waiting(4){ sleep 0.1 until logs.select{|l| l.include?("[warn]: failed to flush the buffer chunk, timeout to commit.") }.size == 2 }
630
+ assert{ logs.select{|l| l.include?("[warn]: failed to flush the buffer chunk, timeout to commit.") }.size == 2 }
631
+ end
632
+
633
+ test 'retry_wait for secondary is same with one for primary' do
634
+ priconf = config_element('buffer','tag',{'flush_interval' => 1, 'retry_type' => :periodic, 'retry_wait' => 3, 'retry_timeout' => 60, 'retry_randomize' => false})
635
+ secconf = config_element('secondary','',{'@type' => 'output_secondary_test2'})
636
+ @i.configure(config_element('ROOT','',{},[priconf,secconf]))
637
+ @i.register(:prefer_buffered_processing){ true }
638
+ @i.register(:prefer_delayed_commit){ false }
639
+ @i.register(:format){|tag,time,record| [tag,time.to_i,record].to_json + "\n" }
640
+ @i.register(:write){|chunk| raise "yay, your #write must fail" }
641
+ @i.secondary.register(:prefer_delayed_commit){ false }
642
+ @i.secondary.register(:write){|chunk| raise "your secondary is also useless." }
643
+ @i.start
644
+ @i.after_start
645
+
646
+ @i.interrupt_flushes
647
+
648
+ now = Time.parse('2016-04-13 18:33:30 -0700')
649
+ Timecop.freeze( now )
650
+
651
+ @i.emit_events("test.tag.1", dummy_event_stream())
652
+
653
+ now = Time.parse('2016-04-13 18:33:31 -0700')
654
+ Timecop.freeze( now )
655
+
656
+ @i.emit_events("test.tag.2", dummy_event_stream())
657
+
658
+ assert_equal 0, @i.write_count
659
+ assert_equal 0, @i.num_errors
660
+
661
+ @i.enqueue_thread_wait
662
+ @i.flush_thread_wakeup
663
+ waiting(4){ sleep 0.1 until @i.write_count > 0 && @i.num_errors > 0 }
664
+
665
+ assert{ @i.buffer.queue.size > 0 }
666
+ assert{ @i.buffer.queue.first.metadata.tag == 'test.tag.1' }
667
+
668
+ assert{ @i.write_count > 0 }
669
+ assert{ @i.num_errors > 0 }
670
+
671
+ prev_write_count = @i.write_count
672
+ prev_num_errors = @i.num_errors
673
+
674
+ first_failure = @i.retry.start
675
+
676
+ # retry_timeout == 60(sec), retry_secondary_threshold == 0.8
677
+
678
+ now = first_failure + 60 * 0.8 + 1
679
+
680
+ Timecop.freeze( now )
681
+ @i.enqueue_thread_wait
682
+ @i.flush_thread_wakeup
683
+ waiting(4){ sleep 0.1 until @i.write_count > prev_write_count }
684
+
685
+ assert{ @i.write_count > prev_write_count }
686
+ assert{ @i.num_errors > prev_num_errors }
687
+
688
+ assert @i.retry
689
+
690
+ assert_equal 3, (@i.next_flush_time - Time.now)
691
+
692
+ logs = @i.log.out.logs
693
+ waiting(4){ sleep 0.1 until logs.any?{|l| l.include?("[warn]: failed to flush the buffer with secondary output.") } }
694
+ assert{ logs.any?{|l| l.include?("[warn]: failed to flush the buffer with secondary output.") } }
695
+ end
696
+ end
697
+
698
+ sub_test_case 'secondary plugin feature for buffered output with exponential backoff' do
699
+ setup do
700
+ Fluent::Plugin.register_output('output_secondary_test', FluentPluginOutputAsBufferedSecondaryTest::DummyFullFeatureOutput)
701
+ Fluent::Plugin.register_output('output_secondary_test2', FluentPluginOutputAsBufferedSecondaryTest::DummyFullFeatureOutput2)
702
+ end
703
+
704
+ test 'primary plugin will emit event streams to secondary after retries for time of retry_timeout * retry_secondary_threshold' do
705
+ written = []
706
+ priconf = config_element('buffer','tag',{'flush_interval' => 1, 'retry_type' => :exponential_backoff, 'retry_wait' => 1, 'retry_timeout' => 60, 'retry_randomize' => false})
707
+ secconf = config_element('secondary','',{'@type' => 'output_secondary_test2'})
708
+ @i.configure(config_element('ROOT','',{},[priconf,secconf]))
709
+ @i.register(:prefer_buffered_processing){ true }
710
+ @i.register(:prefer_delayed_commit){ false }
711
+ @i.register(:format){|tag,time,record| [tag,time.to_i,record].to_json + "\n" }
712
+ @i.register(:write){|chunk| raise "yay, your #write must fail" }
713
+ @i.secondary.register(:prefer_delayed_commit){ false }
714
+ @i.secondary.register(:write){|chunk| chunk.read.split("\n").each{|line| written << JSON.parse(line) } }
715
+ @i.start
716
+ @i.after_start
717
+
718
+ @i.interrupt_flushes
719
+
720
+ now = Time.parse('2016-04-13 18:33:30 -0700')
721
+ Timecop.freeze( now )
722
+
723
+ @i.emit_events("test.tag.1", dummy_event_stream())
724
+
725
+ now = Time.parse('2016-04-13 18:33:31 -0700')
726
+ Timecop.freeze( now )
727
+
728
+ @i.emit_events("test.tag.2", dummy_event_stream())
729
+
730
+ assert_equal 0, @i.write_count
731
+ assert_equal 0, @i.num_errors
732
+
733
+ @i.enqueue_thread_wait
734
+ @i.flush_thread_wakeup
735
+ waiting(4){ sleep 0.1 until @i.write_count > 0 && @i.num_errors > 0 }
736
+
737
+ assert{ @i.buffer.queue.size > 0 }
738
+ assert{ @i.buffer.queue.first.metadata.tag == 'test.tag.1' }
739
+
740
+ assert{ @i.write_count > 0 }
741
+ assert{ @i.num_errors > 0 }
742
+
743
+ prev_write_count = @i.write_count
744
+ first_failure = @i.retry.start
745
+
746
+ 20.times do |i| # large enough
747
+ now = @i.next_flush_time
748
+ Timecop.freeze( now )
749
+ @i.enqueue_thread_wait
750
+ @i.flush_thread_wakeup
751
+ waiting(4){ sleep 0.1 until @i.write_count > prev_write_count }
752
+
753
+ assert{ @i.write_count > prev_write_count }
754
+
755
+ break if @i.buffer.queue.size == 0
756
+
757
+ prev_write_count = @i.write_count
758
+ end
759
+
760
+ # retry_timeout == 60(sec), retry_secondary_threshold == 0.8
761
+
762
+ assert{ now >= first_failure + 60 * 0.8 }
763
+
764
+ assert_nil @i.retry
765
+
766
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:00').to_i, {"name" => "moris", "age" => 36, "message" => "data1"} ], written[0]
767
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:13').to_i, {"name" => "moris", "age" => 36, "message" => "data2"} ], written[1]
768
+ assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:32').to_i, {"name" => "moris", "age" => 36, "message" => "data3"} ], written[2]
769
+
770
+ assert{ @i.log.out.logs.any?{|l| l.include?("[warn]: retry succeeded by secondary.") } }
771
+ end
772
+
773
+ test 'exponential backoff interval will be initialized when switched to secondary' do
774
+ priconf = config_element('buffer','tag',{'flush_interval' => 1, 'retry_type' => :exponential_backoff, 'retry_wait' => 1, 'retry_timeout' => 60, 'retry_randomize' => false})
775
+ secconf = config_element('secondary','',{'@type' => 'output_secondary_test2'})
776
+ @i.configure(config_element('ROOT','',{},[priconf,secconf]))
777
+ @i.register(:prefer_buffered_processing){ true }
778
+ @i.register(:prefer_delayed_commit){ false }
779
+ @i.register(:format){|tag,time,record| [tag,time.to_i,record].to_json + "\n" }
780
+ @i.register(:write){|chunk| raise "yay, your #write must fail" }
781
+ @i.secondary.register(:prefer_delayed_commit){ false }
782
+ @i.secondary.register(:write){|chunk| raise "your secondary is also useless." }
783
+ @i.start
784
+ @i.after_start
785
+
786
+ @i.interrupt_flushes
787
+
788
+ now = Time.parse('2016-04-13 18:33:30 -0700')
789
+ Timecop.freeze( now )
790
+
791
+ @i.emit_events("test.tag.1", dummy_event_stream())
792
+
793
+ now = Time.parse('2016-04-13 18:33:31 -0700')
794
+ Timecop.freeze( now )
795
+
796
+ @i.emit_events("test.tag.2", dummy_event_stream())
797
+
798
+ assert_equal 0, @i.write_count
799
+ assert_equal 0, @i.num_errors
800
+
801
+ @i.enqueue_thread_wait
802
+ @i.flush_thread_wakeup
803
+ waiting(4){ sleep 0.1 until @i.write_count > 0 && @i.num_errors > 0 }
804
+
805
+ assert{ @i.buffer.queue.size > 0 }
806
+ assert{ @i.buffer.queue.first.metadata.tag == 'test.tag.1' }
807
+
808
+ assert{ @i.write_count > 0 }
809
+ assert{ @i.num_errors > 0 }
810
+
811
+ prev_write_count = @i.write_count
812
+ prev_num_errors = @i.num_errors
813
+
814
+ first_failure = @i.retry.start
815
+
816
+ 20.times do |i| # large enough
817
+ now = @i.next_flush_time
818
+ # p({i: i, now: now, diff: (now - Time.now)})
819
+ # {:i=>0, :now=>2016-04-13 18:33:32 -0700, :diff=>1.0}
820
+ # {:i=>1, :now=>2016-04-13 18:33:34 -0700, :diff=>2.0}
821
+ # {:i=>2, :now=>2016-04-13 18:33:38 -0700, :diff=>4.0}
822
+ # {:i=>3, :now=>2016-04-13 18:33:46 -0700, :diff=>8.0}
823
+ # {:i=>4, :now=>2016-04-13 18:34:02 -0700, :diff=>16.0}
824
+ # {:i=>5, :now=>2016-04-13 18:34:19 -0700, :diff=>17.0}
825
+ Timecop.freeze( now )
826
+ @i.enqueue_thread_wait
827
+ @i.flush_thread_wakeup
828
+ waiting(4){ sleep 0.1 until @i.write_count > prev_write_count }
829
+
830
+ assert{ @i.write_count > prev_write_count }
831
+ assert{ @i.num_errors > prev_num_errors }
832
+
833
+ prev_write_count = @i.write_count
834
+ prev_num_errors = @i.num_errors
835
+
836
+ break if @i.retry.secondary?
837
+
838
+ assert{ @i.buffer.queue.first.metadata.tag == 'test.tag.1' }
839
+ end
840
+
841
+ # retry_timeout == 60(sec), retry_secondary_threshold == 0.8
842
+
843
+ assert{ now >= first_failure + 60 * 0.8 }
844
+ assert @i.retry
845
+ logs = @i.log.out.logs
846
+ assert{ logs.any?{|l| l.include?("[warn]: failed to flush the buffer with secondary output.") } }
847
+
848
+ assert{ (@i.next_flush_time - Time.now) <= 2 } # <= retry_wait (1s) * base (2) ** 1
849
+
850
+ 20.times do |i| # large enough again
851
+ now = @i.next_flush_time
852
+ # p({i: i, now: now, diff: (now - Time.now)})
853
+ # {:i=>0, :now=>2016-04-13 18:34:20 -0700, :diff=>1.0}
854
+ # {:i=>1, :now=>2016-04-13 18:34:24 -0700, :diff=>4.0}
855
+ # {:i=>2, :now=>2016-04-13 18:34:31 -0700, :diff=>7.0}
856
+
857
+ Timecop.freeze( now )
858
+ @i.enqueue_thread_wait
859
+ @i.flush_thread_wakeup
860
+ waiting(4){ sleep 0.1 until @i.write_count > prev_write_count }
861
+
862
+ assert{ @i.write_count > prev_write_count }
863
+ assert{ @i.num_errors > prev_num_errors }
864
+
865
+ break if @i.buffer.queue.size == 0
866
+ end
867
+
868
+ logs = @i.log.out.logs
869
+ assert{ logs.any?{|l| l.include?("[error]: failed to flush the buffer, and hit limit for retries. dropping all chunks in the buffer queue.") } }
870
+
871
+ assert{ now >= first_failure + 60 }
872
+ end
873
+ end
874
+ end