fluentd222 1.16.2-x86_64-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (562) hide show
  1. checksums.yaml +7 -0
  2. data/.deepsource.toml +13 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.yaml +71 -0
  4. data/.github/ISSUE_TEMPLATE/config.yml +5 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.yaml +39 -0
  6. data/.github/ISSUE_TEMPLATE.md +17 -0
  7. data/.github/PULL_REQUEST_TEMPLATE.md +14 -0
  8. data/.github/workflows/stale-actions.yml +24 -0
  9. data/.github/workflows/test-ruby-head.yaml +31 -0
  10. data/.github/workflows/test.yaml +32 -0
  11. data/.gitignore +30 -0
  12. data/ADOPTERS.md +5 -0
  13. data/AUTHORS +2 -0
  14. data/CHANGELOG.md +2720 -0
  15. data/CONTRIBUTING.md +45 -0
  16. data/GOVERNANCE.md +55 -0
  17. data/Gemfile +9 -0
  18. data/GithubWorkflow.md +78 -0
  19. data/LICENSE +202 -0
  20. data/MAINTAINERS.md +13 -0
  21. data/README.md +75 -0
  22. data/Rakefile +79 -0
  23. data/SECURITY.md +14 -0
  24. data/bin/fluent-binlog-reader +7 -0
  25. data/bin/fluent-ca-generate +6 -0
  26. data/bin/fluent-cap-ctl +7 -0
  27. data/bin/fluent-cat +5 -0
  28. data/bin/fluent-ctl +7 -0
  29. data/bin/fluent-debug +5 -0
  30. data/bin/fluent-gem +9 -0
  31. data/bin/fluent-plugin-config-format +5 -0
  32. data/bin/fluent-plugin-generate +5 -0
  33. data/bin/fluentd +15 -0
  34. data/code-of-conduct.md +3 -0
  35. data/docs/SECURITY_AUDIT.pdf +0 -0
  36. data/example/copy_roundrobin.conf +39 -0
  37. data/example/counter.conf +18 -0
  38. data/example/filter_stdout.conf +22 -0
  39. data/example/in_forward.conf +14 -0
  40. data/example/in_forward_client.conf +37 -0
  41. data/example/in_forward_shared_key.conf +15 -0
  42. data/example/in_forward_tls.conf +14 -0
  43. data/example/in_forward_users.conf +24 -0
  44. data/example/in_forward_workers.conf +21 -0
  45. data/example/in_http.conf +16 -0
  46. data/example/in_out_forward.conf +17 -0
  47. data/example/in_sample_blocks.conf +17 -0
  48. data/example/in_sample_with_compression.conf +23 -0
  49. data/example/in_syslog.conf +15 -0
  50. data/example/in_tail.conf +14 -0
  51. data/example/in_tcp.conf +13 -0
  52. data/example/in_udp.conf +13 -0
  53. data/example/logevents.conf +25 -0
  54. data/example/multi_filters.conf +61 -0
  55. data/example/out_copy.conf +20 -0
  56. data/example/out_exec_filter.conf +42 -0
  57. data/example/out_file.conf +13 -0
  58. data/example/out_forward.conf +35 -0
  59. data/example/out_forward_buf_file.conf +23 -0
  60. data/example/out_forward_client.conf +109 -0
  61. data/example/out_forward_heartbeat_none.conf +16 -0
  62. data/example/out_forward_sd.conf +17 -0
  63. data/example/out_forward_shared_key.conf +36 -0
  64. data/example/out_forward_tls.conf +18 -0
  65. data/example/out_forward_users.conf +65 -0
  66. data/example/out_null.conf +36 -0
  67. data/example/sd.yaml +8 -0
  68. data/example/secondary_file.conf +42 -0
  69. data/example/suppress_config_dump.conf +7 -0
  70. data/example/v0_12_filter.conf +78 -0
  71. data/example/v1_literal_example.conf +36 -0
  72. data/example/worker_section.conf +36 -0
  73. data/fluent.conf +139 -0
  74. data/fluentd.gemspec +54 -0
  75. data/lib/fluent/agent.rb +168 -0
  76. data/lib/fluent/capability.rb +87 -0
  77. data/lib/fluent/clock.rb +66 -0
  78. data/lib/fluent/command/binlog_reader.rb +244 -0
  79. data/lib/fluent/command/bundler_injection.rb +45 -0
  80. data/lib/fluent/command/ca_generate.rb +184 -0
  81. data/lib/fluent/command/cap_ctl.rb +174 -0
  82. data/lib/fluent/command/cat.rb +365 -0
  83. data/lib/fluent/command/ctl.rb +180 -0
  84. data/lib/fluent/command/debug.rb +103 -0
  85. data/lib/fluent/command/fluentd.rb +374 -0
  86. data/lib/fluent/command/plugin_config_formatter.rb +308 -0
  87. data/lib/fluent/command/plugin_generator.rb +365 -0
  88. data/lib/fluent/compat/call_super_mixin.rb +76 -0
  89. data/lib/fluent/compat/detach_process_mixin.rb +33 -0
  90. data/lib/fluent/compat/exec_util.rb +129 -0
  91. data/lib/fluent/compat/file_util.rb +54 -0
  92. data/lib/fluent/compat/filter.rb +68 -0
  93. data/lib/fluent/compat/formatter.rb +111 -0
  94. data/lib/fluent/compat/formatter_utils.rb +85 -0
  95. data/lib/fluent/compat/handle_tag_and_time_mixin.rb +62 -0
  96. data/lib/fluent/compat/handle_tag_name_mixin.rb +53 -0
  97. data/lib/fluent/compat/input.rb +49 -0
  98. data/lib/fluent/compat/output.rb +721 -0
  99. data/lib/fluent/compat/output_chain.rb +60 -0
  100. data/lib/fluent/compat/parser.rb +310 -0
  101. data/lib/fluent/compat/parser_utils.rb +40 -0
  102. data/lib/fluent/compat/propagate_default.rb +62 -0
  103. data/lib/fluent/compat/record_filter_mixin.rb +34 -0
  104. data/lib/fluent/compat/set_tag_key_mixin.rb +50 -0
  105. data/lib/fluent/compat/set_time_key_mixin.rb +69 -0
  106. data/lib/fluent/compat/socket_util.rb +165 -0
  107. data/lib/fluent/compat/string_util.rb +34 -0
  108. data/lib/fluent/compat/structured_format_mixin.rb +26 -0
  109. data/lib/fluent/compat/type_converter.rb +90 -0
  110. data/lib/fluent/config/basic_parser.rb +123 -0
  111. data/lib/fluent/config/configure_proxy.rb +424 -0
  112. data/lib/fluent/config/dsl.rb +152 -0
  113. data/lib/fluent/config/element.rb +265 -0
  114. data/lib/fluent/config/error.rb +44 -0
  115. data/lib/fluent/config/literal_parser.rb +286 -0
  116. data/lib/fluent/config/parser.rb +107 -0
  117. data/lib/fluent/config/section.rb +272 -0
  118. data/lib/fluent/config/types.rb +249 -0
  119. data/lib/fluent/config/v1_parser.rb +192 -0
  120. data/lib/fluent/config/yaml_parser/fluent_value.rb +47 -0
  121. data/lib/fluent/config/yaml_parser/loader.rb +108 -0
  122. data/lib/fluent/config/yaml_parser/parser.rb +166 -0
  123. data/lib/fluent/config/yaml_parser/section_builder.rb +107 -0
  124. data/lib/fluent/config/yaml_parser.rb +56 -0
  125. data/lib/fluent/config.rb +89 -0
  126. data/lib/fluent/configurable.rb +201 -0
  127. data/lib/fluent/counter/base_socket.rb +44 -0
  128. data/lib/fluent/counter/client.rb +297 -0
  129. data/lib/fluent/counter/error.rb +86 -0
  130. data/lib/fluent/counter/mutex_hash.rb +163 -0
  131. data/lib/fluent/counter/server.rb +273 -0
  132. data/lib/fluent/counter/store.rb +205 -0
  133. data/lib/fluent/counter/validator.rb +145 -0
  134. data/lib/fluent/counter.rb +23 -0
  135. data/lib/fluent/daemon.rb +13 -0
  136. data/lib/fluent/daemonizer.rb +88 -0
  137. data/lib/fluent/engine.rb +253 -0
  138. data/lib/fluent/env.rb +40 -0
  139. data/lib/fluent/error.rb +37 -0
  140. data/lib/fluent/event.rb +330 -0
  141. data/lib/fluent/event_router.rb +315 -0
  142. data/lib/fluent/ext_monitor_require.rb +28 -0
  143. data/lib/fluent/file_wrapper.rb +137 -0
  144. data/lib/fluent/filter.rb +21 -0
  145. data/lib/fluent/fluent_log_event_router.rb +139 -0
  146. data/lib/fluent/formatter.rb +23 -0
  147. data/lib/fluent/input.rb +21 -0
  148. data/lib/fluent/label.rb +46 -0
  149. data/lib/fluent/load.rb +34 -0
  150. data/lib/fluent/log/console_adapter.rb +66 -0
  151. data/lib/fluent/log.rb +752 -0
  152. data/lib/fluent/match.rb +187 -0
  153. data/lib/fluent/mixin.rb +31 -0
  154. data/lib/fluent/msgpack_factory.rb +111 -0
  155. data/lib/fluent/oj_options.rb +61 -0
  156. data/lib/fluent/output.rb +29 -0
  157. data/lib/fluent/output_chain.rb +23 -0
  158. data/lib/fluent/parser.rb +23 -0
  159. data/lib/fluent/plugin/bare_output.rb +104 -0
  160. data/lib/fluent/plugin/base.rb +214 -0
  161. data/lib/fluent/plugin/buf_file.rb +242 -0
  162. data/lib/fluent/plugin/buf_file_single.rb +254 -0
  163. data/lib/fluent/plugin/buf_memory.rb +34 -0
  164. data/lib/fluent/plugin/buffer/chunk.rb +240 -0
  165. data/lib/fluent/plugin/buffer/file_chunk.rb +413 -0
  166. data/lib/fluent/plugin/buffer/file_single_chunk.rb +310 -0
  167. data/lib/fluent/plugin/buffer/memory_chunk.rb +91 -0
  168. data/lib/fluent/plugin/buffer.rb +941 -0
  169. data/lib/fluent/plugin/compressable.rb +96 -0
  170. data/lib/fluent/plugin/exec_util.rb +22 -0
  171. data/lib/fluent/plugin/file_util.rb +22 -0
  172. data/lib/fluent/plugin/filter.rb +127 -0
  173. data/lib/fluent/plugin/filter_grep.rb +189 -0
  174. data/lib/fluent/plugin/filter_parser.rb +130 -0
  175. data/lib/fluent/plugin/filter_record_transformer.rb +324 -0
  176. data/lib/fluent/plugin/filter_stdout.rb +53 -0
  177. data/lib/fluent/plugin/formatter.rb +75 -0
  178. data/lib/fluent/plugin/formatter_csv.rb +78 -0
  179. data/lib/fluent/plugin/formatter_hash.rb +35 -0
  180. data/lib/fluent/plugin/formatter_json.rb +59 -0
  181. data/lib/fluent/plugin/formatter_ltsv.rb +44 -0
  182. data/lib/fluent/plugin/formatter_msgpack.rb +33 -0
  183. data/lib/fluent/plugin/formatter_out_file.rb +53 -0
  184. data/lib/fluent/plugin/formatter_single_value.rb +36 -0
  185. data/lib/fluent/plugin/formatter_stdout.rb +76 -0
  186. data/lib/fluent/plugin/formatter_tsv.rb +40 -0
  187. data/lib/fluent/plugin/in_debug_agent.rb +71 -0
  188. data/lib/fluent/plugin/in_dummy.rb +18 -0
  189. data/lib/fluent/plugin/in_exec.rb +110 -0
  190. data/lib/fluent/plugin/in_forward.rb +473 -0
  191. data/lib/fluent/plugin/in_gc_stat.rb +72 -0
  192. data/lib/fluent/plugin/in_http.rb +677 -0
  193. data/lib/fluent/plugin/in_monitor_agent.rb +412 -0
  194. data/lib/fluent/plugin/in_object_space.rb +93 -0
  195. data/lib/fluent/plugin/in_sample.rb +141 -0
  196. data/lib/fluent/plugin/in_syslog.rb +276 -0
  197. data/lib/fluent/plugin/in_tail/group_watch.rb +204 -0
  198. data/lib/fluent/plugin/in_tail/position_file.rb +269 -0
  199. data/lib/fluent/plugin/in_tail.rb +1299 -0
  200. data/lib/fluent/plugin/in_tcp.rb +226 -0
  201. data/lib/fluent/plugin/in_udp.rb +92 -0
  202. data/lib/fluent/plugin/in_unix.rb +195 -0
  203. data/lib/fluent/plugin/input.rb +75 -0
  204. data/lib/fluent/plugin/metrics.rb +119 -0
  205. data/lib/fluent/plugin/metrics_local.rb +96 -0
  206. data/lib/fluent/plugin/multi_output.rb +195 -0
  207. data/lib/fluent/plugin/out_copy.rb +120 -0
  208. data/lib/fluent/plugin/out_exec.rb +105 -0
  209. data/lib/fluent/plugin/out_exec_filter.rb +319 -0
  210. data/lib/fluent/plugin/out_file.rb +340 -0
  211. data/lib/fluent/plugin/out_forward/ack_handler.rb +176 -0
  212. data/lib/fluent/plugin/out_forward/connection_manager.rb +113 -0
  213. data/lib/fluent/plugin/out_forward/error.rb +28 -0
  214. data/lib/fluent/plugin/out_forward/failure_detector.rb +84 -0
  215. data/lib/fluent/plugin/out_forward/handshake_protocol.rb +125 -0
  216. data/lib/fluent/plugin/out_forward/load_balancer.rb +114 -0
  217. data/lib/fluent/plugin/out_forward/socket_cache.rb +142 -0
  218. data/lib/fluent/plugin/out_forward.rb +826 -0
  219. data/lib/fluent/plugin/out_http.rb +275 -0
  220. data/lib/fluent/plugin/out_null.rb +74 -0
  221. data/lib/fluent/plugin/out_relabel.rb +32 -0
  222. data/lib/fluent/plugin/out_roundrobin.rb +84 -0
  223. data/lib/fluent/plugin/out_secondary_file.rb +148 -0
  224. data/lib/fluent/plugin/out_stdout.rb +74 -0
  225. data/lib/fluent/plugin/out_stream.rb +130 -0
  226. data/lib/fluent/plugin/output.rb +1603 -0
  227. data/lib/fluent/plugin/owned_by_mixin.rb +41 -0
  228. data/lib/fluent/plugin/parser.rb +274 -0
  229. data/lib/fluent/plugin/parser_apache.rb +28 -0
  230. data/lib/fluent/plugin/parser_apache2.rb +88 -0
  231. data/lib/fluent/plugin/parser_apache_error.rb +26 -0
  232. data/lib/fluent/plugin/parser_csv.rb +114 -0
  233. data/lib/fluent/plugin/parser_json.rb +96 -0
  234. data/lib/fluent/plugin/parser_ltsv.rb +51 -0
  235. data/lib/fluent/plugin/parser_msgpack.rb +50 -0
  236. data/lib/fluent/plugin/parser_multiline.rb +152 -0
  237. data/lib/fluent/plugin/parser_nginx.rb +28 -0
  238. data/lib/fluent/plugin/parser_none.rb +36 -0
  239. data/lib/fluent/plugin/parser_regexp.rb +68 -0
  240. data/lib/fluent/plugin/parser_syslog.rb +496 -0
  241. data/lib/fluent/plugin/parser_tsv.rb +42 -0
  242. data/lib/fluent/plugin/sd_file.rb +156 -0
  243. data/lib/fluent/plugin/sd_srv.rb +135 -0
  244. data/lib/fluent/plugin/sd_static.rb +58 -0
  245. data/lib/fluent/plugin/service_discovery.rb +65 -0
  246. data/lib/fluent/plugin/socket_util.rb +22 -0
  247. data/lib/fluent/plugin/storage.rb +84 -0
  248. data/lib/fluent/plugin/storage_local.rb +162 -0
  249. data/lib/fluent/plugin/string_util.rb +22 -0
  250. data/lib/fluent/plugin.rb +206 -0
  251. data/lib/fluent/plugin_helper/cert_option.rb +191 -0
  252. data/lib/fluent/plugin_helper/child_process.rb +369 -0
  253. data/lib/fluent/plugin_helper/compat_parameters.rb +343 -0
  254. data/lib/fluent/plugin_helper/counter.rb +51 -0
  255. data/lib/fluent/plugin_helper/event_emitter.rb +100 -0
  256. data/lib/fluent/plugin_helper/event_loop.rb +170 -0
  257. data/lib/fluent/plugin_helper/extract.rb +104 -0
  258. data/lib/fluent/plugin_helper/formatter.rb +147 -0
  259. data/lib/fluent/plugin_helper/http_server/app.rb +79 -0
  260. data/lib/fluent/plugin_helper/http_server/compat/server.rb +92 -0
  261. data/lib/fluent/plugin_helper/http_server/compat/ssl_context_extractor.rb +52 -0
  262. data/lib/fluent/plugin_helper/http_server/compat/webrick_handler.rb +58 -0
  263. data/lib/fluent/plugin_helper/http_server/methods.rb +35 -0
  264. data/lib/fluent/plugin_helper/http_server/request.rb +42 -0
  265. data/lib/fluent/plugin_helper/http_server/router.rb +54 -0
  266. data/lib/fluent/plugin_helper/http_server/server.rb +94 -0
  267. data/lib/fluent/plugin_helper/http_server/ssl_context_builder.rb +41 -0
  268. data/lib/fluent/plugin_helper/http_server.rb +135 -0
  269. data/lib/fluent/plugin_helper/inject.rb +154 -0
  270. data/lib/fluent/plugin_helper/metrics.rb +129 -0
  271. data/lib/fluent/plugin_helper/parser.rb +147 -0
  272. data/lib/fluent/plugin_helper/record_accessor.rb +207 -0
  273. data/lib/fluent/plugin_helper/retry_state.rb +219 -0
  274. data/lib/fluent/plugin_helper/server.rb +828 -0
  275. data/lib/fluent/plugin_helper/service_discovery/manager.rb +146 -0
  276. data/lib/fluent/plugin_helper/service_discovery/round_robin_balancer.rb +43 -0
  277. data/lib/fluent/plugin_helper/service_discovery.rb +125 -0
  278. data/lib/fluent/plugin_helper/socket.rb +288 -0
  279. data/lib/fluent/plugin_helper/socket_option.rb +98 -0
  280. data/lib/fluent/plugin_helper/storage.rb +349 -0
  281. data/lib/fluent/plugin_helper/thread.rb +180 -0
  282. data/lib/fluent/plugin_helper/timer.rb +92 -0
  283. data/lib/fluent/plugin_helper.rb +75 -0
  284. data/lib/fluent/plugin_id.rb +93 -0
  285. data/lib/fluent/process.rb +22 -0
  286. data/lib/fluent/registry.rb +117 -0
  287. data/lib/fluent/root_agent.rb +372 -0
  288. data/lib/fluent/rpc.rb +95 -0
  289. data/lib/fluent/static_config_analysis.rb +194 -0
  290. data/lib/fluent/supervisor.rb +1076 -0
  291. data/lib/fluent/system_config.rb +189 -0
  292. data/lib/fluent/test/base.rb +78 -0
  293. data/lib/fluent/test/driver/base.rb +231 -0
  294. data/lib/fluent/test/driver/base_owned.rb +83 -0
  295. data/lib/fluent/test/driver/base_owner.rb +135 -0
  296. data/lib/fluent/test/driver/event_feeder.rb +98 -0
  297. data/lib/fluent/test/driver/filter.rb +61 -0
  298. data/lib/fluent/test/driver/formatter.rb +30 -0
  299. data/lib/fluent/test/driver/input.rb +31 -0
  300. data/lib/fluent/test/driver/multi_output.rb +53 -0
  301. data/lib/fluent/test/driver/output.rb +102 -0
  302. data/lib/fluent/test/driver/parser.rb +30 -0
  303. data/lib/fluent/test/driver/storage.rb +30 -0
  304. data/lib/fluent/test/driver/test_event_router.rb +45 -0
  305. data/lib/fluent/test/filter_test.rb +77 -0
  306. data/lib/fluent/test/formatter_test.rb +65 -0
  307. data/lib/fluent/test/helpers.rb +134 -0
  308. data/lib/fluent/test/input_test.rb +174 -0
  309. data/lib/fluent/test/log.rb +79 -0
  310. data/lib/fluent/test/output_test.rb +156 -0
  311. data/lib/fluent/test/parser_test.rb +70 -0
  312. data/lib/fluent/test/startup_shutdown.rb +44 -0
  313. data/lib/fluent/test.rb +58 -0
  314. data/lib/fluent/time.rb +512 -0
  315. data/lib/fluent/timezone.rb +171 -0
  316. data/lib/fluent/tls.rb +81 -0
  317. data/lib/fluent/unique_id.rb +39 -0
  318. data/lib/fluent/variable_store.rb +40 -0
  319. data/lib/fluent/version.rb +21 -0
  320. data/lib/fluent/win32api.rb +38 -0
  321. data/lib/fluent/winsvc.rb +100 -0
  322. data/templates/new_gem/Gemfile +3 -0
  323. data/templates/new_gem/README.md.erb +43 -0
  324. data/templates/new_gem/Rakefile +13 -0
  325. data/templates/new_gem/fluent-plugin.gemspec.erb +27 -0
  326. data/templates/new_gem/lib/fluent/plugin/filter.rb.erb +14 -0
  327. data/templates/new_gem/lib/fluent/plugin/formatter.rb.erb +14 -0
  328. data/templates/new_gem/lib/fluent/plugin/input.rb.erb +11 -0
  329. data/templates/new_gem/lib/fluent/plugin/output.rb.erb +11 -0
  330. data/templates/new_gem/lib/fluent/plugin/parser.rb.erb +15 -0
  331. data/templates/new_gem/lib/fluent/plugin/storage.rb.erb +40 -0
  332. data/templates/new_gem/test/helper.rb.erb +7 -0
  333. data/templates/new_gem/test/plugin/test_filter.rb.erb +18 -0
  334. data/templates/new_gem/test/plugin/test_formatter.rb.erb +18 -0
  335. data/templates/new_gem/test/plugin/test_input.rb.erb +18 -0
  336. data/templates/new_gem/test/plugin/test_output.rb.erb +18 -0
  337. data/templates/new_gem/test/plugin/test_parser.rb.erb +18 -0
  338. data/templates/new_gem/test/plugin/test_storage.rb.erb +18 -0
  339. data/templates/plugin_config_formatter/param.md-compact.erb +25 -0
  340. data/templates/plugin_config_formatter/param.md-table.erb +10 -0
  341. data/templates/plugin_config_formatter/param.md.erb +34 -0
  342. data/templates/plugin_config_formatter/section.md.erb +12 -0
  343. data/test/command/test_binlog_reader.rb +362 -0
  344. data/test/command/test_ca_generate.rb +70 -0
  345. data/test/command/test_cap_ctl.rb +100 -0
  346. data/test/command/test_cat.rb +128 -0
  347. data/test/command/test_ctl.rb +56 -0
  348. data/test/command/test_fluentd.rb +1291 -0
  349. data/test/command/test_plugin_config_formatter.rb +397 -0
  350. data/test/command/test_plugin_generator.rb +109 -0
  351. data/test/compat/test_calls_super.rb +166 -0
  352. data/test/compat/test_parser.rb +92 -0
  353. data/test/config/assertions.rb +42 -0
  354. data/test/config/test_config_parser.rb +551 -0
  355. data/test/config/test_configurable.rb +1784 -0
  356. data/test/config/test_configure_proxy.rb +604 -0
  357. data/test/config/test_dsl.rb +415 -0
  358. data/test/config/test_element.rb +518 -0
  359. data/test/config/test_literal_parser.rb +309 -0
  360. data/test/config/test_plugin_configuration.rb +56 -0
  361. data/test/config/test_section.rb +191 -0
  362. data/test/config/test_system_config.rb +195 -0
  363. data/test/config/test_types.rb +408 -0
  364. data/test/counter/test_client.rb +563 -0
  365. data/test/counter/test_error.rb +44 -0
  366. data/test/counter/test_mutex_hash.rb +179 -0
  367. data/test/counter/test_server.rb +589 -0
  368. data/test/counter/test_store.rb +258 -0
  369. data/test/counter/test_validator.rb +137 -0
  370. data/test/helper.rb +155 -0
  371. data/test/helpers/fuzzy_assert.rb +89 -0
  372. data/test/helpers/process_extenstion.rb +33 -0
  373. data/test/log/test_console_adapter.rb +110 -0
  374. data/test/plugin/data/2010/01/20100102-030405.log +0 -0
  375. data/test/plugin/data/2010/01/20100102-030406.log +0 -0
  376. data/test/plugin/data/2010/01/20100102.log +0 -0
  377. data/test/plugin/data/log/bar +0 -0
  378. data/test/plugin/data/log/foo/bar.log +0 -0
  379. data/test/plugin/data/log/foo/bar2 +0 -0
  380. data/test/plugin/data/log/test.log +0 -0
  381. data/test/plugin/data/sd_file/config +11 -0
  382. data/test/plugin/data/sd_file/config.json +17 -0
  383. data/test/plugin/data/sd_file/config.yaml +11 -0
  384. data/test/plugin/data/sd_file/config.yml +11 -0
  385. data/test/plugin/data/sd_file/invalid_config.yml +7 -0
  386. data/test/plugin/in_tail/test_fifo.rb +121 -0
  387. data/test/plugin/in_tail/test_io_handler.rb +150 -0
  388. data/test/plugin/in_tail/test_position_file.rb +346 -0
  389. data/test/plugin/out_forward/test_ack_handler.rb +140 -0
  390. data/test/plugin/out_forward/test_connection_manager.rb +145 -0
  391. data/test/plugin/out_forward/test_handshake_protocol.rb +112 -0
  392. data/test/plugin/out_forward/test_load_balancer.rb +106 -0
  393. data/test/plugin/out_forward/test_socket_cache.rb +174 -0
  394. data/test/plugin/test_bare_output.rb +131 -0
  395. data/test/plugin/test_base.rb +247 -0
  396. data/test/plugin/test_buf_file.rb +1314 -0
  397. data/test/plugin/test_buf_file_single.rb +898 -0
  398. data/test/plugin/test_buf_memory.rb +42 -0
  399. data/test/plugin/test_buffer.rb +1434 -0
  400. data/test/plugin/test_buffer_chunk.rb +209 -0
  401. data/test/plugin/test_buffer_file_chunk.rb +871 -0
  402. data/test/plugin/test_buffer_file_single_chunk.rb +611 -0
  403. data/test/plugin/test_buffer_memory_chunk.rb +339 -0
  404. data/test/plugin/test_compressable.rb +87 -0
  405. data/test/plugin/test_file_util.rb +96 -0
  406. data/test/plugin/test_filter.rb +368 -0
  407. data/test/plugin/test_filter_grep.rb +697 -0
  408. data/test/plugin/test_filter_parser.rb +731 -0
  409. data/test/plugin/test_filter_record_transformer.rb +577 -0
  410. data/test/plugin/test_filter_stdout.rb +207 -0
  411. data/test/plugin/test_formatter_csv.rb +136 -0
  412. data/test/plugin/test_formatter_hash.rb +38 -0
  413. data/test/plugin/test_formatter_json.rb +61 -0
  414. data/test/plugin/test_formatter_ltsv.rb +70 -0
  415. data/test/plugin/test_formatter_msgpack.rb +28 -0
  416. data/test/plugin/test_formatter_out_file.rb +116 -0
  417. data/test/plugin/test_formatter_single_value.rb +44 -0
  418. data/test/plugin/test_formatter_tsv.rb +76 -0
  419. data/test/plugin/test_in_debug_agent.rb +49 -0
  420. data/test/plugin/test_in_exec.rb +261 -0
  421. data/test/plugin/test_in_forward.rb +1178 -0
  422. data/test/plugin/test_in_gc_stat.rb +62 -0
  423. data/test/plugin/test_in_http.rb +1102 -0
  424. data/test/plugin/test_in_monitor_agent.rb +922 -0
  425. data/test/plugin/test_in_object_space.rb +66 -0
  426. data/test/plugin/test_in_sample.rb +190 -0
  427. data/test/plugin/test_in_syslog.rb +505 -0
  428. data/test/plugin/test_in_tail.rb +3125 -0
  429. data/test/plugin/test_in_tcp.rb +328 -0
  430. data/test/plugin/test_in_udp.rb +296 -0
  431. data/test/plugin/test_in_unix.rb +181 -0
  432. data/test/plugin/test_input.rb +137 -0
  433. data/test/plugin/test_metadata.rb +89 -0
  434. data/test/plugin/test_metrics.rb +294 -0
  435. data/test/plugin/test_metrics_local.rb +96 -0
  436. data/test/plugin/test_multi_output.rb +204 -0
  437. data/test/plugin/test_out_copy.rb +308 -0
  438. data/test/plugin/test_out_exec.rb +312 -0
  439. data/test/plugin/test_out_exec_filter.rb +606 -0
  440. data/test/plugin/test_out_file.rb +1038 -0
  441. data/test/plugin/test_out_forward.rb +1361 -0
  442. data/test/plugin/test_out_http.rb +429 -0
  443. data/test/plugin/test_out_null.rb +105 -0
  444. data/test/plugin/test_out_relabel.rb +28 -0
  445. data/test/plugin/test_out_roundrobin.rb +146 -0
  446. data/test/plugin/test_out_secondary_file.rb +458 -0
  447. data/test/plugin/test_out_stdout.rb +205 -0
  448. data/test/plugin/test_out_stream.rb +103 -0
  449. data/test/plugin/test_output.rb +1334 -0
  450. data/test/plugin/test_output_as_buffered.rb +2024 -0
  451. data/test/plugin/test_output_as_buffered_backup.rb +363 -0
  452. data/test/plugin/test_output_as_buffered_compress.rb +179 -0
  453. data/test/plugin/test_output_as_buffered_overflow.rb +250 -0
  454. data/test/plugin/test_output_as_buffered_retries.rb +966 -0
  455. data/test/plugin/test_output_as_buffered_secondary.rb +882 -0
  456. data/test/plugin/test_output_as_standard.rb +374 -0
  457. data/test/plugin/test_owned_by.rb +34 -0
  458. data/test/plugin/test_parser.rb +399 -0
  459. data/test/plugin/test_parser_apache.rb +42 -0
  460. data/test/plugin/test_parser_apache2.rb +47 -0
  461. data/test/plugin/test_parser_apache_error.rb +45 -0
  462. data/test/plugin/test_parser_csv.rb +200 -0
  463. data/test/plugin/test_parser_json.rb +138 -0
  464. data/test/plugin/test_parser_labeled_tsv.rb +160 -0
  465. data/test/plugin/test_parser_multiline.rb +111 -0
  466. data/test/plugin/test_parser_nginx.rb +88 -0
  467. data/test/plugin/test_parser_none.rb +52 -0
  468. data/test/plugin/test_parser_regexp.rb +284 -0
  469. data/test/plugin/test_parser_syslog.rb +650 -0
  470. data/test/plugin/test_parser_tsv.rb +122 -0
  471. data/test/plugin/test_sd_file.rb +228 -0
  472. data/test/plugin/test_sd_srv.rb +230 -0
  473. data/test/plugin/test_storage.rb +166 -0
  474. data/test/plugin/test_storage_local.rb +335 -0
  475. data/test/plugin/test_string_util.rb +26 -0
  476. data/test/plugin_helper/data/cert/cert-key.pem +27 -0
  477. data/test/plugin_helper/data/cert/cert-with-CRLF.pem +19 -0
  478. data/test/plugin_helper/data/cert/cert-with-no-newline.pem +19 -0
  479. data/test/plugin_helper/data/cert/cert.pem +19 -0
  480. data/test/plugin_helper/data/cert/cert_chains/ca-cert-key.pem +27 -0
  481. data/test/plugin_helper/data/cert/cert_chains/ca-cert.pem +20 -0
  482. data/test/plugin_helper/data/cert/cert_chains/cert-key.pem +27 -0
  483. data/test/plugin_helper/data/cert/cert_chains/cert.pem +40 -0
  484. data/test/plugin_helper/data/cert/empty.pem +0 -0
  485. data/test/plugin_helper/data/cert/generate_cert.rb +125 -0
  486. data/test/plugin_helper/data/cert/with_ca/ca-cert-key-pass.pem +30 -0
  487. data/test/plugin_helper/data/cert/with_ca/ca-cert-key.pem +27 -0
  488. data/test/plugin_helper/data/cert/with_ca/ca-cert-pass.pem +20 -0
  489. data/test/plugin_helper/data/cert/with_ca/ca-cert.pem +20 -0
  490. data/test/plugin_helper/data/cert/with_ca/cert-key-pass.pem +30 -0
  491. data/test/plugin_helper/data/cert/with_ca/cert-key.pem +27 -0
  492. data/test/plugin_helper/data/cert/with_ca/cert-pass.pem +21 -0
  493. data/test/plugin_helper/data/cert/with_ca/cert.pem +21 -0
  494. data/test/plugin_helper/data/cert/without_ca/cert-key-pass.pem +30 -0
  495. data/test/plugin_helper/data/cert/without_ca/cert-key.pem +27 -0
  496. data/test/plugin_helper/data/cert/without_ca/cert-pass.pem +20 -0
  497. data/test/plugin_helper/data/cert/without_ca/cert.pem +20 -0
  498. data/test/plugin_helper/http_server/test_app.rb +65 -0
  499. data/test/plugin_helper/http_server/test_route.rb +32 -0
  500. data/test/plugin_helper/service_discovery/test_manager.rb +93 -0
  501. data/test/plugin_helper/service_discovery/test_round_robin_balancer.rb +21 -0
  502. data/test/plugin_helper/test_cert_option.rb +25 -0
  503. data/test/plugin_helper/test_child_process.rb +862 -0
  504. data/test/plugin_helper/test_compat_parameters.rb +358 -0
  505. data/test/plugin_helper/test_event_emitter.rb +80 -0
  506. data/test/plugin_helper/test_event_loop.rb +52 -0
  507. data/test/plugin_helper/test_extract.rb +194 -0
  508. data/test/plugin_helper/test_formatter.rb +255 -0
  509. data/test/plugin_helper/test_http_server_helper.rb +372 -0
  510. data/test/plugin_helper/test_inject.rb +561 -0
  511. data/test/plugin_helper/test_metrics.rb +137 -0
  512. data/test/plugin_helper/test_parser.rb +264 -0
  513. data/test/plugin_helper/test_record_accessor.rb +238 -0
  514. data/test/plugin_helper/test_retry_state.rb +1006 -0
  515. data/test/plugin_helper/test_server.rb +1895 -0
  516. data/test/plugin_helper/test_service_discovery.rb +165 -0
  517. data/test/plugin_helper/test_socket.rb +146 -0
  518. data/test/plugin_helper/test_storage.rb +542 -0
  519. data/test/plugin_helper/test_thread.rb +164 -0
  520. data/test/plugin_helper/test_timer.rb +130 -0
  521. data/test/scripts/exec_script.rb +32 -0
  522. data/test/scripts/fluent/plugin/formatter1/formatter_test1.rb +7 -0
  523. data/test/scripts/fluent/plugin/formatter2/formatter_test2.rb +7 -0
  524. data/test/scripts/fluent/plugin/formatter_known.rb +8 -0
  525. data/test/scripts/fluent/plugin/out_test.rb +81 -0
  526. data/test/scripts/fluent/plugin/out_test2.rb +80 -0
  527. data/test/scripts/fluent/plugin/parser_known.rb +4 -0
  528. data/test/test_capability.rb +74 -0
  529. data/test/test_clock.rb +164 -0
  530. data/test/test_config.rb +369 -0
  531. data/test/test_configdsl.rb +148 -0
  532. data/test/test_daemonizer.rb +91 -0
  533. data/test/test_engine.rb +203 -0
  534. data/test/test_event.rb +531 -0
  535. data/test/test_event_router.rb +348 -0
  536. data/test/test_event_time.rb +199 -0
  537. data/test/test_file_wrapper.rb +53 -0
  538. data/test/test_filter.rb +121 -0
  539. data/test/test_fluent_log_event_router.rb +99 -0
  540. data/test/test_formatter.rb +369 -0
  541. data/test/test_input.rb +31 -0
  542. data/test/test_log.rb +1076 -0
  543. data/test/test_match.rb +148 -0
  544. data/test/test_mixin.rb +351 -0
  545. data/test/test_msgpack_factory.rb +50 -0
  546. data/test/test_oj_options.rb +55 -0
  547. data/test/test_output.rb +278 -0
  548. data/test/test_plugin.rb +251 -0
  549. data/test/test_plugin_classes.rb +370 -0
  550. data/test/test_plugin_helper.rb +81 -0
  551. data/test/test_plugin_id.rb +119 -0
  552. data/test/test_process.rb +14 -0
  553. data/test/test_root_agent.rb +951 -0
  554. data/test/test_static_config_analysis.rb +177 -0
  555. data/test/test_supervisor.rb +821 -0
  556. data/test/test_test_drivers.rb +136 -0
  557. data/test/test_time_formatter.rb +301 -0
  558. data/test/test_time_parser.rb +362 -0
  559. data/test/test_tls.rb +65 -0
  560. data/test/test_unique_id.rb +47 -0
  561. data/test/test_variable_store.rb +65 -0
  562. metadata +1183 -0
