Skip to content

router_config: wire every route merging into a shared output#12142

Draft
zshuang0316 wants to merge 3 commits into
fluent:masterfrom
zshuang0316:fix-router-drop-merged-output-routes
Draft

router_config: wire every route merging into a shared output#12142
zshuang0316 wants to merge 3 commits into
fluent:masterfrom
zshuang0316:fix-router-drop-merged-output-routes

Conversation

@zshuang0316

@zshuang0316 zshuang0316 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

flb_router_apply_config() deduplicated direct routes by output instance only
(input_has_direct_route()). When several routes point at the same output
instance, only the first was connected via flb_router_connect_direct() and the
rest were silently dropped.

This is incorrect because each route carries its own condition and is evaluated
independently at runtime through its own flb_router_path — see flb_input_log.c,
where per-record routing payloads are keyed by route_path->route and each route's
condition is evaluated separately (flb_router_condition_evaluate_record(payload->route, ...)).
Collapsing multiple routes that merge into a shared output to a single path means
records that should reach that output via a dropped route's condition never get
routed there — the intended union across routes is broken.

Example

inputs:
  - name: dummy
    routes:
      logs:
        - name: error_logs
          condition: { rules: [ { field: "$level", op: eq, value: "error" } ] }
          to: [ es ]
        - name: checkout_logs
          condition: { rules: [ { field: "$service", op: eq, value: "checkout" } ] }
          to: [ es ]

Before this change only error_logs is wired to es; records matching
checkout_logs (but not error_logs) never reach es.

Fix

Key the deduplication on the (route, output) pair so distinct routes merging
into one output are each wired as their own direct path. Identical (route, output)
edges (e.g. an output listed twice within one route) are still collapsed.


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 (see above)
  • Debug log output from testing the change
  • Attached Valgrind output that shows no leaks or memory corruption was found

Added an internal regression test (tests/internal/router_config.c,
apply_config_merged_output_keeps_all_routes) asserting that two distinct routes
targeting the same output instance each produce their own flb_router_path.

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

Documentation

  • [N/A] 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.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Fixed routing deduplication so direct/conditional paths are tracked per route, not just per shared output instance.
    • Prevented loss or unintended collapsing of route entries when multiple distinct routes target the same output.
  • Tests

    • Added a router configuration test to confirm merged outputs keep all distinct routes and associated direct paths.

@zshuang0316

Copy link
Copy Markdown
Contributor Author

@codex review

@coderabbitai

coderabbitai Bot commented Jul 23, 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: 63ed7284-1f59-4b59-ac66-1172edafb1e8

📥 Commits

Reviewing files that changed from the base of the PR and between a94ba37 and 7188d83.

📒 Files selected for processing (3)
  • src/flb_router_config.c
  • src/flb_task.c
  • tests/internal/router_config.c
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/flb_router_config.c
  • tests/internal/router_config.c

📝 Walkthrough

Walkthrough

Direct-route detection now matches route/output pairs, while task creation deduplicates routes per output instance. A regression test confirms that distinct routes sharing an output retain separate direct paths.

Changes

Router direct route handling

Layer / File(s) Summary
Route-aware direct path matching
src/flb_router_config.c
input_has_direct_route matches existing direct paths by both route and output instance.
Task route output deduplication
src/flb_task.c
Task creation prevents duplicate task routes for the same output during stored-route restoration and direct-path evaluation.
Merged output regression coverage
tests/internal/router_config.c
Adds and registers a test confirming that distinct routes sharing an output create two direct paths.

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

Possibly related PRs

  • fluent/fluent-bit#11041: Updates router configuration and direct routing behavior in the same implementation area.

Suggested reviewers: cosmo0920, edsiper

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% 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 is related to the main change: router configuration now treats multiple routes sharing an output more deliberately.
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
🧪 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.

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

🧹 Nitpick comments (1)
tests/internal/router_config.c (1)

1342-1357: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Cover identical route-output deduplication.

This verifies distinct routes sharing an output, but not the identical-pair branch. Add another printme output edge to route_one and keep the expected direct-path count at two.

