fluentd 1.19.3 → 1.20.0

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +46 -0
  3. data/CHANGELOG.md +120 -0
  4. data/GithubWorkflow.md +1 -1
  5. data/MAINTAINERS.md +2 -2
  6. data/README.md +3 -2
  7. data/Rakefile +2 -1
  8. data/SECURITY.md +26 -1
  9. data/lib/fluent/command/cat.rb +3 -3
  10. data/lib/fluent/compat/exec_util.rb +20 -5
  11. data/lib/fluent/config/basic_parser.rb +0 -1
  12. data/lib/fluent/config/literal_parser.rb +22 -10
  13. data/lib/fluent/config/types.rb +10 -2
  14. data/lib/fluent/config/yaml_parser/loader.rb +12 -1
  15. data/lib/fluent/config/yaml_parser/parser.rb +14 -13
  16. data/lib/fluent/configurable.rb +1 -0
  17. data/lib/fluent/daemon.rb +2 -1
  18. data/lib/fluent/env.rb +1 -0
  19. data/lib/fluent/event.rb +37 -0
  20. data/lib/fluent/load.rb +0 -1
  21. data/lib/fluent/log.rb +2 -2
  22. data/lib/fluent/plugin/base.rb +7 -2
  23. data/lib/fluent/plugin/buf_file.rb +3 -3
  24. data/lib/fluent/plugin/buf_file_single.rb +6 -2
  25. data/lib/fluent/plugin/buffer/chunk.rb +14 -6
  26. data/lib/fluent/plugin/buffer/file_chunk.rb +28 -13
  27. data/lib/fluent/plugin/buffer/file_single_chunk.rb +28 -13
  28. data/lib/fluent/plugin/buffer.rb +125 -41
  29. data/lib/fluent/plugin/compressable.rb +2 -2
  30. data/lib/fluent/plugin/extractor.rb +17 -6
  31. data/lib/fluent/plugin/filter_record_transformer.rb +2 -1
  32. data/lib/fluent/plugin/formatter_out_file.rb +3 -4
  33. data/lib/fluent/plugin/in_exec.rb +6 -4
  34. data/lib/fluent/plugin/in_forward.rb +39 -29
  35. data/lib/fluent/plugin/in_http.rb +83 -2
  36. data/lib/fluent/plugin/in_monitor_agent.rb +2 -1
  37. data/lib/fluent/plugin/in_object_space.rb +2 -2
  38. data/lib/fluent/plugin/in_sample.rb +2 -1
  39. data/lib/fluent/plugin/in_syslog.rb +72 -6
  40. data/lib/fluent/plugin/in_tail/compatibility.rb +111 -0
  41. data/lib/fluent/plugin/in_tail/dir_watcher.rb +713 -0
  42. data/lib/fluent/plugin/in_tail/group_watch.rb +13 -13
  43. data/lib/fluent/plugin/in_tail/io_handler.rb +391 -0
  44. data/lib/fluent/plugin/in_tail/line_feeder.rb +230 -0
  45. data/lib/fluent/plugin/in_tail/stat_watcher.rb +52 -0
  46. data/lib/fluent/plugin/in_tail/tail_watcher.rb +276 -0
  47. data/lib/fluent/plugin/in_tail/worker_pool.rb +298 -0
  48. data/lib/fluent/plugin/in_tail.rb +324 -815
  49. data/lib/fluent/plugin/in_unix.rb +5 -3
  50. data/lib/fluent/plugin/out_exec_filter.rb +2 -2
  51. data/lib/fluent/plugin/out_file.rb +10 -4
  52. data/lib/fluent/plugin/out_forward/connection_manager.rb +18 -0
  53. data/lib/fluent/plugin/out_forward.rb +21 -2
  54. data/lib/fluent/plugin/out_http.rb +0 -10
  55. data/lib/fluent/plugin/output.rb +81 -31
  56. data/lib/fluent/plugin/parser_csv.rb +7 -2
  57. data/lib/fluent/plugin/parser_json.rb +25 -12
  58. data/lib/fluent/plugin/parser_ltsv.rb +2 -4
  59. data/lib/fluent/plugin/parser_msgpack.rb +7 -6
  60. data/lib/fluent/plugin/parser_syslog.rb +55 -8
  61. data/lib/fluent/plugin/parser_tsv.rb +6 -1
  62. data/lib/fluent/plugin/sd_file.rb +2 -1
  63. data/lib/fluent/plugin/storage_local.rb +2 -2
  64. data/lib/fluent/plugin_helper/http_server/server.rb +29 -13
  65. data/lib/fluent/plugin_helper/http_server.rb +2 -1
  66. data/lib/fluent/root_agent.rb +1 -1
  67. data/lib/fluent/supervisor.rb +32 -6
  68. data/lib/fluent/system_config.rb +5 -2
  69. data/lib/fluent/time.rb +8 -7
  70. data/lib/fluent/version.rb +1 -1
  71. data/templates/new_gem/.gitignore +8 -0
  72. metadata +41 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9613f1dacdb60cfccb245e988e67cec002daee2f81cbe38c2b80c30d525ad7b8
4
- data.tar.gz: 4a85aa6c3bdaebd9cd069d508ac969d8792586247bef1d73d25cc906f6cd7c87
3
+ metadata.gz: fa67a9199a9bcd73feb7dc286f4a1cb8347bd4d01d515561ceaf151671a9116e
4
+ data.tar.gz: ec7afdf8eea191d4badfb95361c3b41cfb35785c06dbacf3d0c0f65b89d734da
5
5
  SHA512:
