Skip to content

out_file: add logs rotation feature#11352

Open
SagiROosto wants to merge 2 commits intofluent:masterfrom
AnyVisionltd:out_file-rotation
Open

out_file: add logs rotation feature#11352
SagiROosto wants to merge 2 commits intofluent:masterfrom
AnyVisionltd:out_file-rotation

Conversation

@SagiROosto
Copy link
Copy Markdown

@SagiROosto SagiROosto commented Jan 7, 2026

This PR present a new rotation feature to out_file. This will answer #7572 question and solve #7541 suggestion.
This feature is highly required in bare-metal or physical machines where you have finite and limited storage.
The suggested code disables the rotation feature by default to keep backward compatibility without affecting existing plugin users.

(this replaces closed #11110 PR)


Enter [N/A] in the box, if an item is not applicable to your change.

Testing
Before we can approve your change; please submit the following in a comment:

  • Example configuration file for the change
  • Debug log output from testing the change
  • Attached Valgrind output that shows no leaks or memory corruption was found

If this is a change to packaging of containers or native binaries then please confirm it works for all targets.

  • Run local packaging test showing all targets (including any new ones) build.
  • Set ok-package-test label to test for all targets (requires maintainer to do).

Documentation

  • Documentation required for this feature

Backporting

  • Backport to latest stable release.

Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.

Summary by CodeRabbit

  • New Features

    • Adds size-based file rotation with timestamped names, max-files pruning, optional streaming gzip compression, and per-file size tracking with thread-safe writes.
    • Rotation integrated across initialization, writes, flushes and shutdown; improved error handling, logging and directory/path support.
    • Rotation works with all output formats (json, csv, ltsv, plain, template, msgpack).
  • Tests

    • Adds a large cross-platform runtime test suite covering rotation behaviors, gzip, exact-chunk cases, formats, path/mkdir, delimiters and multithreaded scenarios.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 7, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds size-based file rotation with optional streaming gzip compression to the file output plugin, plus per-file size tracking and locking, rotation/retention lifecycle, config schema extensions, and a comprehensive cross-platform runtime test suite for rotation behaviors and formats.

Changes

Cohort / File(s) Summary
File rotation & compression subsystem
plugins/out_file/file.c
Introduces rotation config (files_rotation, max_size, max_files, gzip), rotation state (struct file_file_size, file_sizes, list_lock), helpers for timestamps, gzip header/footer and compression, rotation lifecycle (rotate_file, cleanup_old_files, filename validation), per-entry size accounting and locking; integrates rotation into init/flush/exit paths and error logging.
Runtime tests CMake
tests/runtime/CMakeLists.txt
Adds new runtime test entry tests/runtime/out_file_logrotate.c under the FLB_OUT_FILE test set.
Rotation test suite
tests/runtime/out_file_logrotate.c
Adds extensive cross-platform tests and helpers covering basic rotation, gzip (including exact-chunk), max_files retention/validation, multiple formats (csv, ltsv, plain, msgpack, template), path/mkdir/delimiters, CSV header handling, and a multithreaded stress test; exposes numerous test functions, struct thread_data, and TEST_LIST.

Sequence Diagram(s)

sequenceDiagram
    participant FluentBit
    participant cb_file_flush
    participant SizeRegistry
    participant Rotation
    participant Gzip
    participant Filesystem

    FluentBit->>cb_file_flush: flush(records, filename)
    cb_file_flush->>SizeRegistry: find/create entry(filename) & lock
    cb_file_flush->>Filesystem: ensure directory & write formatted records
    cb_file_flush->>SizeRegistry: increment entry.size
    alt rotation enabled and entry.size >= max_size
        cb_file_flush->>Rotation: rotate_file(filename, entry)
        Rotation->>Filesystem: rename current -> filename.timestamp
        alt gzip enabled
            Rotation->>Gzip: gzip_compress_file(timestamped -> .gz)
            Gzip->>Filesystem: write .gz and remove original
        end
        Rotation->>Filesystem: cleanup_old_files(directory, base_filename)
        Rotation->>SizeRegistry: reset entry.size
    end
    cb_file_flush->>SizeRegistry: unlock
    cb_file_flush->>FluentBit: return status
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Poem

🐇 I nibble bytes and stamp the date,

I roll the logs before they're late,
I zip the crumbs with a hopping cheer,
I prune old trails so burrows clear,
Small paws, neat rolls — a rabbit's cheer!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'out_file: add logs rotation feature' clearly summarizes the main change: adding a rotation feature to the out_file plugin.
Linked Issues check ✅ Passed The PR implements all coding objectives from #11110: log rotation capability, gzip compression, configurable max_size/max_files, format support, directory creation, and comprehensive runtime tests.
Out of Scope Changes check ✅ Passed All changes are within scope: rotation implementation in out_file plugin, test infrastructure addition, and CMakeLists test registration directly support the linked issue requirements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 628922c6a1

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread plugins/out_file/file.c Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @plugins/out_file/file.c:
- Around line 222-238: The error paths after flb_lock_init(&ctx->list_lock) do
not destroy the lock before freeing ctx; update the failure branches for
flb_output_config_map_set and the ctx->max_files validation to call
flb_lock_destroy(&ctx->list_lock) (or the appropriate destroy function) prior to
flb_free(ctx) and returning -1 so that the lock is cleaned up; locate these
spots around the mk_list_init, flb_lock_init, flb_output_config_map_set, and
flb_plg_error calls and add the destroy call in both error branches.
🧹 Nitpick comments (2)
tests/runtime/out_file_logrotate.c (2)

1040-1041: Array oversized for declared usage.

pthread_t threads[8] is declared but only num_threads = 4 threads are used. Consider sizing the array to match actual usage or using a constant.

♻️ Suggested fix
-  pthread_t threads[8];
-  struct thread_data thread_data[8];
+  pthread_t threads[4];
+  struct thread_data thread_data[4];

1160-1164: Remove unused variable.

The timestamp variable is generated but never used in this test function.

♻️ Suggested fix
-  time_t now = time(NULL);
-  struct tm *tm_info = localtime(&now);
-  char timestamp[32];
-
-  strftime(timestamp, sizeof(timestamp), "%Y%m%d_%H%M%S", tm_info);
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e19e07e and 628922c.

📒 Files selected for processing (3)
  • plugins/out_file/file.c
  • tests/runtime/CMakeLists.txt
  • tests/runtime/out_file_logrotate.c
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-08-31T12:46:11.940Z
Learnt from: ThomasDevoogdt
Repo: fluent/fluent-bit PR: 9277
File: .github/workflows/pr-compile-check.yaml:147-151
Timestamp: 2025-08-31T12:46:11.940Z
Learning: In fluent-bit CMakeLists.txt, the system library preference flags are defined as FLB_PREFER_SYSTEM_LIB_ZSTD and FLB_PREFER_SYSTEM_LIB_KAFKA with the FLB_ prefix.

Applied to files:

  • tests/runtime/CMakeLists.txt
📚 Learning: 2025-08-29T06:25:27.250Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:93-107
Timestamp: 2025-08-29T06:25:27.250Z
Learning: In Fluent Bit, ZSTD compression is enabled by default and is treated as a core dependency, not requiring conditional compilation guards like `#ifdef FLB_HAVE_ZSTD`. Unlike some other optional components such as ARROW/PARQUET (which use `#ifdef FLB_HAVE_ARROW` guards), ZSTD support is always available and doesn't need build-time conditionals. ZSTD headers are included directly without guards across multiple plugins and core components.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:25:02.561Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:7-7
Timestamp: 2025-08-29T06:25:02.561Z
Learning: In Fluent Bit, ZSTD (zstandard) compression library is bundled directly in the source tree at `lib/zstd-1.5.7` and is built unconditionally as a static library. Unlike optional external dependencies, ZSTD does not use conditional compilation guards like `FLB_HAVE_ZSTD` and is always available. Headers like `<fluent-bit/flb_zstd.h>` can be included directly without guards.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:24:26.170Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:39-42
Timestamp: 2025-08-29T06:24:26.170Z
Learning: In Fluent Bit, ZSTD compression support is enabled by default and does not require conditional compilation guards (like #ifdef FLB_HAVE_ZSTD) around ZSTD-related code declarations and implementations.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:24:55.855Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: src/aws/flb_aws_compress.c:52-56
Timestamp: 2025-08-29T06:24:55.855Z
Learning: ZSTD compression is always available in Fluent Bit and does not require conditional compilation guards. Unlike Arrow/Parquet which use #ifdef FLB_HAVE_ARROW guards, ZSTD is built unconditionally with flb_zstd.c included directly in src/CMakeLists.txt and a bundled ZSTD library at lib/zstd-1.5.7/.

Applied to files:

  • plugins/out_file/file.c
🧬 Code graph analysis (2)
tests/runtime/out_file_logrotate.c (3)
include/fluent-bit/flb_mem.h (1)
  • flb_free (126-128)
src/flb_lib.c (9)
  • flb_create (143-225)
  • flb_service_set (652-678)
  • flb_input (266-276)
  • flb_output (279-289)
  • flb_output_set (520-551)
  • flb_start (983-994)
  • flb_lib_push (843-870)
  • flb_stop (1011-1055)
  • flb_destroy (228-263)
plugins/in_head/in_head.c (1)
  • read_bytes (87-106)
plugins/out_file/file.c (6)
include/fluent-bit/flb_mem.h (1)
  • flb_calloc (84-96)
src/flb_lock.c (4)
  • flb_lock_init (6-17)
  • flb_lock_acquire (32-65)
  • flb_lock_release (67-100)
  • flb_lock_destroy (19-30)
include/fluent-bit/flb_output.h (1)
  • flb_output_config_map_set (1306-1333)
src/flb_pack.c (1)
  • flb_msgpack_to_json_str (1459-1500)
src/flb_sds.c (2)
  • flb_sds_create (78-90)
  • flb_sds_destroy (389-399)
src/flb_log_event_decoder.c (2)
  • flb_log_event_decoder_init (103-120)
  • flb_log_event_decoder_next (309-456)
🪛 ast-grep (0.40.3)
tests/runtime/out_file_logrotate.c

[warning] 586-586: A check is done with stat and then the file is used. There is no guarantee that the status of the file has not changed since the call to stat which may allow attackers to bypass permission checks.
Context: fopen
Note: [CWE-367]: Time-of-check Time-of-use (TOCTOU) Race Condition [REFERENCES]
- https://wiki.sei.cmu.edu/confluence/display/c/FIO45-C.+Avoid+TOCTOU+race+conditions+while+accessing+files

(file-stat-before-action-c)

🔇 Additional comments (20)
tests/runtime/out_file_logrotate.c (9)

1-34: Well-structured test file with comprehensive coverage.

Good job setting up cross-platform support with appropriate macros for Windows/POSIX and including the necessary test data. The test function declarations provide clear visibility into the test coverage.


80-203: Robust cross-platform directory cleanup implementation.

The helper properly handles both Windows and POSIX platforms, skips special entries, and continues cleanup even on partial failures.


206-248: LGTM!

The file counting helper is correctly implemented for both platforms.


254-315: LGTM!

The polling helper is well-implemented with proper resource cleanup on each iteration.


318-350: LGTM!

The file reading helper properly handles error cases and memory cleanup. The TOCTOU concern (stat before fopen) is acceptable for test code where files are under the test's control.


353-670: Comprehensive format tests with consistent structure.

All format tests follow a good pattern: setup, configure, push data, verify content, cleanup. The assertions check format-specific characteristics (CSV commas, LTSV colons, plain JSON, msgpack binary, template substitution).


1358-1403: Good negative test for configuration validation.

Testing that flb_start fails with invalid max_files values (0 and -1) properly validates the configuration checks in the plugin init.


1405-1483: Excellent edge case coverage for gzip compression.

Testing the exact 64KB chunk boundary ensures the streaming gzip implementation handles the edge case where file size equals the chunk size.


1101-1102: The wait_for_file() function is correctly available. It is defined as a static inline function in tests/runtime/flb_tests_runtime.h.in (lines 29-32) and accessible through the #include "flb_tests_runtime.h" header at line 3 of the file. The function call at line 1101 is valid.

plugins/out_file/file.c (10)

65-75: Well-designed per-file tracking structure.

The file_file_size structure with per-entry locks enables fine-grained concurrent access to different output files.


118-200: Good security measure for tag sanitization.

The function properly prevents path traversal attacks by collapsing ".." and "." segments, sanitizing unsafe characters, and handling edge cases like empty tags.


706-880: Solid streaming gzip implementation.

The function correctly handles:

  • Streaming compression with bounded memory usage
  • Proper gzip header/footer with CRC32
  • The edge case where file size is exactly a multiple of chunk size (lines 819-843)
  • Resource cleanup on all paths

882-969: Well-structured rotation logic with proper cleanup.

The function properly handles the rotation workflow: rename, optional gzip compression, cleanup of failed gzip, and size reset. The lock contract is clearly documented.


1155-1173: Bubble sort is adequate for expected file counts.

The O(n²) sorting algorithm is acceptable here since max_files is typically small (default 7). For very large retention counts, consider using qsort.


1262-1296: Correct hand-over-hand locking pattern.

The locking sequence is properly implemented:

  1. Acquire list_lock
  2. Find/create entry
  3. Acquire entry->lock
  4. Release list_lock
  5. Perform file operations under entry->lock
  6. Release entry->lock

This allows concurrent operations on different files while preventing races on the same file.


1562-1570: LGTM!

The cleanup section properly frees allocated memory for directory and base_filename on all exit paths.


1572-1601: Proper cleanup of all resources.

The exit handler correctly:

  1. Acquires list_lock
  2. Iterates and destroys each entry's lock and filename
  3. Releases and destroys list_lock
  4. Frees the context

1639-1654: Good configuration defaults.

The rotation feature is disabled by default (files_rotation = false) preserving backward compatibility. The defaults (100MB max size, 7 files, gzip enabled) are sensible for typical log rotation scenarios.


1658-1668: Plugin configuration is appropriate.

With .workers = 1, the plugin uses a single worker thread. The per-file locking still provides value when the same plugin instance writes to multiple files (based on tag).

tests/runtime/CMakeLists.txt (1)

235-238: Correctly integrated into the build system.

The new test file is properly added to the Linux-only test block using the existing FLB_OUT_FILE flag, ensuring it builds alongside the existing out_file tests.

Comment thread plugins/out_file/file.c Outdated
Copy link
Copy Markdown
Contributor

@cosmo0920 cosmo0920 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to use 4-spaces width of indentations and also need to add a newline before else keyword.
We need to fix those kind of style errors at first.

Comment thread plugins/out_file/file.c Outdated
Comment thread plugins/out_file/file.c
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In @plugins/out_file/file.c:
- Around line 1249-1262: The flush callback uses plain returns; replace the
plain returns inside the output plugin (e.g., the two occurrences returning
FLB_RETRY after allocating out_file and sanitized_tag) with the
FLB_OUTPUT_RETURN(...) macro so the engine is signaled correctly; update the two
statements that currently read "return FLB_RETRY;" (one after out_file
allocation failure and one after sanitized_tag allocation failure) to use
FLB_OUTPUT_RETURN(FLB_RETRY) and keep existing resource cleanup
(flb_free(out_file), etc.) before invoking the macro.

In @tests/runtime/out_file_logrotate.c:
- Around line 1013-1032: thread_worker contains a typo: it references
*ta->success instead of the correct *data->success; update the error path inside
thread_worker (the block after the flb_lib_push check) to use data->success from
struct thread_data and ensure you lock/unlock data->mutex (already referenced)
correctly so compilation succeeds and the test sets the success flag properly.
- Around line 319-352: In read_file_content replace the typo "*t_size = size;"
with "*out_size = size;" so the function assigns the file size to the provided
out_size parameter (reference: function read_file_content and parameter
out_size); ensure the assignment uses the exact parameter name out_size.
- Around line 587-602: The msgpack verification block contains two unclosed /*
... */ comments causing compilation errors; close the first comment (the
"Msgpack files should not be readable as text" block) by adding "*/" before the
line with fp = fopen(logfile, "rb"); and close the second comment (the "sgpack
typically starts with..." block) by adding "*/" just before the
TEST_CHECK(first_bytes[0] != '{' && first_bytes[0] != '['); line so the fp =
fopen(...) and TEST_CHECK(...) statements are outside the comment blocks.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 628922c and fb54c87.

📒 Files selected for processing (4)
  • build/.empty
  • plugins/out_file/file.c
  • tests/runtime/CMakeLists.txt
  • tests/runtime/out_file_logrotate.c
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/runtime/CMakeLists.txt
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-08-29T06:25:27.250Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:93-107
Timestamp: 2025-08-29T06:25:27.250Z
Learning: In Fluent Bit, ZSTD compression is enabled by default and is treated as a core dependency, not requiring conditional compilation guards like `#ifdef FLB_HAVE_ZSTD`. Unlike some other optional components such as ARROW/PARQUET (which use `#ifdef FLB_HAVE_ARROW` guards), ZSTD support is always available and doesn't need build-time conditionals. ZSTD headers are included directly without guards across multiple plugins and core components.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:25:02.561Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:7-7
Timestamp: 2025-08-29T06:25:02.561Z
Learning: In Fluent Bit, ZSTD (zstandard) compression library is bundled directly in the source tree at `lib/zstd-1.5.7` and is built unconditionally as a static library. Unlike optional external dependencies, ZSTD does not use conditional compilation guards like `FLB_HAVE_ZSTD` and is always available. Headers like `<fluent-bit/flb_zstd.h>` can be included directly without guards.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:24:26.170Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:39-42
Timestamp: 2025-08-29T06:24:26.170Z
Learning: In Fluent Bit, ZSTD compression support is enabled by default and does not require conditional compilation guards (like #ifdef FLB_HAVE_ZSTD) around ZSTD-related code declarations and implementations.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:24:55.855Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: src/aws/flb_aws_compress.c:52-56
Timestamp: 2025-08-29T06:24:55.855Z
Learning: ZSTD compression is always available in Fluent Bit and does not require conditional compilation guards. Unlike Arrow/Parquet which use #ifdef FLB_HAVE_ARROW guards, ZSTD is built unconditionally with flb_zstd.c included directly in src/CMakeLists.txt and a bundled ZSTD library at lib/zstd-1.5.7/.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:25:27.250Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:93-107
Timestamp: 2025-08-29T06:25:27.250Z
Learning: In Fluent Bit, ZSTD compression is enabled by default and is treated as a core dependency, not requiring conditional compilation guards like `#ifdef FLB_HAVE_ZSTD`. Unlike some other optional components, ZSTD support is always available and doesn't need build-time conditionals.

Applied to files:

  • plugins/out_file/file.c
🧬 Code graph analysis (2)
plugins/out_file/file.c (5)
src/flb_lock.c (4)
  • flb_lock_init (6-17)
  • flb_lock_acquire (32-65)
  • flb_lock_release (67-100)
  • flb_lock_destroy (19-30)
include/fluent-bit/flb_output.h (1)
  • flb_output_config_map_set (1306-1333)
src/flb_output.c (1)
  • flb_output_set_context (1602-1605)
lib/cmetrics/src/cmt_decode_msgpack.c (1)
  • cmt_decode_msgpack_create (1450-1496)
src/flb_log_event_decoder.c (1)
  • flb_log_event_decoder_init (103-120)
tests/runtime/out_file_logrotate.c (2)
include/fluent-bit/flb_mem.h (1)
  • flb_free (126-128)
src/flb_lib.c (10)
  • flb_create (143-225)
  • flb_service_set (652-678)
  • flb_input (266-276)
  • flb_input_set (305-335)
  • flb_output (279-289)
  • flb_output_set (520-551)
  • flb_start (983-994)
  • flb_lib_push (843-870)
  • flb_stop (1011-1055)
  • flb_destroy (228-263)
🪛 Cppcheck (2.19.0)
plugins/out_file/file.c

[error] 497-497: Unmatched '{'. Configuration

(syntaxError)


[error] 497-497: Unmatched '{'. Configuration

(syntaxError)


[error] 497-497: Unmatched '{'. Configuration

(syntaxError)


[error] 497-497: Unmatched '{'. Configuration

(syntaxError)


[error] 497-497: Unmatched '{'. Configuration

(syntaxError)


[error] 497-497: Unmatched '{'. Configuration

(syntaxError)


[error] 497-497: Unmatched '{'. Configuration

(syntaxError)


[error] 497-497: Unmatched '{'. Configuration

(syntaxError)


[error] 497-497: Unmatched '{'. Configuration

(syntaxError)


[error] 497-497: Unmatched '{'. Configuration

(syntaxError)


[error] 497-497: Unmatched '{'. Configuration

(syntaxError)


[error] 497-497: Unmatched '{'. Configuration

(syntaxError)

tests/runtime/out_file_logrotate.c

[error] 538-538: Unmatched '{'. Configuration

(syntaxError)


[error] 538-538: Unmatched '{'. Configuration

(syntaxError)


[error] 538-538: Unmatched '{'. Configuration

(syntaxError)


[error] 538-538: Unmatched '{'. Configuration

(syntaxError)


[error] 538-538: Unmatched '{'. Configuration

(syntaxError)


[error] 538-538: Unmatched '{'. Configuration

(syntaxError)


[error] 538-538: Unmatched '{'. Configuration

(syntaxError)


[error] 538-538: Unmatched '{'. Configuration

(syntaxError)


[error] 538-538: Unmatched '{'. Configuration

(syntaxError)


[error] 538-538: Unmatched '{'. Configuration

(syntaxError)


[error] 538-538: Unmatched '{'. Configuration

(syntaxError)


[error] 538-538: Unmatched '{'. Configuration

(syntaxError)

🔇 Additional comments (1)
plugins/out_file/file.c (1)

1343-1350: Memory leak of directory on allocation failure of base_filename.

If base_filename allocation fails at line 1344, the code releases the entry lock and jumps to cleanup, but directory was already allocated at line 1333 and will be freed in cleanup at line 1596-1598. Wait, let me re-check...

Actually, looking at the cleanup section (lines 1595-1607), directory and base_filename are freed if non-NULL. So this is handled correctly since the goto goes to cleanup.

Comment thread plugins/out_file/file.c Outdated
Comment thread tests/runtime/out_file_logrotate.c
Comment thread tests/runtime/out_file_logrotate.c Outdated
Comment thread tests/runtime/out_file_logrotate.c Outdated
@SagiROosto SagiROosto marked this pull request as draft January 11, 2026 12:58
@SagiROosto SagiROosto marked this pull request as ready for review January 11, 2026 13:13
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @tests/runtime/out_file_logrotate.c:
- Around line 329-362: The read_file_content function has a TOCTOU between
stat() and fopen(); fix it by opening the file first with open() to obtain a
file descriptor, call fstat() on that fd to get the size, then use fdopen() (or
read from the fd directly) to read the contents; ensure you replace
stat(filename, &st) and fopen(filename, "rb") with this open->fstat->fdopen
sequence, handle errors by closing the fd and freeing buffers on failure, and
set *out_size and return the allocated buffer as before.
🧹 Nitpick comments (1)
plugins/out_file/file.c (1)

1463-1468: Consider making fsync optional for performance.

The code uses fsync() after every flush to ensure data is written to disk before updating the size counter (lines 1463-1468, 1510-1515, 1631-1636). While this ensures data durability, it can significantly impact performance in high-throughput scenarios.

Since the size counter is used only for rotation decisions and not for data integrity, consider:

  1. Making fsync optional via a configuration parameter (e.g., fsync_on_flush)
  2. Using fflush() alone for size tracking (already ensures buffered data is written)
  3. Accepting that size tracking may be slightly behind actual file size in some cases

The current approach prioritizes correctness over performance, which is reasonable for the default behavior.

Also applies to: 1510-1515, 1631-1636

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fb54c87 and 637cd27.

📒 Files selected for processing (3)
  • plugins/out_file/file.c
  • tests/runtime/CMakeLists.txt
  • tests/runtime/out_file_logrotate.c
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/runtime/CMakeLists.txt
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-08-29T06:25:02.561Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:7-7
Timestamp: 2025-08-29T06:25:02.561Z
Learning: In Fluent Bit, ZSTD (zstandard) compression library is bundled directly in the source tree at `lib/zstd-1.5.7` and is built unconditionally as a static library. Unlike optional external dependencies, ZSTD does not use conditional compilation guards like `FLB_HAVE_ZSTD` and is always available. Headers like `<fluent-bit/flb_zstd.h>` can be included directly without guards.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:25:27.250Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:93-107
Timestamp: 2025-08-29T06:25:27.250Z
Learning: In Fluent Bit, ZSTD compression is enabled by default and is treated as a core dependency, not requiring conditional compilation guards like `#ifdef FLB_HAVE_ZSTD`. Unlike some other optional components such as ARROW/PARQUET (which use `#ifdef FLB_HAVE_ARROW` guards), ZSTD support is always available and doesn't need build-time conditionals. ZSTD headers are included directly without guards across multiple plugins and core components.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:24:26.170Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:39-42
Timestamp: 2025-08-29T06:24:26.170Z
Learning: In Fluent Bit, ZSTD compression support is enabled by default and does not require conditional compilation guards (like #ifdef FLB_HAVE_ZSTD) around ZSTD-related code declarations and implementations.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:24:55.855Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: src/aws/flb_aws_compress.c:52-56
Timestamp: 2025-08-29T06:24:55.855Z
Learning: ZSTD compression is always available in Fluent Bit and does not require conditional compilation guards. Unlike Arrow/Parquet which use #ifdef FLB_HAVE_ARROW guards, ZSTD is built unconditionally with flb_zstd.c included directly in src/CMakeLists.txt and a bundled ZSTD library at lib/zstd-1.5.7/.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:25:27.250Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:93-107
Timestamp: 2025-08-29T06:25:27.250Z
Learning: In Fluent Bit, ZSTD compression is enabled by default and is treated as a core dependency, not requiring conditional compilation guards like `#ifdef FLB_HAVE_ZSTD`. Unlike some other optional components, ZSTD support is always available and doesn't need build-time conditionals.

Applied to files:

  • plugins/out_file/file.c
🧬 Code graph analysis (2)
plugins/out_file/file.c (5)
src/flb_lock.c (4)
  • flb_lock_init (6-17)
  • flb_lock_acquire (32-65)
  • flb_lock_release (67-100)
  • flb_lock_destroy (19-30)
include/fluent-bit/flb_output.h (1)
  • flb_output_config_map_set (1306-1333)
include/fluent-bit/flb_mem.h (1)
  • flb_free (126-128)
src/flb_sds.c (1)
  • flb_sds_create (78-90)
src/flb_log_event_decoder.c (1)
  • flb_log_event_decoder_destroy (151-178)
tests/runtime/out_file_logrotate.c (2)
include/fluent-bit/flb_mem.h (1)
  • flb_free (126-128)
src/flb_lib.c (6)
  • flb_create (143-225)
  • flb_service_set (652-678)
  • flb_input (266-276)
  • flb_lib_push (843-870)
  • flb_stop (1011-1055)
  • flb_destroy (228-263)
🪛 ast-grep (0.40.4)
tests/runtime/out_file_logrotate.c

[warning] 603-603: A check is done with stat and then the file is used. There is no guarantee that the status of the file has not changed since the call to stat which may allow attackers to bypass permission checks.
Context: fopen
Note: [CWE-367]: Time-of-check Time-of-use (TOCTOU) Race Condition [REFERENCES]
- https://wiki.sei.cmu.edu/confluence/display/c/FIO45-C.+Avoid+TOCTOU+race+conditions+while+accessing+files

(file-stat-before-action-c)

🔇 Additional comments (11)
plugins/out_file/file.c (7)

228-230: LGTM! Proper initialization of rotation structures.

The rotation subsystem is correctly initialized with both the file_sizes list and the list_lock mutex, establishing the foundation for thread-safe per-file tracking.


238-244: Good validation: max_files must be positive when rotation is enabled.

This validation prevents misconfigurations that could lead to unexpected behavior. The error message is clear and actionable.


634-691: Well-structured entry management with proper error handling.

Both helper functions follow best practices:

  • Caller holds list_lock (documented clearly)
  • create_file_size_entry has complete error handling with cleanup
  • Lock initialization failure is properly checked
  • Dynamic string (flb_sds_t) is used correctly

851-882: Excellent edge-case handling for exact chunk-size files.

This code correctly handles the scenario where a file's size is an exact multiple of GZIP_CHUNK_SIZE. When fread returns 0, the loop exits without calling deflate with Z_FINISH, so this block ensures the stream is properly finalized.


1199-1217: Bubble sort is acceptable for typical rotation file counts.

While O(n²) complexity is generally suboptimal, it's reasonable here because:

  • File counts are typically small (max_files defaults to 7)
  • Sorting overhead is negligible compared to I/O operations
  • Code simplicity is prioritized over micro-optimization

1314-1409: Excellent hand-over-hand locking pattern for thread safety.

The implementation correctly:

  1. Acquires list_lock to search/create entry
  2. Acquires entry->lock before any file operations
  3. Releases list_lock (minimizing contention)
  4. Performs rotation logic while holding entry->lock
  5. Properly releases locks on all error paths

This design allows multiple threads to work on different files concurrently while protecting per-file operations.


740-919: The streaming gzip compression implementation correctly uses the miniz API with proper parameters and error handling. The deflateInit2() call with Z_DEFAULT_COMPRESSION, Z_DEFLATED, -Z_DEFAULT_WINDOW_BITS, 9, Z_DEFAULT_STRATEGY matches the established pattern in src/flb_gzip.c. The buffer sizing with mz_compressBound(), streaming with appropriate flush modes (Z_NO_FLUSH and Z_FINISH), and edge case handling for files that are exact multiples of the chunk size (lines 851-882) are all implemented correctly.

tests/runtime/out_file_logrotate.c (4)

365-425: Format tests follow good testing patterns.

The CSV format test correctly:

  • Sets up isolated test environment
  • Configures rotation with format-specific options
  • Writes sample data and allows flush time
  • Validates format-specific characteristics (commas, timestamp)
  • Cleans up test artifacts

This pattern is consistently applied across all format tests.


1444-1523: Excellent edge-case test for exact chunk-size compression.

This test specifically exercises the code path at lines 851-882 in file.c, where a file's size is an exact multiple of GZIP_CHUNK_SIZE (64KB). This ensures the streaming compression correctly finalizes the stream even when the last fread returns 0.

The test:

  1. Creates exactly 64KB of data
  2. Triggers rotation
  3. Verifies gzipped output exists

This validates the fix for a subtle bug that could leave compressed files incomplete.


1058-1177: Multithreaded test validates concurrent rotation safety.

This test effectively validates the thread-safety of the rotation implementation by:

  1. Creating 4 concurrent threads writing to the same output
  2. Using shared mutex to protect the success flag
  3. Verifying all data was written correctly
  4. Checking file content integrity

The test correctly initializes the mutex with PTHREAD_MUTEX_INITIALIZER (line 1069) and destroys it with pthread_mutex_destroy (line 1173).

One minor note: The mutex is used only for the success flag. The actual thread-safety of the file plugin is tested implicitly through concurrent flb_lib_push calls, which exercise the hand-over-hand locking in cb_file_flush.


36-72: Comprehensive test suite covering all rotation features.

The test list includes 16 tests that thoroughly validate:

  • Core rotation functionality (basic, gzip, max_files)
  • All output formats (csv, ltsv, plain, msgpack, template)
  • Configuration options (path, mkdir, delimiters, column names)
  • Edge cases (exact chunk size, invalid config)
  • Concurrent access (multithreaded)

This provides excellent coverage of the new rotation feature across multiple dimensions.

Comment thread tests/runtime/out_file_logrotate.c
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 637cd2703e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread plugins/out_file/file.c
Comment thread plugins/out_file/file.c Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
plugins/out_file/file.c (2)

1147-1154: Handle flb_strdup failure to avoid NULL entries in files array.

If flb_strdup fails (returns NULL), the index i is still incremented but files[i] will be NULL. This is handled defensively in the sort and delete loops, but for correctness it would be better to only increment i on successful allocation.

Suggested fix
         if (is_valid_rotation_filename(findData.cFileName, pattern) &&
             i < file_count) {
             snprintf(full_path, PATH_MAX - 1, "%s" FLB_PATH_SEPARATOR "%s",
                      directory, findData.cFileName);
-            files[i] = flb_strdup(full_path);
-            i++;
+            files[i] = flb_strdup(full_path);
+            if (files[i] != NULL) {
+                i++;
+            }
         }

Apply similar fix for the POSIX path at lines 1189-1193.


1476-1482: Consider using fdatasync instead of fsync for better performance.

Since you only need accurate file size tracking (data, not all metadata), fdatasync() would be sufficient and slightly faster than fsync() as it doesn't force sync of metadata that doesn't affect data retrieval (like access time).

Suggested change
 #ifndef FLB_SYSTEM_WINDOWS
         /* Only fsync when rotation is enabled - needed for accurate size tracking */
         if (ctx->files_rotation == FLB_TRUE && ctx->max_size > 0) {
-            fsync(fileno(fp));
+            fdatasync(fileno(fp));
         }
 #endif

Apply to all three fsync call sites (lines 1480, 1529, 1652).

tests/runtime/out_file_logrotate.c (2)

1190-1194: Remove unused timestamp generation code.

The tm_info, timestamp variable and strftime call are not used anywhere in this test function. This appears to be leftover debug code.

Suggested fix
     int out_ffd;
     FILE *fp;
     char logfile[512];
-    time_t now = time(NULL);
-    struct tm *tm_info = localtime(&now);
-    char timestamp[32];
-
-    strftime(timestamp, sizeof(timestamp), "%Y%m%d_%H%M%S", tm_info);

     /* Clean up any existing directory and contents */

1177-1177: Remove extraneous semicolons after function definitions.

There are semicolons after the closing braces of flb_test_file_logrotate_multithreaded (line 1177), flb_test_file_logrotate_basic_rotation (line 1261), and flb_test_file_logrotate_gzip_compression (line 1328). While harmless, they are non-standard.

Suggested fix
-};
+}

Apply to lines 1177, 1261, and 1328.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 637cd27 and e6bb50d.

📒 Files selected for processing (3)
  • plugins/out_file/file.c
  • tests/runtime/CMakeLists.txt
  • tests/runtime/out_file_logrotate.c
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/runtime/CMakeLists.txt
🧰 Additional context used
🧠 Learnings (6)
📚 Learning: 2025-08-29T06:25:02.561Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:7-7
Timestamp: 2025-08-29T06:25:02.561Z
Learning: In Fluent Bit, ZSTD (zstandard) compression library is bundled directly in the source tree at `lib/zstd-1.5.7` and is built unconditionally as a static library. Unlike optional external dependencies, ZSTD does not use conditional compilation guards like `FLB_HAVE_ZSTD` and is always available. Headers like `<fluent-bit/flb_zstd.h>` can be included directly without guards.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:25:27.250Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:93-107
Timestamp: 2025-08-29T06:25:27.250Z
Learning: In Fluent Bit, ZSTD compression is enabled by default and is treated as a core dependency, not requiring conditional compilation guards like `#ifdef FLB_HAVE_ZSTD`. Unlike some other optional components such as ARROW/PARQUET (which use `#ifdef FLB_HAVE_ARROW` guards), ZSTD support is always available and doesn't need build-time conditionals. ZSTD headers are included directly without guards across multiple plugins and core components.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:24:26.170Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:39-42
Timestamp: 2025-08-29T06:24:26.170Z
Learning: In Fluent Bit, ZSTD compression support is enabled by default and does not require conditional compilation guards (like #ifdef FLB_HAVE_ZSTD) around ZSTD-related code declarations and implementations.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:24:55.855Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: src/aws/flb_aws_compress.c:52-56
Timestamp: 2025-08-29T06:24:55.855Z
Learning: ZSTD compression is always available in Fluent Bit and does not require conditional compilation guards. Unlike Arrow/Parquet which use #ifdef FLB_HAVE_ARROW guards, ZSTD is built unconditionally with flb_zstd.c included directly in src/CMakeLists.txt and a bundled ZSTD library at lib/zstd-1.5.7/.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-08-29T06:25:27.250Z
Learnt from: shadowshot-x
Repo: fluent/fluent-bit PR: 10794
File: tests/internal/aws_compress.c:93-107
Timestamp: 2025-08-29T06:25:27.250Z
Learning: In Fluent Bit, ZSTD compression is enabled by default and is treated as a core dependency, not requiring conditional compilation guards like `#ifdef FLB_HAVE_ZSTD`. Unlike some other optional components, ZSTD support is always available and doesn't need build-time conditionals.

Applied to files:

  • plugins/out_file/file.c
📚 Learning: 2025-10-23T07:43:16.216Z
Learnt from: cosmo0920
Repo: fluent/fluent-bit PR: 11059
File: plugins/in_tail/tail_file.c:1618-1640
Timestamp: 2025-10-23T07:43:16.216Z
Learning: In plugins/in_tail/tail_file.c, when truncate_long_lines is enabled and the buffer is full, the early truncation path uses `lines > 0` as the validation pattern to confirm whether process_content successfully processed content. This is intentional to track occurrences of line processing rather than byte consumption, and consuming bytes based on `processed_bytes > 0` would be overkill for this validation purpose.

Applied to files:

  • tests/runtime/out_file_logrotate.c
🧬 Code graph analysis (1)
plugins/out_file/file.c (4)
src/flb_lock.c (4)
  • flb_lock_init (6-17)
  • flb_lock_acquire (32-65)
  • flb_lock_release (67-100)
  • flb_lock_destroy (19-30)
include/fluent-bit/flb_output.h (1)
  • flb_output_config_map_set (1306-1333)
include/fluent-bit/flb_mem.h (1)
  • flb_free (126-128)
src/flb_sds.c (2)
  • flb_sds_create (78-90)
  • flb_sds_destroy (389-399)
🪛 ast-grep (0.40.4)
tests/runtime/out_file_logrotate.c

[warning] 603-603: A check is done with stat and then the file is used. There is no guarantee that the status of the file has not changed since the call to stat which may allow attackers to bypass permission checks.
Context: fopen
Note: [CWE-367]: Time-of-check Time-of-use (TOCTOU) Race Condition [REFERENCES]
- https://wiki.sei.cmu.edu/confluence/display/c/FIO45-C.+Avoid+TOCTOU+race+conditions+while+accessing+files

(file-stat-before-action-c)

🔇 Additional comments (8)
plugins/out_file/file.c (3)

1692-1708: LGTM - Proper cleanup of rotation state.

The exit callback correctly acquires the list lock, safely iterates and cleans up all file size entries (destroying per-entry locks and freeing memory), then releases and destroys the list lock. This is the correct order of operations.


1768-1790: Good default configuration for rotation feature.

The rotation feature is disabled by default (files_rotation = false), preserving backward compatibility. The default values (100MB max_size, 7 max_files, gzip enabled) are sensible for typical use cases.


238-244: LGTM - Proper validation of rotation configuration.

The validation ensures max_files >= 1 when rotation is enabled, with clear error messaging. Memory cleanup is handled correctly on validation failure.

tests/runtime/out_file_logrotate.c (5)

329-362: TOCTOU race condition in read_file_content is acceptable for tests.

The static analyzer flagged a time-of-check-time-of-use (TOCTOU) race between stat() and fopen(). In production code this could be exploited, but for test helper functions operating on controlled test directories, this is acceptable. The test files are created/controlled by the test itself.


54-72: Comprehensive test coverage for the rotation feature.

The TEST_LIST covers all major scenarios: basic rotation, gzip compression, max_files enforcement, various output formats (csv, ltsv, plain, msgpack, template), configuration options (path, mkdir, delimiter), and multithreaded scenarios. This aligns well with the PR objectives from linked issue #11110.


1179-1261: LGTM - Basic rotation test is well-structured.

The test properly verifies that:

  1. Writing data beyond max_size triggers rotation
  2. The original file continues to exist after rotation
  3. At least one rotated file is created

Good use of count_files_in_directory to verify rotation occurred.


1396-1442: Good negative testing for configuration validation.

This test verifies that invalid max_files values (0 and -1) cause plugin initialization to fail, ensuring the validation logic in cb_file_init works correctly.


709-713: Pragma usage is acceptable for test code.

The GCC diagnostic pragmas suppress format-truncation warnings for snprintf calls where the paths are known to be short. The comments document the rationale. This is reasonable for test code with controlled inputs.

Copy link
Copy Markdown
Contributor

@cosmo0920 cosmo0920 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to use compatible layer functions at first before entering full process of reviewing.

Comment thread plugins/out_file/file.c Outdated
@SagiROosto
Copy link
Copy Markdown
Author

Failure seems like fleaky CI not-related to actual changes

Copy link
Copy Markdown
Contributor

@cosmo0920 cosmo0920 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a strong feature addition overall, but I would be hesitant to merge it as-is. There are a couple of correctness issues that look important enough to fix before merge.

fwrite() error handling in the msgpack path looks broken

In the msgpack branch, the code does:

ret = fwrite(...);
if (ret < 0) {
    ...
}

fwrite() does not return a negative value here, so this condition will never trigger. On write failure, this can turn into a loop that does not make forward progress.

I think this should be handled using something like ret == 0 && ferror(fp) instead.

This one feels blocker-level to me.

Plus, there's a curious question.
How do we handle multiple rotation within the same second?
And we might need to add a test for multiple rotations within the same second.

SagiROosto added 2 commits May 4, 2026 11:21
Signed-off-by: SagiROosto <sagi.rosenthal@oosto.com>
Signed-off-by: SagiROosto <sagi.rosenthal@oosto.com>
@SagiROosto SagiROosto force-pushed the out_file-rotation branch from f4a0773 to eb23273 Compare May 4, 2026 08:23
@SagiROosto
Copy link
Copy Markdown
Author

I think this is a strong feature addition overall, but I would be hesitant to merge it as-is. There are a couple of correctness issues that look important enough to fix before merge.

fwrite() error handling in the msgpack path looks broken

In the msgpack branch, the code does:

ret = fwrite(...);
if (ret < 0) {
    ...
}

fwrite() does not return a negative value here, so this condition will never trigger. On write failure, this can turn into a loop that does not make forward progress.

I think this should be handled using something like ret == 0 && ferror(fp) instead.

This one feels blocker-level to me.

Plus, there's a curious question. How do we handle multiple rotation within the same second? And we might need to add a test for multiple rotations within the same second.

well TBH if one reaches a case where the plugin rotates the log file twice in the same wall-clock second then there is probably have greater issues...
but to keep on the safe side, yet not overkilling the feature with custom timestamp formatting I added random 8bytes at the file suffix - YYYYMMDD_HHMMSS_12345678

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants