Skip to content

io: http_client: Implement batching io write#11501

Open
cosmo0920 wants to merge 4 commits intomasterfrom
cosmo0920-implement-batching-io_write
Open

io: http_client: Implement batching io write#11501
cosmo0920 wants to merge 4 commits intomasterfrom
cosmo0920-implement-batching-io_write

Conversation

@cosmo0920
Copy link
Contributor

@cosmo0920 cosmo0920 commented Feb 26, 2026

This is internal component change and optimization.
When sending HTTP request, we need to send header and body pair if body length is greater than zero.
However, this can be concatenated with one request if possible.
So, we can concatenate with memcpy to reduce calling of write syscall.


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

    • Added cross-platform vectorized network write support and a public API to send headers and bodies together for more efficient requests and improved Windows compatibility.
  • Bug Fixes

    • Improved HTTP write error handling with robust fallback behavior on resource failures.
    • Corrected byte accounting when sending combined header+body to ensure accurate reporting and preserved existing timeout/error semantics.

@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 85cbf67 and 0534987.

📒 Files selected for processing (3)
  • include/fluent-bit/flb_io.h
  • src/flb_http_client.c
  • src/flb_io.c

📝 Walkthrough

Walkthrough

Adds a public flb_iovec and flb_io_net_writev API; HTTP client uses writev to send header+body in one operation when a body exists; I/O layer enforces iov limits, concatenates iovecs into a temporary buffer, and delegates to existing connection write path.

Changes

Cohort / File(s) Summary
I/O Header
include/fluent-bit/flb_io.h
Adds struct flb_iovec, #include <stddef.h>, and declares int flb_io_net_writev(struct flb_connection *connection, const struct flb_iovec *iov, int iovcnt, size_t *out_len);.
HTTP Client
src/flb_http_client.c
When request has a body, uses flb_io_net_writev to send header+body together, updates sent-byte accounting and error handling; header-only path unchanged.
I/O Implementation
src/flb_io.c
Adds flb_io_get_iov_max() and implements flb_io_net_writev with input validation, iovcnt clamping, overflow checks, temporary buffer allocation/concatenation of iovecs, and delegation to flb_io_net_write.

Sequence Diagram

sequenceDiagram
    participant HTTP as HTTP Client
    participant IO as I/O Layer
    participant Conn as Connection

    HTTP->>IO: flb_io_net_writev(connection, iov[], iovcnt, &out_len)
    Note over IO: validate inputs\ncheck iovcnt vs IOV_MAX\ncompute total size (overflow checks)
    IO->>IO: allocate temporary buffer\nconcatenate iov data into buffer
    IO->>Conn: flb_io_net_write(connection, buffer, total_len)
    Conn-->>IO: bytes_written / error
    IO->>IO: free buffer
    IO-->>HTTP: return result, out_len
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • edsiper
  • koleini
  • fujimotos

Poem

🐰 I stitched the chunks in a cozy heap,

Header and body, packed snug and neat,
I hopped them off in a single bound,
Through sockets swift they sailed outbound,
A carrot cheer for bytes complete 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'io: http_client: Implement batching io write' clearly and concisely describes the main change: implementing a batching I/O write optimization that combines header and body writes into a single syscall for HTTP requests.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cosmo0920-implement-batching-io_write

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.

@cosmo0920 cosmo0920 marked this pull request as ready for review February 26, 2026 11:02
@cosmo0920 cosmo0920 requested a review from edsiper as a code owner February 26, 2026 11:02
@cosmo0920 cosmo0920 added this to the Fluent Bit v5.0 milestone Feb 26, 2026
Copy link

@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: e5b09d6a8a

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link

@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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@include/fluent-bit/flb_io.h`:
- Around line 23-36: The Windows build fails because the iovec alias is only
defined when a preexisting iovec macro is present; move or add an unconditional
alias so that after defining struct flb_iovec (inside the FLB_SYSTEM_WINDOWS
guard) you always map the symbol iovec to flb_iovec (i.e., ensure iovec is
defined/aliased to flb_iovec regardless of whether a prior iovec macro exists)
so uses of const struct iovec *iov compile on MSVC; update the code around the
FLB_SYSTEM_WINDOWS block to `#undef` iovec if needed and then `#define` iovec
flb_iovec unconditionally after the struct definition.

In `@src/flb_http_client.c`:
- Around line 1494-1509: The current code hard-fails when
flb_io_net_writev(c->u_conn, io_vector, 2, &bytes_header) returns -1; change
this to try a graceful fallback: on flb_io_net_writev failure, log the error
(flb_errno()) but then attempt two separate writes using the underlying
single-write API (e.g., call flb_io_net_write(c->u_conn, c->header_buf,
c->header_len, &bytes_written) and then flb_io_net_write(c->u_conn, c->body_buf,
c->body_len, &bytes_written) or equivalent), and only return FLB_HTTP_ERROR if
those fallback writes fail; keep existing success path when writev succeeds and
preserve bytes_header/bytes_written handling.
- Around line 1511-1513: The subtraction bytes_body = bytes_header -
c->header_len can underflow because bytes_header and c->header_len are size_t;
before doing the subtraction (in the block that updates bytes_body and
bytes_header) add a guard that verifies bytes_header >= c->header_len and handle
the else-case (e.g., set bytes_body = 0 and keep bytes_header unchanged or clamp
to 0 and log/return an error); update references to bytes_body and bytes_header
accordingly so no unsigned wraparound occurs when partial writes happen.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc966ed and e5b09d6.

📒 Files selected for processing (3)
  • include/fluent-bit/flb_io.h
  • src/flb_http_client.c
  • src/flb_io.c