6
- metadata.gz: c2d63e0bd8cf51a61d254cfda559f38ed1bcc79ceb1bf1f0d0c80b21b922e67091d2ee8c291a0dc0fcac0110873d0045874df297e0795c0cd604af64f431f845
7
- data.tar.gz: 5fe9e2450048bacc978389621b0e3f2c8aed0e9136ffe11192945a754173c1ce13ff50c310cfcdf1633d7dc784e14e9a4fc5a6de519da3bc81decb12f6d5b28d
6
+ metadata.gz: 1e900ecc699cb16836f2467105c09d51917446f7d7a885cbd66512e1fb8d24a2807a5b3ff7eeedec969e3e9dde7f8bc2cff40624e5c7d3d45d2bb5e4b536a75e
7
+ data.tar.gz: 8c258d373881b49dc90bc8e93ade34d46fb79b768203e05889a4ac3196361c97d185fa8b6c8006c9d985df65da20eabf1df62a802a3e365d27ba2f5cc345c1be
data/AGENTS.md ADDED
@@ -0,0 +1,46 @@
1
+ # Guidance for coding agents
2
+
3
+ This file is for AI coding agents (Claude Code, Cursor, Codex, Copilot, ...) working in this repository. Humans should read CONTRIBUTING.md.
4
+
5
+ ## Primary sources
6
+
7
+ - Official documentation: https://docs.fluentd.org/
8
+ - Index for agents: https://docs.fluentd.org/llms.txt
9
+ - Every page is also available as Markdown by appending `.md` to its URL, e.g. https://docs.fluentd.org/configuration/config-file.md
10
+ - Read the documentation before answering questions about configuration syntax or plugin parameters. Do not invent parameters; check the plugin's page or its `config_param` declarations in this repository.
11
+ - Configuration has two formats.
12
+ - Classic: https://docs.fluentd.org/configuration/config-file.md
13
+ - YAML: https://docs.fluentd.org/configuration/config-file-yaml.md
14
+
15
+ ## Repository layout
16
+
17
+ - `lib/fluent/plugin/` – bundled plugins (`in_*.rb`, `out_*.rb`, `filter_*.rb`, `parser_*.rb`, `formatter_*.rb`, `buf_*.rb`, `storage_*.rb`, `sd_*.rb`, `metrics_*.rb`)
18
+ - `lib/fluent/plugin_helper/` – plugin helpers
19
+ - `lib/fluent/config/` – configuration parsers (classic and YAML)
20
+ - `test/` – tests written with test-unit
21
+ - `templates/new_gem/` – files generated by `fluent-plugin-generate`
22
+
23
+ ## Developing
24
+
25
+ - Install: `bundle install`
26
+ - Run all tests: `bundle exec rake test`
27
+ - Run one file: `bundle exec ruby -Ilib -Itest test/plugin/test_in_tail.rb`
28
+ - Plugin API reference: https://docs.fluentd.org/plugin-development/README.md
29
+ - Plugin helper reference: https://docs.fluentd.org/plugin-helper-overview/README.md
30
+ - Test helpers for plugins: https://docs.fluentd.org/plugin-development/plugin-test-code.md
31
+
32
+ ## Conventions
33
+
34
+ - Follow CONTRIBUTING.md. Commits need a DCO sign-off (`git commit -s`).
35
+ - Keep changes minimal and focused; do not reformat unrelated code.
36
+ - Add or update tests under `test/` for behavior changes.
37
+ - Do not add runtime dependencies without discussion.
38
+ - Match the surrounding code style; there is no autoformatter to run. CI runs `rubocop`, but only the Security and Performance cops are enabled.
39
+ - Fluentd runs on Linux, macOS and Windows. CI tests `ubuntu-latest`, `macos-latest`, `windows-latest` and `windows-11-arm`. Assume your change must work on Windows.
40
+
41
+ ## Issues and pull requests
42
+
43
+ - Pull requests follow `.github/PULL_REQUEST_TEMPLATE.md`. Keep its headings, including `Docs Changes` and `Release Note`, and write `Fixes #<n>` when an issue exists.
44
+ - Blank issues are disabled. Use `.github/ISSUE_TEMPLATE/bug_report.yml` or `.github/ISSUE_TEMPLATE/feature_request.yml` and answer every required field.
45
+ - Questions belong in [Discussions](https://github.com/fluent/fluentd/discussions), not in issues.
46
+ - Note that `gh pr create --body` and `gh issue create --body` skip the template. Pass `--template`, or reproduce the template's sections in the body you supply.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,125 @@
1
+ # v1.20
2
+
3
+ ## Release v1.20.0 - 2026/10/23
4
+
5
+ ### Enhancement
6
+
7
+ * Replace Yajl with built-in JSON for simple cases https://github.com/fluent/fluentd/pull/5090
8
+ * out_forward: add `send_keepalive_packet` option to enable TCP keepalive (SO_KEEPALIVE) https://github.com/fluent/fluentd/pull/5262
9
+ * in_exec: add `command_timeout` option to limit child process execution time https://github.com/fluent/fluentd/pull/5320
10
+ * Replace Yajl with JSON for handling JSON stream https://github.com/fluent/fluentd/pull/5383
11
+ * When an input stream ends in the middle of a JSON document, Fluentd now logs a warning and discards the incomplete tail instead of raising `ParseError`.
12
+ * system_config: add `umask` option to `<system>` directive https://github.com/fluent/fluentd/pull/5390
13
+ * parser_syslog: accept a space after RFC3164 priority https://github.com/fluent/fluentd/pull/5449
14
+ * in_tail: add opt-in `enable_dir_watcher` and `dir_watcher_limit` to discover new files earlier by watching directories https://github.com/fluent/fluentd/pull/5528
15
+ * in_tail: add opt-in worker-thread parsing via `num_threads` to offload parsing from the event loop https://github.com/fluent/fluentd/pull/5529
16
+ * The default `num_threads 1` keeps the previous synchronous behavior.
17
+ * In worker mode, `monitor_agent` also reports `worker_pending_batch_count`, `worker_pending_bytes` and `worker_parse_error_count`.
18
+ * buffer: add `evacuate_limit_size` to keep evacuated chunks from filling the disk https://github.com/fluent/fluentd/pull/5473
19
+ * This option sets an approximate limit on the total size of the chunk files evacuated when the retry limit is reached, including the ones evacuated before. Chunks that do not fit are purged without being evacuated.
20
+ * The default `nil` keeps the previous behavior. Set `0` to disable evacuation.
21
+ * in_forward: accept metadata on encapsulated timestamps sent by Fluent Bit v5.0.5 or later https://github.com/fluent/fluentd/pull/5411
22
+ * Enable Ruby JIT by default https://github.com/fluent/fluentd/pull/5464
23
+ * The system configuration `enable_jit` now defaults to `true`.
24
+ * JIT increases memory usage of each worker process. Set `enable_jit false` in the `<system>` section to restore the previous behavior.
25
+ * This has no effect on Windows because YJIT is not supported there.
26
+ * fluent-plugin-generate: add .gitignore file https://github.com/fluent/fluentd/pull/5370
27
+ * Performance improvements
28
+ * https://github.com/fluent/fluentd/pull/5281
29
+ * https://github.com/fluent/fluentd/pull/5288
30
+ * https://github.com/fluent/fluentd/pull/5289
31
+ * https://github.com/fluent/fluentd/pull/5344
32
+ * https://github.com/fluent/fluentd/pull/5353
33
+ * https://github.com/fluent/fluentd/pull/5354
34
+ * https://github.com/fluent/fluentd/pull/5357
35
+ * https://github.com/fluent/fluentd/pull/5287
36
+ * https://github.com/fluent/fluentd/pull/5278
37
+ * https://github.com/fluent/fluentd/pull/5567
38
+
39
+ ### Bug Fix
40
+
41
+ * http_server helper: Fix IPv6 bind address support in URI construction https://github.com/fluent/fluentd/pull/5239
42
+ * Fixed `URI::InvalidURIError` when binding to IPv6 addresses (e.g., `::`, `::1`)
43
+ * IPv6 addresses are now properly bracketed in URIs per RFC 3986 (e.g., `http://[::]:24231`)
44
+ * Handles pre-bracketed addresses correctly to avoid double-bracketing
45
+ * Affects all plugins using http_server helper with IPv6 bind addresses
46
+ * out_file: create symlinks for all chunks sharing the latest timekey https://github.com/fluent/fluentd/pull/5476
47
+ * time: fix TimeFormatter returning nil for the Unix epoch https://github.com/fluent/fluentd/pull/5420
48
+ * in_tail: fix log duplication when a rotated file is appended during `rotate_wait` with `follow_inodes` https://github.com/fluent/fluentd/pull/5499
49
+ * in_tail: fix `NameError` raised when flushing buffered lines with `emit_unmatched_lines true` https://github.com/fluent/fluentd/pull/5513
50
+ * in_tail: fix unread lines never being collected when a throttled file is removed from the watch list https://github.com/fluent/fluentd/pull/5515
51
+ * in_tail: fix shutdown errors and timeouts caused by an ongoing watcher refresh https://github.com/fluent/fluentd/pull/5530
52
+ * in_tail: fix closed stream error when file rotation overlaps with shutdown https://github.com/fluent/fluentd/pull/5551
53
+ * in_tail: use a monotonic clock for multiline flush timers so that they are not affected by wall-clock adjustments https://github.com/fluent/fluentd/pull/5542
54
+ * buffer: fix a race that could make the buffer `stage_size` gauge transiently negative while a write and a chunk enqueue overlap https://github.com/fluent/fluentd/pull/5481
55
+ * buffer: fix an enqueued unstaged file chunk being re-staged and flushed twice, which caused `closed stream` / `ENOENT` errors and leaked buffer size gauges https://github.com/fluent/fluentd/pull/5517
56
+ * parser_msgpack: fix leftover data from one parse call leaking into the next https://github.com/fluent/fluentd/pull/5553
57
+ * http_server helper: fix HTTP endpoints never recovering after a bind failure https://github.com/fluent/fluentd/pull/5523
58
+ * The plugin now fails to start, and the worker is restarted until the port is available.
59
+ * root_agent: fix `emit_records` and `emit_size` never counted for inputs with `@label` https://github.com/fluent/fluentd/pull/5526
60
+ * supervisor: fix graceful config reload failing for YAML configuration https://github.com/fluent/fluentd/pull/5522
61
+ * It also fixes `<<: !include` of a file that contains a mapping.
62
+
63
+ ### Misc
64
+
65
+ * Drop Ruby 3.2 support https://github.com/fluent/fluentd/pull/5465
66
+ * out_http: remove the Net::HTTP extra_chain_cert monkey patch https://github.com/fluent/fluentd/pull/5484
67
+ * gem: add aarch64-mingw-ucrt gem https://github.com/fluent/fluentd/pull/5400
68
+ * gem: add json gem (>= 2.21) as runtime dependency and remove Refinements workaround https://github.com/fluent/fluentd/pull/5429
69
+ * in_tail: internal refactoring
70
+ * https://github.com/fluent/fluentd/pull/5518
71
+ * https://github.com/fluent/fluentd/pull/5520
72
+ * https://github.com/fluent/fluentd/pull/5521
73
+ * https://github.com/fluent/fluentd/pull/5527
74
+ * https://github.com/fluent/fluentd/pull/5554
75
+
1
76
  # v1.19
2
77
 
78
+ ## Release v1.19.4 - 2026/09/28
79
+
80
+ ### Bug Fix
81
+
82
+ * buffer: enforce decompression_size_limit on the chunk IO path https://github.com/fluent/fluentd/pull/5504
83
+ * buffer: clamp exported buffer size metrics to non-negative values https://github.com/fluent/fluentd/pull/5488
84
+ * buffer: fix spurious `BufferOverflowError` caused by `queue_size` leaking when a chunk purge fails https://github.com/fluent/fluentd/pull/5487
85
+ * buffer: fix `stage_byte_size` leak on staged to unstaged chunk demotion that could eventually raise spurious `BufferOverflowError` in plugins implementing `#format` https://github.com/fluent/fluentd/pull/5456
86
+ * in_syslog: enforce message_length_limit on TCP/TLS transport https://github.com/fluent/fluentd/pull/5502
87
+ * The default value of `message_length_limit` is changed from 2048 to 8192 to match rsyslog's default `MaxMessageSize`.
88
+ * output: fix incomplete path traversal check in extract_placeholders https://github.com/fluent/fluentd/pull/5501
89
+ * output: treat JSON::GeneratorError as unrecoverable error https://github.com/fluent/fluentd/pull/5423
90
+ * parser_syslog: fix NameError when RFC5424 timestamp has repeated spaces https://github.com/fluent/fluentd/pull/5500
91
+ * parser_syslog: fix NameError when RFC3164 timestamp has repeated spaces https://github.com/fluent/fluentd/pull/5497
92
+ * parser_syslog: avoid excessive backtracking when parsing malformed RFC5424 structured data https://github.com/fluent/fluentd/pull/5444
93
+ * chunk: ensure to close the Tempfile for decompressed data https://github.com/fluent/fluentd/pull/5486
94
+ * plugin base: bound the number of worker lock files by hashing the path into a fixed set of buckets https://github.com/fluent/fluentd/pull/5471
95
+ * out_forward: stop the endless "ack in response and chunk id in sent data are different" warning storm by discarding (instead of reusing) a keepalive socket whose ack failed or came back with a mismatched chunk id https://github.com/fluent/fluentd/pull/5445
96
+ * config: accept empty lines in quoted strings https://github.com/fluent/fluentd/pull/5478
97
+ * config: fix a config error when a single scalar value is given to an array option in YAML config syntax (for example `retryable_response_codes: 503`) https://github.com/fluent/fluentd/pull/5433
98
+ * supervisor: reduce memory usage of cleanup_lock_dir with huge number of lock files https://github.com/fluent/fluentd/pull/5472
99
+
100
+ ### Enhancement
101
+
102
+ * in_http: add `<auth>` for basic authentication and `<security>` for client network allowlisting https://github.com/fluent/fluentd/pull/5503
103
+
104
+ ### Misc
105
+
106
+ * gem: support json gem v3.x https://github.com/fluent/fluentd/pull/5493
107
+ * Add `allow_comments: true` option for json parser https://github.com/fluent/fluentd/pull/5432
108
+ * Set `allow_duplicate_key: true` for all `JSON.parse` call https://github.com/fluent/fluentd/pull/5430
109
+ * CI fixes
110
+ * https://github.com/fluent/fluentd/pull/5495
111
+ * https://github.com/fluent/fluentd/pull/5477
112
+ * https://github.com/fluent/fluentd/pull/5466
113
+ * https://github.com/fluent/fluentd/pull/5460
114
+ * https://github.com/fluent/fluentd/pull/5455
115
+ * https://github.com/fluent/fluentd/pull/5454
116
+ * https://github.com/fluent/fluentd/pull/5453
117
+ * https://github.com/fluent/fluentd/pull/5452
118
+ * https://github.com/fluent/fluentd/pull/5434
119
+ * https://github.com/fluent/fluentd/pull/5426
120
+ * https://github.com/fluent/fluentd/pull/5425
121
+ * https://github.com/fluent/fluentd/pull/5424
122
+
3
123
  ## Release v1.19.3 - 2026/06/25
4
124
 
5
125
  ### Bug Fix
data/GithubWorkflow.md CHANGED
@@ -9,7 +9,7 @@ Table of Contents
9
9
  * [Create a Pull Request](#create-a-pull-request)
10
10
 
11
11
 
12
- The [fluentd](https://github.com/fluent/fluentd.git) code is hosted on Github (https://github.com/fluent/fluentd). The repository is called `upstream`. Contributors will develop and commit their changes in a clone of upstream repository. Then contributors push their change to their forked repository (`origin`) and create a Pull Request (PR), the PR will be merged to `upstream` repository if it meets the all the necessary requirements.
12
+ The [fluentd](https://github.com/fluent/fluentd.git) code is hosted on Github (https://github.com/fluent/fluentd). The repository is called `upstream`. Contributors will develop and commit their changes in a clone of upstream repository. Then contributors push their change to their forked repository (`origin`) and create a Pull Request (PR), the PR will be merged to `upstream` repository if it meets all the necessary requirements.
13
13
 
14
14
  ## Fork a repository
15
15
 
data/MAINTAINERS.md CHANGED
@@ -7,10 +7,10 @@
7
7
  - [Satoshi Tagomori](https://github.com/tagomoris)
8
8
  - [Toru Takahashi](https://github.com/toru-takahashi), [Treasure Data](https://www.treasuredata.com/)
9
9
  - [Eduardo Silva](https://github.com/edsiper), [Chronosphere](https://chronosphere.io/)
10
- - [Fujimoto Seiji](https://github.com/fujimots)
10
+ - [Fujimoto Seiji](https://github.com/fujimotos)
11
11
  - [Takuro Ashie](https://github.com/ashie), [ClearCode](https://www.clear-code.com/)
12
12
  - [Kentaro Hayashi](https://github.com/kenhys), [ClearCode](https://www.clear-code.com/)
13
- - [Daijiro Fukuda](https://github.com/daipom), [ClearCode](https://www.clear-code.com/)
13
+ - [Daijiro Fukuda](https://github.com/daipom)
14
14
 
15
15
  ## Sub Projects: Fluent Bit
16
16
 
data/README.md CHANGED
@@ -5,6 +5,7 @@ Fluentd: Open-Source Log Collector
5
5
  [![Test with Ruby head](https://github.com/fluent/fluentd/actions/workflows/test-ruby-head.yml/badge.svg)](https://github.com/fluent/fluentd/actions/workflows/test-ruby-head.yml)
6
6
  [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1189/badge)](https://bestpractices.coreinfrastructure.org/projects/1189)
7
7
  [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/fluent/fluentd/badge)](https://scorecard.dev/viewer/?uri=github.com/fluent/fluentd)
8
+ [![Backport Pull Requests](https://github.com/fluent/fluentd/actions/workflows/backport.yml/badge.svg)](https://github.com/fluent/fluentd/actions/workflows/backport.yml)
8
9
 
9
10
  [Fluentd](https://www.fluentd.org/) collects events from various data sources and writes them to files, RDBMS, NoSQL, IaaS, SaaS, Hadoop and so on. Fluentd helps you unify your logging infrastructure (Learn more about the [Unified Logging Layer](https://www.fluentd.org/blog/unified-logging-layer)).
10
11
 
@@ -24,11 +25,11 @@ Fluentd: Open-Source Log Collector
24
25
  ### Branch
25
26
 
26
27
  - master: For v1 development.
27
- - v0.12: For v0.12. This is deprecated version. we already stopped supporting (See https://www.fluentd.org/blog/drop-schedule-announcement-in-2019).
28
+ - v0.12: For v0.12. This is a deprecated version. we already stopped supporting (See https://www.fluentd.org/blog/drop-schedule-announcement-in-2019).
28
29
 
29
30
  ### Prerequisites
30
31
 
31
- - Ruby 3.2 or later
32
+ - Ruby 3.3 or later
32
33
  - git
33
34
 
34
35
  `git` should be in `PATH`. On Windows, you can use `Github for Windows` and `GitShell` for easy setup.
data/Rakefile CHANGED
@@ -6,6 +6,7 @@ require 'rake/testtask'
6
6
  require 'rake/clean'
7
7
 
8
8
  require_relative 'tasks/benchmark'
9
+ require_relative 'tasks/backport'
9
10
 
10
11
  task test: [:base_test]
11
12
 
@@ -16,7 +17,7 @@ namespace :build do
16
17
  desc 'Build gems for all platforms'
17
18
  task :all do
18
19
  Bundler.with_original_env do
19
- %w[ruby x86-mingw32 x64-mingw32 x64-mingw-ucrt].each do |name|
20
+ %w[ruby x86-mingw32 x64-mingw32 x64-mingw-ucrt aarch64-mingw-ucrt].each do |name|
20
21
  ENV['GEM_BUILD_FAKE_PLATFORM'] = name
21
22
  Rake::Task["build"].execute
22
23
  end
data/SECURITY.md CHANGED
@@ -4,10 +4,11 @@
4
4
 
5
5
  | Version | Supported |
6
6
  |-----------|--------------------|
7
+ | 1.20.x | :white_check_mark: |
7
8
  | 1.19.x | :white_check_mark: |
8
9
  | 1.18.x | :x: |
9
10
  | 1.17.x | :x: |
10
- | 1.16.x | :white_check_mark: |
11
+ | 1.16.x | :x: |
11
12
  | <= 1.15.x | :x: |
12
13
 
13
14
  ## Reporting a Vulnerability
@@ -15,8 +16,32 @@
15
16
  Please post your vulnerability report from the following page:
16
17
  https://github.com/fluent/fluentd/security/advisories
17
18
 
19
+ > [!CAUTION]
20
+ > In above contact form, we accept about **ONLY** Fluentd's vulnerability, in contrast, **REJECT** your vulnerability report about Fluentd derivative products such as fluent-package, Fluentd container images and Fluentd kubernetes deamonset images and so on. There are appropriate contact forms for every these derivative products. See the following notice.
21
+
18
22
  > [!NOTE]
19
23
  > If you use fluent-package, please check [fluent-package-builder](https://github.com/fluent/fluent-package-builder/blob/master/SECURITY.md) and report it there.
20
24
 
21
25
  > [!NOTE]
22
26
  > If you use a Docker image of Fluentd, please check [Fluentd Docker Image](https://github.com/fluent/fluentd-docker-image/blob/master/SECURITY.md) and report it there.
27
+
28
+
29
+ ## Out of Scope / Non-Vulnerabilities
30
+
31
+ Before reporting a vulnerability, please check if it falls under the following expected behaviors, design choices, or configuration issues. Reports regarding these items will be closed immediately as **not a bug** or **out of scope**.
32
+
33
+ ### 1. `in_debug_agent` and arbitrary code execution (`eval`)
34
+
35
+ * **Description:** The `in_debug_agent` plugin is a developer tool designed specifically for debugging a running Fluentd process via dRuby. It requires explicit activation in the local configuration file and is disabled by default.
36
+ * **Why it is not a vulnerability:** The ability to execute arbitrary Ruby code (`eval`) is **by design**. It functions similarly to `gdbserver`, allowing maintainers to inspect internal process states. It does not introduce a security risk unless an administrator explicitly enables it and exposes the port to an untrusted network, which constitutes a severe misconfiguration rather than a flaw in Fluentd itself.
37
+
38
+ ### 2. `record_transformer` with `enable_ruby`
39
+
40
+ * **Description:** The `enable_ruby` option in the `record_transformer` plugin allows administrators to use Ruby expressions within the configuration file to transform log records dynamically.
41
+ * **Why it is not a vulnerability:** Executing the Ruby code block defined in the configuration file is **by design**. It does not allow arbitrary code execution from untrusted log inputs unless the user explicitly writes insecure expressions (e.g., passing untrusted input directly into another dynamic evaluation nested inside the block). If an attacker can modify the local Fluentd configuration file to enable this feature and inject malicious Ruby code, the system is already fully compromised at the OS/infrastructure level (Post-Exploitation). We do not accept RCE reports that rely on the ability to modify the local configuration file.
42
+
43
+ ### 3. ReDoS (Regular Expression Denial of Service) reproducible only on Ruby 3.2 or older
44
+
45
+ * **Description:** Potential algorithmic complexity issues in regular expressions that could lead to High CPU usage or Denial of Service on older Ruby runtimes.
46
+ * **Why it is out of scope:** Fluentd officially supports modern Ruby environments. Our primary distribution channels including the official `fluent-package` and official Docker images ship with **Ruby 3.3 or later (e.g., Ruby 3.4)**, which includes built-in, robust mitigation against ReDoS at the language level (such as matching timeouts and engine-level optimizations). We do not accept ReDoS reports that only impact legacy Ruby versions (Ruby 3.2 or older) unless the issue can be demonstrated to cause a practical denial of service on Ruby 3.3+.
47
+ However, if you find inefficient regular expressions, we welcome them as standard bug reports or performance improvement suggestions via regular GitHub Issues rather than security advisories.
@@ -107,7 +107,7 @@ rescue
107
107
  end
108
108
 
109
109
  require 'socket'
110
- require 'yajl'
110
+ require 'json'
111
111
  require 'msgpack'
112
112
  require 'fluent/ext_monitor_require'
113
113
 
@@ -304,7 +304,7 @@ class Writer
304
304
  end
305
305
 
306
306
  def abort_message(time, record)
307
- $stdout.puts "!#{time}:#{Yajl.dump(record)}"
307
+ $stdout.puts "!#{time}:#{JSON.generate(record)}"
308
308
  end
309
309
  end
310
310
 
@@ -326,7 +326,7 @@ case format
326
326
  when 'json'
327
327
  begin
328
328
  while line = $stdin.gets
329
- record = Yajl.load(line)
329
+ record = JSON.parse(line, **Fluent::DEFAULT_JSON_PARSE_OPTIONS)
330
330
  w.write(record)
331
331
  end
332
332
  rescue
@@ -15,8 +15,9 @@
15
15
  #
16
16
 
17
17
  require 'msgpack'
18
- require 'yajl'
18
+ require 'json'
19
19
 
20
+ require 'fluent/env'
20
21
  require 'fluent/engine'
21
22
  require 'fluent/plugin'
22
23
  require 'fluent/parser'
@@ -76,10 +77,24 @@ module Fluent
76
77
  end
77
78
 
78
79
  class JSONParser < Parser
80
+ BYTES_TO_READ = 8192
81
+
79
82
  def call(io)
80
- y = Yajl::Parser.new
81
- y.on_parse_complete = @on_message
82
- y.parse(io)
83
+ parser = JSON::ResumableParser.new(**Fluent::DEFAULT_JSON_PARSE_OPTIONS)
84
+ begin
85
+ chunk = +"".b
86
+ while io.readpartial(BYTES_TO_READ, chunk)
87
+ parser << chunk
88
+ while parser.parse
89
+ @on_message.call(parser.value)
90
+ end
91
+ end
92
+ rescue EOFError
93
+ unless parser.empty?
94
+ $log&.warn "JSON stream ended in the middle of a document; " \
95
+ "discarding incomplete data"
96
+ end
97
+ end
83
98
  end
84
99
  end
85
100
 
@@ -115,7 +130,7 @@ module Fluent
115
130
 
116
131
  class JSONFormatter < Formatter
117
132
  def call(record, out)
118
- out << Yajl.dump(record) << "\n"
133
+ out << JSON.generate(record) << "\n"
119
134
  end
120
135
  end
121
136
 
@@ -28,7 +28,6 @@ module Fluent
28
28
  SPACING = /(?:[ \t\r\n]|\z|\#.*?(?:\z|[\r\n]))+/
29
29
  ZERO_OR_MORE_SPACING = /(?:[ \t\r\n]|\z|\#.*?(?:\z|[\r\n]))*/
30
30
  SPACING_WITHOUT_COMMENT = /(?:[ \t\r\n]|\z)+/
31
- LINE_END_WITHOUT_SPACING_AND_COMMENT = /(?:\z|[\r\n])/
32
31
 
33
32
  module ClassMethods
34
33
  def symbol(string)
@@ -17,15 +17,24 @@
17
17
  require 'stringio'
18
18
 
19
19
  require 'json'
20
- require 'yajl'
21
20
  require 'socket'
22
21
  require 'ripper'
23
22
 
23
+ require 'fluent/env'
24
24
  require 'fluent/config/basic_parser'
25
25
 
26
26
  module Fluent
27
27
  module Config
28
28
  class LiteralParser < BasicParser
29
+ # A physical line break (LF, CR, or CRLF) inside a quoted string.
30
+ # CRLF is normalized to LF so that the same config text does not produce a
31
+ # different value depending on whether the file was saved with LF or CRLF.
32
+ # A lone CR is kept as-is, and an escaped "\r\n" still produces CRLF.
33
+ LINE_BREAK = /\r\n|[\r\n]/
34
+ # A backslash immediately followed by a physical line break.
35
+ # It works as a line continuation, so both are stripped from the value.
36
+ LINE_CONTINUATION = /\\#{LINE_BREAK}/o
37
+
29
38
  def self.unescape_char(c)
30
39
  case c
31
40
  when '"'
@@ -98,11 +107,10 @@ module Fluent
98
107
  else
99
108
  return string.join
100
109
  end
101
- elsif check(/[^"]#{LINE_END_WITHOUT_SPACING_AND_COMMENT}/o)
102
- if s = check(/[^\\]#{LINE_END_WITHOUT_SPACING_AND_COMMENT}/o)
103
- string << s
104
- end
105
- skip(/[^"]#{LINE_END_WITHOUT_SPACING_AND_COMMENT}/o)
110
+ elsif skip(LINE_CONTINUATION)
111
+ next
112
+ elsif s = scan(LINE_BREAK)
113
+ string << (s == "\r\n" ? "\n" : s)
106
114
  elsif s = scan(/\\./)
107
115
  string << eval_escape_char(s[1,1])
108
116
  elsif skip(/\#\{/)
@@ -125,6 +133,8 @@ module Fluent
125
133
  string << "'"
126
134
  elsif s = scan(/\\\\/)
127
135
  string << "\\"
136
+ elsif s = scan(LINE_BREAK)
137
+ string << (s == "\r\n" ? "\n" : s)
128
138
  elsif s = scan(/./)
129
139
  string << s
130
140
  else
@@ -225,8 +235,10 @@ EOM
225
235
 
226
236
  def scan_json(is_array)
227
237
  result = nil
228
- # Yajl does not raise ParseError for incomplete json string, like '[1', '{"h"', '{"h":' or '{"h1":1'
229
- # This is the reason to use JSON module.
238
+ # scan_json detects the end of a JSON literal by repeatedly attempting
239
+ # to parse the buffer and treating a successful parse as completion.
240
+ # This requires a parser that raises JSON::ParserError for incomplete
241
+ # input like '[1', '{"h"', '{"h":' or '{"h1":1'.
230
242
 
231
243
  buffer = (is_array ? "[" : "{")
232
244
  line_buffer = ""
@@ -241,7 +253,7 @@ EOM
241
253
  # '{"foo":"bar", #' -> '{"foo":"bar"}' (to check)
242
254
  parsed = nil
243
255
  begin
244
- parsed = JSON.parse(buffer + line_buffer.rstrip.sub(/,$/, '') + (is_array ? "]" : "}"))
256
+ parsed = JSON.parse(buffer + line_buffer.rstrip.sub(/,$/, '') + (is_array ? "]" : "}"), **Fluent::DEFAULT_JSON_PARSE_OPTIONS)
245
257
  rescue JSON::ParserError
246
258
  # This '#' is in json string literals
247
259
  end
@@ -276,7 +288,7 @@ EOM
276
288
 
277
289
  line_buffer << char
278
290
  begin
279
- result = JSON.parse(buffer + line_buffer)
291
+ result = JSON.parse(buffer + line_buffer, **Fluent::DEFAULT_JSON_PARSE_OPTIONS)
280
292
  rescue JSON::ParserError
281
293
  # Incomplete json string yet
282
294
  end
@@ -201,7 +201,7 @@ module Fluent
201
201
  return nil if val.nil?
202
202
 
203
203
  param = if val.is_a?(String)
204
- val.start_with?('{') ? JSON.parse(val) : Hash[val.strip.split(/\s*,\s*/).map{|v| v.split(':', 2)}]
204
+ val.start_with?('{') ? JSON.parse(val, **Fluent::DEFAULT_JSON_PARSE_OPTIONS) : Hash[val.strip.split(/\s*,\s*/).map{|v| v.split(':', 2)}]
205
205
  else
206
206
  val
207
207
  end
@@ -228,7 +228,15 @@ module Fluent
228
228
  return nil if val.nil?
229
229
 
230
230
  param = if val.is_a?(String)
231
- val.start_with?('[') ? JSON.parse(val) : val.strip.split(/\s*,\s*/)
231
+ val.start_with?('[') ? JSON.parse(val, **Fluent::DEFAULT_JSON_PARSE_OPTIONS) : val.strip.split(/\s*,\s*/)
232
+ elsif val.is_a?(Array)
233
+ val
234
+ elsif val.is_a?(Numeric) || val == true || val == false
235
+ # Wrap only the bare scalars that Psych/YAML actually produces
236
+ # here (nil is handled by the early return above). Any other
237
+ # type (Hash, Symbol, Time, arbitrary objects) falls through and
238
+ # still raises "array required" below.
239
+ [val]
232
240
  else
233
241
  val
234
242
  end
@@ -71,9 +71,17 @@ module Fluent
71
71
  else
72
72
  pattern = path
73
73
  end
74
+ # A single file keeps its own shape; only glob matches are aggregated.
75
+ return load(pattern) if File.file?(pattern)
76
+
74
77
  result = []
75
78
  Dir.glob(pattern).sort.each do |path|
76
- result.concat(load(Pathname.new(path)))
79
+ loaded = load(Pathname.new(path))
80
+ if loaded.is_a?(Hash)
81
+ result.push(loaded)
82
+ else
83
+ result.concat(loaded)
84
+ end
77
85
  end
78
86
  result
79
87
  rescue SystemCallError => e
@@ -93,6 +101,9 @@ module Fluent
93
101
 
94
102
  def revive_hash(hash, o)
95
103
  super(hash, o).tap do |r|
104
+ if r[SHOVEL].is_a?(Array) && r[SHOVEL].all?(Hash)
105
+ r[SHOVEL] = r[SHOVEL].reverse_each.reduce({}) { |a, e| a.merge!(e) }
106
+ end
96
107
  if r[SHOVEL].is_a?(Hash)
97
108
  h2 = {}
98
109
  r.each do |k, v|
@@ -106,19 +106,20 @@ module Fluent
106
106
 
107
107
  def included_sections_build(config, section_builder, indent: 0)
108
108
  config.each_entry do |e|
109
- k = e.keys.first
110
- cc = e.delete(k)
111
- case k
112
- when 'label'
113
- section_builder.add_section(label_build(cc, indent: indent))
114
- when 'worker'
115
- section_builder.add_section(worker_build(cc, indent: indent))
116
- when 'source'
117
- section_builder.add_section(source_build(cc, indent: indent))
118
- when 'filter'
119
- section_builder.add_section(filter_build(cc, indent: indent))
120
- when 'match'
121
- section_builder.add_section(match_build(cc, indent: indent))
109
+ e.keys.each do |k|
110
+ cc = e.delete(k)
111
+ case k
112
+ when 'label'
113
+ section_builder.add_section(label_build(cc, indent: indent))
114
+ when 'worker'
115
+ section_builder.add_section(worker_build(cc, indent: indent))
116
+ when 'source'
117
+ section_builder.add_section(source_build(cc, indent: indent))
118
+ when 'filter'
119
+ section_builder.add_section(filter_build(cc, indent: indent))
120
+ when 'match'
121
+ section_builder.add_section(match_build(cc, indent: indent))
122
+ end
122
123
  end
123
124
  end
124
125
  end
@@ -14,6 +14,7 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
+ require 'fluent/env'
17
18
  require 'fluent/config/configure_proxy'
18
19
  require 'fluent/config/section'
19
20
  require 'fluent/config/error'
data/lib/fluent/daemon.rb CHANGED
@@ -5,9 +5,10 @@ here = File.dirname(__FILE__)
5
5
  $LOAD_PATH << File.expand_path(File.join(here, '..'))
6
6
 
7
7
  require 'serverengine'
8
+ require 'fluent/env'
8
9
  require 'fluent/supervisor'
9
10
 
10
11
  server_module = Fluent.const_get(ARGV[0])
11
12
  worker_module = Fluent.const_get(ARGV[1])
12
- params = JSON.parse(ARGV[2])
13
+ params = JSON.parse(ARGV[2], **Fluent::DEFAULT_JSON_PARSE_OPTIONS)
13
14
  ServerEngine::Daemon.run_server(server_module, worker_module) { Fluent::Supervisor.serverengine_config(params) }
data/lib/fluent/env.rb CHANGED
@@ -26,6 +26,7 @@ module Fluent
26
26
  DEFAULT_SOCKET_PATH = ENV['FLUENT_SOCKET'] || '/var/run/fluent/fluent.sock'
27
27
  DEFAULT_BACKUP_DIR = ENV['FLUENT_BACKUP_DIR'] || '/tmp/fluent'
28
28
  DEFAULT_OJ_OPTIONS = Fluent::OjOptions.load_env
29
+ DEFAULT_JSON_PARSE_OPTIONS = { allow_duplicate_key: true, allow_comments: true }.freeze
29
30
  DEFAULT_DIR_PERMISSION = 0755
30
31
  DEFAULT_FILE_PERMISSION = 0644
31
32
  INSTANCE_ID = ENV['FLUENT_INSTANCE_ID'] || SecureRandom.uuid
data/lib/fluent/event.rb CHANGED
@@ -309,6 +309,43 @@ module Fluent
309
309
  end
310
310
  end
311
311
 
312
+ class MetadataTimeEventStream < EventStream
313
+ def initialize(es)
314
+ @es = es
315
+ end
316
+
317
+ def empty?
318
+ @es.empty?
319
+ end
320
+
321
+ def dup
322
+ self.class.new(@es.dup)
323
+ end
324
+
325
+ def size
326
+ @es.size
327
+ end
328
+
329
+ def repeatable?
330
+ @es.repeatable?
331
+ end
332
+
333
+ def slice(index, num)
334
+ self.class.new(@es.slice(index, num))
335
+ end
336
+
337
+ def each(unpacker: nil, &block)
338
+ @es.each(unpacker: unpacker) do |time, record|
339
+ next if record.nil?
340
+
341
+ time = time[0] if time.is_a?(Array)
342
+ time = Fluent::EventTime.now if time.nil? || time.to_i == 0
343
+ block.call(time, record)
344
+ end
345
+ nil
346
+ end
347
+ end
348
+
312
349
  module ChunkMessagePackEventStreamer
313
350
  # chunk.extend(ChunkMessagePackEventStreamer)
314
351
  # => chunk.each{|time, record| ... }
data/lib/fluent/load.rb CHANGED
@@ -4,7 +4,6 @@ require 'time'
4
4
  require 'stringio'
5
5
  require 'fileutils'
6
6
  require 'json'
7
- require 'yajl'
8
7
  require 'uri'
9
8
  require 'msgpack'
10
9
  require 'strptime'