fluentd 1.19.4 → 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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +46 -0
  3. data/CHANGELOG.md +75 -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 +2 -2
  10. data/lib/fluent/compat/exec_util.rb +20 -5
  11. data/lib/fluent/config/literal_parser.rb +4 -3
  12. data/lib/fluent/config/yaml_parser/loader.rb +12 -1
  13. data/lib/fluent/config/yaml_parser/parser.rb +14 -13
  14. data/lib/fluent/event.rb +37 -0
  15. data/lib/fluent/load.rb +0 -1
  16. data/lib/fluent/log.rb +2 -2
  17. data/lib/fluent/plugin/buf_file.rb +2 -2
  18. data/lib/fluent/plugin/buf_file_single.rb +6 -2
  19. data/lib/fluent/plugin/buffer/file_chunk.rb +23 -10
  20. data/lib/fluent/plugin/buffer/file_single_chunk.rb +23 -10
  21. data/lib/fluent/plugin/buffer.rb +102 -36
  22. data/lib/fluent/plugin/formatter_out_file.rb +3 -4
  23. data/lib/fluent/plugin/in_exec.rb +6 -4
  24. data/lib/fluent/plugin/in_forward.rb +39 -29
  25. data/lib/fluent/plugin/in_object_space.rb +2 -2
  26. data/lib/fluent/plugin/in_syslog.rb +2 -2
  27. data/lib/fluent/plugin/in_tail/compatibility.rb +111 -0
  28. data/lib/fluent/plugin/in_tail/dir_watcher.rb +713 -0
  29. data/lib/fluent/plugin/in_tail/group_watch.rb +13 -13
  30. data/lib/fluent/plugin/in_tail/io_handler.rb +391 -0
  31. data/lib/fluent/plugin/in_tail/line_feeder.rb +230 -0
  32. data/lib/fluent/plugin/in_tail/stat_watcher.rb +52 -0
  33. data/lib/fluent/plugin/in_tail/tail_watcher.rb +276 -0
  34. data/lib/fluent/plugin/in_tail/worker_pool.rb +298 -0
  35. data/lib/fluent/plugin/in_tail.rb +324 -815
  36. data/lib/fluent/plugin/in_unix.rb +5 -3
  37. data/lib/fluent/plugin/out_exec_filter.rb +2 -2
  38. data/lib/fluent/plugin/out_file.rb +10 -4
  39. data/lib/fluent/plugin/out_forward.rb +8 -0
  40. data/lib/fluent/plugin/out_http.rb +0 -10
  41. data/lib/fluent/plugin/output.rb +49 -19
  42. data/lib/fluent/plugin/parser_csv.rb +7 -2
  43. data/lib/fluent/plugin/parser_json.rb +20 -12
  44. data/lib/fluent/plugin/parser_ltsv.rb +2 -4
  45. data/lib/fluent/plugin/parser_msgpack.rb +7 -6
  46. data/lib/fluent/plugin/parser_syslog.rb +52 -5
  47. data/lib/fluent/plugin/parser_tsv.rb +6 -1
  48. data/lib/fluent/plugin_helper/http_server/server.rb +29 -13
  49. data/lib/fluent/plugin_helper/http_server.rb +2 -1
  50. data/lib/fluent/root_agent.rb +1 -1
  51. data/lib/fluent/supervisor.rb +24 -5
  52. data/lib/fluent/system_config.rb +5 -2
  53. data/lib/fluent/time.rb +8 -7
  54. data/lib/fluent/version.rb +1 -1
  55. data/templates/new_gem/.gitignore +8 -0
  56. metadata +39 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cab6a9d7ebeaec3be80f888c3b787fb8810fbd9bb78aad85aa5a96192d33365e
4
- data.tar.gz: d80e36b87699060e8c895d9fb332dc521f0ba9cdbb0b0f4c80dd996003fdca50
3
+ metadata.gz: fa67a9199a9bcd73feb7dc286f4a1cb8347bd4d01d515561ceaf151671a9116e
4
+ data.tar.gz: ec7afdf8eea191d4badfb95361c3b41cfb35785c06dbacf3d0c0f65b89d734da
5
5
  SHA512:
6
- metadata.gz: 2ace1e9bde616fc42f958893bd9b8540f8047981f33bb7e22b8f595bf0296900125d8609976f45e2560f97b4cac40da5420adfa6d25589c0a04115093fb1aa40
7
- data.tar.gz: 7af35f61b6d84663e4871f410e9f4d32116d59e5953ecf32797fbb3331f5caefff699d1a55820967b4b45d183ac0980a9776284e4d29ed94828264d5648d7992
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,3 +1,78 @@
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
 
3
78
  ## Release v1.19.4 - 2026/09/28
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
 
@@ -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
 
@@ -17,7 +17,6 @@
17
17
  require 'stringio'
18
18
 
19
19
  require 'json'
20
- require 'yajl'
21
20
  require 'socket'
22
21
  require 'ripper'
23
22
 
@@ -236,8 +235,10 @@ EOM
236
235
 
237
236
  def scan_json(is_array)
238
237
  result = nil
239
- # Yajl does not raise ParseError for incomplete json string, like '[1', '{"h"', '{"h":' or '{"h1":1'
240
- # 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'.
241
242
 
242
243
  buffer = (is_array ? "[" : "{")
243
244
  line_buffer = ""
@@ -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
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'
data/lib/fluent/log.rb CHANGED
@@ -221,7 +221,7 @@ module Fluent
221
221
  if wid = get_worker_id(type)
222
222
  r['worker_id'] = wid
223
223
  end
224
- Yajl.dump(r)
224
+ JSON.generate(r)
225
225
  }
226
226
  end
227
227
 
@@ -554,7 +554,7 @@ module Fluent
554
554
  Thread.current[:last_repeated_stacktrace] = CachedLog.new(backtrace, time) if @suppress_repeated_stacktrace
555
555
  end
556
556
 
557
- puts Yajl.dump(r)
557
+ puts JSON.generate(r)
558
558
  end
559
559
 
560
560
  nil
@@ -174,7 +174,7 @@ module Fluent
174
174
  when :staged
175
175
  # unstaged chunk created at Buffer#write_step_by_step is identified as the staged chunk here because FileChunk#assume_chunk_state checks only the file name.
176
176
  # https://github.com/fluent/fluentd/blob/9d113029d4550ce576d8825bfa9612aa3e55bff0/lib/fluent/plugin/buffer.rb#L663
177
- # This case can happen when fluentd process is killed by signal or other reasons between creating unstaged chunks and changing them to staged mode in Buffer#write
177
+ # This case can happen when fluentd process is killed by signal or other reasons between creating unstaged chunks and enqueueing them (which renames them) in Buffer#write
178
178
  # these chunks(unstaged chunks) has shared the same metadata
179
179
  # So perform enqueue step again https://github.com/fluent/fluentd/blob/9d113029d4550ce576d8825bfa9612aa3e55bff0/lib/fluent/plugin/buffer.rb#L364
180
180
  if chunk_size_full?(chunk) || stage.key?(chunk.metadata)
@@ -234,7 +234,7 @@ module Fluent
234
234
  raise ArgumentError, "The chunk must be FileChunk, but it was #{chunk.class}."
235
235
  end
236
236
 
237
- backup_dir = File.join(backup_base_dir, 'buffer', safe_owner_id)
237
+ backup_dir = evacuate_dir
238
238
  FileUtils.mkdir_p(backup_dir, mode: system_config.dir_permission || Fluent::DEFAULT_DIR_PERMISSION) unless Dir.exist?(backup_dir)
239
239
 
240
240
  FileUtils.copy([chunk.path, chunk.meta_path], backup_dir)
@@ -193,7 +193,11 @@ module Fluent
193
193
 
194
194
  case chunk.state
195
195
  when :staged
196
- stage[chunk.metadata] = chunk
196
+ if chunk_size_full?(chunk) || stage.key?(chunk.metadata)
197
+ queue << chunk.enqueued!
198
+ else
199
+ stage[chunk.metadata] = chunk
200
+ end
197
201
  when :queued
198
202
  queue << chunk
199
203
  end
@@ -246,7 +250,7 @@ module Fluent
246
250
  raise ArgumentError, "The chunk must be FileSingleChunk, but it was #{chunk.class}."
247
251
  end
248
252
 
249
- backup_dir = File.join(backup_base_dir, 'buffer', safe_owner_id)
253
+ backup_dir = evacuate_dir
250
254
  FileUtils.mkdir_p(backup_dir, mode: system_config.dir_permission || Fluent::DEFAULT_DIR_PERMISSION) unless Dir.exist?(backup_dir)
251
255
 
252
256
  FileUtils.copy(chunk.path, backup_dir)
@@ -100,8 +100,14 @@ module Fluent
100
100
  end
101
101
 
102
102
  def enqueued!
103
- return unless self.staged?
103
+ return self unless self.writable?
104
104
 
105
+ super
106
+ rename_to_queued_path
107
+ self
108
+ end
109
+
110
+ def rename_to_queued_path
105
111
  new_chunk_path = self.class.generate_queued_chunk_path(@path, @unique_id)
106
112
  new_meta_path = new_chunk_path + '.meta'
107
113
 
@@ -139,9 +145,8 @@ module Fluent
139
145
 
140
146
  @path = new_chunk_path
141
147
  @meta_path = new_meta_path
142
-
143
- super
144
148
  end
149
+ private :rename_to_queued_path
145
150
 
146
151
  def close
147
152
  super
@@ -266,19 +271,27 @@ module Fluent
266
271
 
267
272
  def file_rename(file, old_path, new_path, callback=nil)
268
273
  pos = file.pos
274
+ setup = ->(f) {
275
+ f.set_encoding(Encoding::ASCII_8BIT)
276
+ f.sync = true
277
+ f.binmode
278
+ f.pos = pos
279
+ callback.call(f) if callback
280
+ }
269
281
  if Fluent.windows?
270
282
  file.close
271
- File.rename(old_path, new_path)
272
- file = File.open(new_path, 'rb', @permission)
283
+ renamed = false
284
+ begin
285
+ File.rename(old_path, new_path)
286
+ renamed = true
287
+ ensure
288
+ setup.call(File.open(renamed ? new_path : old_path, 'rb', @permission))
289
+ end
273
290
  else
274
291
  File.rename(old_path, new_path)
275
292
  file.reopen(new_path, 'rb')
293
+ setup.call(file)
276
294
  end
277
- file.set_encoding(Encoding::ASCII_8BIT)
278
- file.sync = true
279
- file.binmode
280
- file.pos = pos
281
- callback.call(file) if callback
282
295
  end
283
296
 
284
297
  def create_new_chunk(path, perm)
@@ -93,8 +93,14 @@ module Fluent
93
93
  end
94
94
 
95
95
  def enqueued!
96
- return unless self.staged?
96
+ return self unless self.writable?
97
97
 
98
+ super
99
+ rename_to_queued_path
100
+ self
101
+ end
102
+
103
+ def rename_to_queued_path
98
104
  new_chunk_path = self.class.generate_queued_chunk_path(@path, @unique_id)
99
105
 
100
106
  begin
@@ -114,9 +120,8 @@ module Fluent
114
120
  end
115
121
 
116
122
  @path = new_chunk_path
117
-
118
- super
119
123
  end
124
+ private :rename_to_queued_path
120
125
 
121
126
  def close
122
127
  super
@@ -225,19 +230,27 @@ module Fluent
225
230
 
226
231
  def file_rename(file, old_path, new_path, callback = nil)
227
232
  pos = file.pos
233
+ setup = ->(f) {
234
+ f.set_encoding(Encoding::ASCII_8BIT)
235
+ f.sync = true
236
+ f.binmode
237
+ f.pos = pos
238
+ callback.call(f) if callback
239
+ }
228
240
  if Fluent.windows?
229
241
  file.close
230
- File.rename(old_path, new_path)
231
- file = File.open(new_path, 'rb', @permission)
242
+ renamed = false
243
+ begin
244
+ File.rename(old_path, new_path)
245
+ renamed = true
246
+ ensure
247
+ setup.call(File.open(renamed ? new_path : old_path, 'rb', @permission))
248
+ end
232
249
  else
233
250
  File.rename(old_path, new_path)
234
251
  file.reopen(new_path, 'rb')
252
+ setup.call(file)
235
253
  end
236
- file.set_encoding(Encoding::ASCII_8BIT)
237
- file.sync = true
238
- file.binmode
239
- file.pos = pos
240
- callback.call(file) if callback
241
254
  end
242
255
 
243
256
  ESCAPE_REGEXP = /[^-_.a-zA-Z0-9]/n