Copy link

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/flb_io.c`:
- Around line 735-738: The check allows iov[index].iov_base to be NULL when
iov[index].iov_len == 0 but later still calls memcpy with that NULL source;
update the code path around the memcpy call to skip calling memcpy when
iov[index].iov_len == 0 (i.e., only call memcpy when iov[index].iov_len > 0),
ensuring you keep the existing validation that sets errno = EINVAL when iov_len
> 0 and iov_base == NULL; refer to the iov[index].iov_len / iov[index].iov_base
checks and the memcpy invocation to locate and change the logic.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e5b09d6 and 39a6a71.

📒 Files selected for processing (2)
  • include/fluent-bit/flb_io.h
  • src/flb_io.c
🚧 Files skipped from review as they are similar to previous changes (1)
  • include/fluent-bit/flb_io.h

Copy link

@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: 2

♻️ Duplicate comments (1)
src/flb_http_client.c (1)

1494-1538: ⚠️ Potential issue | 🟠 Major

Guard against unsigned underflow in byte accounting.

At line 1536, bytes_body = bytes_header - c->header_len performs subtraction on size_t values. If the underlying write completes only partially (a valid scenario in network I/O), bytes_header could be less than c->header_len, causing unsigned wraparound to a huge value.

Proposed defensive check
         else {
+            if (bytes_header < c->header_len) {
+                flb_error("[http_client] partial write: total=%zu header_len=%zu",
+                          bytes_header, c->header_len);
+                return FLB_HTTP_ERROR;
+            }
             bytes_body = bytes_header - c->header_len;
             bytes_header = c->header_len;
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/flb_http_client.c` around lines 1494 - 1538, The subtraction bytes_body =
bytes_header - c->header_len can underflow because bytes_header may be less than
c->header_len after a partial write from flb_io_net_writev; modify the
post-write branch that currently sets bytes_body and bytes_header to first check
if bytes_header >= c->header_len and only then compute bytes_body = bytes_header
- c->header_len and set bytes_header = c->header_len, otherwise treat it as a
partial-header write by setting bytes_body = 0 and leaving bytes_header as the
actual bytes_header (or handle as appropriate), so no unsigned underflow occurs
(refer to flb_io_net_writev, bytes_header, bytes_body, and c->header_len).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@include/fluent-bit/flb_io.h`:
- Around line 69-72: The function declaration flb_io_net_writev currently uses
"const struct flb_iovec *iov" which will not compile on POSIX because flb_iovec
is a typedef (no struct tag); change the declaration to use the typedef name
"const flb_iovec *iov" and remove the "struct" keyword from all uses of
flb_iovec (including the implementation in src/flb_io.c where flb_io_net_writev
is defined and callers such as the io_vector[] in src/flb_http_client.c) so
every reference uses the typedef type name flb_iovec rather than struct
flb_iovec.

In `@src/flb_http_client.c`:
- Line 1495: The declaration uses "struct flb_iovec io_vector[2];" which fails
on POSIX because flb_iovec is a typedef alias to struct iovec; change the
declaration to use the typedef name directly (flb_iovec io_vector[2];) and
remove the "struct" keyword anywhere "struct flb_iovec" appears (e.g., local
variable io_vector in flb_http_client.c and any other occurrences referenced by
the same header) so the code compiles on POSIX.

---

Duplicate comments:
In `@src/flb_http_client.c`:
- Around line 1494-1538: The subtraction bytes_body = bytes_header -
c->header_len can underflow because bytes_header may be less than c->header_len
after a partial write from flb_io_net_writev; modify the post-write branch that
currently sets bytes_body and bytes_header to first check if bytes_header >=
c->header_len and only then compute bytes_body = bytes_header - c->header_len
and set bytes_header = c->header_len, otherwise treat it as a partial-header
write by setting bytes_body = 0 and leaving bytes_header as the actual
bytes_header (or handle as appropriate), so no unsigned underflow occurs (refer
to flb_io_net_writev, bytes_header, bytes_body, and c->header_len).

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39a6a71 and fc849bf.

📒 Files selected for processing (3)
  • include/fluent-bit/flb_io.h
  • src/flb_http_client.c
  • src/flb_io.c
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/flb_io.c

Copy link

@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.

♻️ Duplicate comments (1)
src/flb_io.c (1)

714-718: ⚠️ Potential issue | 🟠 Major

Add missing connection null-guard in input validation.

Line 714 validates several inputs but not connection. A null connection can flow into flb_io_net_write() and dereference-crash.

💡 Suggested fix
-    if (iov == NULL || iovcnt <= 0 || out_len == NULL) {
+    if (connection == NULL || iov == NULL || iovcnt <= 0 || out_len == NULL) {
         errno = EINVAL;

         return -1;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/flb_io.c` around lines 714 - 718, Add a null-guard for the connection
pointer in the input validation so a NULL connection cannot be passed into
flb_io_net_write() and cause a dereference crash: in the validation block that
currently checks iov, iovcnt and out_len (around the start of the function in
flb_io.c) include connection == NULL (or a dedicated if that sets errno = EINVAL
and returns -1) so the function returns early on a NULL connection with the same
error handling path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/flb_io.c`:
- Around line 714-718: Add a null-guard for the connection pointer in the input
validation so a NULL connection cannot be passed into flb_io_net_write() and
cause a dereference crash: in the validation block that currently checks iov,
iovcnt and out_len (around the start of the function in flb_io.c) include
connection == NULL (or a dedicated if that sets errno = EINVAL and returns -1)
so the function returns early on a NULL connection with the same error handling
path.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc849bf and 85cbf67.

📒 Files selected for processing (3)
  • include/fluent-bit/flb_io.h
  • src/flb_http_client.c
  • src/flb_io.c

Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
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.

1 participant