As per coding guidelines, “Add or update tests for behavior changes.”

🤖 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 `@tests/internal/router_config.c` around lines 1342 - 1357, Add a second output
edge using route_output_one’s “printme” destination to route_one, exercising
identical route-output deduplication while preserving the expected direct-path
count of two in the relevant router configuration test.

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.

Nitpick comments:
In `@tests/internal/router_config.c`:
- Around line 1342-1357: Add a second output edge using route_output_one’s
“printme” destination to route_one, exercising identical route-output
deduplication while preserving the expected direct-path count of two in the
relevant router configuration test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ae50a7ba-14f8-46b1-89d1-64fa8be902cf

📥 Commits

Reviewing files that changed from the base of the PR and between cb7256c and a94ba37.

📒 Files selected for processing (2)
  • src/flb_router_config.c
  • tests/internal/router_config.c

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a94ba37d9a

ℹ️ 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 src/flb_router_config.c
cfl_list_foreach(head, &in->routes_direct) {
path = cfl_list_entry(head, struct flb_router_path, _head);
if (path->ins == out) {
if (path->ins == out && path->route == route) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Prevent merged routes from duplicating output flushes

When two conditional routes target the same output and their predicates can both match a record, this route-aware dedupe leaves both flb_router_paths in routes_direct, but the later routing mask is only keyed by output id. A route-specific chunk for either route therefore passes both paths in flb_task_create() and creates duplicate flb_task_route entries for the same output; the task status/data helpers then update only the first matching route->out, so delivery, retry, and accounting for that chunk can be duplicated or inconsistent. Please keep the per-route paths for condition evaluation, but collapse matched paths to one task route per output or carry route identity through the mask/task layer.

AGENTS.md reference: AGENTS.md:L224-L228

Useful? React with 👍 / 👎.

zshuang0316 and others added 3 commits July 23, 2026 17:23
flb_router_apply_config() deduplicated direct routes by output instance
only (input_has_direct_route). When several routes point at the same
output instance, only the first was connected and the rest were silently
dropped, even though each route carries its own condition and is
evaluated independently at runtime through its own flb_router_path.

Key the deduplication on the (route, output) pair so distinct routes
merging into one output are each wired as their own direct path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: zshuang0316 <zshuang0316@163.com>
Routes are now deduplicated per (route, output) pair, so several matching
routes can resolve to the same output instance. flb_task_create() builds
one flb_task_route per direct path, so a chunk matching more than one such
route produced duplicate task routes for the same output. The engine
dispatcher iterates task routes and flushes each one, so the chunk was
delivered to that output more than once and its records/bytes were counted
multiple times.

Skip outputs that already have a task route when building both the live
and restored direct-route task paths, keeping at most one route per output.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: zshuang0316 <zshuang0316@163.com>
Add a router_config case asserting that two distinct routes targeting the
same output instance each produce their own direct path, while a single
route listing that output twice collapses to one path. This guards the
(route, output) deduplication against both dropping distinct routes and
duplicating identical ones.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: zshuang0316 <zshuang0316@163.com>
@zshuang0316

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7188d83ebb

ℹ️ 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 src/flb_router_config.c
cfl_list_foreach(head, &in->routes_direct) {
path = cfl_list_entry(head, struct flb_router_path, _head);
if (path->ins == out) {
if (path->ins == out && path->route == route) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve storage accounting for shared-output routes

With filesystem storage and total_limit_size, allowing multiple routes_direct entries for the same output breaks the existing route-mask accounting path because masks are keyed only by output id. In route_payload_apply_outputs(), a conditional/per-record payload chunk that was already fs_counted (for example when the output also has Match *) subtracts and clears any “other route” whose output bit is set; after this change, a second route to the same output matches that test, so the current output is subtracted even though the payload still routes there, and it is not added back because chunk->fs_counted remains true. This undercounts the output’s fs_chunks_size and can bypass storage pressure for shared-output conditional routes.

AGENTS.md reference: AGENTS.md:L239-L241

Useful? React with 👍 / 👎.

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