fluentd 1.14.4-x64-mingw-ucrt

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 (558) hide show
  1. checksums.yaml +7 -0
  2. data/.deepsource.toml +13 -0
  3. data/.drone.yml +35 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.yaml +70 -0
  5. data/.github/ISSUE_TEMPLATE/config.yml +5 -0
  6. data/.github/ISSUE_TEMPLATE/feature_request.yaml +38 -0
  7. data/.github/ISSUE_TEMPLATE.md +17 -0
  8. data/.github/PULL_REQUEST_TEMPLATE.md +14 -0
  9. data/.github/workflows/issue-auto-closer.yml +12 -0
  10. data/.github/workflows/linux-test.yaml +36 -0
  11. data/.github/workflows/macos-test.yaml +30 -0
  12. data/.github/workflows/stale-actions.yml +22 -0
  13. data/.github/workflows/windows-test.yaml +46 -0
  14. data/.gitignore +30 -0
  15. data/.gitlab-ci.yml +103 -0
  16. data/ADOPTERS.md +5 -0
  17. data/AUTHORS +2 -0
  18. data/CHANGELOG.md +2409 -0
  19. data/CONTRIBUTING.md +45 -0
  20. data/GOVERNANCE.md +55 -0
  21. data/Gemfile +9 -0
  22. data/GithubWorkflow.md +78 -0
  23. data/LICENSE +202 -0
  24. data/MAINTAINERS.md +11 -0
  25. data/README.md +97 -0
  26. data/Rakefile +79 -0
  27. data/SECURITY.md +18 -0
  28. data/bin/fluent-binlog-reader +7 -0
  29. data/bin/fluent-ca-generate +6 -0
  30. data/bin/fluent-cap-ctl +7 -0
  31. data/bin/fluent-cat +5 -0
  32. data/bin/fluent-ctl +7 -0
  33. data/bin/fluent-debug +5 -0
  34. data/bin/fluent-gem +9 -0
  35. data/bin/fluent-plugin-config-format +5 -0
  36. data/bin/fluent-plugin-generate +5 -0
  37. data/bin/fluentd +15 -0
  38. data/code-of-conduct.md +3 -0
  39. data/docs/SECURITY_AUDIT.pdf +0 -0
  40. data/example/copy_roundrobin.conf +39 -0
  41. data/example/counter.conf +18 -0
  42. data/example/filter_stdout.conf +22 -0
  43. data/example/in_forward.conf +14 -0
  44. data/example/in_forward_client.conf +37 -0
  45. data/example/in_forward_shared_key.conf +15 -0
  46. data/example/in_forward_tls.conf +14 -0
  47. data/example/in_forward_users.conf +24 -0
  48. data/example/in_forward_workers.conf +21 -0
  49. data/example/in_http.conf +16 -0
  50. data/example/in_out_forward.conf +17 -0
  51. data/example/in_sample_blocks.conf +17 -0
  52. data/example/in_sample_with_compression.conf +23 -0
  53. data/example/in_syslog.conf +15 -0
  54. data/example/in_tail.conf +14 -0
  55. data/example/in_tcp.conf +13 -0
  56. data/example/in_udp.conf +13 -0
  57. data/example/logevents.conf +25 -0
  58. data/example/multi_filters.conf +61 -0
  59. data/example/out_copy.conf +20 -0
  60. data/example/out_exec_filter.conf +42 -0
  61. data/example/out_file.conf +13 -0
  62. data/example/out_forward.conf +35 -0
  63. data/example/out_forward_buf_file.conf +23 -0
  64. data/example/out_forward_client.conf +109 -0
  65. data/example/out_forward_heartbeat_none.conf +16 -0
  66. data/example/out_forward_sd.conf +17 -0
  67. data/example/out_forward_shared_key.conf +36 -0
  68. data/example/out_forward_tls.conf +18 -0
  69. data/example/out_forward_users.conf +65 -0
  70. data/example/out_null.conf +36 -0
  71. data/example/sd.yaml +8 -0
  72. data/example/secondary_file.conf +42 -0
  73. data/example/suppress_config_dump.conf +7 -0
  74. data/example/v0_12_filter.conf +78 -0
  75. data/example/v1_literal_example.conf +36 -0
  76. data/example/worker_section.conf +36 -0
  77. data/fluent.conf +139 -0
  78. data/fluentd.gemspec +55 -0
  79. data/lib/fluent/agent.rb +168 -0
  80. data/lib/fluent/capability.rb +87 -0
  81. data/lib/fluent/clock.rb +66 -0
  82. data/lib/fluent/command/binlog_reader.rb +244 -0
  83. data/lib/fluent/command/bundler_injection.rb +45 -0
  84. data/lib/fluent/command/ca_generate.rb +184 -0
  85. data/lib/fluent/command/cap_ctl.rb +174 -0
  86. data/lib/fluent/command/cat.rb +365 -0
  87. data/lib/fluent/command/ctl.rb +177 -0
  88. data/lib/fluent/command/debug.rb +103 -0
  89. data/lib/fluent/command/fluentd.rb +374 -0
  90. data/lib/fluent/command/plugin_config_formatter.rb +308 -0
  91. data/lib/fluent/command/plugin_generator.rb +365 -0
  92. data/lib/fluent/compat/call_super_mixin.rb +76 -0
  93. data/lib/fluent/compat/detach_process_mixin.rb +33 -0
  94. data/lib/fluent/compat/exec_util.rb +129 -0
  95. data/lib/fluent/compat/file_util.rb +54 -0
  96. data/lib/fluent/compat/filter.rb +68 -0
  97. data/lib/fluent/compat/formatter.rb +111 -0
  98. data/lib/fluent/compat/formatter_utils.rb +85 -0
  99. data/lib/fluent/compat/handle_tag_and_time_mixin.rb +62 -0
  100. data/lib/fluent/compat/handle_tag_name_mixin.rb +53 -0
  101. data/lib/fluent/compat/input.rb +49 -0
  102. data/lib/fluent/compat/output.rb +721 -0
  103. data/lib/fluent/compat/output_chain.rb +60 -0
  104. data/lib/fluent/compat/parser.rb +310 -0
  105. data/lib/fluent/compat/parser_utils.rb +40 -0
  106. data/lib/fluent/compat/propagate_default.rb +62 -0
  107. data/lib/fluent/compat/record_filter_mixin.rb +34 -0
  108. data/lib/fluent/compat/set_tag_key_mixin.rb +50 -0
  109. data/lib/fluent/compat/set_time_key_mixin.rb +69 -0
  110. data/lib/fluent/compat/socket_util.rb +165 -0
  111. data/lib/fluent/compat/string_util.rb +34 -0
  112. data/lib/fluent/compat/structured_format_mixin.rb +26 -0
  113. data/lib/fluent/compat/type_converter.rb +90 -0
  114. data/lib/fluent/config/basic_parser.rb +123 -0
  115. data/lib/fluent/config/configure_proxy.rb +424 -0
  116. data/lib/fluent/config/dsl.rb +152 -0
  117. data/lib/fluent/config/element.rb +265 -0
  118. data/lib/fluent/config/error.rb +32 -0
  119. data/lib/fluent/config/literal_parser.rb +286 -0
  120. data/lib/fluent/config/parser.rb +107 -0
  121. data/lib/fluent/config/section.rb +272 -0
  122. data/lib/fluent/config/types.rb +249 -0
  123. data/lib/fluent/config/v1_parser.rb +192 -0
  124. data/lib/fluent/config.rb +76 -0
  125. data/lib/fluent/configurable.rb +201 -0
  126. data/lib/fluent/counter/base_socket.rb +44 -0
  127. data/lib/fluent/counter/client.rb +297 -0
  128. data/lib/fluent/counter/error.rb +86 -0
  129. data/lib/fluent/counter/mutex_hash.rb +163 -0
  130. data/lib/fluent/counter/server.rb +273 -0
  131. data/lib/fluent/counter/store.rb +205 -0
  132. data/lib/fluent/counter/validator.rb +145 -0
  133. data/lib/fluent/counter.rb +23 -0
  134. data/lib/fluent/daemon.rb +15 -0
  135. data/lib/fluent/daemonizer.rb +88 -0
  136. data/lib/fluent/engine.rb +253 -0
  137. data/lib/fluent/env.rb +40 -0
  138. data/lib/fluent/error.rb +34 -0
  139. data/lib/fluent/event.rb +326 -0
  140. data/lib/fluent/event_router.rb +297 -0
  141. data/lib/fluent/ext_monitor_require.rb +28 -0
  142. data/lib/fluent/filter.rb +21 -0
  143. data/lib/fluent/fluent_log_event_router.rb +141 -0
  144. data/lib/fluent/formatter.rb +23 -0
  145. data/lib/fluent/input.rb +21 -0
  146. data/lib/fluent/label.rb +46 -0
  147. data/lib/fluent/load.rb +34 -0
  148. data/lib/fluent/log.rb +713 -0
  149. data/lib/fluent/match.rb +187 -0
  150. data/lib/fluent/mixin.rb +31 -0
  151. data/lib/fluent/msgpack_factory.rb +106 -0
  152. data/lib/fluent/oj_options.rb +62 -0
  153. data/lib/fluent/output.rb +29 -0
  154. data/lib/fluent/output_chain.rb +23 -0
  155. data/lib/fluent/parser.rb +23 -0
  156. data/lib/fluent/plugin/bare_output.rb +104 -0
  157. data/lib/fluent/plugin/base.rb +197 -0
  158. data/lib/fluent/plugin/buf_file.rb +213 -0
  159. data/lib/fluent/plugin/buf_file_single.rb +225 -0
  160. data/lib/fluent/plugin/buf_memory.rb +34 -0
  161. data/lib/fluent/plugin/buffer/chunk.rb +240 -0
  162. data/lib/fluent/plugin/buffer/file_chunk.rb +413 -0
  163. data/lib/fluent/plugin/buffer/file_single_chunk.rb +311 -0
  164. data/lib/fluent/plugin/buffer/memory_chunk.rb +91 -0
  165. data/lib/fluent/plugin/buffer.rb +918 -0
  166. data/lib/fluent/plugin/compressable.rb +96 -0
  167. data/lib/fluent/plugin/exec_util.rb +22 -0
  168. data/lib/fluent/plugin/file_util.rb +22 -0
  169. data/lib/fluent/plugin/file_wrapper.rb +187 -0
  170. data/lib/fluent/plugin/filter.rb +127 -0
  171. data/lib/fluent/plugin/filter_grep.rb +189 -0
  172. data/lib/fluent/plugin/filter_parser.rb +130 -0
  173. data/lib/fluent/plugin/filter_record_transformer.rb +324 -0
  174. data/lib/fluent/plugin/filter_stdout.rb +53 -0
  175. data/lib/fluent/plugin/formatter.rb +75 -0
  176. data/lib/fluent/plugin/formatter_csv.rb +78 -0
  177. data/lib/fluent/plugin/formatter_hash.rb +35 -0
  178. data/lib/fluent/plugin/formatter_json.rb +59 -0
  179. data/lib/fluent/plugin/formatter_ltsv.rb +44 -0
  180. data/lib/fluent/plugin/formatter_msgpack.rb +33 -0
  181. data/lib/fluent/plugin/formatter_out_file.rb +53 -0
  182. data/lib/fluent/plugin/formatter_single_value.rb +36 -0
  183. data/lib/fluent/plugin/formatter_stdout.rb +76 -0
  184. data/lib/fluent/plugin/formatter_tsv.rb +40 -0
  185. data/lib/fluent/plugin/in_debug_agent.rb +71 -0
  186. data/lib/fluent/plugin/in_dummy.rb +18 -0
  187. data/lib/fluent/plugin/in_exec.rb +110 -0
  188. data/lib/fluent/plugin/in_forward.rb +473 -0
  189. data/lib/fluent/plugin/in_gc_stat.rb +72 -0
  190. data/lib/fluent/plugin/in_http.rb +667 -0
  191. data/lib/fluent/plugin/in_monitor_agent.rb +412 -0
  192. data/lib/fluent/plugin/in_object_space.rb +93 -0
  193. data/lib/fluent/plugin/in_sample.rb +141 -0
  194. data/lib/fluent/plugin/in_syslog.rb +276 -0
  195. data/lib/fluent/plugin/in_tail/position_file.rb +269 -0
  196. data/lib/fluent/plugin/in_tail.rb +1228 -0
  197. data/lib/fluent/plugin/in_tcp.rb +181 -0
  198. data/lib/fluent/plugin/in_udp.rb +92 -0
  199. data/lib/fluent/plugin/in_unix.rb +195 -0
  200. data/lib/fluent/plugin/input.rb +75 -0
  201. data/lib/fluent/plugin/metrics.rb +119 -0
  202. data/lib/fluent/plugin/metrics_local.rb +96 -0
  203. data/lib/fluent/plugin/multi_output.rb +195 -0
  204. data/lib/fluent/plugin/out_copy.rb +120 -0
  205. data/lib/fluent/plugin/out_exec.rb +105 -0
  206. data/lib/fluent/plugin/out_exec_filter.rb +319 -0
  207. data/lib/fluent/plugin/out_file.rb +334 -0
  208. data/lib/fluent/plugin/out_forward/ack_handler.rb +161 -0
  209. data/lib/fluent/plugin/out_forward/connection_manager.rb +113 -0
  210. data/lib/fluent/plugin/out_forward/error.rb +28 -0
  211. data/lib/fluent/plugin/out_forward/failure_detector.rb +84 -0
  212. data/lib/fluent/plugin/out_forward/handshake_protocol.rb +125 -0
  213. data/lib/fluent/plugin/out_forward/load_balancer.rb +114 -0
  214. data/lib/fluent/plugin/out_forward/socket_cache.rb +140 -0
  215. data/lib/fluent/plugin/out_forward.rb +826 -0
  216. data/lib/fluent/plugin/out_http.rb +275 -0
  217. data/lib/fluent/plugin/out_null.rb +74 -0
  218. data/lib/fluent/plugin/out_relabel.rb +32 -0
  219. data/lib/fluent/plugin/out_roundrobin.rb +84 -0
  220. data/lib/fluent/plugin/out_secondary_file.rb +131 -0
  221. data/lib/fluent/plugin/out_stdout.rb +74 -0
  222. data/lib/fluent/plugin/out_stream.rb +130 -0
  223. data/lib/fluent/plugin/output.rb +1556 -0
  224. data/lib/fluent/plugin/owned_by_mixin.rb +42 -0
  225. data/lib/fluent/plugin/parser.rb +275 -0
  226. data/lib/fluent/plugin/parser_apache.rb +28 -0
  227. data/lib/fluent/plugin/parser_apache2.rb +88 -0
  228. data/lib/fluent/plugin/parser_apache_error.rb +26 -0
  229. data/lib/fluent/plugin/parser_csv.rb +114 -0
  230. data/lib/fluent/plugin/parser_json.rb +96 -0
  231. data/lib/fluent/plugin/parser_ltsv.rb +51 -0
  232. data/lib/fluent/plugin/parser_msgpack.rb +50 -0
  233. data/lib/fluent/plugin/parser_multiline.rb +152 -0
  234. data/lib/fluent/plugin/parser_nginx.rb +28 -0
  235. data/lib/fluent/plugin/parser_none.rb +36 -0
  236. data/lib/fluent/plugin/parser_regexp.rb +68 -0
  237. data/lib/fluent/plugin/parser_syslog.rb +496 -0
  238. data/lib/fluent/plugin/parser_tsv.rb +42 -0
  239. data/lib/fluent/plugin/sd_file.rb +156 -0
  240. data/lib/fluent/plugin/sd_srv.rb +135 -0
  241. data/lib/fluent/plugin/sd_static.rb +58 -0
  242. data/lib/fluent/plugin/service_discovery.rb +65 -0
  243. data/lib/fluent/plugin/socket_util.rb +22 -0
  244. data/lib/fluent/plugin/storage.rb +84 -0
  245. data/lib/fluent/plugin/storage_local.rb +162 -0
  246. data/lib/fluent/plugin/string_util.rb +22 -0
  247. data/lib/fluent/plugin.rb +206 -0
  248. data/lib/fluent/plugin_helper/cert_option.rb +191 -0
  249. data/lib/fluent/plugin_helper/child_process.rb +366 -0
  250. data/lib/fluent/plugin_helper/compat_parameters.rb +343 -0
  251. data/lib/fluent/plugin_helper/counter.rb +51 -0
  252. data/lib/fluent/plugin_helper/event_emitter.rb +100 -0
  253. data/lib/fluent/plugin_helper/event_loop.rb +170 -0
  254. data/lib/fluent/plugin_helper/extract.rb +104 -0
  255. data/lib/fluent/plugin_helper/formatter.rb +147 -0
  256. data/lib/fluent/plugin_helper/http_server/app.rb +79 -0
  257. data/lib/fluent/plugin_helper/http_server/compat/server.rb +92 -0
  258. data/lib/fluent/plugin_helper/http_server/compat/ssl_context_extractor.rb +52 -0
  259. data/lib/fluent/plugin_helper/http_server/compat/webrick_handler.rb +58 -0
  260. data/lib/fluent/plugin_helper/http_server/methods.rb +35 -0
  261. data/lib/fluent/plugin_helper/http_server/request.rb +42 -0
  262. data/lib/fluent/plugin_helper/http_server/router.rb +54 -0
  263. data/lib/fluent/plugin_helper/http_server/server.rb +93 -0
  264. data/lib/fluent/plugin_helper/http_server/ssl_context_builder.rb +41 -0
  265. data/lib/fluent/plugin_helper/http_server.rb +135 -0
  266. data/lib/fluent/plugin_helper/inject.rb +154 -0
  267. data/lib/fluent/plugin_helper/metrics.rb +129 -0
  268. data/lib/fluent/plugin_helper/parser.rb +147 -0
  269. data/lib/fluent/plugin_helper/record_accessor.rb +207 -0
  270. data/lib/fluent/plugin_helper/retry_state.rb +209 -0
  271. data/lib/fluent/plugin_helper/server.rb +801 -0
  272. data/lib/fluent/plugin_helper/service_discovery/manager.rb +146 -0
  273. data/lib/fluent/plugin_helper/service_discovery/round_robin_balancer.rb +43 -0
  274. data/lib/fluent/plugin_helper/service_discovery.rb +125 -0
  275. data/lib/fluent/plugin_helper/socket.rb +277 -0
  276. data/lib/fluent/plugin_helper/socket_option.rb +98 -0
  277. data/lib/fluent/plugin_helper/storage.rb +349 -0
  278. data/lib/fluent/plugin_helper/thread.rb +180 -0
  279. data/lib/fluent/plugin_helper/timer.rb +92 -0
  280. data/lib/fluent/plugin_helper.rb +75 -0
  281. data/lib/fluent/plugin_id.rb +93 -0
  282. data/lib/fluent/process.rb +22 -0
  283. data/lib/fluent/registry.rb +116 -0
  284. data/lib/fluent/root_agent.rb +372 -0
  285. data/lib/fluent/rpc.rb +94 -0
  286. data/lib/fluent/static_config_analysis.rb +194 -0
  287. data/lib/fluent/supervisor.rb +1054 -0
  288. data/lib/fluent/system_config.rb +187 -0
  289. data/lib/fluent/test/base.rb +78 -0
  290. data/lib/fluent/test/driver/base.rb +225 -0
  291. data/lib/fluent/test/driver/base_owned.rb +83 -0
  292. data/lib/fluent/test/driver/base_owner.rb +135 -0
  293. data/lib/fluent/test/driver/event_feeder.rb +98 -0
  294. data/lib/fluent/test/driver/filter.rb +57 -0
  295. data/lib/fluent/test/driver/formatter.rb +30 -0
  296. data/lib/fluent/test/driver/input.rb +31 -0
  297. data/lib/fluent/test/driver/multi_output.rb +53 -0
  298. data/lib/fluent/test/driver/output.rb +102 -0
  299. data/lib/fluent/test/driver/parser.rb +30 -0
  300. data/lib/fluent/test/driver/storage.rb +30 -0
  301. data/lib/fluent/test/driver/test_event_router.rb +45 -0
  302. data/lib/fluent/test/filter_test.rb +77 -0
  303. data/lib/fluent/test/formatter_test.rb +65 -0
  304. data/lib/fluent/test/helpers.rb +134 -0
  305. data/lib/fluent/test/input_test.rb +174 -0
  306. data/lib/fluent/test/log.rb +79 -0
  307. data/lib/fluent/test/output_test.rb +156 -0
  308. data/lib/fluent/test/parser_test.rb +70 -0
  309. data/lib/fluent/test/startup_shutdown.rb +46 -0
  310. data/lib/fluent/test.rb +58 -0
  311. data/lib/fluent/time.rb +512 -0
  312. data/lib/fluent/timezone.rb +171 -0
  313. data/lib/fluent/tls.rb +81 -0
  314. data/lib/fluent/unique_id.rb +39 -0
  315. data/lib/fluent/variable_store.rb +40 -0
  316. data/lib/fluent/version.rb +21 -0
  317. data/lib/fluent/winsvc.rb +103 -0
  318. data/templates/new_gem/Gemfile +3 -0
  319. data/templates/new_gem/README.md.erb +43 -0
  320. data/templates/new_gem/Rakefile +13 -0
  321. data/templates/new_gem/fluent-plugin.gemspec.erb +27 -0
  322. data/templates/new_gem/lib/fluent/plugin/filter.rb.erb +14 -0
  323. data/templates/new_gem/lib/fluent/plugin/formatter.rb.erb +14 -0
  324. data/templates/new_gem/lib/fluent/plugin/input.rb.erb +11 -0
  325. data/templates/new_gem/lib/fluent/plugin/output.rb.erb +11 -0
  326. data/templates/new_gem/lib/fluent/plugin/parser.rb.erb +15 -0
  327. data/templates/new_gem/lib/fluent/plugin/storage.rb.erb +40 -0
  328. data/templates/new_gem/test/helper.rb.erb +8 -0
  329. data/templates/new_gem/test/plugin/test_filter.rb.erb +18 -0
  330. data/templates/new_gem/test/plugin/test_formatter.rb.erb +18 -0
  331. data/templates/new_gem/test/plugin/test_input.rb.erb +18 -0
  332. data/templates/new_gem/test/plugin/test_output.rb.erb +18 -0
  333. data/templates/new_gem/test/plugin/test_parser.rb.erb +18 -0
  334. data/templates/new_gem/test/plugin/test_storage.rb.erb +18 -0
  335. data/templates/plugin_config_formatter/param.md-compact.erb +25 -0
  336. data/templates/plugin_config_formatter/param.md-table.erb +10 -0
  337. data/templates/plugin_config_formatter/param.md.erb +34 -0
  338. data/templates/plugin_config_formatter/section.md.erb +12 -0
  339. data/test/command/test_binlog_reader.rb +362 -0
  340. data/test/command/test_ca_generate.rb +70 -0
  341. data/test/command/test_cap_ctl.rb +100 -0
  342. data/test/command/test_cat.rb +128 -0
  343. data/test/command/test_ctl.rb +57 -0
  344. data/test/command/test_fluentd.rb +1106 -0
  345. data/test/command/test_plugin_config_formatter.rb +398 -0
  346. data/test/command/test_plugin_generator.rb +109 -0
  347. data/test/compat/test_calls_super.rb +166 -0
  348. data/test/compat/test_parser.rb +92 -0
  349. data/test/config/assertions.rb +42 -0
  350. data/test/config/test_config_parser.rb +551 -0
  351. data/test/config/test_configurable.rb +1784 -0
  352. data/test/config/test_configure_proxy.rb +604 -0
  353. data/test/config/test_dsl.rb +415 -0
  354. data/test/config/test_element.rb +518 -0
  355. data/test/config/test_literal_parser.rb +309 -0
  356. data/test/config/test_plugin_configuration.rb +56 -0
  357. data/test/config/test_section.rb +191 -0
  358. data/test/config/test_system_config.rb +199 -0
  359. data/test/config/test_types.rb +408 -0
  360. data/test/counter/test_client.rb +563 -0
  361. data/test/counter/test_error.rb +44 -0
  362. data/test/counter/test_mutex_hash.rb +179 -0
  363. data/test/counter/test_server.rb +589 -0
  364. data/test/counter/test_store.rb +258 -0
  365. data/test/counter/test_validator.rb +137 -0
  366. data/test/helper.rb +155 -0
  367. data/test/helpers/fuzzy_assert.rb +89 -0
  368. data/test/helpers/process_extenstion.rb +33 -0
  369. data/test/plugin/data/2010/01/20100102-030405.log +0 -0
  370. data/test/plugin/data/2010/01/20100102-030406.log +0 -0
  371. data/test/plugin/data/2010/01/20100102.log +0 -0
  372. data/test/plugin/data/log/bar +0 -0
  373. data/test/plugin/data/log/foo/bar.log +0 -0
  374. data/test/plugin/data/log/foo/bar2 +0 -0
  375. data/test/plugin/data/log/test.log +0 -0
  376. data/test/plugin/data/sd_file/config +11 -0
  377. data/test/plugin/data/sd_file/config.json +17 -0
  378. data/test/plugin/data/sd_file/config.yaml +11 -0
  379. data/test/plugin/data/sd_file/config.yml +11 -0
  380. data/test/plugin/data/sd_file/invalid_config.yml +7 -0
  381. data/test/plugin/in_tail/test_fifo.rb +121 -0
  382. data/test/plugin/in_tail/test_io_handler.rb +140 -0
  383. data/test/plugin/in_tail/test_position_file.rb +379 -0
  384. data/test/plugin/out_forward/test_ack_handler.rb +101 -0
  385. data/test/plugin/out_forward/test_connection_manager.rb +145 -0
  386. data/test/plugin/out_forward/test_handshake_protocol.rb +112 -0
  387. data/test/plugin/out_forward/test_load_balancer.rb +106 -0
  388. data/test/plugin/out_forward/test_socket_cache.rb +149 -0
  389. data/test/plugin/test_bare_output.rb +131 -0
  390. data/test/plugin/test_base.rb +115 -0
  391. data/test/plugin/test_buf_file.rb +1275 -0
  392. data/test/plugin/test_buf_file_single.rb +833 -0
  393. data/test/plugin/test_buf_memory.rb +42 -0
  394. data/test/plugin/test_buffer.rb +1383 -0
  395. data/test/plugin/test_buffer_chunk.rb +198 -0
  396. data/test/plugin/test_buffer_file_chunk.rb +871 -0
  397. data/test/plugin/test_buffer_file_single_chunk.rb +611 -0
  398. data/test/plugin/test_buffer_memory_chunk.rb +339 -0
  399. data/test/plugin/test_compressable.rb +87 -0
  400. data/test/plugin/test_file_util.rb +96 -0
  401. data/test/plugin/test_file_wrapper.rb +126 -0
  402. data/test/plugin/test_filter.rb +368 -0
  403. data/test/plugin/test_filter_grep.rb +697 -0
  404. data/test/plugin/test_filter_parser.rb +731 -0
  405. data/test/plugin/test_filter_record_transformer.rb +577 -0
  406. data/test/plugin/test_filter_stdout.rb +207 -0
  407. data/test/plugin/test_formatter_csv.rb +136 -0
  408. data/test/plugin/test_formatter_hash.rb +38 -0
  409. data/test/plugin/test_formatter_json.rb +61 -0
  410. data/test/plugin/test_formatter_ltsv.rb +70 -0
  411. data/test/plugin/test_formatter_msgpack.rb +28 -0
  412. data/test/plugin/test_formatter_out_file.rb +116 -0
  413. data/test/plugin/test_formatter_single_value.rb +44 -0
  414. data/test/plugin/test_formatter_tsv.rb +76 -0
  415. data/test/plugin/test_in_debug_agent.rb +49 -0
  416. data/test/plugin/test_in_exec.rb +261 -0
  417. data/test/plugin/test_in_forward.rb +1180 -0
  418. data/test/plugin/test_in_gc_stat.rb +62 -0
  419. data/test/plugin/test_in_http.rb +1080 -0
  420. data/test/plugin/test_in_monitor_agent.rb +923 -0
  421. data/test/plugin/test_in_object_space.rb +60 -0
  422. data/test/plugin/test_in_sample.rb +190 -0
  423. data/test/plugin/test_in_syslog.rb +505 -0
  424. data/test/plugin/test_in_tail.rb +2363 -0
  425. data/test/plugin/test_in_tcp.rb +243 -0
  426. data/test/plugin/test_in_udp.rb +268 -0
  427. data/test/plugin/test_in_unix.rb +181 -0
  428. data/test/plugin/test_input.rb +137 -0
  429. data/test/plugin/test_metadata.rb +89 -0
  430. data/test/plugin/test_metrics.rb +294 -0
  431. data/test/plugin/test_metrics_local.rb +96 -0
  432. data/test/plugin/test_multi_output.rb +204 -0
  433. data/test/plugin/test_out_copy.rb +308 -0
  434. data/test/plugin/test_out_exec.rb +312 -0
  435. data/test/plugin/test_out_exec_filter.rb +606 -0
  436. data/test/plugin/test_out_file.rb +1037 -0
  437. data/test/plugin/test_out_forward.rb +1348 -0
  438. data/test/plugin/test_out_http.rb +428 -0
  439. data/test/plugin/test_out_null.rb +105 -0
  440. data/test/plugin/test_out_relabel.rb +28 -0
  441. data/test/plugin/test_out_roundrobin.rb +146 -0
  442. data/test/plugin/test_out_secondary_file.rb +458 -0
  443. data/test/plugin/test_out_stdout.rb +205 -0
  444. data/test/plugin/test_out_stream.rb +103 -0
  445. data/test/plugin/test_output.rb +1065 -0
  446. data/test/plugin/test_output_as_buffered.rb +2024 -0
  447. data/test/plugin/test_output_as_buffered_backup.rb +363 -0
  448. data/test/plugin/test_output_as_buffered_compress.rb +165 -0
  449. data/test/plugin/test_output_as_buffered_overflow.rb +250 -0
  450. data/test/plugin/test_output_as_buffered_retries.rb +919 -0
  451. data/test/plugin/test_output_as_buffered_secondary.rb +882 -0
  452. data/test/plugin/test_output_as_standard.rb +374 -0
  453. data/test/plugin/test_owned_by.rb +35 -0
  454. data/test/plugin/test_parser.rb +399 -0
  455. data/test/plugin/test_parser_apache.rb +42 -0
  456. data/test/plugin/test_parser_apache2.rb +47 -0
  457. data/test/plugin/test_parser_apache_error.rb +45 -0
  458. data/test/plugin/test_parser_csv.rb +200 -0
  459. data/test/plugin/test_parser_json.rb +138 -0
  460. data/test/plugin/test_parser_labeled_tsv.rb +160 -0
  461. data/test/plugin/test_parser_multiline.rb +111 -0
  462. data/test/plugin/test_parser_nginx.rb +88 -0
  463. data/test/plugin/test_parser_none.rb +52 -0
  464. data/test/plugin/test_parser_regexp.rb +289 -0
  465. data/test/plugin/test_parser_syslog.rb +650 -0
  466. data/test/plugin/test_parser_tsv.rb +122 -0
  467. data/test/plugin/test_sd_file.rb +228 -0
  468. data/test/plugin/test_sd_srv.rb +230 -0
  469. data/test/plugin/test_storage.rb +167 -0
  470. data/test/plugin/test_storage_local.rb +335 -0
  471. data/test/plugin/test_string_util.rb +26 -0
  472. data/test/plugin_helper/data/cert/cert-key.pem +27 -0
  473. data/test/plugin_helper/data/cert/cert-with-CRLF.pem +19 -0
  474. data/test/plugin_helper/data/cert/cert-with-no-newline.pem +19 -0
  475. data/test/plugin_helper/data/cert/cert.pem +19 -0
  476. data/test/plugin_helper/data/cert/cert_chains/ca-cert-key.pem +27 -0
  477. data/test/plugin_helper/data/cert/cert_chains/ca-cert.pem +20 -0
  478. data/test/plugin_helper/data/cert/cert_chains/cert-key.pem +27 -0
  479. data/test/plugin_helper/data/cert/cert_chains/cert.pem +40 -0
  480. data/test/plugin_helper/data/cert/empty.pem +0 -0
  481. data/test/plugin_helper/data/cert/generate_cert.rb +125 -0
  482. data/test/plugin_helper/data/cert/with_ca/ca-cert-key-pass.pem +30 -0
  483. data/test/plugin_helper/data/cert/with_ca/ca-cert-key.pem +27 -0
  484. data/test/plugin_helper/data/cert/with_ca/ca-cert-pass.pem +20 -0
  485. data/test/plugin_helper/data/cert/with_ca/ca-cert.pem +20 -0
  486. data/test/plugin_helper/data/cert/with_ca/cert-key-pass.pem +30 -0
  487. data/test/plugin_helper/data/cert/with_ca/cert-key.pem +27 -0
  488. data/test/plugin_helper/data/cert/with_ca/cert-pass.pem +21 -0
  489. data/test/plugin_helper/data/cert/with_ca/cert.pem +21 -0
  490. data/test/plugin_helper/data/cert/without_ca/cert-key-pass.pem +30 -0
  491. data/test/plugin_helper/data/cert/without_ca/cert-key.pem +27 -0
  492. data/test/plugin_helper/data/cert/without_ca/cert-pass.pem +20 -0
  493. data/test/plugin_helper/data/cert/without_ca/cert.pem +20 -0
  494. data/test/plugin_helper/http_server/test_app.rb +65 -0
  495. data/test/plugin_helper/http_server/test_route.rb +32 -0
  496. data/test/plugin_helper/service_discovery/test_manager.rb +93 -0
  497. data/test/plugin_helper/service_discovery/test_round_robin_balancer.rb +21 -0
  498. data/test/plugin_helper/test_cert_option.rb +25 -0
  499. data/test/plugin_helper/test_child_process.rb +840 -0
  500. data/test/plugin_helper/test_compat_parameters.rb +358 -0
  501. data/test/plugin_helper/test_event_emitter.rb +80 -0
  502. data/test/plugin_helper/test_event_loop.rb +52 -0
  503. data/test/plugin_helper/test_extract.rb +194 -0
  504. data/test/plugin_helper/test_formatter.rb +255 -0
  505. data/test/plugin_helper/test_http_server_helper.rb +372 -0
  506. data/test/plugin_helper/test_inject.rb +561 -0
  507. data/test/plugin_helper/test_metrics.rb +137 -0
  508. data/test/plugin_helper/test_parser.rb +264 -0
  509. data/test/plugin_helper/test_record_accessor.rb +238 -0
  510. data/test/plugin_helper/test_retry_state.rb +442 -0
  511. data/test/plugin_helper/test_server.rb +1823 -0
  512. data/test/plugin_helper/test_service_discovery.rb +165 -0
  513. data/test/plugin_helper/test_socket.rb +146 -0
  514. data/test/plugin_helper/test_storage.rb +542 -0
  515. data/test/plugin_helper/test_thread.rb +164 -0
  516. data/test/plugin_helper/test_timer.rb +130 -0
  517. data/test/scripts/exec_script.rb +32 -0
  518. data/test/scripts/fluent/plugin/formatter1/formatter_test1.rb +7 -0
  519. data/test/scripts/fluent/plugin/formatter2/formatter_test2.rb +7 -0
  520. data/test/scripts/fluent/plugin/formatter_known.rb +8 -0
  521. data/test/scripts/fluent/plugin/out_test.rb +81 -0
  522. data/test/scripts/fluent/plugin/out_test2.rb +80 -0
  523. data/test/scripts/fluent/plugin/parser_known.rb +4 -0
  524. data/test/test_capability.rb +74 -0
  525. data/test/test_clock.rb +164 -0
  526. data/test/test_config.rb +202 -0
  527. data/test/test_configdsl.rb +148 -0
  528. data/test/test_daemonizer.rb +91 -0
  529. data/test/test_engine.rb +203 -0
  530. data/test/test_event.rb +531 -0
  531. data/test/test_event_router.rb +331 -0
  532. data/test/test_event_time.rb +199 -0
  533. data/test/test_filter.rb +121 -0
  534. data/test/test_fluent_log_event_router.rb +99 -0
  535. data/test/test_formatter.rb +366 -0
  536. data/test/test_input.rb +31 -0
  537. data/test/test_log.rb +994 -0
  538. data/test/test_logger_initializer.rb +46 -0
  539. data/test/test_match.rb +148 -0
  540. data/test/test_mixin.rb +351 -0
  541. data/test/test_msgpack_factory.rb +18 -0
  542. data/test/test_oj_options.rb +55 -0
  543. data/test/test_output.rb +278 -0
  544. data/test/test_plugin.rb +251 -0
  545. data/test/test_plugin_classes.rb +370 -0
  546. data/test/test_plugin_helper.rb +81 -0
  547. data/test/test_plugin_id.rb +119 -0
  548. data/test/test_process.rb +14 -0
  549. data/test/test_root_agent.rb +951 -0
  550. data/test/test_static_config_analysis.rb +177 -0
  551. data/test/test_supervisor.rb +601 -0
  552. data/test/test_test_drivers.rb +136 -0
  553. data/test/test_time_formatter.rb +301 -0
  554. data/test/test_time_parser.rb +362 -0
  555. data/test/test_tls.rb +65 -0
  556. data/test/test_unique_id.rb +47 -0
  557. data/test/test_variable_store.rb +65 -0
  558. metadata +1261 -0
