Skip to content

in_opentelemetry: optimize batched protobuf ingestion - #12171

Merged
edsiper merged 3 commits into
masterfrom
in-opentelemetry-protobuf-ingest-perf
Jul 29, 2026
Merged

in_opentelemetry: optimize batched protobuf ingestion#12171
edsiper merged 3 commits into
masterfrom
in-opentelemetry-protobuf-ingest-perf

Conversation

@edsiper

@edsiper edsiper commented Jul 29, 2026

Copy link
Copy Markdown
Member

Problem

Batched OTLP/HTTP Protobuf logs performed avoidable allocation and record-accounting work. The Protobuf arena was only enabled for payloads at least 64 KiB, excluding realistic medium batches, and the worker decoded every logical record only for the central ingress thread to scan the resulting MessagePack again to count records.

Changes

  • Enable the request-scoped protobuf arena for payloads of at least 8 KiB while retaining protobuf-c's default allocator for small requests.
  • Count successfully committed log records during OTLP Protobuf conversion.
  • Carry a known record count through the worker ingress queue and use flb_input_log_append_records() in the central input thread.
  • Preserve the existing fallback recount for JSON and other producers without a known count.
  • Preserve the existing flb_input_ingress_queue_log_take() API for out-of-tree callers and add a separate counted variant for OpenTelemetry.
  • Add an integration regression covering four-worker batched Protobuf ingestion and input-record accounting.

Caller and compatibility audit

The generic log queue is used by Forward, TCP, UDP, HTTP, Splunk, Elasticsearch, ETW, and OpenTelemetry. Ingress events are zero-initialized with flb_calloc(), so existing callers retain records == 0 and the established MessagePack recount path. The ownership, busy-queue, queue-drain, and destruction paths are unchanged.

The initial patch changed the positional signature of flb_input_ingress_queue_log_take(). Although OpenTelemetry was its only in-tree caller, this could break out-of-tree plugins. The original function signature and symbol are now preserved; flb_input_ingress_queue_log_take_records() is the opt-in counted interface.

Impact

In the controlled four-worker benchmark, these changes improved Fluent Bit Protobuf ingest-only end-to-end throughput from 1.25M to 1.67M records/s (+33.4%) and records per CPU-second by 74.6%. With 256 persistent connections balancing all four listeners, Fluent Bit accepted 3.03M records/s at 376.9% aggregate CPU.

No configuration or wire-protocol behavior changes. JSON, profiles-as-logs, and unknown-count ingestion continue through the existing counting path.

Validation

Build and internal/runtime CTest

  • cmake -S . -B build -DFLB_TESTS_RUNTIME=On -DFLB_TESTS_INTERNAL=On
  • cmake --build build -j8: passed; all in-tree input callers compiled.
  • ctest --test-dir build --output-on-failure -j8: 194/197 passed directly.
  • flb-rt-in_forward and flb-rt-out_http were blocked by the host fluentd.service owning ports 24224 and 8888. Both passed in isolation after rebuilding with temporary unused test ports; those test-only edits were removed.
  • flb-rt-out_td remains blocked by its external /tmp/td.conf credential-file requirement.

Complete Python integration suite

  • cd tests/integration && ./run_tests.py
  • Result: 365 passed, 6 skipped, 4 unrelated failures in 29m28s.
  • Every covered ingress-queue consumer passed, including four-worker Forward, TCP, UDP, HTTP, Splunk, Elasticsearch, Prometheus remote write, and the complete OpenTelemetry protocol/worker matrix.
  • Three unrelated hot-reload tests fail because the current FluentBitManager harness lacks wait_for_hot_reload_count().
  • One unrelated Tail ignore_active_older_files case consistently accepts a second line after aging; it also failed when rerun alone.

Focused memory safety and lint

  • VALGRIND=1 VALGRIND_STRICT=1 tests/integration/.venv/bin/python -m pytest tests/integration/scenarios/in_opentelemetry/tests/test_in_opentelemetry_001.py::test_in_opentelemetry_batched_protobuf_logs_with_workers -q: passed.
  • Full PR-range commit-prefix validation against master: passed.

Summary by CodeRabbit

  • New Features

    • Enhanced OpenTelemetry log ingestion to support batched protobuf payloads when worker processing is enabled.
    • Deferred ingestion can now queue and process multiple log records per request.
  • Bug Fixes

    • Correctly counts and records the number of log records delivered for batched OpenTelemetry protobuf logs.
    • Prometheus metrics now align with the number of processed records.
    • Profile-based log entries continue to work properly through worker queues.
  • Tests

    • Added an integration test covering batched protobuf logs with workers, validating delivery, record counts, and metrics.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f6e31fef-b143-411a-8761-c12f9d6eb423