@@ -0,0 +1,941 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'fluent/plugin/base'
18
+ require 'fluent/plugin/owned_by_mixin'
19
+ require 'fluent/plugin_id'
20
+ require 'fluent/plugin_helper'
21
+ require 'fluent/unique_id'
22
+ require 'fluent/ext_monitor_require'
23
+
24
+ module Fluent
25
+ module Plugin
26
+ class Buffer < Base
27
+ include OwnedByMixin
28
+ include UniqueId::Mixin
29
+ include PluginId
30
+ include MonitorMixin
31
+ include PluginHelper::Mixin # for metrics
32
+
33
+ class BufferError < StandardError; end
34
+ class BufferOverflowError < BufferError; end
35
+ class BufferChunkOverflowError < BufferError; end # A record size is larger than chunk size limit
36
+
37
+ MINIMUM_APPEND_ATTEMPT_RECORDS = 10
38
+
39
+ DEFAULT_CHUNK_LIMIT_SIZE = 8 * 1024 * 1024 # 8MB
40
+ DEFAULT_TOTAL_LIMIT_SIZE = 512 * 1024 * 1024 # 512MB, same with v0.12 (BufferedOutput + buf_memory: 64 x 8MB)
41
+
42
+ DEFAULT_CHUNK_FULL_THRESHOLD = 0.95
43
+
44
+ configured_in :buffer
45
+
46
+ helpers_internal :metrics
47
+
48
+ # TODO: system total buffer limit size in bytes by SystemConfig
49
+
50
+ config_param :chunk_limit_size, :size, default: DEFAULT_CHUNK_LIMIT_SIZE
51
+ config_param :total_limit_size, :size, default: DEFAULT_TOTAL_LIMIT_SIZE
52
+
53
+ # If user specify this value and (chunk_size * queue_length) is smaller than total_size,
54
+ # then total_size is automatically configured to that value
55
+ config_param :queue_limit_length, :integer, default: nil
56
+
57
+ # optional new limitations
58
+ config_param :chunk_limit_records, :integer, default: nil
59
+
60
+ # if chunk size (or records) is 95% or more after #write, then that chunk will be enqueued
61
+ config_param :chunk_full_threshold, :float, default: DEFAULT_CHUNK_FULL_THRESHOLD
62
+
63
+ desc 'The max number of queued chunks.'
64
+ config_param :queued_chunks_limit_size, :integer, default: nil
65
+
66
+ desc 'Compress buffered data.'
67
+ config_param :compress, :enum, list: [:text, :gzip], default: :text
68
+
69
+ desc 'If true, chunks are thrown away when unrecoverable error happens'
70
+ config_param :disable_chunk_backup, :bool, default: false
71
+
72
+ Metadata = Struct.new(:timekey, :tag, :variables, :seq) do
73
+ def initialize(timekey, tag, variables)
74
+ super(timekey, tag, variables, 0)
75
+ end
76
+
77
+ def dup_next
78
+ m = dup
79
+ m.seq = seq + 1
80
+ m
81
+ end
82
+
83
+ def empty?
84
+ timekey.nil? && tag.nil? && variables.nil?
85
+ end
86
+
87
+ def cmp_variables(v1, v2)
88
+ if v1.nil? && v2.nil?
89
+ return 0
90
+ elsif v1.nil? # v2 is non-nil
91
+ return -1
92
+ elsif v2.nil? # v1 is non-nil
93
+ return 1
94
+ end
95
+ # both of v1 and v2 are non-nil
96
+ v1_sorted_keys = v1.keys.sort
97
+ v2_sorted_keys = v2.keys.sort
98
+ if v1_sorted_keys != v2_sorted_keys
99
+ if v1_sorted_keys.size == v2_sorted_keys.size
100
+ v1_sorted_keys <=> v2_sorted_keys
101
+ else
102
+ v1_sorted_keys.size <=> v2_sorted_keys.size
103
+ end
104
+ else
105
+ v1_sorted_keys.each do |k|
106
+ a = v1[k]
107
+ b = v2[k]
108
+ if a && b && a != b
109
+ return a <=> b
110
+ elsif a && b || (!a && !b) # same value (including both are nil)
111
+ next
112
+ elsif a # b is nil
113
+ return 1
114
+ else # a is nil (but b is non-nil)
115
+ return -1
116
+ end
117
+ end
118
+
119
+ 0
120
+ end
121
+ end
122
+
123
+ def <=>(o)
124
+ timekey2 = o.timekey
125
+ tag2 = o.tag
126
+ variables2 = o.variables
127
+ if (!!timekey ^ !!timekey2) || (!!tag ^ !!tag2) || (!!variables ^ !!variables2)
128
+ # One has value in a field, but another doesn't have value in same field
129
+ # This case occurs very rarely
130
+ if timekey == timekey2 # including the case of nil == nil
131
+ if tag == tag2
132
+ cmp_variables(variables, variables2)
133
+ elsif tag.nil?
134
+ -1
135
+ elsif tag2.nil?
136
+ 1
137
+ else
138
+ tag <=> tag2
139
+ end
140
+ elsif timekey.nil?
141
+ -1
142
+ elsif timekey2.nil?
143
+ 1
144
+ else
145
+ timekey <=> timekey2
146
+ end
147
+ else
148
+ # objects have values in same field pairs (comparison with non-nil and nil doesn't occur here)
149
+ (timekey <=> timekey2 || 0).nonzero? || # if `a <=> b` is nil, then both are nil
150
+ (tag <=> tag2 || 0).nonzero? ||
151
+ cmp_variables(variables, variables2)
152
+ end
153
+ end
154
+
155
+ # This is an optimization code. Current Struct's implementation is comparing all data.
156
+ # https://github.com/ruby/ruby/blob/0623e2b7cc621b1733a760b72af246b06c30cf96/struct.c#L1200-L1203
157
+ # Actually this overhead is very small but this class is generated *per chunk* (and used in hash object).
158
+ # This means that this class is one of the most called object in Fluentd.
159
+ # See https://github.com/fluent/fluentd/pull/2560
160
+ def hash
161
+ timekey.hash
162
+ end
163
+ end
164
+
165
+ # for metrics
166
+ attr_reader :stage_size_metrics, :stage_length_metrics, :queue_size_metrics, :queue_length_metrics
167
+ attr_reader :available_buffer_space_ratios_metrics, :total_queued_size_metrics
168
+ attr_reader :newest_timekey_metrics, :oldest_timekey_metrics
169
+ # for tests
170
+ attr_reader :stage, :queue, :dequeued, :queued_num
171
+
172
+ def initialize
173
+ super
174
+
175
+ @chunk_limit_size = nil
176
+ @total_limit_size = nil
177
+ @queue_limit_length = nil
178
+ @chunk_limit_records = nil
179
+
180
+ @stage = {} #=> Hash (metadata -> chunk) : not flushed yet
181
+ @queue = [] #=> Array (chunks) : already flushed (not written)
182
+ @dequeued = {} #=> Hash (unique_id -> chunk): already written (not purged)
183
+ @queued_num = {} # metadata => int (number of queued chunks)
184
+ @dequeued_num = {} # metadata => int (number of dequeued chunks)
185
+
186
+ @stage_length_metrics = nil
187
+ @stage_size_metrics = nil
188
+ @queue_length_metrics = nil
189
+ @queue_size_metrics = nil
190
+ @available_buffer_space_ratios_metrics = nil
191
+ @total_queued_size_metrics = nil
192
+ @newest_timekey_metrics = nil
193
+ @oldest_timekey_metrics = nil
194
+ @timekeys = Hash.new(0)
195
+ @enable_update_timekeys = false
196
+ @mutex = Mutex.new
197
+ end
198
+
199
+ def stage_size
200
+ @stage_size_metrics.get
201
+ end
202
+
203
+ def stage_size=(value)
204
+ @stage_size_metrics.set(value)
205
+ end
206
+
207
+ def queue_size
208
+ @queue_size_metrics.get
209
+ end
210
+
211
+ def queue_size=(value)
212
+ @queue_size_metrics.set(value)
213
+ end
214
+
215
+ def persistent?
216
+ false
217
+ end
218
+
219
+ def configure(conf)
220
+ super
221
+
222
+ unless @queue_limit_length.nil?
223
+ @total_limit_size = @chunk_limit_size * @queue_limit_length
224
+ end
225
+ @stage_length_metrics = metrics_create(namespace: "fluentd", subsystem: "buffer", name: "stage_length",
226
+ help_text: 'Length of stage buffers', prefer_gauge: true)
227
+ @stage_length_metrics.set(0)
228
+ @stage_size_metrics = metrics_create(namespace: "fluentd", subsystem: "buffer", name: "stage_byte_size",
229
+ help_text: 'Total size of stage buffers', prefer_gauge: true)
230
+ @stage_size_metrics.set(0) # Ensure zero.
231
+ @queue_length_metrics = metrics_create(namespace: "fluentd", subsystem: "buffer", name: "queue_length",
232
+ help_text: 'Length of queue buffers', prefer_gauge: true)
233
+ @queue_length_metrics.set(0)
234
+ @queue_size_metrics = metrics_create(namespace: "fluentd", subsystem: "buffer", name: "queue_byte_size",
235
+ help_text: 'Total size of queue buffers', prefer_gauge: true)
236
+ @queue_size_metrics.set(0) # Ensure zero.
237
+ @available_buffer_space_ratios_metrics = metrics_create(namespace: "fluentd", subsystem: "buffer", name: "available_buffer_space_ratios",
238
+ help_text: 'Ratio of available space in buffer', prefer_gauge: true)
239
+ @available_buffer_space_ratios_metrics.set(100) # Default is 100%.
240
+ @total_queued_size_metrics = metrics_create(namespace: "fluentd", subsystem: "buffer", name: "total_queued_size",
241
+ help_text: 'Total size of stage and queue buffers', prefer_gauge: true)
242
+ @total_queued_size_metrics.set(0)
243
+ @newest_timekey_metrics = metrics_create(namespace: "fluentd", subsystem: "buffer", name: "newest_timekey",
244
+ help_text: 'Newest timekey in buffer', prefer_gauge: true)
245
+ @oldest_timekey_metrics = metrics_create(namespace: "fluentd", subsystem: "buffer", name: "oldest_timekey",
246
+ help_text: 'Oldest timekey in buffer', prefer_gauge: true)
247
+ end
248
+
249
+ def enable_update_timekeys
250
+ @enable_update_timekeys = true
251
+ end
252
+
253
+ def start
254
+ super
255
+
256
+ @stage, @queue = resume
257
+ @stage.each_pair do |metadata, chunk|
258
+ @stage_size_metrics.add(chunk.bytesize)
259
+ end
260
+ @queue.each do |chunk|
261
+ @queued_num[chunk.metadata] ||= 0
262
+ @queued_num[chunk.metadata] += 1
263
+ @queue_size_metrics.add(chunk.bytesize)
264
+ end
265
+ update_timekeys
266
+ log.debug "buffer started", instance: self.object_id, stage_size: @stage_size_metrics.get, queue_size: @queue_size_metrics.get
267
+ end
268
+
269
+ def close
270
+ super
271
+ synchronize do
272
+ log.debug "closing buffer", instance: self.object_id
273
+ @dequeued.each_pair do |chunk_id, chunk|
274
+ chunk.close
275
+ end
276
+ until @queue.empty?
277
+ @queue.shift.close
278
+ end
279
+ @stage.each_pair do |metadata, chunk|
280
+ chunk.close
281
+ end
282
+ end
283
+ end
284
+
285
+ def terminate
286
+ super
287
+ @dequeued = @stage = @queue = @queued_num = nil
288
+ @stage_length_metrics = @stage_size_metrics = @queue_length_metrics = @queue_size_metrics = nil
289
+ @available_buffer_space_ratios_metrics = @total_queued_size_metrics = nil
290
+ @newest_timekey_metrics = @oldest_timekey_metrics = nil
291
+ @timekeys.clear
292
+ end
293
+
294
+ def storable?
295
+ @total_limit_size > @stage_size_metrics.get + @queue_size_metrics.get
296
+ end
297
+
298
+ ## TODO: for back pressure feature
299
+ # def used?(ratio)
300
+ # @total_limit_size * ratio > @stage_size_metrics.get + @queue_size_metrics.get
301
+ # end
302
+
303
+ def resume
304
+ # return {}, []
305
+ raise NotImplementedError, "Implement this method in child class"
306
+ end
307
+
308
+ def generate_chunk(metadata)
309
+ raise NotImplementedError, "Implement this method in child class"
310
+ end
311
+
312
+ def new_metadata(timekey: nil, tag: nil, variables: nil)
313
+ Metadata.new(timekey, tag, variables)
314
+ end
315
+
316
+ # Keep this method for existing code
317
+ def metadata(timekey: nil, tag: nil, variables: nil)
318
+ Metadata.new(timekey, tag, variables)
319
+ end
320
+
321
+ def timekeys
322
+ @timekeys.keys
323
+ end
324
+
325
+ # metadata MUST have consistent object_id for each variation
326
+ # data MUST be Array of serialized events, or EventStream
327
+ # metadata_and_data MUST be a hash of { metadata => data }
328
+ def write(metadata_and_data, format: nil, size: nil, enqueue: false)
329
+ return if metadata_and_data.size < 1
330
+ raise BufferOverflowError, "buffer space has too many data" unless storable?
331
+
332
+ log.on_trace { log.trace "writing events into buffer", instance: self.object_id, metadata_size: metadata_and_data.size }
333
+
334
+ operated_chunks = []
335
+ unstaged_chunks = {} # metadata => [chunk, chunk, ...]
336
+ chunks_to_enqueue = []
337
+ staged_bytesizes_by_chunk = {}
338
+ # track internal BufferChunkOverflowError in write_step_by_step
339
+ buffer_chunk_overflow_errors = []
340
+
341
+ begin
342
+ # sort metadata to get lock of chunks in same order with other threads
343
+ metadata_and_data.keys.sort.each do |metadata|
344
+ data = metadata_and_data[metadata]
345
+ write_once(metadata, data, format: format, size: size) do |chunk, adding_bytesize, error|
346
+ chunk.mon_enter # add lock to prevent to be committed/rollbacked from other threads
347
+ operated_chunks << chunk
348
+ if chunk.staged?
349
+ #
350
+ # https://github.com/fluent/fluentd/issues/2712
351
+ # write_once is supposed to write to a chunk only once
352
+ # but this block **may** run multiple times from write_step_by_step and previous write may be rollbacked
353
+ # So we should be counting the stage_size only for the last successful write
354
+ #
355
+ staged_bytesizes_by_chunk[chunk] = adding_bytesize
356
+ elsif chunk.unstaged?
357
+ unstaged_chunks[metadata] ||= []
358
+ unstaged_chunks[metadata] << chunk
359
+ end
360
+ if error && !error.empty?
361
+ buffer_chunk_overflow_errors << error
362
+ end
363
+ end
364
+ end
365
+
366
+ return if operated_chunks.empty?
367
+
368
+ # Now, this thread acquires many locks of chunks... getting buffer-global lock causes dead lock.
369
+ # Any operations needs buffer-global lock (including enqueueing) should be done after releasing locks.
370
+
371
+ first_chunk = operated_chunks.shift
372
+ # Following commits for other chunks also can finish successfully if the first commit operation
373
+ # finishes without any exceptions.
374
+ # In most cases, #commit just requires very small disk spaces, so major failure reason are
375
+ # permission errors, disk failures and other permanent(fatal) errors.
376
+ begin
377
+ first_chunk.commit
378
+ if enqueue || first_chunk.unstaged? || chunk_size_full?(first_chunk)
379
+ chunks_to_enqueue << first_chunk
380
+ end
381
+ first_chunk.mon_exit
382
+ rescue
383
+ operated_chunks.unshift(first_chunk)
384
+ raise
385
+ end
386
+
387
+ errors = []
388
+ # Buffer plugin estimates there's no serious error cause: will commit for all chunks eigher way
389
+ operated_chunks.each do |chunk|
390
+ begin
391
+ chunk.commit
392
+ if enqueue || chunk.unstaged? || chunk_size_full?(chunk)
393
+ chunks_to_enqueue << chunk
394
+ end
395
+ chunk.mon_exit
396
+ rescue => e
397
+ chunk.rollback
398
+ chunk.mon_exit
399
+ errors << e
400
+ end
401
+ end
402
+
403
+ # All locks about chunks are released.
404
+
405
+ #
406
+ # Now update the stage, stage_size with proper locking
407
+ # FIX FOR stage_size miscomputation - https://github.com/fluent/fluentd/issues/2712
408
+ #
409
+ staged_bytesizes_by_chunk.each do |chunk, bytesize|
410
+ chunk.synchronize do
411
+ synchronize { @stage_size_metrics.add(bytesize) }
412
+ log.on_trace { log.trace { "chunk #{chunk.path} size_added: #{bytesize} new_size: #{chunk.bytesize}" } }
413
+ end
414
+ end
415
+
416
+ chunks_to_enqueue.each do |c|
417
+ if c.staged? && (enqueue || chunk_size_full?(c))
418
+ m = c.metadata
419
+ enqueue_chunk(m)
420
+ if unstaged_chunks[m] && !unstaged_chunks[m].empty?
421
+ u = unstaged_chunks[m].pop
422
+ u.synchronize do
423
+ if u.unstaged? && !chunk_size_full?(u)
424
+ # `u.metadata.seq` and `m.seq` can be different but Buffer#enqueue_chunk expect them to be the same value
425
+ u.metadata.seq = 0
426
+ synchronize {
427
+ @stage[m] = u.staged!
428
+ @stage_size_metrics.add(u.bytesize)
429
+ }
430
+ end
431
+ end
432
+ end
433
+ elsif c.unstaged?
434
+ enqueue_unstaged_chunk(c)
435
+ else
436
+ # previously staged chunk is already enqueued, closed or purged.
437
+ # no problem.
438
+ end
439
+ end
440
+
441
+ operated_chunks.clear if errors.empty?
442
+
443
+ if errors.size > 0
444
+ log.warn "error occurs in committing chunks: only first one raised", errors: errors.map(&:class)
445
+ raise errors.first
446
+ end
447
+ ensure
448
+ operated_chunks.each do |chunk|
449
+ chunk.rollback rescue nil # nothing possible to do for #rollback failure
450
+ if chunk.unstaged?
451
+ chunk.purge rescue nil # to prevent leakage of unstaged chunks
452
+ end
453
+ chunk.mon_exit rescue nil # this may raise ThreadError for chunks already committed
454
+ end
455
+ unless buffer_chunk_overflow_errors.empty?
456
+ # Notify delayed BufferChunkOverflowError here
457
+ raise BufferChunkOverflowError, buffer_chunk_overflow_errors.join(", ")
458
+ end
459
+ end
460
+ end
461
+
462
+ def queue_full?
463
+ synchronize { @queue.size } >= @queued_chunks_limit_size
464
+ end
465
+
466
+ def queued_records
467
+ synchronize { @queue.reduce(0){|r, chunk| r + chunk.size } }
468
+ end
469
+
470
+ def queued?(metadata = nil, optimistic: false)
471
+ if optimistic
472
+ optimistic_queued?(metadata)
473
+ else
474
+ synchronize do
475
+ optimistic_queued?(metadata)
476
+ end
477
+ end
478
+ end
479
+
480
+ def enqueue_chunk(metadata)
481
+ log.on_trace { log.trace "enqueueing chunk", instance: self.object_id, metadata: metadata }
482
+
483
+ chunk = synchronize do
484
+ @stage.delete(metadata)
485
+ end
486
+ return nil unless chunk
487
+
488
+ chunk.synchronize do
489
+ synchronize do
490
+ if chunk.empty?
491
+ chunk.close
492
+ else
493
+ chunk.metadata.seq = 0 # metadata.seq should be 0 for counting @queued_num
494
+ @queue << chunk
495
+ @queued_num[metadata] = @queued_num.fetch(metadata, 0) + 1
496
+ chunk.enqueued!
497
+ end
498
+ bytesize = chunk.bytesize
499
+ @stage_size_metrics.sub(bytesize)
500
+ @queue_size_metrics.add(bytesize)
501
+ end
502
+ end
503
+ nil
504
+ end
505
+
506
+ def enqueue_unstaged_chunk(chunk)
507
+ log.on_trace { log.trace "enqueueing unstaged chunk", instance: self.object_id, metadata: chunk.metadata }
508
+
509
+ synchronize do
510
+ chunk.synchronize do
511
+ metadata = chunk.metadata
512
+ metadata.seq = 0 # metadata.seq should be 0 for counting @queued_num
513
+ @queue << chunk
514
+ @queued_num[metadata] = @queued_num.fetch(metadata, 0) + 1
515
+ chunk.enqueued!
516
+ end
517
+ @queue_size_metrics.add(chunk.bytesize)
518
+ end
519
+ end
520
+
521
+ def update_timekeys
522
+ synchronize do
523
+ chunks = @stage.values
524
+ chunks.concat(@queue)
525
+ @timekeys = chunks.each_with_object({}) do |chunk, keys|
526
+ if chunk.metadata && chunk.metadata.timekey
527
+ t = chunk.metadata.timekey
528
+ keys[t] = keys.fetch(t, 0) + 1
529
+ end
530
+ end
531
+ end
532
+ end
533
+
534
+ # At flush_at_shutdown, all staged chunks should be enqueued for buffer flush. Set true to force_enqueue for it.
535
+ def enqueue_all(force_enqueue = false)
536
+ log.on_trace { log.trace "enqueueing all chunks in buffer", instance: self.object_id }
537
+ update_timekeys if @enable_update_timekeys
538
+
539
+ if block_given?
540
+ synchronize{ @stage.keys }.each do |metadata|
541
+ return if !force_enqueue && queue_full?
542
+ # NOTE: The following line might cause data race depending on Ruby implementations except CRuby
543
+ # cf. https://github.com/fluent/fluentd/pull/1721#discussion_r146170251
544
+ chunk = @stage[metadata]
545
+ next unless chunk
546
+ v = yield metadata, chunk
547
+ enqueue_chunk(metadata) if v
548
+ end
549
+ else
550
+ synchronize{ @stage.keys }.each do |metadata|
551
+ return if !force_enqueue && queue_full?
552
+ enqueue_chunk(metadata)
553
+ end
554
+ end
555
+ end
556
+
557
+ def dequeue_chunk
558
+ return nil if @queue.empty?
559
+ log.on_trace { log.trace "dequeueing a chunk", instance: self.object_id }
560
+
561
+ synchronize do
562
+ chunk = @queue.shift
563
+
564
+ # this buffer is dequeued by other thread just before "synchronize" in this thread
565
+ return nil unless chunk
566
+
567
+ @dequeued[chunk.unique_id] = chunk
568
+ @queued_num[chunk.metadata] -= 1 # BUG if nil, 0 or subzero
569
+ @dequeued_num[chunk.metadata] ||= 0
570
+ @dequeued_num[chunk.metadata] += 1
571
+ log.trace "chunk dequeued", instance: self.object_id, metadata: chunk.metadata
572
+ chunk
573
+ end
574
+ end
575
+
576
+ def takeback_chunk(chunk_id)
577
+ log.on_trace { log.trace "taking back a chunk", instance: self.object_id, chunk_id: dump_unique_id_hex(chunk_id) }
578
+
579
+ synchronize do
580
+ chunk = @dequeued.delete(chunk_id)
581
+ return false unless chunk # already purged by other thread
582
+ @queue.unshift(chunk)
583
+ log.on_trace { log.trace "chunk taken back", instance: self.object_id, chunk_id: dump_unique_id_hex(chunk_id), metadata: chunk.metadata }
584
+ @queued_num[chunk.metadata] += 1 # BUG if nil
585
+ @dequeued_num[chunk.metadata] -= 1
586
+ end
587
+ true
588
+ end
589
+
590
+ def purge_chunk(chunk_id)
591
+ metadata = nil
592
+ synchronize do
593
+ chunk = @dequeued.delete(chunk_id)
594
+ return nil unless chunk # purged by other threads
595
+
596
+ metadata = chunk.metadata
597
+ log.on_trace { log.trace "purging a chunk", instance: self.object_id, chunk_id: dump_unique_id_hex(chunk_id), metadata: metadata }
598
+
599
+ begin
600
+ bytesize = chunk.bytesize
601
+ chunk.purge
602
+ @queue_size_metrics.sub(bytesize)
603
+ rescue => e
604
+ log.error "failed to purge buffer chunk", chunk_id: dump_unique_id_hex(chunk_id), error_class: e.class, error: e
605
+ log.error_backtrace
606
+ end
607
+
608
+ @dequeued_num[chunk.metadata] -= 1
609
+ if metadata && !@stage[metadata] && (!@queued_num[metadata] || @queued_num[metadata] < 1) && @dequeued_num[metadata].zero?
610
+ @queued_num.delete(metadata)
611
+ @dequeued_num.delete(metadata)
612
+ end
613
+ log.on_trace { log.trace "chunk purged", instance: self.object_id, chunk_id: dump_unique_id_hex(chunk_id), metadata: metadata }
614
+ end
615
+
616
+ nil
617
+ end
618
+
619
+ def clear_queue!
620
+ log.on_trace { log.trace "clearing queue", instance: self.object_id }
621
+
622
+ synchronize do
623
+ until @queue.empty?
624
+ begin
625
+ q = @queue.shift
626
+ log.trace("purging a chunk in queue"){ {id: dump_unique_id_hex(chunk.unique_id), bytesize: chunk.bytesize, size: chunk.size} }
627
+ q.purge
628
+ rescue => e
629
+ log.error "unexpected error while clearing buffer queue", error_class: e.class, error: e
630
+ log.error_backtrace
631
+ end
632
+ end
633
+ @queue_size_metrics.set(0)
634
+ end
635
+ end
636
+
637
+ def chunk_size_over?(chunk)
638
+ chunk.bytesize > @chunk_limit_size || (@chunk_limit_records && chunk.size > @chunk_limit_records)
639
+ end
640
+
641
+ def chunk_size_full?(chunk)
642
+ chunk.bytesize >= @chunk_limit_size * @chunk_full_threshold || (@chunk_limit_records && chunk.size >= @chunk_limit_records * @chunk_full_threshold)
643
+ end
644
+
645
+ class ShouldRetry < StandardError; end
646
+
647
+ # write once into a chunk
648
+ # 1. append whole data into existing chunk
649
+ # 2. commit it & return unless chunk_size_over?
650
+ # 3. enqueue existing chunk & retry whole method if chunk was not empty
651
+ # 4. go to step_by_step writing
652
+
653
+ def write_once(metadata, data, format: nil, size: nil, &block)
654
+ return if data.empty?
655
+
656
+ stored = false
657
+ adding_bytesize = nil
658
+
659
+ chunk = synchronize { @stage[metadata] ||= generate_chunk(metadata).staged! }
660
+ enqueue_chunk_before_retry = false
661
+ chunk.synchronize do
662
+ # retry this method if chunk is already queued (between getting chunk and entering critical section)
663
+ raise ShouldRetry unless chunk.staged?
664
+
665
+ empty_chunk = chunk.empty?
666
+
667
+ original_bytesize = chunk.bytesize
668
+ begin
669
+ if format
670
+ serialized = format.call(data)
671
+ chunk.concat(serialized, size ? size.call : data.size)
672
+ else
673
+ chunk.append(data, compress: @compress)
674
+ end
675
+ adding_bytesize = chunk.bytesize - original_bytesize
676
+
677
+ if chunk_size_over?(chunk)
678
+ if format && empty_chunk
679
+ if chunk.bytesize > @chunk_limit_size
680
+ log.warn "chunk bytes limit exceeds for an emitted event stream: #{adding_bytesize}bytes"
681
+ else
682
+ log.warn "chunk size limit exceeds for an emitted event stream: #{chunk.size}records"
683
+ end
684
+ end
685
+ chunk.rollback
686
+
687
+ if format && !empty_chunk
688
+ # Event streams should be appended into a chunk at once
689
+ # as far as possible, to improve performance of formatting.
690
+ # Event stream may be a MessagePackEventStream. We don't want to split it into
691
+ # 2 or more chunks (except for a case that the event stream is larger than chunk limit).
692
+ enqueue_chunk_before_retry = true
693
+ raise ShouldRetry
694
+ end
695
+ else
696
+ stored = true
697
+ end
698
+ rescue
699
+ chunk.rollback
700
+ raise
701
+ end
702
+
703
+ if stored
704
+ block.call(chunk, adding_bytesize)
705
+ end
706
+ end
707
+
708
+ unless stored
709
+ # try step-by-step appending if data can't be stored into existing a chunk in non-bulk mode
710
+ #
711
+ # 1/10 size of original event stream (splits_count == 10) seems enough small
712
+ # to try emitting events into existing chunk.
713
+ # it does not matter to split event stream into very small splits, because chunks have less
714
+ # overhead to write data many times (even about file buffer chunks).
715
+ write_step_by_step(metadata, data, format, 10, &block)
716
+ end
717
+ rescue ShouldRetry
718
+ enqueue_chunk(metadata) if enqueue_chunk_before_retry
719
+ retry
720
+ end
721
+
722
+ # EventStream can be split into many streams
723
+ # because (es1 + es2).to_msgpack_stream == es1.to_msgpack_stream + es2.to_msgpack_stream
724
+
725
+ # 1. split event streams into many (10 -> 100 -> 1000 -> ...) chunks
726
+ # 2. append splits into the staged chunks as much as possible
727
+ # 3. create unstaged chunk and append rest splits -> repeat it for all splits
728
+
729
+ def write_step_by_step(metadata, data, format, splits_count, &block)
730
+ splits = []
731
+ if splits_count > data.size
732
+ splits_count = data.size
733
+ end
734
+ slice_size = if data.size % splits_count == 0
735
+ data.size / splits_count
736
+ else
737
+ data.size / (splits_count - 1)
738
+ end
739
+ slice_origin = 0
740
+ while slice_origin < data.size
741
+ splits << data.slice(slice_origin, slice_size)
742
+ slice_origin += slice_size
743
+ end
744
+
745
+ # This method will append events into the staged chunk at first.
746
+ # Then, will generate chunks not staged (not queued) to append rest data.
747
+ staged_chunk_used = false
748
+ modified_chunks = []
749
+ modified_metadata = metadata
750
+ get_next_chunk = ->(){
751
+ if staged_chunk_used
752
+ # Staging new chunk here is bad idea:
753
+ # Recovering whole state including newly staged chunks is much harder than current implementation.
754
+ modified_metadata = modified_metadata.dup_next
755
+ generate_chunk(modified_metadata)
756
+ else
757
+ synchronize { @stage[modified_metadata] ||= generate_chunk(modified_metadata).staged! }
758
+ end
759
+ }
760
+
761
+ writing_splits_index = 0
762
+ enqueue_chunk_before_retry = false
763
+
764
+ while writing_splits_index < splits.size
765
+ chunk = get_next_chunk.call
766
+ errors = []
767
+ modified_chunks << {chunk: chunk, adding_bytesize: 0, errors: errors}
768
+ chunk.synchronize do
769
+ raise ShouldRetry unless chunk.writable?
770
+ staged_chunk_used = true if chunk.staged?
771
+
772
+ original_bytesize = committed_bytesize = chunk.bytesize
773
+ begin
774
+ while writing_splits_index < splits.size
775
+ split = splits[writing_splits_index]
776
+ formatted_split = format ? format.call(split) : nil
777
+
778
+ if split.size == 1 # Check BufferChunkOverflowError
779
+ determined_bytesize = nil
780
+ if @compress != :text
781
+ determined_bytesize = nil
782
+ elsif formatted_split
783
+ determined_bytesize = formatted_split.bytesize
784
+ elsif split.first.respond_to?(:bytesize)
785
+ determined_bytesize = split.first.bytesize
786
+ end
787
+
788
+ if determined_bytesize && determined_bytesize > @chunk_limit_size
789
+ # It is a obvious case that BufferChunkOverflowError should be raised here.
790
+ # But if it raises here, already processed 'split' or
791
+ # the proceeding 'split' will be lost completely.
792
+ # So it is a last resort to delay raising such a exception
793
+ errors << "a #{determined_bytesize} bytes record (nth: #{writing_splits_index}) is larger than buffer chunk limit size (#{@chunk_limit_size})"
794
+ writing_splits_index += 1
795
+ next
796
+ end
797
+
798
+ if determined_bytesize.nil? || chunk.bytesize + determined_bytesize > @chunk_limit_size
799
+ # The split will (might) cause size over so keep already processed
800
+ # 'split' content here (allow performance regression a bit).
801
+ chunk.commit
802
+ committed_bytesize = chunk.bytesize
803
+ end
804
+ end
805
+
806
+ if format
807
+ chunk.concat(formatted_split, split.size)
808
+ else
809
+ chunk.append(split, compress: @compress)
810
+ end
811
+ adding_bytes = chunk.bytesize - committed_bytesize
812
+
813
+ if chunk_size_over?(chunk) # split size is larger than difference between size_full? and size_over?
814
+ chunk.rollback
815
+ committed_bytesize = chunk.bytesize
816
+
817
+ if split.size == 1 # Check BufferChunkOverflowError again
818
+ if adding_bytes > @chunk_limit_size
819
+ errors << "concatenated/appended a #{adding_bytes} bytes record (nth: #{writing_splits_index}) is larger than buffer chunk limit size (#{@chunk_limit_size})"
820
+ writing_splits_index += 1
821
+ next
822
+ else
823
+ # As already processed content is kept after rollback, then unstaged chunk should be queued.
824
+ # After that, re-process current split again.
825
+ # New chunk should be allocated, to do it, modify @stage and so on.
826
+ synchronize { @stage.delete(modified_metadata) }
827
+ staged_chunk_used = false
828
+ chunk.unstaged!
829
+ break
830
+ end
831
+ end
832
+
833
+ if chunk_size_full?(chunk) || split.size == 1
834
+ enqueue_chunk_before_retry = true
835
+ else
836
+ splits_count *= 10
837
+ end
838
+
839
+ raise ShouldRetry
840
+ end
841
+
842
+ writing_splits_index += 1
843
+
844
+ if chunk_size_full?(chunk)
845
+ break
846
+ end
847
+ end
848
+ rescue
849
+ chunk.purge if chunk.unstaged? # unstaged chunk will leak unless purge it
850
+ raise
851
+ end
852
+
853
+ modified_chunks.last[:adding_bytesize] = chunk.bytesize - original_bytesize
854
+ end
855
+ end
856
+ modified_chunks.each do |data|
857
+ block.call(data[:chunk], data[:adding_bytesize], data[:errors])
858
+ end
859
+ rescue ShouldRetry
860
+ modified_chunks.each do |data|
861
+ chunk = data[:chunk]
862
+ chunk.rollback rescue nil
863
+ if chunk.unstaged?
864
+ chunk.purge rescue nil
865
+ end
866
+ end
867
+ enqueue_chunk(metadata) if enqueue_chunk_before_retry
868
+ retry
869
+ end
870
+
871
+ STATS_KEYS = [
872
+ 'stage_length',
873
+ 'stage_byte_size',
874
+ 'queue_length',
875
+ 'queue_byte_size',
876
+ 'available_buffer_space_ratios',
877
+ 'total_queued_size',
878
+ 'oldest_timekey',
879
+ 'newest_timekey'
880
+ ]
881
+
882
+ def statistics
883
+ stage_size, queue_size = @stage_size_metrics.get, @queue_size_metrics.get
884
+ buffer_space = 1.0 - ((stage_size + queue_size * 1.0) / @total_limit_size)
885
+ @stage_length_metrics.set(@stage.size)
886
+ @queue_length_metrics.set(@queue.size)
887
+ @available_buffer_space_ratios_metrics.set(buffer_space * 100)
888
+ @total_queued_size_metrics.set(stage_size + queue_size)
889
+ stats = {
890
+ 'stage_length' => @stage_length_metrics.get,
891
+ 'stage_byte_size' => stage_size,
892
+ 'queue_length' => @queue_length_metrics.get,
893
+ 'queue_byte_size' => queue_size,
894
+ 'available_buffer_space_ratios' => @available_buffer_space_ratios_metrics.get.round(1),
895
+ 'total_queued_size' => @total_queued_size_metrics.get,
896
+ }
897
+
898
+ tkeys = timekeys
899
+ if (m = tkeys.min)
900
+ @oldest_timekey_metrics.set(m)
901
+ stats['oldest_timekey'] = @oldest_timekey_metrics.get
902
+ end
903
+ if (m = tkeys.max)
904
+ @newest_timekey_metrics.set(m)
905
+ stats['newest_timekey'] = @newest_timekey_metrics.get
906
+ end
907
+
908
+ { 'buffer' => stats }
909
+ end
910
+
911
+ def backup(chunk_unique_id)
912
+ unique_id = dump_unique_id_hex(chunk_unique_id)
913
+
914
+ if @disable_chunk_backup
915
+ log.warn "disable_chunk_backup is true. #{unique_id} chunk is not backed up."
916
+ return
917
+ end
918
+
919
+ safe_owner_id = owner.plugin_id.gsub(/[ "\/\\:;|*<>?]/, '_')
920
+ backup_base_dir = system_config.root_dir || DEFAULT_BACKUP_DIR
921
+ backup_file = File.join(backup_base_dir, 'backup', "worker#{fluentd_worker_id}", safe_owner_id, "#{unique_id}.log")
922
+ backup_dir = File.dirname(backup_file)
923
+
924
+ log.warn "bad chunk is moved to #{backup_file}"
925
+ FileUtils.mkdir_p(backup_dir, mode: system_config.dir_permission || Fluent::DEFAULT_DIR_PERMISSION) unless Dir.exist?(backup_dir)
926
+ File.open(backup_file, 'ab', system_config.file_permission || Fluent::DEFAULT_FILE_PERMISSION) { |f| yield f }
927
+ end
928
+
929
+ private
930
+
931
+ def optimistic_queued?(metadata = nil)
932
+ if metadata
933
+ n = @queued_num[metadata]
934
+ n && n.nonzero?
935
+ else
936
+ !@queue.empty?
937
+ end
938
+ end
939
+ end
940
+ end
941
+ end