@@ -0,0 +1,1037 @@
1
+ require_relative '../helper'
2
+ require 'fluent/test/driver/output'
3
+ require 'fluent/plugin/out_file'
4
+ require 'fileutils'
5
+ require 'time'
6
+ require 'timecop'
7
+ require 'zlib'
8
+
9
+ class FileOutputTest < Test::Unit::TestCase
10
+ def setup
11
+ Fluent::Test.setup
12
+ FileUtils.rm_rf(TMP_DIR)
13
+ FileUtils.mkdir_p(TMP_DIR)
14
+ @default_newline = if Fluent.windows?
15
+ "\r\n"
16
+ else
17
+ "\n"
18
+ end
19
+ end
20
+
21
+ TMP_DIR = File.expand_path(File.dirname(__FILE__) + "/../tmp/out_file#{ENV['TEST_ENV_NUMBER']}")
22
+
23
+ CONFIG = %[
24
+ path #{TMP_DIR}/out_file_test
25
+ compress gz
26
+ utc
27
+ <buffer>
28
+ timekey_use_utc true
29
+ </buffer>
30
+ ]
31
+
32
+ def create_driver(conf = CONFIG, opts = {})
33
+ Fluent::Test::Driver::Output.new(Fluent::Plugin::FileOutput, opts: opts).configure(conf)
34
+ end
35
+
36
+ sub_test_case 'configuration' do
37
+ test 'basic configuration' do
38
+ d = create_driver %[
39
+ path test_path
40
+ compress gz
41
+ ]
42
+ assert_equal 'test_path', d.instance.path
43
+ assert_equal :gz, d.instance.compress
44
+ assert_equal :gzip, d.instance.instance_eval{ @compress_method }
45
+ end
46
+
47
+ test 'using root_dir for buffer path' do
48
+ system_conf_opts = {'root_dir' => File.join(TMP_DIR, 'testrootdir')}
49
+ buf_conf = config_element('buffer', '', {'flush_interval' => '1s'})
50
+ conf = config_element('match', '**', {'@id' => 'myout', 'path' => 'test_path', 'append' => 'true'}, [buf_conf])
51
+ d = create_driver(conf, system_conf_opts)
52
+
53
+ assert_equal 'test_path', d.instance.path
54
+ assert d.instance.append
55
+
56
+ assert d.instance.buffer.respond_to?(:path) # file buffer
57
+ assert_equal 1, d.instance.buffer_config.flush_interval
58
+
59
+ assert_equal File.join(TMP_DIR, 'testrootdir', 'worker0', 'myout'), d.instance.plugin_root_dir
60
+
61
+ buffer_path_under_root_dir = File.join(TMP_DIR, 'testrootdir', 'worker0', 'myout', 'buffer', 'buffer.*.log')
62
+ assert_equal buffer_path_under_root_dir, d.instance.buffer.path
63
+ end
64
+
65
+ test 'path should be writable' do
66
+ assert_raise(Fluent::ConfigError.new("'path' parameter is required")) do
67
+ create_driver ""
68
+ end
69
+
70
+ assert_nothing_raised do
71
+ create_driver %[path #{TMP_DIR}/test_path]
72
+ end
73
+
74
+ assert_nothing_raised do
75
+ FileUtils.mkdir_p("#{TMP_DIR}/test_dir")
76
+ File.chmod(0777, "#{TMP_DIR}/test_dir")
77
+ create_driver %[path #{TMP_DIR}/test_dir/foo/bar/baz]
78
+ end
79
+
80
+ if Process.uid.nonzero?
81
+ assert_raise(Fluent::ConfigError) do
82
+ FileUtils.mkdir_p("#{TMP_DIR}/test_dir")
83
+ File.chmod(0555, "#{TMP_DIR}/test_dir")
84
+ create_driver %[path #{TMP_DIR}/test_dir/foo/bar/baz]
85
+ end
86
+ end
87
+ end
88
+
89
+ test 'default timezone is localtime' do
90
+ d = create_driver(%[path #{TMP_DIR}/out_file_test])
91
+ time = event_time("2011-01-02 13:14:15 UTC")
92
+
93
+ with_timezone(Fluent.windows? ? 'NST-8' : 'Asia/Taipei') do
94
+ d.run(default_tag: 'test') do
95
+ d.feed(time, {"a"=>1})
96
+ end
97
+ end
98
+ assert_equal 1, d.formatted.size
99
+ assert_equal %[2011-01-02T21:14:15+08:00\ttest\t{"a":1}#{@default_newline}], d.formatted[0]
100
+ end
101
+
102
+ test 'no configuration error raised for basic configuration using "*" (v0.12 style)' do
103
+ conf = config_element('match', '**', {
104
+ 'path' => "#{TMP_DIR}/test_out.*.log",
105
+ 'time_slice_format' => '%Y%m%d',
106
+ })
107
+ assert_nothing_raised do
108
+ create_driver(conf)
109
+ end
110
+ end
111
+
112
+ if Process.uid.nonzero?
113
+ test 'configuration error raised if specified directory via template is not writable' do
114
+ Timecop.freeze(Time.parse("2016-10-04 21:33:27 UTC")) do
115
+ conf = config_element('match', '**', {
116
+ 'path' => "#{TMP_DIR}/prohibited/${tag}/file.%Y%m%d.log",
117
+ }, [ config_element('buffer', 'time,tag', {'timekey' => 86400, 'timekey_zone' => '+0000'}) ])
118
+ FileUtils.mkdir_p("#{TMP_DIR}/prohibited")
119
+ File.chmod(0555, "#{TMP_DIR}/prohibited")
120
+ assert_raise Fluent::ConfigError.new("out_file: `#{TMP_DIR}/prohibited/a/file.20161004.log_**.log` is not writable") do
121
+ create_driver(conf)
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ test 'configuration using inject/format/buffer sections fully' do
128
+ conf = config_element('match', '**', {
129
+ 'path' => "#{TMP_DIR}/${tag}/${type}/conf_test.%Y%m%d.%H%M.log",
130
+ 'add_path_suffix' => 'false',
131
+ 'append' => "true",
132
+ 'symlink_path' => "#{TMP_DIR}/conf_test.current.log",
133
+ 'compress' => 'gzip',
134
+ 'recompress' => 'true',
135
+ }, [
136
+ config_element('inject', '', {
137
+ 'hostname_key' => 'hostname',
138
+ 'hostname' => 'testing.local',
139
+ 'tag_key' => 'tag',
140
+ 'time_key' => 'time',
141
+ 'time_type' => 'string',
142
+ 'time_format' => '%Y/%m/%d %H:%M:%S %z',
143
+ 'timezone' => '+0900',
144
+ }),
145
+ config_element('format', '', {
146
+ '@type' => 'out_file',
147
+ 'include_tag' => 'true',
148
+ 'include_time' => 'true',
149
+ 'delimiter' => 'COMMA',
150
+ 'time_type' => 'string',
151
+ 'time_format' => '%Y-%m-%d %H:%M:%S %z',
152
+ 'utc' => 'true',
153
+ }),
154
+ config_element('buffer', 'time,tag,type', {
155
+ '@type' => 'file',
156
+ 'timekey' => '15m',
157
+ 'timekey_wait' => '5s',
158
+ 'timekey_zone' => '+0000',
159
+ 'path' => "#{TMP_DIR}/buf_conf_test",
160
+ 'chunk_limit_size' => '50m',
161
+ 'total_limit_size' => '1g',
162
+ 'compress' => 'gzip',
163
+ }),
164
+ ])
165
+ assert_nothing_raised do
166
+ create_driver(conf)
167
+ end
168
+ end
169
+
170
+ test 'configured as secondary with primary using chunk_key_tag and not using chunk_key_time' do
171
+ require 'fluent/plugin/out_null'
172
+ conf = config_element('match', '**', {
173
+ }, [
174
+ config_element('buffer', 'tag', {
175
+ }),
176
+ config_element('secondary', '', {
177
+ '@type' => 'file',
178
+ 'path' => "#{TMP_DIR}/testing_to_dump_by_out_file",
179
+ }),
180
+ ])
181
+ assert_nothing_raised do
182
+ Fluent::Test::Driver::Output.new(Fluent::Plugin::NullOutput).configure(conf)
183
+ end
184
+ end
185
+ end
186
+
187
+ sub_test_case 'fully configured output' do
188
+ setup do
189
+ Timecop.freeze(Time.parse("2016-10-03 23:58:00 UTC"))
190
+ conf = config_element('match', '**', {
191
+ 'path' => "#{TMP_DIR}/${tag}/${type}/full.%Y%m%d.%H%M.log",
192
+ 'add_path_suffix' => 'false',
193
+ 'append' => "true",
194
+ 'symlink_path' => "#{TMP_DIR}/full.current.log",
195
+ 'compress' => 'gzip',
196
+ 'recompress' => 'true',
197
+ }, [
198
+ config_element('inject', '', {
199
+ 'hostname_key' => 'hostname',
200
+ 'hostname' => 'testing.local',
201
+ 'tag_key' => 'tag',
202
+ 'time_key' => 'time',
203
+ 'time_type' => 'string',
204
+ 'time_format' => '%Y/%m/%d %H:%M:%S %z',
205
+ 'timezone' => '+0900',
206
+ }),
207
+ config_element('format', '', {
208
+ '@type' => 'out_file',
209
+ 'include_tag' => 'true',
210
+ 'include_time' => 'true',
211
+ 'delimiter' => 'COMMA',
212
+ 'time_type' => 'string',
213
+ 'time_format' => '%Y-%m-%d %H:%M:%S %z',
214
+ 'utc' => 'true',
215
+ }),
216
+ config_element('buffer', 'time,tag,type', {
217
+ '@type' => 'file',
218
+ 'timekey' => '15m',
219
+ 'timekey_wait' => '5s',
220
+ 'timekey_zone' => '+0000',
221
+ 'path' => "#{TMP_DIR}/buf_full",
222
+ 'chunk_limit_size' => '50m',
223
+ 'total_limit_size' => '1g',
224
+ 'compress' => 'gzip',
225
+ }),
226
+ ])
227
+ @d = create_driver(conf)
228
+ end
229
+
230
+ teardown do
231
+ FileUtils.rm_rf("#{TMP_DIR}/buf_full")
232
+ FileUtils.rm_rf("#{TMP_DIR}/my.data")
233
+ FileUtils.rm_rf("#{TMP_DIR}/your.data")
234
+ FileUtils.rm_rf("#{TMP_DIR}/full.current.log")
235
+ Timecop.return
236
+ end
237
+
238
+ test 'can format/write data correctly' do
239
+ d = @d
240
+
241
+ assert_equal 50*1024*1024, d.instance.buffer.chunk_limit_size
242
+ assert_equal 1*1024*1024*1024, d.instance.buffer.total_limit_size
243
+
244
+ assert !(File.symlink?("#{TMP_DIR}/full.current.log"))
245
+
246
+ t1 = event_time("2016-10-03 23:58:09 UTC")
247
+ t2 = event_time("2016-10-03 23:59:33 UTC")
248
+ t3 = event_time("2016-10-03 23:59:57 UTC")
249
+ t4 = event_time("2016-10-04 00:00:17 UTC")
250
+ t5 = event_time("2016-10-04 00:01:59 UTC")
251
+
252
+ Timecop.freeze(Time.parse("2016-10-03 23:58:30 UTC"))
253
+
254
+ d.run(start: true, flush: false, shutdown: false) do
255
+ d.feed('my.data', t1, {"type" => "a", "message" => "data raw content"})
256
+ d.feed('my.data', t2, {"type" => "a", "message" => "data raw content"})
257
+ d.feed('your.data', t3, {"type" => "a", "message" => "data raw content"})
258
+ end
259
+
260
+ assert_equal 3, d.formatted.size
261
+
262
+ assert Dir.exist?("#{TMP_DIR}/buf_full")
263
+ assert !(Dir.exist?("#{TMP_DIR}/my.data/a"))
264
+ assert !(Dir.exist?("#{TMP_DIR}/your.data/a"))
265
+ buffer_files = Dir.entries("#{TMP_DIR}/buf_full").reject{|e| e =~ /^\.+$/ }
266
+ assert_equal 2, buffer_files.select{|n| n.end_with?('.meta') }.size
267
+ assert_equal 2, buffer_files.select{|n| !n.end_with?('.meta') }.size
268
+
269
+ m1 = d.instance.metadata('my.data', t1, {"type" => "a"})
270
+ m2 = d.instance.metadata('your.data', t3, {"type" => "a"})
271
+
272
+ assert_equal 2, d.instance.buffer.stage.size
273
+ b1_path = d.instance.buffer.stage[m1].path
274
+ b1_size = File.lstat(b1_path).size
275
+
276
+ unless Fluent.windows?
277
+ assert File.symlink?("#{TMP_DIR}/full.current.log")
278
+ assert_equal d.instance.buffer.stage[m2].path, File.readlink("#{TMP_DIR}/full.current.log")
279
+ end
280
+
281
+ Timecop.freeze(Time.parse("2016-10-04 00:00:06 UTC"))
282
+
283
+ d.run(start: false, flush: true, shutdown: true) do
284
+ d.feed('my.data', t4, {"type" => "a", "message" => "data raw content"})
285
+ d.feed('your.data', t5, {"type" => "a", "message" => "data raw content"})
286
+ end
287
+
288
+ assert Dir.exist?("#{TMP_DIR}/buf_full")
289
+ assert Dir.exist?("#{TMP_DIR}/my.data/a")
290
+ assert Dir.exist?("#{TMP_DIR}/your.data/a")
291
+
292
+ buffer_files = Dir.entries("#{TMP_DIR}/buf_full").reject{|e| e =~ /^\.+$/ }
293
+ assert_equal 0, buffer_files.size
294
+
295
+ assert File.exist?("#{TMP_DIR}/my.data/a/full.20161003.2345.log.gz")
296
+ assert File.exist?("#{TMP_DIR}/my.data/a/full.20161004.0000.log.gz")
297
+ assert File.exist?("#{TMP_DIR}/your.data/a/full.20161003.2345.log.gz")
298
+ assert File.exist?("#{TMP_DIR}/your.data/a/full.20161004.0000.log.gz")
299
+
300
+ assert{ File.lstat("#{TMP_DIR}/my.data/a/full.20161003.2345.log.gz").size < b1_size } # recompress
301
+
302
+ assert_equal 5, d.formatted.size
303
+
304
+ r1 = %!2016-10-03 23:58:09 +0000,my.data,{"type":"a","message":"data raw content","hostname":"testing.local","tag":"my.data","time":"2016/10/04 08:58:09 +0900"}#{@default_newline}!
305
+ r2 = %!2016-10-03 23:59:33 +0000,my.data,{"type":"a","message":"data raw content","hostname":"testing.local","tag":"my.data","time":"2016/10/04 08:59:33 +0900"}#{@default_newline}!
306
+ r3 = %!2016-10-03 23:59:57 +0000,your.data,{"type":"a","message":"data raw content","hostname":"testing.local","tag":"your.data","time":"2016/10/04 08:59:57 +0900"}#{@default_newline}!
307
+ r4 = %!2016-10-04 00:00:17 +0000,my.data,{"type":"a","message":"data raw content","hostname":"testing.local","tag":"my.data","time":"2016/10/04 09:00:17 +0900"}#{@default_newline}!
308
+ r5 = %!2016-10-04 00:01:59 +0000,your.data,{"type":"a","message":"data raw content","hostname":"testing.local","tag":"your.data","time":"2016/10/04 09:01:59 +0900"}#{@default_newline}!
309
+ assert_equal r1, d.formatted[0]
310
+ assert_equal r2, d.formatted[1]
311
+ assert_equal r3, d.formatted[2]
312
+ assert_equal r4, d.formatted[3]
313
+ assert_equal r5, d.formatted[4]
314
+
315
+ read_gunzip = ->(path){
316
+ File.open(path){ |fio|
317
+ Zlib::GzipReader.new(StringIO.new(fio.read)).read
318
+ }
319
+ }
320
+ assert_equal r1 + r2, read_gunzip.call("#{TMP_DIR}/my.data/a/full.20161003.2345.log.gz")
321
+ assert_equal r3, read_gunzip.call("#{TMP_DIR}/your.data/a/full.20161003.2345.log.gz")
322
+ assert_equal r4, read_gunzip.call("#{TMP_DIR}/my.data/a/full.20161004.0000.log.gz")
323
+ assert_equal r5, read_gunzip.call("#{TMP_DIR}/your.data/a/full.20161004.0000.log.gz")
324
+ end
325
+ end
326
+
327
+ sub_test_case 'format' do
328
+ test 'timezone UTC specified' do
329
+ d = create_driver
330
+
331
+ time = event_time("2011-01-02 13:14:15 UTC")
332
+ d.run(default_tag: 'test') do
333
+ d.feed(time, {"a"=>1})
334
+ d.feed(time, {"a"=>2})
335
+ end
336
+ assert_equal 2, d.formatted.size
337
+ assert_equal %[2011-01-02T13:14:15Z\ttest\t{"a":1}#{@default_newline}], d.formatted[0]
338
+ assert_equal %[2011-01-02T13:14:15Z\ttest\t{"a":2}#{@default_newline}], d.formatted[1]
339
+ end
340
+
341
+ test 'time formatted with specified timezone, using area name' do
342
+ d = create_driver %[
343
+ path #{TMP_DIR}/out_file_test
344
+ timezone Asia/Taipei
345
+ ]
346
+
347
+ time = event_time("2011-01-02 13:14:15 UTC")
348
+ d.run(default_tag: 'test') do
349
+ d.feed(time, {"a"=>1})
350
+ end
351
+ assert_equal 1, d.formatted.size
352
+ assert_equal %[2011-01-02T21:14:15+08:00\ttest\t{"a":1}#{@default_newline}], d.formatted[0]
353
+ end
354
+
355
+ test 'time formatted with specified timezone, using offset' do
356
+ d = create_driver %[
357
+ path #{TMP_DIR}/out_file_test
358
+ timezone -03:30
359
+ ]
360
+
361
+ time = event_time("2011-01-02 13:14:15 UTC")
362
+ d.run(default_tag: 'test') do
363
+ d.feed(time, {"a"=>1})
364
+ end
365
+ assert_equal 1, d.formatted.size
366
+ assert_equal %[2011-01-02T09:44:15-03:30\ttest\t{"a":1}#{@default_newline}], d.formatted[0]
367
+ end
368
+
369
+ test 'configuration error raised for invalid timezone' do
370
+ assert_raise(Fluent::ConfigError) do
371
+ create_driver %[
372
+ path #{TMP_DIR}/out_file_test
373
+ timezone Invalid/Invalid
374
+ ]
375
+ end
376
+ end
377
+ end
378
+
379
+ def check_gzipped_result(path, expect)
380
+ # Zlib::GzipReader has a bug of concatenated file: https://bugs.ruby-lang.org/issues/9790
381
+ # Following code from https://www.ruby-forum.com/topic/971591#979520
382
+ result = ''
383
+ File.open(path, "rb") { |io|
384
+ loop do
385
+ gzr = Zlib::GzipReader.new(StringIO.new(io.read))
386
+ result << gzr.read
387
+ unused = gzr.unused
388
+ gzr.finish
389
+ break if unused.nil?
390
+ io.pos -= unused.length
391
+ end
392
+ }
393
+
394
+ assert_equal expect, result
395
+ end
396
+
397
+ def check_result(path, expect)
398
+ result = File.read(path, mode: "rb")
399
+ assert_equal expect, result
400
+ end
401
+
402
+ sub_test_case 'write' do
403
+ test 'basic case' do
404
+ d = create_driver
405
+
406
+ assert_false File.exist?("#{TMP_DIR}/out_file_test.20110102_0.log.gz")
407
+
408
+ time = event_time("2011-01-02 13:14:15 UTC")
409
+ d.run(default_tag: 'test') do
410
+ d.feed(time, {"a"=>1})
411
+ d.feed(time, {"a"=>2})
412
+ end
413
+
414
+ assert File.exist?("#{TMP_DIR}/out_file_test.20110102_0.log.gz")
415
+ check_gzipped_result("#{TMP_DIR}/out_file_test.20110102_0.log.gz", %[2011-01-02T13:14:15Z\ttest\t{"a":1}#{@default_newline}] + %[2011-01-02T13:14:15Z\ttest\t{"a":2}#{@default_newline}])
416
+ end
417
+ end
418
+
419
+ sub_test_case 'file/directory permissions' do
420
+ TMP_DIR_WITH_SYSTEM = File.expand_path(File.dirname(__FILE__) + "/../tmp/out_file_system#{ENV['TEST_ENV_NUMBER']}")
421
+ # 0750 interprets as "488". "488".to_i(8) # => 4. So, it makes wrong permission. Umm....
422
+ OVERRIDE_DIR_PERMISSION = 750
423
+ OVERRIDE_FILE_PERMISSION = 0620
424
+ CONFIG_WITH_SYSTEM = %[
425
+ path #{TMP_DIR_WITH_SYSTEM}/out_file_test
426
+ compress gz
427
+ utc
428
+ <buffer>
429
+ timekey_use_utc true
430
+ </buffer>
431
+ <system>
432
+ file_permission #{OVERRIDE_FILE_PERMISSION}
433
+ dir_permission #{OVERRIDE_DIR_PERMISSION}
434
+ </system>
435
+ ]
436
+
437
+ setup do
438
+ omit "NTFS doesn't support UNIX like permissions" if Fluent.windows?
439
+ FileUtils.rm_rf(TMP_DIR_WITH_SYSTEM)
440
+ end
441
+
442
+ def parse_system(text)
443
+ basepath = File.expand_path(File.dirname(__FILE__) + '/../../')
444
+ Fluent::Config.parse(text, '(test)', basepath, true).elements.find { |e| e.name == 'system' }
445
+ end
446
+
447
+ test 'write to file with permission specifications' do
448
+ system_conf = parse_system(CONFIG_WITH_SYSTEM)
449
+ sc = Fluent::SystemConfig.new(system_conf)
450
+ Fluent::Engine.init(sc)
451
+ d = create_driver CONFIG_WITH_SYSTEM
452
+
453
+ assert_false File.exist?("#{TMP_DIR_WITH_SYSTEM}/out_file_test.20110102_0.log.gz")
454
+
455
+ time = event_time("2011-01-02 13:14:15 UTC")
456
+ d.run(default_tag: 'test') do
457
+ d.feed(time, {"a"=>1})
458
+ d.feed(time, {"a"=>2})
459
+ end
460
+
461
+ assert File.exist?("#{TMP_DIR_WITH_SYSTEM}/out_file_test.20110102_0.log.gz")
462
+
463
+ check_gzipped_result("#{TMP_DIR_WITH_SYSTEM}/out_file_test.20110102_0.log.gz", %[2011-01-02T13:14:15Z\ttest\t{"a":1}\n] + %[2011-01-02T13:14:15Z\ttest\t{"a":2}\n])
464
+ dir_mode = "%o" % File::stat(TMP_DIR_WITH_SYSTEM).mode
465
+ assert_equal(OVERRIDE_DIR_PERMISSION, dir_mode[-3, 3].to_i)
466
+ file_mode = "%o" % File::stat("#{TMP_DIR_WITH_SYSTEM}/out_file_test.20110102_0.log.gz").mode
467
+ assert_equal(OVERRIDE_FILE_PERMISSION, file_mode[-3, 3].to_i)
468
+ end
469
+ end
470
+
471
+ sub_test_case 'format specified' do
472
+ test 'json' do
473
+ d = create_driver [CONFIG, 'format json', 'include_time_key true', 'time_as_epoch'].join("\n")
474
+
475
+ time = event_time("2011-01-02 13:14:15 UTC")
476
+ d.run(default_tag: 'test') do
477
+ d.feed(time, {"a"=>1})
478
+ d.feed(time, {"a"=>2})
479
+ end
480
+
481
+ path = d.instance.last_written_path
482
+ check_gzipped_result(path, %[#{Yajl.dump({"a" => 1, 'time' => time.to_i})}#{@default_newline}] + %[#{Yajl.dump({"a" => 2, 'time' => time.to_i})}#{@default_newline}])
483
+ end
484
+
485
+ test 'ltsv' do
486
+ d = create_driver [CONFIG, 'format ltsv', 'include_time_key true'].join("\n")
487
+
488
+ time = event_time("2011-01-02 13:14:15 UTC")
489
+ d.run(default_tag: 'test') do
490
+ d.feed(time, {"a"=>1})
491
+ d.feed(time, {"a"=>2})
492
+ end
493
+
494
+ path = d.instance.last_written_path
495
+ check_gzipped_result(path, %[a:1\ttime:2011-01-02T13:14:15Z#{@default_newline}] + %[a:2\ttime:2011-01-02T13:14:15Z#{@default_newline}])
496
+ end
497
+
498
+ test 'single_value' do
499
+ d = create_driver [CONFIG, 'format single_value', 'message_key a'].join("\n")
500
+
501
+ time = event_time("2011-01-02 13:14:15 UTC")
502
+ d.run(default_tag: 'test') do
503
+ d.feed(time, {"a"=>1})
504
+ d.feed(time, {"a"=>2})
505
+ end
506
+
507
+ path = d.instance.last_written_path
508
+ check_gzipped_result(path, %[1#{@default_newline}] + %[2#{@default_newline}])
509
+ end
510
+ end
511
+
512
+ test 'path with index number' do
513
+ time = event_time("2011-01-02 13:14:15 UTC")
514
+ formatted_lines = %[2011-01-02T13:14:15Z\ttest\t{"a":1}#{@default_newline}] + %[2011-01-02T13:14:15Z\ttest\t{"a":2}#{@default_newline}]
515
+
516
+ write_once = ->(){
517
+ d = create_driver
518
+ d.run(default_tag: 'test'){
519
+ d.feed(time, {"a"=>1})
520
+ d.feed(time, {"a"=>2})
521
+ }
522
+ d.instance.last_written_path
523
+ }
524
+
525
+ assert !File.exist?("#{TMP_DIR}/out_file_test.20110102_0.log.gz")
526
+
527
+ path = write_once.call
528
+ assert_equal "#{TMP_DIR}/out_file_test.20110102_0.log.gz", path
529
+ check_gzipped_result(path, formatted_lines)
530
+ assert_equal 1, Dir.glob("#{TMP_DIR}/out_file_test.*").size
531
+
532
+ path = write_once.call
533
+ assert_equal "#{TMP_DIR}/out_file_test.20110102_1.log.gz", path
534
+ check_gzipped_result(path, formatted_lines)
535
+ assert_equal 2, Dir.glob("#{TMP_DIR}/out_file_test.*").size
536
+
537
+ path = write_once.call
538
+ assert_equal "#{TMP_DIR}/out_file_test.20110102_2.log.gz", path
539
+ check_gzipped_result(path, formatted_lines)
540
+ assert_equal 3, Dir.glob("#{TMP_DIR}/out_file_test.*").size
541
+ end
542
+
543
+ data(
544
+ "with compression" => true,
545
+ "without compression" => false,
546
+ )
547
+ test 'append' do |compression|
548
+ time = event_time("2011-01-02 13:14:15 UTC")
549
+ formatted_lines = %[2011-01-02T13:14:15Z\ttest\t{"a":1}#{@default_newline}] + %[2011-01-02T13:14:15Z\ttest\t{"a":2}#{@default_newline}]
550
+
551
+ write_once = ->(){
552
+ config = %[
553
+ path #{TMP_DIR}/out_file_test
554
+ utc
555
+ append true
556
+ <buffer>
557
+ timekey_use_utc true
558
+ </buffer>
559
+ ]
560
+ if compression
561
+ config << " compress gz"
562
+ end
563
+ d = create_driver(config)
564
+ d.run(default_tag: 'test'){
565
+ d.feed(time, {"a"=>1})
566
+ d.feed(time, {"a"=>2})
567
+ }
568
+ d.instance.last_written_path
569
+ }
570
+
571
+ log_file_name = "out_file_test.20110102.log"
572
+ if compression
573
+ log_file_name << ".gz"
574
+ end
575
+
576
+ 1.upto(3) do |i|
577
+ path = write_once.call
578
+ assert_equal "#{TMP_DIR}/#{log_file_name}", path
579
+ expect = formatted_lines * i
580
+ if compression
581
+ check_gzipped_result(path, expect)
582
+ else
583
+ check_result(path, expect)
584
+ end
585
+ end
586
+ end
587
+
588
+ test 'append when JST' do
589
+ with_timezone(Fluent.windows? ? "JST-9" : "Asia/Tokyo") do
590
+ time = event_time("2011-01-02 03:14:15+09:00")
591
+ formatted_lines = %[2011-01-02T03:14:15+09:00\ttest\t{"a":1}#{@default_newline}] + %[2011-01-02T03:14:15+09:00\ttest\t{"a":2}#{@default_newline}]
592
+
593
+ write_once = ->(){
594
+ d = create_driver %[
595
+ path #{TMP_DIR}/out_file_test
596
+ compress gz
597
+ append true
598
+ <buffer>
599
+ timekey_use_utc false
600
+ timekey_zone Asia/Tokyo
601
+ </buffer>
602
+ ]
603
+ d.run(default_tag: 'test'){
604
+ d.feed(time, {"a"=>1})
605
+ d.feed(time, {"a"=>2})
606
+ }
607
+ d.instance.last_written_path
608
+ }
609
+
610
+ path = write_once.call
611
+ assert_equal "#{TMP_DIR}/out_file_test.20110102.log.gz", path
612
+ check_gzipped_result(path, formatted_lines)
613
+
614
+ path = write_once.call
615
+ assert_equal "#{TMP_DIR}/out_file_test.20110102.log.gz", path
616
+ check_gzipped_result(path, formatted_lines * 2)
617
+
618
+ path = write_once.call
619
+ assert_equal "#{TMP_DIR}/out_file_test.20110102.log.gz", path
620
+ check_gzipped_result(path, formatted_lines * 3)
621
+ end
622
+ end
623
+
624
+ test 'append when UTC-02 but timekey_zone is +0900' do
625
+ with_timezone("UTC-02") do # +0200
626
+ time = event_time("2011-01-02 17:14:15+02:00")
627
+ formatted_lines = %[2011-01-02T17:14:15+02:00\ttest\t{"a":1}#{@default_newline}] + %[2011-01-02T17:14:15+02:00\ttest\t{"a":2}#{@default_newline}]
628
+
629
+ write_once = ->(){
630
+ d = create_driver %[
631
+ path #{TMP_DIR}/out_file_test
632
+ compress gz
633
+ append true
634
+ <buffer>
635
+ timekey_use_utc false
636
+ timekey_zone +0900
637
+ </buffer>
638
+ ]
639
+ d.run(default_tag: 'test'){
640
+ d.feed(time, {"a"=>1})
641
+ d.feed(time, {"a"=>2})
642
+ }
643
+ d.instance.last_written_path
644
+ }
645
+
646
+ path = write_once.call
647
+ # Rotated at 2011-01-02 17:00:00+02:00
648
+ assert_equal "#{TMP_DIR}/out_file_test.20110103.log.gz", path
649
+ check_gzipped_result(path, formatted_lines)
650
+
651
+ path = write_once.call
652
+ assert_equal "#{TMP_DIR}/out_file_test.20110103.log.gz", path
653
+ check_gzipped_result(path, formatted_lines * 2)
654
+
655
+ path = write_once.call
656
+ assert_equal "#{TMP_DIR}/out_file_test.20110103.log.gz", path
657
+ check_gzipped_result(path, formatted_lines * 3)
658
+ end
659
+ end
660
+
661
+ test '${chunk_id}' do
662
+ time = event_time("2011-01-02 13:14:15 UTC")
663
+
664
+ write_once = ->(){
665
+ d = create_driver %[
666
+ path #{TMP_DIR}/out_file_chunk_id_${chunk_id}
667
+ utc
668
+ append true
669
+ <buffer>
670
+ timekey_use_utc true
671
+ </buffer>
672
+ ]
673
+ d.run(default_tag: 'test'){
674
+ d.feed(time, {"a"=>1})
675
+ d.feed(time, {"a"=>2})
676
+ }
677
+ d.instance.last_written_path
678
+ }
679
+
680
+ path = write_once.call
681
+ if File.basename(path) =~ /out_file_chunk_id_([-_.@a-zA-Z0-9].*).20110102.log/
682
+ unique_id = Fluent::UniqueId.hex(Fluent::UniqueId.generate)
683
+ assert_equal unique_id.size, $1.size, "chunk_id size is mismatched"
684
+ else
685
+ flunk "chunk_id is not included in the path"
686
+ end
687
+ end
688
+
689
+ SYMLINK_PATH = File.expand_path("#{TMP_DIR}/current")
690
+
691
+ sub_test_case 'symlink' do
692
+ test 'static symlink' do
693
+ omit "Windows doesn't support symlink" if Fluent.windows?
694
+ conf = CONFIG + %[
695
+ symlink_path #{SYMLINK_PATH}
696
+ ]
697
+ symlink_path = "#{SYMLINK_PATH}"
698
+
699
+ d = create_driver(conf)
700
+ begin
701
+ run_and_check(d, symlink_path)
702
+ ensure
703
+ FileUtils.rm_rf(symlink_path)
704
+ end
705
+ end
706
+
707
+ test 'symlink with placeholders' do
708
+ omit "Windows doesn't support symlink" if Fluent.windows?
709
+ conf = %[
710
+ path #{TMP_DIR}/${tag}/out_file_test
711
+ symlink_path #{SYMLINK_PATH}/foo/${tag}
712
+ <buffer tag,time>
713
+ </buffer>
714
+ ]
715
+ symlink_path = "#{SYMLINK_PATH}/foo/tag"
716
+
717
+ d = create_driver(conf)
718
+ begin
719
+ run_and_check(d, symlink_path)
720
+ ensure
721
+ FileUtils.rm_rf(symlink_path)
722
+ end
723
+ end
724
+
725
+ def run_and_check(d, symlink_path)
726
+ d.run(default_tag: 'tag') do
727
+ es = Fluent::OneEventStream.new(event_time("2011-01-02 13:14:15 UTC"), {"a"=>1})
728
+ d.feed(es)
729
+
730
+ assert File.symlink?(symlink_path)
731
+ assert File.exist?(symlink_path) # This checks dest of symlink exists or not.
732
+
733
+ es = Fluent::OneEventStream.new(event_time("2011-01-03 14:15:16 UTC"), {"a"=>2})
734
+ d.feed(es)
735
+
736
+ assert File.symlink?(symlink_path)
737
+ assert File.exist?(symlink_path)
738
+
739
+ meta = d.instance.metadata('tag', event_time("2011-01-03 14:15:16 UTC"), {})
740
+ assert_equal d.instance.buffer.instance_eval{ @stage[meta].path }, File.readlink(symlink_path)
741
+ end
742
+ end
743
+ end
744
+
745
+ sub_test_case 'path' do
746
+ test 'normal' do
747
+ d = create_driver(%[
748
+ path #{TMP_DIR}/out_file_test
749
+ time_slice_format %Y-%m-%d-%H
750
+ utc true
751
+ ])
752
+ time = event_time("2011-01-02 13:14:15 UTC")
753
+ d.run(default_tag: 'test') do
754
+ d.feed(time, {"a"=>1})
755
+ end
756
+ path = d.instance.last_written_path
757
+ assert_equal "#{TMP_DIR}/out_file_test.2011-01-02-13_0.log", path
758
+ end
759
+
760
+ test 'normal with append' do
761
+ d = create_driver(%[
762
+ path #{TMP_DIR}/out_file_test
763
+ time_slice_format %Y-%m-%d-%H
764
+ utc true
765
+ append true
766
+ ])
767
+ time = event_time("2011-01-02 13:14:15 UTC")
768
+ d.run(default_tag: 'test') do
769
+ d.feed(time, {"a"=>1})
770
+ end
771
+ path = d.instance.last_written_path
772
+ assert_equal "#{TMP_DIR}/out_file_test.2011-01-02-13.log", path
773
+ end
774
+
775
+ test '*' do
776
+ d = create_driver(%[
777
+ path #{TMP_DIR}/out_file_test.*.txt
778
+ time_slice_format %Y-%m-%d-%H
779
+ utc true
780
+ ])
781
+ time = event_time("2011-01-02 13:14:15 UTC")
782
+ d.run(default_tag: 'test') do
783
+ d.feed(time, {"a"=>1})
784
+ end
785
+ path = d.instance.last_written_path
786
+ assert_equal "#{TMP_DIR}/out_file_test.2011-01-02-13_0.txt", path
787
+ end
788
+
789
+ test '* with append' do
790
+ d = create_driver(%[
791
+ path #{TMP_DIR}/out_file_test.*.txt
792
+ time_slice_format %Y-%m-%d-%H
793
+ utc true
794
+ append true
795
+ ])
796
+ time = event_time("2011-01-02 13:14:15 UTC")
797
+ d.run(default_tag: 'test') do
798
+ d.feed(time, {"a"=>1})
799
+ end
800
+ path = d.instance.last_written_path
801
+ assert_equal "#{TMP_DIR}/out_file_test.2011-01-02-13.txt", path
802
+ end
803
+ end
804
+
805
+ sub_test_case '#timekey_to_timeformat' do
806
+ setup do
807
+ @d = create_driver
808
+ @i = @d.instance
809
+ end
810
+
811
+ test 'returns empty string for nil' do
812
+ assert_equal '', @i.timekey_to_timeformat(nil)
813
+ end
814
+
815
+ test 'returns timestamp string with seconds for timekey smaller than 60' do
816
+ assert_equal '%Y%m%d%H%M%S', @i.timekey_to_timeformat(1)
817
+ assert_equal '%Y%m%d%H%M%S', @i.timekey_to_timeformat(30)
818
+ assert_equal '%Y%m%d%H%M%S', @i.timekey_to_timeformat(59)
819
+ end
820
+
821
+ test 'returns timestamp string with minutes for timekey smaller than 3600' do
822
+ assert_equal '%Y%m%d%H%M', @i.timekey_to_timeformat(60)
823
+ assert_equal '%Y%m%d%H%M', @i.timekey_to_timeformat(180)
824
+ assert_equal '%Y%m%d%H%M', @i.timekey_to_timeformat(1800)
825
+ assert_equal '%Y%m%d%H%M', @i.timekey_to_timeformat(3599)
826
+ end
827
+
828
+ test 'returns timestamp string with hours for timekey smaller than 86400 (1 day)' do
829
+ assert_equal '%Y%m%d%H', @i.timekey_to_timeformat(3600)
830
+ assert_equal '%Y%m%d%H', @i.timekey_to_timeformat(7200)
831
+ assert_equal '%Y%m%d%H', @i.timekey_to_timeformat(86399)
832
+ end
833
+
834
+ test 'returns timestamp string with days for timekey equal or greater than 86400' do
835
+ assert_equal '%Y%m%d', @i.timekey_to_timeformat(86400)
836
+ assert_equal '%Y%m%d', @i.timekey_to_timeformat(1000000)
837
+ assert_equal '%Y%m%d', @i.timekey_to_timeformat(1000000000)
838
+ end
839
+ end
840
+
841
+ sub_test_case '#compression_suffix' do
842
+ setup do
843
+ @i = create_driver.instance
844
+ end
845
+
846
+ test 'returns empty string for nil (no compression method specified)' do
847
+ assert_equal '', @i.compression_suffix(nil)
848
+ end
849
+
850
+ test 'returns .gz for gzip' do
851
+ assert_equal '.gz', @i.compression_suffix(:gzip)
852
+ end
853
+ end
854
+
855
+ sub_test_case '#generate_path_template' do
856
+ setup do
857
+ @i = create_driver.instance
858
+ end
859
+
860
+ data(
861
+ 'day' => [86400, '%Y%m%d', '%Y-%m-%d'],
862
+ 'hour' => [3600, '%Y%m%d%H', '%Y-%m-%d_%H'],
863
+ 'minute' => [60, '%Y%m%d%H%M', '%Y-%m-%d_%H%M'],
864
+ )
865
+ test 'generates path with timestamp placeholder for original path with tailing star with timekey' do |data|
866
+ timekey, placeholder, time_slice_format = data
867
+ # with index placeholder, without compression suffix when append disabled and compression disabled
868
+ assert_equal "/path/to/file.#{placeholder}_**", @i.generate_path_template('/path/to/file.*', timekey, false, nil)
869
+ # with index placeholder, with .gz suffix when append disabled and gzip compression enabled
870
+ assert_equal "/path/to/file.#{placeholder}_**.gz", @i.generate_path_template('/path/to/file.*', timekey, false, :gzip)
871
+ # without index placeholder, without compression suffix when append enabled and compression disabled
872
+ assert_equal "/path/to/file.#{placeholder}", @i.generate_path_template('/path/to/file.*', timekey, true, nil)
873
+ # without index placeholder, with .gz suffix when append disabled and gzip compression enabled
874
+ assert_equal "/path/to/file.#{placeholder}.gz", @i.generate_path_template('/path/to/file.*', timekey, true, :gzip)
875
+
876
+ # time_slice_format will used instead of computed placeholder if specified
877
+ assert_equal "/path/to/file.#{time_slice_format}_**", @i.generate_path_template('/path/to/file.*', timekey, false, nil, time_slice_format: time_slice_format)
878
+ assert_equal "/path/to/file.#{time_slice_format}_**.gz", @i.generate_path_template('/path/to/file.*', timekey, false, :gzip, time_slice_format: time_slice_format)
879
+ assert_equal "/path/to/file.#{time_slice_format}", @i.generate_path_template('/path/to/file.*', timekey, true, nil, time_slice_format: time_slice_format)
880
+ assert_equal "/path/to/file.#{time_slice_format}.gz", @i.generate_path_template('/path/to/file.*', timekey, true, :gzip, time_slice_format: time_slice_format)
881
+ end
882
+
883
+ data(
884
+ 'day' => [86400 * 2, '%Y%m%d', '%Y-%m-%d'],
885
+ 'hour' => [7200, '%Y%m%d%H', '%Y-%m-%d_%H'],
886
+ 'minute' => [180, '%Y%m%d%H%M', '%Y-%m-%d_%H%M'],
887
+ )
888
+ test 'generates path with timestamp placeholder for original path with star and suffix with timekey' do |data|
889
+ timekey, placeholder, time_slice_format = data
890
+ # with index placeholder, without compression suffix when append disabled and compression disabled
891
+ assert_equal "/path/to/file.#{placeholder}_**.data", @i.generate_path_template('/path/to/file.*.data', timekey, false, nil)
892
+ # with index placeholder, with .gz suffix when append disabled and gzip compression enabled
893
+ assert_equal "/path/to/file.#{placeholder}_**.data.gz", @i.generate_path_template('/path/to/file.*.data', timekey, false, :gzip)
894
+ # without index placeholder, without compression suffix when append enabled and compression disabled
895
+ assert_equal "/path/to/file.#{placeholder}.data", @i.generate_path_template('/path/to/file.*.data', timekey, true, nil)
896
+ # without index placeholder, with .gz suffix when append disabled and gzip compression enabled
897
+ assert_equal "/path/to/file.#{placeholder}.data.gz", @i.generate_path_template('/path/to/file.*.data', timekey, true, :gzip)
898
+
899
+ # time_slice_format will used instead of computed placeholder if specified
900
+ assert_equal "/path/to/file.#{time_slice_format}_**.data", @i.generate_path_template('/path/to/file.*.data', timekey, false, nil, time_slice_format: time_slice_format)
901
+ assert_equal "/path/to/file.#{time_slice_format}_**.data.gz", @i.generate_path_template('/path/to/file.*.data', timekey, false, :gzip, time_slice_format: time_slice_format)
902
+ assert_equal "/path/to/file.#{time_slice_format}.data", @i.generate_path_template('/path/to/file.*.data', timekey, true, nil, time_slice_format: time_slice_format)
903
+ assert_equal "/path/to/file.#{time_slice_format}.data.gz", @i.generate_path_template('/path/to/file.*.data', timekey, true, :gzip, time_slice_format: time_slice_format)
904
+ end
905
+
906
+ test 'raise error to show it is a bug when path including * specified without timekey' do
907
+ assert_raise RuntimeError.new("BUG: configuration error must be raised for path including '*' without timekey") do
908
+ @i.generate_path_template('/path/to/file.*.log', nil, false, nil)
909
+ end
910
+ end
911
+
912
+ data(
913
+ 'day' => [86400 * 7, '%Y%m%d', '%Y-%m-%d'],
914
+ 'hour' => [3600 * 6, '%Y%m%d%H', '%Y-%m-%d_%H'],
915
+ 'minute' => [60 * 15, '%Y%m%d%H%M', '%Y-%m-%d_%H%M'],
916
+ )
917
+ test 'generates path with timestamp placeholder for original path without time placeholders & star with timekey, and path_suffix configured' do |data|
918
+ timekey, placeholder, time_slice_format = data
919
+ # with index placeholder, without compression suffix when append disabled and compression disabled
920
+ assert_equal "/path/to/file.#{placeholder}_**.log", @i.generate_path_template('/path/to/file', timekey, false, nil, path_suffix: '.log')
921
+ # with index placeholder, with .gz suffix when append disabled and gzip compression enabled
922
+ assert_equal "/path/to/file.#{placeholder}_**.log.gz", @i.generate_path_template('/path/to/file', timekey, false, :gzip, path_suffix: '.log')
923
+ # without index placeholder, without compression suffix when append enabled and compression disabled
924
+ assert_equal "/path/to/file.#{placeholder}.log", @i.generate_path_template('/path/to/file', timekey, true, nil, path_suffix: '.log')
925
+ # without index placeholder, with compression suffix when append enabled and gzip compression enabled
926
+ assert_equal "/path/to/file.#{placeholder}.log.gz", @i.generate_path_template('/path/to/file', timekey, true, :gzip, path_suffix: '.log')
927
+
928
+ # time_slice_format will be appended always if it's specified
929
+ assert_equal "/path/to/file.#{time_slice_format}_**.log", @i.generate_path_template('/path/to/file', timekey, false, nil, path_suffix: '.log', time_slice_format: time_slice_format)
930
+ assert_equal "/path/to/file.#{time_slice_format}_**.log.gz", @i.generate_path_template('/path/to/file', timekey, false, :gzip, path_suffix: '.log', time_slice_format: time_slice_format)
931
+ assert_equal "/path/to/file.#{time_slice_format}.log", @i.generate_path_template('/path/to/file', timekey, true, nil, path_suffix: '.log', time_slice_format: time_slice_format)
932
+ assert_equal "/path/to/file.#{time_slice_format}.log.gz", @i.generate_path_template('/path/to/file', timekey, true, :gzip, path_suffix: '.log', time_slice_format: time_slice_format)
933
+ end
934
+
935
+ data(
936
+ 'day' => [86400, '%Y%m%d'],
937
+ 'hour' => [3600, '%Y%m%d%H'],
938
+ 'minute' => [60, '%Y%m%d%H%M'],
939
+ )
940
+ test 'generates path with timestamp placeholder for original path without star with timekey, and path_suffix not configured' do |data|
941
+ timekey, placeholder = data
942
+ # with index placeholder, without compression suffix when append disabled and compression disabled
943
+ assert_equal "/path/to/file.#{placeholder}_**", @i.generate_path_template('/path/to/file', timekey, false, nil)
944
+ # with index placeholder, with .gz suffix when append disabled and gzip compression enabled
945
+ assert_equal "/path/to/file.#{placeholder}_**.gz", @i.generate_path_template('/path/to/file', timekey, false, :gzip)
946
+ # without index placeholder, without compression suffix when append enabled and compression disabled
947
+ assert_equal "/path/to/file.#{placeholder}", @i.generate_path_template('/path/to/file', timekey, true, nil)
948
+ # without index placeholder, with compression suffix when append enabled and gzip compression enabled
949
+ assert_equal "/path/to/file.#{placeholder}.gz", @i.generate_path_template('/path/to/file', timekey, true, :gzip)
950
+ end
951
+
952
+ test 'generates path without adding timestamp placeholder part if original path has enough placeholders for specified timekey' do
953
+ assert_equal "/path/to/file.%Y%m%d", @i.generate_path_template('/path/to/file.%Y%m%d', 86400, true, nil)
954
+ assert_equal "/path/to/%Y%m%d/file", @i.generate_path_template('/path/to/%Y%m%d/file', 86400, true, nil)
955
+
956
+ assert_equal "/path/to/%Y%m%d/file_**", @i.generate_path_template('/path/to/%Y%m%d/file', 86400, false, nil)
957
+
958
+ assert_raise Fluent::ConfigError.new("insufficient timestamp placeholders in path") do
959
+ @i.generate_path_template('/path/to/%Y%m/file', 86400, true, nil)
960
+ end
961
+ assert_raise Fluent::ConfigError.new("insufficient timestamp placeholders in path") do
962
+ @i.generate_path_template('/path/to/file.%Y%m%d.log', 3600, true, nil)
963
+ end
964
+
965
+ assert_equal "/path/to/file.%Y%m%d_%H_**.log.gz", @i.generate_path_template('/path/to/file.%Y%m%d_%H', 7200, false, :gzip, path_suffix: '.log')
966
+ assert_equal "/path/to/${tag}/file.%Y%m%d_%H_**.log.gz", @i.generate_path_template('/path/to/${tag}/file.%Y%m%d_%H', 7200, false, :gzip, path_suffix: '.log')
967
+ end
968
+
969
+ test 'generates path with specified time_slice_format appended even if path has sufficient timestamp placeholders' do
970
+ assert_equal "/path/to/%Y%m%d/file.%Y-%m-%d_%H_**", @i.generate_path_template('/path/to/%Y%m%d/file', 86400, false, nil, time_slice_format: '%Y-%m-%d_%H')
971
+ assert_equal "/path/to/%Y%m%d/file.%Y-%m-%d_%H", @i.generate_path_template('/path/to/%Y%m%d/file', 86400, true, nil, time_slice_format: '%Y-%m-%d_%H')
972
+ assert_equal "/path/to/%Y%m%d/file.%Y-%m-%d_%H_**.log", @i.generate_path_template('/path/to/%Y%m%d/file', 86400, false, nil, time_slice_format: '%Y-%m-%d_%H', path_suffix: '.log')
973
+ assert_equal "/path/to/%Y%m%d/file.%Y-%m-%d_%H.log", @i.generate_path_template('/path/to/%Y%m%d/file', 86400, true, nil, time_slice_format: '%Y-%m-%d_%H', path_suffix: '.log')
974
+ assert_equal "/path/to/%Y%m%d/file.%Y-%m-%d_%H.log.gz", @i.generate_path_template('/path/to/%Y%m%d/file', 86400, true, :gzip, time_slice_format: '%Y-%m-%d_%H', path_suffix: '.log')
975
+ end
976
+
977
+ test 'generates path without timestamp placeholder when path does not include * and timekey not specified' do
978
+ assert_equal '/path/to/file.log', @i.generate_path_template('/path/to/file.log', nil, true, nil)
979
+ assert_equal '/path/to/file.log_**', @i.generate_path_template('/path/to/file.log', nil, false, nil)
980
+ assert_equal '/path/to/file.${tag}.log_**', @i.generate_path_template('/path/to/file.${tag}.log', nil, false, nil)
981
+ assert_equal '/path/to/file.${tag}_**.log', @i.generate_path_template('/path/to/file.${tag}', nil, false, nil, path_suffix: '.log')
982
+ end
983
+ end
984
+
985
+ sub_test_case '#find_filepath_available' do
986
+ setup do
987
+ @tmp = File.join(TMP_DIR, 'find_filepath_test')
988
+ FileUtils.mkdir_p @tmp
989
+ @i = create_driver.instance
990
+ end
991
+
992
+ teardown do
993
+ FileUtils.rm_rf @tmp
994
+ end
995
+
996
+ test 'raise error if argument path does not include index placeholder' do
997
+ assert_raise RuntimeError.new("BUG: index placeholder not found in path: #{@tmp}/myfile") do
998
+ @i.find_filepath_available("#{@tmp}/myfile") do |path|
999
+ # ...
1000
+ end
1001
+ end
1002
+ end
1003
+
1004
+ data(
1005
+ 'without suffix' => ['myfile_0', 'myfile_**'],
1006
+ 'with timestamp' => ['myfile_20161003_0', 'myfile_20161003_**'],
1007
+ 'with base suffix' => ['myfile_0.log', 'myfile_**.log'],
1008
+ 'with compression suffix' => ['myfile_0.log.gz', 'myfile_**.log.gz'],
1009
+ )
1010
+ test 'returns filepath with _0 at first' do |data|
1011
+ expected, argument = data
1012
+ @i.find_filepath_available(File.join(@tmp, argument)) do |path|
1013
+ assert_equal File.join(@tmp, expected), path
1014
+ end
1015
+ end
1016
+
1017
+ test 'returns filepath with index which does not exist yet' do
1018
+ 5.times do |i|
1019
+ File.open(File.join(@tmp, "exist_#{i}.log"), 'a'){|f| } # open(create) and close
1020
+ end
1021
+ @i.find_filepath_available(File.join(@tmp, "exist_**.log")) do |path|
1022
+ assert_equal File.join(@tmp, "exist_5.log"), path
1023
+ end
1024
+ end
1025
+
1026
+ test 'creates lock directory when with_lock is true to exclude operations of other worker process' do
1027
+ 5.times do |i|
1028
+ File.open(File.join(@tmp, "exist_#{i}.log"), 'a')
1029
+ end
1030
+ Dir.mkdir(File.join(@tmp, "exist_5.log.lock"))
1031
+ @i.find_filepath_available(File.join(@tmp, "exist_**.log"), with_lock: true) do |path|
1032
+ assert Dir.exist?(File.join(@tmp, "exist_6.log.lock"))
1033
+ assert_equal File.join(@tmp, "exist_6.log"), path
1034
+ end
1035
+ end
1036
+ end
1037
+ end