📥 Commits

Reviewing files that changed from the base of the PR and between 9e769d2 and 744cf0c.

📒 Files selected for processing (6)
  • include/fluent-bit/flb_input.h
  • plugins/in_opentelemetry/opentelemetry.h
  • plugins/in_opentelemetry/opentelemetry_logs.c
  • plugins/in_opentelemetry/opentelemetry_prot.c
  • src/flb_input_ingest.c
  • tests/integration/scenarios/in_opentelemetry/tests/test_in_opentelemetry_001.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • include/fluent-bit/flb_input.h
  • plugins/in_opentelemetry/opentelemetry_prot.c
  • src/flb_input_ingest.c
  • plugins/in_opentelemetry/opentelemetry.h
  • plugins/in_opentelemetry/opentelemetry_logs.c
  • tests/integration/scenarios/in_opentelemetry/tests/test_in_opentelemetry_001.py

📝 Walkthrough

Walkthrough

OpenTelemetry protobuf log decoding now counts committed records and propagates that count through worker ingress queues, which select batched append handling. A new integration test validates received records and Prometheus metrics for batched worker requests.

Changes

OpenTelemetry batched log ingestion

Layer / File(s) Summary
Ingress queue record-count handling
include/fluent-bit/flb_input.h, src/flb_input_ingest.c
The ingress queue API and deferred collector carry record counts and choose between single-record and batched append functions.
OpenTelemetry count propagation
plugins/in_opentelemetry/opentelemetry.h, plugins/in_opentelemetry/opentelemetry_logs.c, plugins/in_opentelemetry/opentelemetry_prot.c
Protobuf decoding counts committed records, forwards the count through ingestion helpers, reduces the arena threshold, and supplies zero for profile log entries.
Batched worker ingestion validation
tests/integration/scenarios/in_opentelemetry/tests/test_in_opentelemetry_001.py
A worker-based integration test sends batched OTLP logs and verifies received records and Prometheus input-record metrics.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant OTLPClient
  participant OpenTelemetryInput
  participant IngressQueue
  participant LogStorage
  OTLPClient->>OpenTelemetryInput: Send batched protobuf logs
  OpenTelemetryInput->>IngressQueue: Queue encoded logs and record count
  IngressQueue->>LogStorage: Append batched records
  LogStorage-->>OTLPClient: Return HTTP 201
Loading

Possibly related PRs

Suggested reviewers: cosmo0920

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% 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 clearly matches the main change: optimizing batched protobuf ingestion in in_opentelemetry.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch in-opentelemetry-protobuf-ingest-perf

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/flb_input_ingest.c (1)

54-54: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Do not overload records == 0 as “unknown”.

The event stores only a size_t count, while the collector uses the counted path only for records > 0; the compatibility wrapper passes 0 for callers without a count. A legitimate known zero-count payload is therefore indistinguishable from an unknown count and is reparsed through flb_input_log_append(), making input-record accounting dependent on fallback parsing.

Use an explicit known flag or documented sentinel, update the compatibility wrapper and OpenTelemetry helper consistently, and branch on knownness rather than positivity.

As per coding guidelines, explicit zero values must be preserved and unknown values must use a clear sentinel.

Also applies to: 385-401, 577-593

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/flb_input_ingest.c` at line 54, Separate “count is known” from the
`records` value in the event and ingestion flow: preserve a legitimate known
zero, while representing unknown counts with an explicit flag or documented
sentinel. Update the compatibility wrapper and OpenTelemetry helper
consistently, and make the counting branch test knownness rather than `records >
0`, including the related paths around the event structure and helper calls.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/flb_input_ingest.c`:
- Line 54: Separate “count is known” from the `records` value in the event and
ingestion flow: preserve a legitimate known zero, while representing unknown
counts with an explicit flag or documented sentinel. Update the compatibility
wrapper and OpenTelemetry helper consistently, and make the counting branch test
knownness rather than `records > 0`, including the related paths around the
event structure and helper calls.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d67ac3d-b3be-4940-9c71-bdd87054dadb

📥 Commits

Reviewing files that changed from the base of the PR and between eefd865 and 9e769d2.

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

edsiper added 3 commits July 29, 2026 08:12
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
@edsiper
edsiper merged commit 3af25c4 into master Jul 29, 2026
62 of 64 checks passed
@edsiper
edsiper deleted the in-opentelemetry-protobuf-ingest-perf branch July 29, 2026 15:49
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