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,984 @@
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
+
10
+ module FluentPluginOutputTest
11
+ class DummyBareOutput < Fluent::Plugin::Output
12
+ def register(name, &block)
13
+ instance_variable_set("@#{name}", block)
14
+ end
15
+ end
16
+ class DummySyncOutput < DummyBareOutput
17
+ def initialize
18
+ super
19
+ @process = nil
20
+ end
21
+ def process(tag, es)
22
+ @process ? @process.call(tag, es) : nil
23
+ end
24
+ end
25
+ class DummyAsyncOutput < DummyBareOutput
26
+ def initialize
27
+ super
28
+ @format = nil
29
+ @write = nil
30
+ end
31
+ def format(tag, time, record)
32
+ @format ? @format.call(tag, time, record) : [tag, time, record].to_json
33
+ end
34
+ def write(chunk)
35
+ @write ? @write.call(chunk) : nil
36
+ end
37
+ end
38
+ class DummyAsyncStandardOutput < DummyBareOutput
39
+ def initialize
40
+ super
41
+ @write = nil
42
+ end
43
+ def write(chunk)
44
+ @write ? @write.call(chunk) : nil
45
+ end
46
+ end
47
+ class DummyDelayedOutput < DummyBareOutput
48
+ def initialize
49
+ super
50
+ @format = nil
51
+ @try_write = nil
52
+ end
53
+ def format(tag, time, record)
54
+ @format ? @format.call(tag, time, record) : [tag, time, record].to_json
55
+ end
56
+ def try_write(chunk)
57
+ @try_write ? @try_write.call(chunk) : nil
58
+ end
59
+ end
60
+ class DummyDelayedStandardOutput < DummyBareOutput
61
+ def initialize
62
+ super
63
+ @try_write = nil
64
+ end
65
+ def try_write(chunk)
66
+ @try_write ? @try_write.call(chunk) : nil
67
+ end
68
+ end
69
+ class DummyFullFeatureOutput < DummyBareOutput
70
+ def initialize
71
+ super
72
+ @prefer_buffered_processing = nil
73
+ @prefer_delayed_commit = nil
74
+ @process = nil
75
+ @format = nil
76
+ @write = nil
77
+ @try_write = nil
78
+ end
79
+ def prefer_buffered_processing
80
+ @prefer_buffered_processing ? @prefer_buffered_processing.call : false
81
+ end
82
+ def prefer_delayed_commit
83
+ @prefer_delayed_commit ? @prefer_delayed_commit.call : false
84
+ end
85
+ def process(tag, es)
86
+ @process ? @process.call(tag, es) : nil
87
+ end
88
+ def format(tag, time, record)
89
+ @format ? @format.call(tag, time, record) : [tag, time, record].to_json
90
+ end
91
+ def write(chunk)
92
+ @write ? @write.call(chunk) : nil
93
+ end
94
+ def try_write(chunk)
95
+ @try_write ? @try_write.call(chunk) : nil
96
+ end
97
+ end
98
+ end
99
+
100
+ class OutputTest < Test::Unit::TestCase
101
+ class << self
102
+ def startup
103
+ $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '../scripts'))
104
+ require 'fluent/plugin/out_test'
105
+ end
106
+
107
+ def shutdown
108
+ $LOAD_PATH.shift
109
+ end
110
+ end
111
+
112
+ def create_output(type=:full)
113
+ case type
114
+ when :bare then FluentPluginOutputTest::DummyBareOutput.new
115
+ when :sync then FluentPluginOutputTest::DummySyncOutput.new
116
+ when :buffered then FluentPluginOutputTest::DummyAsyncOutput.new
117
+ when :standard then FluentPluginOutputTest::DummyAsyncStandardOutput.new
118
+ when :delayed then FluentPluginOutputTest::DummyDelayedOutput.new
119
+ when :sdelayed then FluentPluginOutputTest::DummyDelayedStandardOutput.new
120
+ when :full then FluentPluginOutputTest::DummyFullFeatureOutput.new
121
+ else
122
+ raise ArgumentError, "unknown type: #{type}"
123
+ end
124
+ end
125
+ def create_metadata(timekey: nil, tag: nil, variables: nil)
126
+ Fluent::Plugin::Buffer::Metadata.new(timekey, tag, variables)
127
+ end
128
+ def create_chunk(timekey: nil, tag: nil, variables: nil)
129
+ m = Fluent::Plugin::Buffer::Metadata.new(timekey, tag, variables)
130
+ Fluent::Plugin::Buffer::MemoryChunk.new(m)
131
+ end
132
+ def waiting(seconds)
133
+ begin
134
+ Timeout.timeout(seconds) do
135
+ yield
136
+ end
137
+ rescue Timeout::Error
138
+ STDERR.print(*@i.log.out.logs)
139
+ raise
140
+ end
141
+ end
142
+
143
+ sub_test_case 'basic output feature' do
144
+ setup do
145
+ @i = create_output(:full)
146
+ end
147
+
148
+ test 'are not available with multi workers configuration in default' do
149
+ assert_false @i.multi_workers_ready?
150
+ end
151
+
152
+ test '#implement? can return features for plugin instances' do
153
+ i1 = FluentPluginOutputTest::DummyBareOutput.new
154
+ assert !i1.implement?(:synchronous)
155
+ assert !i1.implement?(:buffered)
156
+ assert !i1.implement?(:delayed_commit)
157
+ assert !i1.implement?(:custom_format)
158
+
159
+ i2 = FluentPluginOutputTest::DummySyncOutput.new
160
+ assert i2.implement?(:synchronous)
161
+ assert !i2.implement?(:buffered)
162
+ assert !i2.implement?(:delayed_commit)
163
+ assert !i2.implement?(:custom_format)
164
+
165
+ i3 = FluentPluginOutputTest::DummyAsyncOutput.new
166
+ assert !i3.implement?(:synchronous)
167
+ assert i3.implement?(:buffered)
168
+ assert !i3.implement?(:delayed_commit)
169
+ assert i3.implement?(:custom_format)
170
+
171
+ i4 = FluentPluginOutputTest::DummyAsyncStandardOutput.new
172
+ assert !i4.implement?(:synchronous)
173
+ assert i4.implement?(:buffered)
174
+ assert !i4.implement?(:delayed_commit)
175
+ assert !i4.implement?(:custom_format)
176
+
177
+ i5 = FluentPluginOutputTest::DummyDelayedOutput.new
178
+ assert !i5.implement?(:synchronous)
179
+ assert !i5.implement?(:buffered)
180
+ assert i5.implement?(:delayed_commit)
181
+ assert i5.implement?(:custom_format)
182
+
183
+ i6 = FluentPluginOutputTest::DummyDelayedStandardOutput.new
184
+ assert !i6.implement?(:synchronous)
185
+ assert !i6.implement?(:buffered)
186
+ assert i6.implement?(:delayed_commit)
187
+ assert !i6.implement?(:custom_format)
188
+
189
+ i6 = FluentPluginOutputTest::DummyFullFeatureOutput.new
190
+ assert i6.implement?(:synchronous)
191
+ assert i6.implement?(:buffered)
192
+ assert i6.implement?(:delayed_commit)
193
+ assert i6.implement?(:custom_format)
194
+ end
195
+
196
+ test 'plugin lifecycle for configure/start/stop/before_shutdown/shutdown/after_shutdown/close/terminate' do
197
+ assert !@i.configured?
198
+ @i.configure(config_element())
199
+ assert @i.configured?
200
+ assert !@i.started?
201
+ @i.start
202
+ assert @i.started?
203
+ assert !@i.after_started?
204
+ @i.after_start
205
+ assert @i.after_started?
206
+ assert !@i.stopped?
207
+ @i.stop
208
+ assert @i.stopped?
209
+ assert !@i.before_shutdown?
210
+ @i.before_shutdown
211
+ assert @i.before_shutdown?
212
+ assert !@i.shutdown?
213
+ @i.shutdown
214
+ assert @i.shutdown?
215
+ assert !@i.after_shutdown?
216
+ @i.after_shutdown
217
+ assert @i.after_shutdown?
218
+ assert !@i.closed?
219
+ @i.close
220
+ assert @i.closed?
221
+ assert !@i.terminated?
222
+ @i.terminate
223
+ assert @i.terminated?
224
+ end
225
+
226
+ data(:new_api => :chunk,
227
+ :old_api => :metadata)
228
+ test '#extract_placeholders does nothing if chunk key is not specified' do |api|
229
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
230
+ assert !@i.chunk_key_time
231
+ assert !@i.chunk_key_tag
232
+ assert_equal [], @i.chunk_keys
233
+ tmpl = "/mypath/%Y/%m/%d/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
234
+ t = event_time('2016-04-11 20:30:00 +0900')
235
+ v = {key1: "value1", key2: "value2"}
236
+ c = if api == :chunk
237
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
238
+ else
239
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
240
+ end
241
+ assert_equal tmpl, @i.extract_placeholders(tmpl, c)
242
+ end
243
+
244
+ data(:new_api => :chunk,
245
+ :old_api => :metadata)
246
+ test '#extract_placeholders can extract time if time key and range are configured' do |api|
247
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
248
+ assert @i.chunk_key_time
249
+ assert !@i.chunk_key_tag
250
+ assert_equal [], @i.chunk_keys
251
+ tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
252
+ t = event_time('2016-04-11 20:30:00 +0900')
253
+ v = {key1: "value1", key2: "value2"}
254
+ c = if api == :chunk
255
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
256
+ else
257
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
258
+ end
259
+ assert_equal "/mypath/2016/04/11/20-30/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail", @i.extract_placeholders(tmpl, c)
260
+ end
261
+
262
+ data(:new_api => :chunk,
263
+ :old_api => :metadata)
264
+ test '#extract_placeholders can extract tag and parts of tag if tag is configured' do |api|
265
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'tag', {})]))
266
+ assert !@i.chunk_key_time
267
+ assert @i.chunk_key_tag
268
+ assert_equal [], @i.chunk_keys
269
+ tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
270
+ t = event_time('2016-04-11 20:30:00 +0900')
271
+ v = {key1: "value1", key2: "value2"}
272
+ c = if api == :chunk
273
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
274
+ else
275
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
276
+ end
277
+ assert_equal "/mypath/%Y/%m/%d/%H-%M/fluentd.test.output/test/output/${key1}/${key2}/tail", @i.extract_placeholders(tmpl, c)
278
+ end
279
+
280
+ data(:new_api => :chunk,
281
+ :old_api => :metadata)
282
+ test '#extract_placeholders can extract variables if variables are configured' do |api|
283
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'key1,key2', {})]))
284
+ assert !@i.chunk_key_time
285
+ assert !@i.chunk_key_tag
286
+ assert_equal ['key1','key2'], @i.chunk_keys
287
+ tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
288
+ t = event_time('2016-04-11 20:30:00 +0900')
289
+ v = {key1: "value1", key2: "value2"}
290
+ c = if api == :chunk
291
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
292
+ else
293
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
294
+ end
295
+ assert_equal "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/value1/value2/tail", @i.extract_placeholders(tmpl, c)
296
+ end
297
+
298
+ data(:new_api => :chunk,
299
+ :old_api => :metadata)
300
+ test '#extract_placeholders can extract nested variables if variables are configured with dot notation' do |api|
301
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'key,$.nest.key', {})]))
302
+ assert !@i.chunk_key_time
303
+ assert !@i.chunk_key_tag
304
+ assert_equal ['key','$.nest.key'], @i.chunk_keys
305
+ tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key}/${$.nest.key}/tail"
306
+ t = event_time('2016-04-11 20:30:00 +0900')
307
+ v = {:key => "value1", :"$.nest.key" => "value2"}
308
+ c = if api == :chunk
309
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
310
+ else
311
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
312
+ end
313
+ assert_equal "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/value1/value2/tail", @i.extract_placeholders(tmpl, c)
314
+ end
315
+
316
+ data(:new_api => :chunk,
317
+ :old_api => :metadata)
318
+ test '#extract_placeholders can extract all chunk keys if configured' do |api|
319
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,key1,key2', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
320
+ assert @i.chunk_key_time
321
+ assert @i.chunk_key_tag
322
+ assert_equal ['key1','key2'], @i.chunk_keys
323
+ tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
324
+ t = event_time('2016-04-11 20:30:00 +0900')
325
+ v = {key1: "value1", key2: "value2"}
326
+ c = if api == :chunk
327
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
328
+ else
329
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
330
+ end
331
+ assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/test/output/value1/value2/tail", @i.extract_placeholders(tmpl, c)
332
+ end
333
+
334
+ data(:new_api => :chunk,
335
+ :old_api => :metadata)
336
+ test '#extract_placeholders can extract negative index with tag' do |api|
337
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,key1,key2', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
338
+ assert @i.chunk_key_time
339
+ assert @i.chunk_key_tag
340
+ assert_equal ['key1','key2'], @i.chunk_keys
341
+ tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[-1]}/${tag[-2]}/${key1}/${key2}/tail"
342
+ t = event_time('2016-04-11 20:30:00 +0900')
343
+ v = {key1: "value1", key2: "value2"}
344
+ c = if api == :chunk
345
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
346
+ else
347
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
348
+ end
349
+ assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/output/test/value1/value2/tail", @i.extract_placeholders(tmpl, c)
350
+ end
351
+
352
+ data(:new_api => :chunk,
353
+ :old_api => :metadata)
354
+ test '#extract_placeholders removes out-of-range tag part and unknown variable placeholders' do |api|
355
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,key1,key2', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
356
+ assert @i.chunk_key_time
357
+ assert @i.chunk_key_tag
358
+ assert_equal ['key1','key2'], @i.chunk_keys
359
+ tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[3]}/${tag[-4]}/${key3}/${key4}/tail"
360
+ t = event_time('2016-04-11 20:30:00 +0900')
361
+ v = {key1: "value1", key2: "value2"}
362
+ c = if api == :chunk
363
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
364
+ else
365
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
366
+ end
367
+ assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/////tail", @i.extract_placeholders(tmpl, c)
368
+ end
369
+
370
+ test '#extract_placeholders logs warn message if metadata is passed for ${chunk_id} placeholder' do
371
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
372
+ tmpl = "/mypath/${chunk_id}/tail"
373
+ t = event_time('2016-04-11 20:30:00 +0900')
374
+ v = {key1: "value1", key2: "value2"}
375
+ m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
376
+ @i.extract_placeholders(tmpl, m)
377
+ logs = @i.log.out.logs
378
+ assert { logs.any? { |log| log.include?("${chunk_id} is not allowed in this plugin") } }
379
+ end
380
+
381
+ sub_test_case '#placeholder_validators' do
382
+ test 'returns validators for time, tag and keys when a template has placeholders even if plugin is not configured with these keys' do
383
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
384
+ validators = @i.placeholder_validators(:path, "/my/path/${tag}/${username}/file.%Y%m%d_%H%M.log")
385
+ assert_equal 3, validators.size
386
+ assert_equal 1, validators.select(&:time?).size
387
+ assert_equal 1, validators.select(&:tag?).size
388
+ assert_equal 1, validators.select(&:keys?).size
389
+ end
390
+
391
+ test 'returns validators for time, tag and keys when a plugin is configured with these keys even if a template does not have placeholders' do
392
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,username', {'timekey' => 60})]))
393
+ validators = @i.placeholder_validators(:path, "/my/path/file.log")
394
+ assert_equal 3, validators.size
395
+ assert_equal 1, validators.select(&:time?).size
396
+ assert_equal 1, validators.select(&:tag?).size
397
+ assert_equal 1, validators.select(&:keys?).size
398
+ end
399
+
400
+ test 'returns a validator for time if a template has timestamp placeholders' do
401
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
402
+ validators = @i.placeholder_validators(:path, "/my/path/file.%Y-%m-%d.log")
403
+ assert_equal 1, validators.size
404
+ assert_equal 1, validators.select(&:time?).size
405
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.%Y-%m-%d.log' has timestamp placeholders, but chunk key 'time' is not configured") do
406
+ validators.first.validate!
407
+ end
408
+ end
409
+
410
+ test 'returns a validator for time if a plugin is configured with time key' do
411
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {'timekey' => '30'})]))
412
+ validators = @i.placeholder_validators(:path, "/my/path/to/file.log")
413
+ assert_equal 1, validators.size
414
+ assert_equal 1, validators.select(&:time?).size
415
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/to/file.log' doesn't have timestamp placeholders for timekey 30") do
416
+ validators.first.validate!
417
+ end
418
+ end
419
+
420
+ test 'returns a validator for tag if a template has tag placeholders' do
421
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
422
+ validators = @i.placeholder_validators(:path, "/my/path/${tag}/file.log")
423
+ assert_equal 1, validators.size
424
+ assert_equal 1, validators.select(&:tag?).size
425
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${tag}/file.log' has tag placeholders, but chunk key 'tag' is not configured") do
426
+ validators.first.validate!
427
+ end
428
+ end
429
+
430
+ test 'returns a validator for tag if a plugin is configured with tag key' do
431
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'tag')]))
432
+ validators = @i.placeholder_validators(:path, "/my/path/file.log")
433
+ assert_equal 1, validators.size
434
+ assert_equal 1, validators.select(&:tag?).size
435
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have tag placeholder") do
436
+ validators.first.validate!
437
+ end
438
+ end
439
+
440
+ test 'returns a validator for variable keys if a template has variable placeholders' do
441
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
442
+ validators = @i.placeholder_validators(:path, "/my/path/${username}/file.${group}.log")
443
+ assert_equal 1, validators.size
444
+ assert_equal 1, validators.select(&:keys?).size
445
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${username}/file.${group}.log' has placeholders, but chunk keys doesn't have keys group,username") do
446
+ validators.first.validate!
447
+ end
448
+ end
449
+
450
+ test 'returns a validator for variable keys if a plugin is configured with variable keys' do
451
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'username,group')]))
452
+ validators = @i.placeholder_validators(:path, "/my/path/file.log")
453
+ assert_equal 1, validators.size
454
+ assert_equal 1, validators.select(&:keys?).size
455
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have enough placeholders for keys group,username") do
456
+ validators.first.validate!
457
+ end
458
+ end
459
+ end
460
+
461
+ sub_test_case '#placeholder_validate!' do
462
+ test 'raises configuration error for a template when timestamp placeholders exist but time key is missing' do
463
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
464
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /path/without/timestamp/file.%Y%m%d-%H%M.log' has timestamp placeholders, but chunk key 'time' is not configured") do
465
+ @i.placeholder_validate!(:path, "/path/without/timestamp/file.%Y%m%d-%H%M.log")
466
+ end
467
+ end
468
+
469
+ test 'raises configuration error for a template without timestamp placeholders when timekey is configured' do
470
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {"timekey" => 180})]))
471
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have timestamp placeholders for timekey 180") do
472
+ @i.placeholder_validate!(:path, "/my/path/file.log")
473
+ end
474
+ assert_nothing_raised do
475
+ @i.placeholder_validate!(:path, "/my/path/%Y%m%d/file.%H%M.log")
476
+ end
477
+ end
478
+
479
+ test 'raises configuration error for a template with timestamp placeholders when plugin is configured more fine timekey' do
480
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {"timekey" => 180})]))
481
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.%Y%m%d_%H.log' doesn't have timestamp placeholder for hour('%H') for timekey 180") do
482
+ @i.placeholder_validate!(:path, "/my/path/file.%Y%m%d_%H.log")
483
+ end
484
+ assert_nothing_raised do
485
+ @i.placeholder_validate!(:path, "/my/path/file.%Y%m%d_%H%M.log")
486
+ end
487
+ end
488
+
489
+ test 'raises configuration error for a template when tag placeholders exist but tag key is missing' do
490
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
491
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${tag}/file.${tag[2]}.log' has tag placeholders, but chunk key 'tag' is not configured") do
492
+ @i.placeholder_validate!(:path, "/my/path/${tag}/file.${tag[2]}.log")
493
+ end
494
+ end
495
+
496
+ test 'raises configuration error for a template without tag placeholders when tagkey is configured' do
497
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'tag')]))
498
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have tag placeholder") do
499
+ @i.placeholder_validate!(:path, "/my/path/file.log")
500
+ end
501
+ assert_nothing_raised do
502
+ @i.placeholder_validate!(:path, "/my/path/${tag}/file.${tag[2]}.log")
503
+ end
504
+ assert_nothing_raised do
505
+ @i.placeholder_validate!(:path, "/my/path/${tag}/file.${tag[-1]}.log")
506
+ end
507
+ end
508
+
509
+ test 'raises configuration error for a template when variable key placeholders exist but chunk keys are missing' do
510
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
511
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${service}/file.${username}.log' has placeholders, but chunk keys doesn't have keys service,username") do
512
+ @i.placeholder_validate!(:path, "/my/path/${service}/file.${username}.log")
513
+ end
514
+ end
515
+
516
+ test 'raises configuration error for a template without variable key placeholders when chunk keys are configured' do
517
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'username,service')]))
518
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have enough placeholders for keys service,username") do
519
+ @i.placeholder_validate!(:path, "/my/path/file.log")
520
+ end
521
+ assert_nothing_raised do
522
+ @i.placeholder_validate!(:path, "/my/path/${service}/file.${username}.log")
523
+ end
524
+ end
525
+
526
+ test 'raise configuration error for a template and configuration with keys mismatch' do
527
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'username,service')]))
528
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.${username}.log' doesn't have enough placeholders for keys service") do
529
+ @i.placeholder_validate!(:path, "/my/path/file.${username}.log")
530
+ end
531
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${service}/file.log' doesn't have enough placeholders for keys username") do
532
+ @i.placeholder_validate!(:path, "/my/path/${service}/file.log")
533
+ end
534
+ assert_nothing_raised do
535
+ @i.placeholder_validate!(:path, "/my/path/${service}/file.${username}.log")
536
+ end
537
+ end
538
+ end
539
+
540
+ test '#get_placeholders_time returns seconds,title and example placeholder for a template' do
541
+ s, t, e = @i.get_placeholders_time("/path/to/dir/yay")
542
+ assert_nil s
543
+ assert_nil t
544
+ assert_nil e
545
+
546
+ s, t, e = @i.get_placeholders_time("/path/to/%Y%m%d/yay")
547
+ assert_equal 86400, s
548
+ assert_equal :day, t
549
+ assert_equal '%d', e
550
+ s, t, e = @i.get_placeholders_time("my birthday! at %F")
551
+ assert_equal 86400, s
552
+ assert_equal :day, t
553
+ assert_equal '%d', e
554
+
555
+ s, t, e = @i.get_placeholders_time("myfile.%Y-%m-%d_%H.log")
556
+ assert_equal 3600, s
557
+ assert_equal :hour, t
558
+ assert_equal '%H', e
559
+
560
+ s, t, e = @i.get_placeholders_time("part-%Y%m%d-%H%M.ts")
561
+ assert_equal 60, s
562
+ assert_equal :minute, t
563
+ assert_equal '%M', e
564
+
565
+ s, t, e = @i.get_placeholders_time("my first data at %F %T %z")
566
+ assert_equal 1, s
567
+ assert_equal :second, t
568
+ assert_equal '%S', e
569
+ end
570
+
571
+ test '#get_placeholders_tag returns a list of tag part position for a template' do
572
+ assert_equal [], @i.get_placeholders_tag("db.table")
573
+ assert_equal [], @i.get_placeholders_tag("db.table_${non_tag}")
574
+ assert_equal [-1], @i.get_placeholders_tag("table_${tag}")
575
+ assert_equal [0, 1], @i.get_placeholders_tag("db_${tag[0]}.table_${tag[1]}")
576
+ assert_equal [-1, 0], @i.get_placeholders_tag("/treedir/${tag[0]}/${tag}")
577
+ end
578
+
579
+ test '#get_placeholders_keys returns a list of keys for a template' do
580
+ assert_equal [], @i.get_placeholders_keys("/path/to/my/data/file.log")
581
+ assert_equal [], @i.get_placeholders_keys("/path/to/my/${tag}/file.log")
582
+ assert_equal ['key1', 'key2'], @i.get_placeholders_keys("/path/to/${key2}/${tag}/file.${key1}.log")
583
+ assert_equal ['.hidden', '0001', '@timestamp', 'a_key', 'my-domain'], @i.get_placeholders_keys("http://${my-domain}/${.hidden}/${0001}/${a_key}?timestamp=${@timestamp}")
584
+ end
585
+
586
+ data('include space' => 'ke y',
587
+ 'bracket notation' => "$['key']",
588
+ 'invalid notation' => "$.ke y")
589
+ test 'configure checks invalid chunk keys' do |chunk_keys|
590
+ i = create_output(:buffered)
591
+ assert_raise Fluent::ConfigError do
592
+ i.configure(config_element('ROOT' , '', {}, [config_element('buffer', chunk_keys)]))
593
+ end
594
+ end
595
+
596
+ test '#metadata returns object which contains tag/timekey/variables from records as specified in configuration' do
597
+ tag = 'test.output'
598
+ time = event_time('2016-04-12 15:31:23 -0700')
599
+ timekey = event_time('2016-04-12 15:00:00 -0700')
600
+ record = {"key1" => "value1", "num1" => 1, "message" => "my message", "nest" => {"key" => "nested value"}}
601
+
602
+ i1 = create_output(:buffered)
603
+ i1.configure(config_element('ROOT','',{},[config_element('buffer', '')]))
604
+ assert_equal create_metadata(), i1.metadata(tag, time, record)
605
+
606
+ i2 = create_output(:buffered)
607
+ i2.configure(config_element('ROOT','',{},[config_element('buffer', 'tag')]))
608
+ assert_equal create_metadata(tag: tag), i2.metadata(tag, time, record)
609
+
610
+ i3 = create_output(:buffered)
611
+ i3.configure(config_element('ROOT','',{},[config_element('buffer', 'time', {"timekey" => 3600, "timekey_zone" => "-0700"})]))
612
+ assert_equal create_metadata(timekey: timekey), i3.metadata(tag, time, record)
613
+
614
+ i4 = create_output(:buffered)
615
+ i4.configure(config_element('ROOT','',{},[config_element('buffer', 'key1', {})]))
616
+ assert_equal create_metadata(variables: {key1: "value1"}), i4.metadata(tag, time, record)
617
+
618
+ i5 = create_output(:buffered)
619
+ i5.configure(config_element('ROOT','',{},[config_element('buffer', 'key1,num1', {})]))
620
+ assert_equal create_metadata(variables: {key1: "value1", num1: 1}), i5.metadata(tag, time, record)
621
+
622
+ i6 = create_output(:buffered)
623
+ i6.configure(config_element('ROOT','',{},[config_element('buffer', 'tag,time', {"timekey" => 3600, "timekey_zone" => "-0700"})]))
624
+ assert_equal create_metadata(timekey: timekey, tag: tag), i6.metadata(tag, time, record)
625
+
626
+ i7 = create_output(:buffered)
627
+ i7.configure(config_element('ROOT','',{},[config_element('buffer', 'tag,num1', {"timekey" => 3600, "timekey_zone" => "-0700"})]))
628
+ assert_equal create_metadata(tag: tag, variables: {num1: 1}), i7.metadata(tag, time, record)
629
+
630
+ i8 = create_output(:buffered)
631
+ i8.configure(config_element('ROOT','',{},[config_element('buffer', 'time,tag,key1', {"timekey" => 3600, "timekey_zone" => "-0700"})]))
632
+ assert_equal create_metadata(timekey: timekey, tag: tag, variables: {key1: "value1"}), i8.metadata(tag, time, record)
633
+
634
+ i9 = create_output(:buffered)
635
+ i9.configure(config_element('ROOT','',{},[config_element('buffer', 'key1,$.nest.key', {})]))
636
+ assert_equal create_metadata(variables: {:key1 => "value1", :"$.nest.key" => 'nested value'}), i9.metadata(tag, time, record)
637
+ end
638
+
639
+ test '#emit calls #process via #emit_sync for non-buffered output' do
640
+ i = create_output(:sync)
641
+ process_called = false
642
+ i.register(:process){|tag, es| process_called = true }
643
+ i.configure(config_element())
644
+ i.start
645
+ i.after_start
646
+
647
+ t = event_time()
648
+ i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
649
+
650
+ assert process_called
651
+
652
+ i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
653
+ end
654
+
655
+ test '#emit calls #format for buffered output' do
656
+ i = create_output(:buffered)
657
+ format_called_times = 0
658
+ i.register(:format){|tag, time, record| format_called_times += 1; '' }
659
+ i.configure(config_element())
660
+ i.start
661
+ i.after_start
662
+
663
+ t = event_time()
664
+ i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
665
+
666
+ assert_equal 2, format_called_times
667
+
668
+ i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
669
+ end
670
+
671
+ test '#prefer_buffered_processing (returns false) decides non-buffered without <buffer> section' do
672
+ i = create_output(:full)
673
+
674
+ process_called = false
675
+ format_called_times = 0
676
+ i.register(:process){|tag, es| process_called = true }
677
+ i.register(:format){|tag, time, record| format_called_times += 1; '' }
678
+
679
+ i.configure(config_element())
680
+ i.register(:prefer_buffered_processing){ false } # delayed decision is possible to change after (output's) configure
681
+ i.start
682
+ i.after_start
683
+
684
+ assert !i.prefer_buffered_processing
685
+
686
+ t = event_time()
687
+ i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
688
+
689
+ waiting(4){ Thread.pass until process_called }
690
+
691
+ assert process_called
692
+ assert_equal 0, format_called_times
693
+
694
+ i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
695
+ end
696
+
697
+ test '#prefer_buffered_processing (returns true) decides buffered without <buffer> section' do
698
+ i = create_output(:full)
699
+
700
+ process_called = false
701
+ format_called_times = 0
702
+ i.register(:process){|tag, es| process_called = true }
703
+ i.register(:format){|tag, time, record| format_called_times += 1; '' }
704
+
705
+ i.configure(config_element())
706
+ i.register(:prefer_buffered_processing){ true } # delayed decision is possible to change after (output's) configure
707
+ i.start
708
+ i.after_start
709
+
710
+ assert i.prefer_buffered_processing
711
+
712
+ t = event_time()
713
+ i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
714
+
715
+ assert !process_called
716
+ assert_equal 2, format_called_times
717
+
718
+ i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
719
+ end
720
+
721
+ test 'output plugin will call #write for normal buffered plugin to flush buffer chunks' do
722
+ i = create_output(:buffered)
723
+ write_called = false
724
+ i.register(:write){ |chunk| write_called = true }
725
+
726
+ i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {"flush_mode" => "immediate"})]))
727
+ i.start
728
+ i.after_start
729
+
730
+ t = event_time()
731
+ i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
732
+ i.force_flush
733
+
734
+ waiting(4){ Thread.pass until write_called }
735
+
736
+ assert write_called
737
+
738
+ i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
739
+ end
740
+
741
+ test 'output plugin will call #try_write for plugin supports delayed commit only to flush buffer chunks' do
742
+ i = create_output(:delayed)
743
+ try_write_called = false
744
+ i.register(:try_write){|chunk| try_write_called = true; commit_write(chunk.unique_id) }
745
+
746
+ i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {"flush_mode" => "immediate"})]))
747
+ i.start
748
+ i.after_start
749
+
750
+ t = event_time()
751
+ i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
752
+ i.force_flush
753
+
754
+ waiting(4){ Thread.pass until try_write_called }
755
+
756
+ assert try_write_called
757
+
758
+ i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
759
+ end
760
+
761
+ test '#prefer_delayed_commit (returns false) decides delayed commit is disabled if both are implemented' do
762
+ i = create_output(:full)
763
+ write_called = false
764
+ try_write_called = false
765
+ i.register(:write){ |chunk| write_called = true }
766
+ i.register(:try_write){|chunk| try_write_called = true; commit_write(chunk.unique_id) }
767
+
768
+ i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {"flush_mode" => "immediate"})]))
769
+ i.register(:prefer_delayed_commit){ false } # delayed decision is possible to change after (output's) configure
770
+ i.start
771
+ i.after_start
772
+
773
+ assert !i.prefer_delayed_commit
774
+
775
+ t = event_time()
776
+ i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
777
+ i.force_flush
778
+
779
+ waiting(4){ Thread.pass until write_called || try_write_called }
780
+
781
+ assert write_called
782
+ assert !try_write_called
783
+
784
+ i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
785
+ end
786
+
787
+ test '#prefer_delayed_commit (returns true) decides delayed commit is enabled if both are implemented' do
788
+ i = create_output(:full)
789
+ write_called = false
790
+ try_write_called = false
791
+ i.register(:write){ |chunk| write_called = true }
792
+ i.register(:try_write){|chunk| try_write_called = true; commit_write(chunk.unique_id) }
793
+
794
+ i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {"flush_mode" => "immediate"})]))
795
+ i.register(:prefer_delayed_commit){ true } # delayed decision is possible to change after (output's) configure
796
+ i.start
797
+ i.after_start
798
+
799
+ assert i.prefer_delayed_commit
800
+
801
+ t = event_time()
802
+ i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
803
+ i.force_flush
804
+
805
+ waiting(4){ Thread.pass until write_called || try_write_called }
806
+
807
+ assert !write_called
808
+ assert try_write_called
809
+
810
+ i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
811
+ end
812
+
813
+ test 'flush_interval is ignored when flush_mode is not interval' do
814
+ mock(@i.log).warn("'flush_interval' is ignored because default 'flush_mode' is not 'interval': 'lazy'")
815
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {'timekey' => 60*30, 'flush_interval' => 10})]))
816
+ end
817
+
818
+ data(:lazy => 'lazy', :immediate => 'immediate')
819
+ test 'flush_interval and non-interval flush_mode is exclusive ' do |mode|
820
+ assert_raise Fluent::ConfigError.new("'flush_interval' can't be specified when 'flush_mode' is not 'interval' explicitly: '#{mode}'") do
821
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {'flush_mode' => mode, 'flush_interval' => 10})]))
822
+ end
823
+ end
824
+
825
+ test 'flush_mode is set to interval when flush_interval with v0.12 configuration is given' do
826
+ mock(@i.log).info("'flush_interval' is configured at out side of <buffer>. 'flush_mode' is set to 'interval' to keep existing behaviour")
827
+ @i.configure(config_element('ROOT', '', {'flush_interval' => 60}, []))
828
+ assert_equal :interval, @i.instance_variable_get(:@flush_mode)
829
+ end
830
+
831
+ sub_test_case 'configure secondary' do
832
+ test "Warn if primary type is different from secondary type and either primary or secondary has custom_format" do
833
+ o = create_output(:buffered)
834
+ mock(o.log).warn("secondary type should be same with primary one",
835
+ { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" })
836
+
837
+ o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'test', 'name' => "cool"})]))
838
+ assert_not_nil o.instance_variable_get(:@secondary)
839
+ end
840
+
841
+ test "don't warn if primary type is the same as secondary type" do
842
+ o = Fluent::Plugin::TestOutput.new
843
+ mock(o.log).warn("secondary type should be same with primary one",
844
+ { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" }).never
845
+
846
+ o.configure(config_element('ROOT','',{'name' => "cool2"},
847
+ [config_element('secondary','',{'@type'=>'test', 'name' => "cool"}),
848
+ config_element('buffer','',{'@type'=>'memory'})]
849
+ ))
850
+ assert_not_nil o.instance_variable_get(:@secondary)
851
+ end
852
+
853
+ test "don't warn if primary type is different from secondary type and both don't have custom_format" do
854
+ o = create_output(:standard)
855
+ mock(o.log).warn("secondary type should be same with primary one",
856
+ { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" }).never
857
+
858
+ o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'test', 'name' => "cool"})]))
859
+ assert_not_nil o.instance_variable_get(:@secondary)
860
+ end
861
+
862
+ test "raise configuration error if secondary type specifies non buffered output" do
863
+ o = create_output(:standard)
864
+ assert_raise Fluent::ConfigError do
865
+ o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'copy'})]))
866
+ end
867
+ end
868
+ end
869
+ end
870
+
871
+ sub_test_case 'sync output feature' do
872
+ setup do
873
+ @i = create_output(:sync)
874
+ end
875
+
876
+ test 'raises configuration error if <buffer> section is specified' do
877
+ assert_raise Fluent::ConfigError do
878
+ @i.configure(config_element('ROOT','',{},[config_element('buffer', '')]))
879
+ end
880
+ end
881
+
882
+ test 'raises configuration error if <secondary> section is specified' do
883
+ assert_raise Fluent::ConfigError do
884
+ @i.configure(config_element('ROOT','',{},[config_element('secondary','')]))
885
+ end
886
+ end
887
+
888
+ test '#process is called for each event streams' do
889
+ ary = []
890
+ @i.register(:process){|tag, es| ary << [tag, es] }
891
+ @i.configure(config_element())
892
+ @i.start
893
+ @i.after_start
894
+
895
+ t = event_time()
896
+ es = Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ])
897
+ 5.times do
898
+ @i.emit_events('tag', es)
899
+ end
900
+ assert_equal 5, ary.size
901
+
902
+ @i.stop; @i.before_shutdown; @i.shutdown; @i.after_shutdown; @i.close; @i.terminate
903
+ end
904
+ end
905
+
906
+ sub_test_case '#generate_format_proc' do
907
+ test "when output doesn't have <buffer>" do
908
+ i = create_output(:sync)
909
+ i.configure(config_element('ROOT', '', {}, []))
910
+ assert_equal Fluent::Plugin::Output::FORMAT_MSGPACK_STREAM, i.generate_format_proc
911
+ end
912
+
913
+ test "when output doesn't have <buffer> and time_as_integer is true" do
914
+ i = create_output(:sync)
915
+ i.configure(config_element('ROOT', '', {'time_as_integer' => true}))
916
+ assert_equal Fluent::Plugin::Output::FORMAT_MSGPACK_STREAM_TIME_INT, i.generate_format_proc
917
+ end
918
+
919
+ test 'when output has <buffer> and compress is gzip' do
920
+ i = create_output(:buffered)
921
+ i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {'compress' => 'gzip'})]))
922
+ assert_equal Fluent::Plugin::Output::FORMAT_COMPRESSED_MSGPACK_STREAM, i.generate_format_proc
923
+ end
924
+
925
+ test 'when output has <buffer> and compress is gzip and time_as_integer is true' do
926
+ i = create_output(:buffered)
927
+ i.configure(config_element('ROOT', '', {'time_as_integer' => true}, [config_element('buffer', '', {'compress' => 'gzip'})]))
928
+ assert_equal Fluent::Plugin::Output::FORMAT_COMPRESSED_MSGPACK_STREAM_TIME_INT, i.generate_format_proc
929
+ end
930
+
931
+ test 'when output has <buffer> and compress is text' do
932
+ i = create_output(:buffered)
933
+ i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {'compress' => 'text'})]))
934
+ assert_equal Fluent::Plugin::Output::FORMAT_MSGPACK_STREAM, i.generate_format_proc
935
+ end
936
+ end
937
+
938
+ sub_test_case 'slow_flush_log_threshold' do
939
+ def invoke_slow_flush_log_threshold_test(i)
940
+ i.configure(config_element('ROOT', '', {'slow_flush_log_threshold' => 0.5},
941
+ [config_element('buffer', '', {"flush_mode" => "immediate", "flush_thread_interval" => 30})]))
942
+ i.start
943
+ i.after_start
944
+
945
+ t = event_time()
946
+ i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
947
+ i.force_flush
948
+
949
+ waiting(4) { Thread.pass until i.test_finished? }
950
+
951
+ yield
952
+ ensure
953
+ i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
954
+ end
955
+
956
+ test '#write flush took longer time than slow_flush_log_threshold' do
957
+ i = create_output(:buffered)
958
+ write_called = false
959
+ i.register(:write) { |chunk| sleep 3 }
960
+ i.define_singleton_method(:test_finished?) { write_called }
961
+ i.define_singleton_method(:try_flush) { super(); write_called = true }
962
+
963
+ invoke_slow_flush_log_threshold_test(i) {
964
+ assert write_called
965
+ logs = i.log.out.logs
966
+ assert{ logs.any?{|log| log.include?("buffer flush took longer time than slow_flush_log_threshold: elapsed_time") } }
967
+ }
968
+ end
969
+
970
+ test '#try_write flush took longer time than slow_flush_log_threshold' do
971
+ i = create_output(:delayed)
972
+ try_write_called = false
973
+ i.register(:try_write){ |chunk| sleep 3 }
974
+ i.define_singleton_method(:test_finished?) { try_write_called }
975
+ i.define_singleton_method(:try_flush) { super(); try_write_called = true }
976
+
977
+ invoke_slow_flush_log_threshold_test(i) {
978
+ assert try_write_called
979
+ logs = i.log.out.logs
980
+ assert{ logs.any?{|log| log.include?("buffer flush took longer time than slow_flush_log_threshold: elapsed_time") } }
981
+ }
982
+ end
983
+ end
984
+ end