Skip to content

Conversation

edsiper
Copy link
Member

@edsiper edsiper commented Sep 30, 2025

This PR introduces routing metrics into the Fluent Bit router. The router API now uses dedicated contexts that extend the existing design to provide proper metric instrumentation, details:

  • New router context which provides separated metrics for logs (will extend to other signals soon)
  • New metrics are exposed to answer critical questions such as:
    • Which sources are connected to which destinations?
    • How many records/bytes are routed from a given input to a specific output?
    • These metrics provide greater visibility into the full data path from source → router → destination.

Goals:

  • Improves observability for routing decisions and pipeline debugging.
  • Allows operators to identify bottlenecks and misrouted traffic.
  • Extensible foundation for future enhancements (per-route latency, retries, filtering impact, etc.).

Here is an example of the new routing metrics:

Fluent Bit Pipeline

bin/fluent-bit -H -i dummy -i cpu -o stdout -m 'cpu*' -o null -m '*'
Fluent Bit v4.1.1
* Copyright (C) 2015-2025 The Fluent Bit Authors
* Fluent Bit is a CNCF sub-project under the umbrella of Fluentd
* https://fluentbit.io

______ _                  _    ______ _ _             ___   __  
|  ___| |                | |   | ___ (_) |           /   | /  | 
| |_  | |_   _  ___ _ __ | |_  | |_/ /_| |_  __   __/ /| | `| | 
|  _| | | | | |/ _ \ '_ \| __| | ___ \ | __| \ \ / / /_| |  | | 
| |   | | |_| |  __/ | | | |_  | |_/ / | |_   \ V /\___  |__| |_
\_|   |_|\__,_|\___|_| |_|\__| \____/|_|\__|   \_/     |_(_)___/

Metrics exposed

curl -s http://127.0.0.1:2020/api/v2/metrics/prometheus |grep rout

output:

# HELP fluentbit_routing_logs_records_total Total log records routed from input to output
# TYPE fluentbit_routing_logs_records_total counter
fluentbit_routing_logs_records_total{input="dummy.0",output="null.1"} 3
fluentbit_routing_logs_records_total{input="cpu.1",output="stdout.0"} 3
fluentbit_routing_logs_records_total{input="cpu.1",output="null.1"} 3
# HELP fluentbit_routing_logs_bytes_total Total bytes routed from input to output (logs)
# TYPE fluentbit_routing_logs_bytes_total counter
fluentbit_routing_logs_bytes_total{input="dummy.0",output="null.1"} 108
fluentbit_routing_logs_bytes_total{input="cpu.1",output="stdout.0"} 3363
fluentbit_routing_logs_bytes_total{input="cpu.1",output="null.1"} 3363

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 routing metrics for logs (records, bytes, dropped) with per-input and per-output labels and integrates them into the metrics exporter; metric labeling improved for inputs/outputs.
  • Refactor

    • Consolidates routing state into a dedicated router component and centralizes routing-mask handling, standardizing lifecycle, allocations and routing checks across the system.

Signed-off-by: Eduardo Silva <[email protected]>
Signed-off-by: Eduardo Silva <[email protected]>
Signed-off-by: Eduardo Silva <[email protected]>
Copy link

coderabbitai bot commented Sep 30, 2025

Walkthrough

Moves routing state out of flb_config into a new flb_router object, exposes router-aware routes-mask APIs, creates/destroys router during config lifecycle, wires router metrics into exporter, and updates engine, input-chunk, backlog, and task code to use the router for mask and metrics operations. (40 words)

Changes

Cohort / File(s) Summary of changes
Config struct update
include/fluent-bit/flb_config.h
Removes route_mask_size, route_mask_slots, route_empty_mask; adds struct flb_router *router.
Router public API
include/fluent-bit/flb_router.h
Adds struct flb_router (mask fields + cmetrics pointers) and declarations: flb_router_metrics_create, flb_router_create, flb_router_destroy.
Routes mask header
include/fluent-bit/flb_routes_mask.h
Changes mask helper signatures to accept struct flb_router *; adds flb_routes_mask_get_size and flb_routes_mask_get_slots.
Router implementation
src/flb_router.c
Implements flb_router_create, flb_router_destroy, and internal router metrics setup (cmetrics and four counters).
Routes mask implementation
src/flb_routes_mask.c
Replaces config-based accesses with router-based ones; adds flb_routes_mask_get_size/get_slots; manages router->route_empty_mask lifecycle and bounds checks.
Config lifecycle integration
src/flb_config.c
Creates flb_router on init (flb_router_create), sets mask size via router, and destroys router on cleanup.
Engine metrics & labeling
src/flb_engine.c
Introduces in_name/out_name, records router log metrics (records/bytes/drops) for LOGS path, and uses config->router for mask sizing.
Input chunk routing & metrics
src/flb_input_chunk.c
Replaces config with config->router for mask ops, sizing, allocations, and updates router drop counters for logs.
Routes mask usages in tasks
src/flb_task.c
Passes o_ins->config->router to flb_routes_mask_get_bit when deciding route creation.
Backlog plugin adjustments
plugins/in_storage_backlog/sb.c
Uses flb_routes_mask_get_slots(config->router) and allocates/initializes dummy route mask via router-derived size.
Metrics exporter aggregation
src/flb_metrics_exporter.c
Appends router cmetrics (cmt_cat) when router and its cmt exist; handles append errors and includes flb_router.h.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Main as Main
  participant Config as flb_config
  participant Router as flb_router
  participant Routes as RoutesMask

  Main->>Config: flb_config_init(...)
  Config->>Router: flb_router_create(config)
  Router-->>Config: router*
  Config->>Routes: flb_routes_mask_set_size(N, router)
  Routes-->>Config: OK
  Note right of Router: holds mask fields\nand cmetrics
  Main->>Config: flb_config_exit(...)
  Config->>Router: flb_router_destroy(router)
  Router-->>Config: freed
Loading
sequenceDiagram
  autonumber
  participant In as Input
  participant Eng as Engine
  participant Task as Task
  participant Router as flb_router
  participant Out as Output

  In->>Eng: EventChunk (type=LOGS)
  Eng->>Task: schedule/process
  Task->>Router: flb_routes_mask_get_bit(router)
  alt Eligible
    Eng->>Router: inc logs_records_total{in,out}
    Eng->>Router: inc logs_bytes_total{in,out}
  else Not eligible / Dropped
    Eng->>Router: inc logs_drop_records_total{in,out}
    Eng->>Router: inc logs_drop_bytes_total{in,out}
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • koleini
  • fujimotos

Poem

I nibbled the masks into one tidy burrow,
A router now guides where the log-streams go.
Counters hum softly where routes intertwine,
I twitch my nose—metrics align.
Hop, hop, commit—bytes counted just so. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ 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 clearly and concisely summarizes the primary change by indicating that the router interface is being extended with metrics support, which directly aligns with the PR’s introduction of router metrics. It avoids unnecessary details and uses a standard “component: change” format familiar in commit hygiene.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch router-metrics-v2

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 26ca515 and bfeac40.

📒 Files selected for processing (1)
  • src/flb_routes_mask.c (7 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/flb_routes_mask.c (1)
include/fluent-bit/flb_mem.h (2)
  • flb_calloc (84-96)
  • flb_free (126-128)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (30)
  • GitHub Check: pr-windows-build / call-build-windows-package (Windows 64bit (Arm64), amd64_arm64, -DCMAKE_SYSTEM_NAME=Windows -DCMA...
  • GitHub Check: pr-windows-build / call-build-windows-package (Windows 32bit, x86, x86-windows-static, 3.31.6)
  • GitHub Check: pr-windows-build / call-build-windows-package (Windows 64bit, x64, x64-windows-static, 3.31.6)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_MEMORY=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_ARROW=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_ADDRESS=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_ADDRESS=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_MEMORY=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_COVERAGE=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=On, 3.31.6, gcc, g++)
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-22.04, clang-12)
  • GitHub Check: pr-compile-without-cxx (3.31.6)
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-24.04, clang-14)
  • GitHub Check: pr-compile-centos-7
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-24.04, clang-14)
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-22.04, clang-12)
  • GitHub Check: PR - fuzzing test
🔇 Additional comments (8)
src/flb_routes_mask.c (8)

26-40: LGTM! NULL guards properly added.

Both getter functions correctly validate the router parameter before dereferencing, returning 0 when router is NULL. This resolves the past review concern about missing NULL checks.


52-64: LGTM! Router-based sizing correctly implemented.

The function now properly validates in->config and in->config->router, uses the router-based getter for size determination, and correctly computes the byte count for memset. This resolves past review concerns about NULL guards and router integration.


93-111: LGTM! Properly refactored to use router parameter.

The function correctly validates the router parameter, guards against NULL, and performs bounds checking using router->route_mask_slots. This properly addresses past review concerns.


120-138: LGTM! Consistent router-based implementation.

The function follows the same correct pattern as flb_routes_mask_set_bit, with proper NULL validation and router-based bounds checking.


148-166: LGTM! Router-based bounds checking correctly implemented.

The function properly validates the router parameter and uses router-based bounds checking, consistent with the other mask bit manipulation functions.


168-177: LGTM! Correct byte count and NULL guards.

The function now properly validates both the router and route_empty_mask for NULL, and uses the correct byte count (router->route_mask_size * sizeof(flb_route_mask_element)) for memcmp. This resolves the past review concerns about incorrect element count and missing NULL guards.


179-206: LGTM! Proper NULL guards added to lifecycle functions.

Both flb_routes_empty_mask_create and flb_routes_empty_mask_destroy now validate the router parameter before dereferencing, resolving past review concerns. The create function returns -1 on NULL router, while destroy returns early, both appropriate for their respective error handling semantics.


208-224: LGTM! Correct ceiling division and NULL guard.

The function now validates the router parameter before dereferencing and uses the proper ceiling division formula (mask_size + FLB_ROUTES_MASK_ELEMENT_BITS - 1) / FLB_ROUTES_MASK_ELEMENT_BITS to compute the element count. This resolves past review concerns about incorrect mask size calculation and missing NULL checks.


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

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

Caution

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

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

181-194: Correct routes mask sizing: use ceiling division to compute element count.

The current formula adds the remainder instead of rounding up, which can wildly over-allocate or under-allocate (e.g., 127 slots → 64 elements instead of 2). Use ceiling division.

 int flb_routes_mask_set_size(size_t mask_size, struct flb_router *router)
 {
-    if (mask_size < 1) {
-        mask_size = 1;
-    }
-
-    mask_size = (mask_size / FLB_ROUTES_MASK_ELEMENT_BITS) +
-                (mask_size % FLB_ROUTES_MASK_ELEMENT_BITS);
-
-    router->route_mask_size = mask_size;
-    router->route_mask_slots = mask_size * FLB_ROUTES_MASK_ELEMENT_BITS;
-
-    return flb_routes_empty_mask_create(router);
+    /* mask_size is the requested number of slots (bits) */
+    if (mask_size < 1) {
+        mask_size = 1;
+    }
+    /* number of elements needed to hold mask_size bits */
+    size_t elements = (mask_size + FLB_ROUTES_MASK_ELEMENT_BITS - 1) /
+                      FLB_ROUTES_MASK_ELEMENT_BITS;
+
+    router->route_mask_size  = elements;
+    router->route_mask_slots = elements * FLB_ROUTES_MASK_ELEMENT_BITS;
+
+    return flb_routes_empty_mask_create(router);
 }
🧹 Nitpick comments (11)
src/flb_engine.c (3)

420-431: Router drop metrics in RETRY (max retries) path are consistent.

When maximum retries are exhausted, drop metrics are correctly updated. Note that in_name and out_name are reassigned (lines 421-422) but already have the correct values from line 294-295, so this is redundant but harmless.

Lines 421-422 reassign in_name and out_name but they already have the correct values from lines 294-295. Consider removing these redundant assignments:

             if (task->event_chunk->type == FLB_INPUT_LOGS) {
-                in_name = (char *) flb_input_name(task->i_ins);
-                out_name = (char *) flb_output_name(ins);
-
                 cmt_counter_add(config->router->logs_drop_records_total, ts,

246-248: Use const for names to document immutability.

in_name/out_name are not modified; prefer const char *. Keep casts at call sites if needed by cmetrics API.

-    char *in_name;
-    char *out_name;
+    const char *in_name;
+    const char *out_name;
@@
-    in_name = (char *) flb_input_name(task->i_ins);
-    out_name = (char *) flb_output_name(ins);
+    in_name = flb_input_name(task->i_ins);
+    out_name = flb_output_name(ins);

Also applies to: 294-296


415-436: Remove redundant name re-assignments.

in_name/out_name are already set above; reassigning adds noise.

-            if (task->event_chunk->type == FLB_INPUT_LOGS) {
-                in_name = (char *) flb_input_name(task->i_ins);
-                out_name = (char *) flb_output_name(ins);
-
+            if (task->event_chunk->type == FLB_INPUT_LOGS) {
                 cmt_counter_add(config->router->logs_drop_records_total, ts,
                                 task->records,
                                 2, (char *[]) {in_name, out_name});
src/flb_router.c (3)

359-369: Router destruction is correct but has a minor issue.

The cleanup sequence is correct (masks → cmt → router). However, line 368 sets router = NULL after freeing, which has no effect since router is a local parameter. The caller's pointer remains unchanged.

Line 368 sets router = NULL but this only affects the local parameter, not the caller's pointer. Consider removing this line as it has no effect:

     flb_free(router);
-    router = NULL;
 }

Alternatively, if the intent is to null the caller's pointer, change the signature to void flb_router_destroy(struct flb_router **router) and dereference accordingly. However, this is inconsistent with other destroy functions in the codebase (e.g., flb_cf_destroy), so removing the line is preferred.


273-333: Metrics definitions look good; consider de-duplicating label keys.

Minor DRY: reuse a single label_keys array for the four counters.

 static int router_metrics_create(struct flb_router *router)
 {
@@
-    router->logs_records_total = cmt_counter_create(
+    static char *labels_io[] = { "input", "output" };
+    router->logs_records_total = cmt_counter_create(
                                                     router->cmt,
                                                     "fluentbit", "routing_logs", "records_total",
                                                     "Total log records routed from input to output",
-                                                    2,
-                                                    (char *[]) { "input", "output" });
+                                                    2, labels_io);
@@
-    router->logs_bytes_total = cmt_counter_create(
+    router->logs_bytes_total = cmt_counter_create(
                                                  router->cmt,
                                                  "fluentbit", "routing_logs", "bytes_total",
                                                  "Total bytes routed from input to output (logs)",
-                                                 2,
-                                                 (char *[]) { "input", "output" });
+                                                 2, labels_io);
@@
-    router->logs_drop_records_total = cmt_counter_create(
+    router->logs_drop_records_total = cmt_counter_create(
                                                         router->cmt,
                                                         "fluentbit", "routing_logs", "drop_records_total",
                                                         "Total log records dropped during routing",
-                                                        2,
-                                                        (char *[]) { "input", "output" });
+                                                        2, labels_io);
@@
-    router->logs_drop_bytes_total = cmt_counter_create(
+    router->logs_drop_bytes_total = cmt_counter_create(
                                                        router->cmt,
                                                        "fluentbit", "routing_logs", "drop_bytes_total",
                                                        "Total bytes dropped during routing (logs)",
-                                                       2,
-                                                       (char *[]) { "input", "output" });
+                                                       2, labels_io);

335-357: Silence unused parameter warning.

config is not used; cast to void.

 struct flb_router *flb_router_create(struct flb_config *config)
 {
     struct flb_router *router;
 
+    (void) config;
src/flb_routes_mask.c (4)

159-171: Add failure log and ensure mem utilities header is included.

On allocation failure, emit a clear error for troubleshooting. Also ensure flb_mem.h is included directly (if not via transitive includes) so flb_calloc/flb_free are declared.

 int flb_routes_empty_mask_create(struct flb_router *router)
 {
     flb_routes_empty_mask_destroy(router);
 
     router->route_empty_mask = flb_calloc(router->route_mask_size,
                                           sizeof(flb_route_mask_element));
 
     if (router->route_empty_mask == NULL) {
+        flb_error("[routes_mask] cannot allocate empty mask (elements=%zu)",
+                  router->route_mask_size);
         return -1;
     }
 
     return 0;
 }

Please verify whether this file directly includes <fluent-bit/flb_mem.h>. If not, add:

 #include <fluent-bit/flb_routes_mask.h>
+#include <fluent-bit/flb_mem.h>

26-34: Optional: add defensive checks for getters.

These helpers assume non-NULL router. Consider asserting or returning 0 when router is NULL to avoid UB in edge paths.

 size_t flb_routes_mask_get_size(struct flb_router *router)
 {
-    return router->route_mask_size;
+    return router ? router->route_mask_size : 0;
 }
 
 size_t flb_routes_mask_get_slots(struct flb_router *router)
 {
-    return router->route_mask_slots;
+    return router ? router->route_mask_slots : 0;
 }

55-56: Consider copying the canonical empty mask instead of memset(0).

If the empty mask ever changes semantics, memcpy from router->route_empty_mask keeps behavior consistent and avoids duplicating assumptions.

-    size = flb_routes_mask_get_size(in->config->router);
-    memset(routes_mask, 0, sizeof(flb_route_mask_element) * size);
+    size = flb_routes_mask_get_size(in->config->router);
+    if (in->config->router->route_empty_mask) {
+        memcpy(routes_mask,
+               in->config->router->route_empty_mask,
+               sizeof(flb_route_mask_element) * size);
+    }
+    else {
+        memset(routes_mask, 0, sizeof(flb_route_mask_element) * size);
+    }

91-99: Deduplicate index validation across set/get/clear.

The bounds check logic is repeated. Factor into a small static inline helper to reduce drift and keep warnings uniform.

+static inline int routes_mask_index_invalid(const struct flb_router *router, int value)
+{
+    if (value < 0 || (size_t) value >= router->route_mask_slots) {
+        return 1;
+    }
+    return 0;
+}
...
-    if (value < 0 || value >= router->route_mask_slots) {
+    if (routes_mask_index_invalid(router, value)) {
         flb_warn("[routes_mask] Can't set bit (%d) past limits of bitfield", value);
         return;
     }

(Apply similarly to clear/get.)

Also applies to: 115-124, 140-149

src/flb_config.c (1)

623-623: Guard router destroy or make flb_router_destroy NULL-safe.

Defensive check prevents crashes if config->router is NULL on unusual init/fail paths. Alternatively, add a NULL guard inside flb_router_destroy (preferred; see router.c comment).

-    flb_router_destroy(config->router);
+    if (config->router) {
+        flb_router_destroy(config->router);
+    }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d985e8e and cfe6474.

📒 Files selected for processing (11)
  • include/fluent-bit/flb_config.h (1 hunks)
  • include/fluent-bit/flb_router.h (2 hunks)
  • include/fluent-bit/flb_routes_mask.h (1 hunks)
  • plugins/in_storage_backlog/sb.c (4 hunks)
  • src/flb_config.c (3 hunks)
  • src/flb_engine.c (9 hunks)
  • src/flb_input_chunk.c (15 hunks)
  • src/flb_metrics_exporter.c (2 hunks)
  • src/flb_router.c (1 hunks)
  • src/flb_routes_mask.c (8 hunks)
  • src/flb_task.c (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (10)
src/flb_task.c (1)
src/flb_routes_mask.c (1)
  • flb_routes_mask_get_bit (134-149)
src/flb_router.c (3)
lib/cmetrics/src/cmt_counter.c (1)
  • cmt_counter_create (26-81)
include/fluent-bit/flb_mem.h (2)
  • flb_calloc (84-96)
  • flb_free (126-128)
src/flb_routes_mask.c (1)
  • flb_routes_empty_mask_destroy (173-179)
src/flb_routes_mask.c (1)
include/fluent-bit/flb_mem.h (2)
  • flb_calloc (84-96)
  • flb_free (126-128)
include/fluent-bit/flb_router.h (1)
src/flb_router.c (2)
  • flb_router_create (335-357)
  • flb_router_destroy (359-369)
src/flb_metrics_exporter.c (1)
lib/cmetrics/src/cmt_cat.c (1)
  • cmt_cat (638-649)
plugins/in_storage_backlog/sb.c (2)
src/flb_routes_mask.c (1)
  • flb_routes_mask_get_slots (31-34)
include/fluent-bit/flb_mem.h (1)
  • flb_calloc (84-96)
src/flb_engine.c (4)
src/flb_input.c (1)
  • flb_input_name (790-797)
src/flb_output.c (1)
  • flb_output_name (1087-1094)
lib/cmetrics/src/cmt_counter.c (1)
  • cmt_counter_add (119-135)
src/flb_routes_mask.c (1)
  • flb_routes_mask_set_size (181-194)
src/flb_config.c (4)
src/flb_router.c (2)
  • flb_router_create (335-357)
  • flb_router_destroy (359-369)
src/config_format/flb_config_format.c (1)
  • flb_cf_destroy (151-157)
include/fluent-bit/flb_mem.h (1)
  • flb_free (126-128)
src/flb_routes_mask.c (1)
  • flb_routes_mask_set_size (181-194)
src/flb_input_chunk.c (5)
src/flb_routes_mask.c (2)
  • flb_routes_mask_is_empty (151-157)
  • flb_routes_mask_get_size (26-29)
lib/cmetrics/src/cmt_counter.c (1)
  • cmt_counter_add (119-135)
src/flb_input.c (1)
  • flb_input_name (790-797)
src/flb_output.c (1)
  • flb_output_name (1087-1094)
include/fluent-bit/flb_mem.h (1)
  • flb_calloc (84-96)
include/fluent-bit/flb_routes_mask.h (1)
src/flb_routes_mask.c (10)
  • flb_routes_mask_set_by_tag (40-76)
  • flb_routes_mask_get_bit (134-149)
  • flb_routes_mask_set_bit (85-100)
  • flb_routes_mask_clear_bit (109-124)
  • flb_routes_mask_is_empty (151-157)
  • flb_routes_empty_mask_create (159-171)
  • flb_routes_empty_mask_destroy (173-179)
  • flb_routes_mask_set_size (181-194)
  • flb_routes_mask_get_size (26-29)
  • flb_routes_mask_get_slots (31-34)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (29)
  • GitHub Check: pr-windows-build / call-build-windows-package (Windows 32bit, x86, x86-windows-static, 3.31.6)
  • GitHub Check: pr-windows-build / call-build-windows-package (Windows 64bit (Arm64), amd64_arm64, -DCMAKE_SYSTEM_NAME=Windows -DCMA...
  • GitHub Check: pr-windows-build / call-build-windows-package (Windows 64bit, x64, x64-windows-static, 3.31.6)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 3.31.6, gcc, g++)
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-24.04, clang-14)
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-24.04, clang-14)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_ADDRESS=On, 3.31.6, clang, clang++)
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-22.04, clang-12)
  • GitHub Check: pr-compile-centos-7
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-22.04, clang-12)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_ARROW=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_MEMORY=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_COVERAGE=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_MEMORY=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_ADDRESS=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=On, 3.31.6, clang, clang++)
  • GitHub Check: PR - fuzzing test
🔇 Additional comments (23)
src/flb_metrics_exporter.c (1)

35-35: Concatenate router CMetrics into exporter context: LGTM

The null checks and cmt_cat error handling are consistent with existing patterns.

Also applies to: 312-319

include/fluent-bit/flb_config.h (1)

294-296: Router pointer initialization and teardown confirmedconfig->router is created in flb_config_init() (flb_config.c:307) and destroyed in flb_config_exit() (flb_config.c:623).

src/flb_task.c (1)

447-450: Router lifecycle validated
config->router is instantiated in flb_config_init (src/flb_config.c:307) and cleaned up in flb_config_exit (src/flb_config.c:623), ensuring it exists before any task is created and is properly destroyed on exit.

src/flb_input_chunk.c (3)

217-233: LGTM! Router metrics integration for logs is correct.

The new metrics block properly gates router metrics updates with an event type check and uses the correct counter APIs with appropriate labels (input name, output name).


965-966: Same router null-check concern.

Ensure in->config->router is valid before calling flb_routes_mask_get_size.


662-664: Resolve: router always initialized
config->router is created at src/flb_config.c:307 and immediately checked (and aborts config creation) if null (lines 307–312), so by the time flb_input_chunk_map runs, in->config->router cannot be NULL. No additional null check needed.

src/flb_config.c (3)

307-314: Router creation order looks correct.

Router is created before inputs/outputs are initialized (which happens later in flb_engine_start). The initial size is set to 1, then resized in the engine once the actual output count is known (line 861 in flb_engine.c). Error handling properly cleans up on failure.


623-623: LGTM! Router cleanup is correct.

The router is destroyed in the cleanup path, which properly releases all router resources including metrics and masks.


47-47: Include looks correct.

Header addition aligns with new router usage.

src/flb_engine.c (10)

294-295: LGTM! Input/output names extracted correctly.

Using flb_input_name and flb_output_name ensures alias is preferred over instance name, providing consistent labeling.


314-322: Verify metrics are incremented for the OK path.

Router metrics correctly increment records and bytes for the FLB_INPUT_LOGS type with input/output labels. This mirrors the output plugin metrics above.


374-382: Router drop metrics in RETRY (no retry config) path are consistent.

When retry_limit == FLB_OUT_RETRY_NONE, both drop_records and drop_bytes are correctly incremented for logs.


510-518: Router drop metrics in ERROR path are consistent.

Drop metrics for errors match the pattern used in the retry paths.


861-861: LGTM! Routes mask sizing now uses router.

The call to flb_routes_mask_set_size correctly passes config->router instead of config, aligning with the new router-centric API.


304-322: Router metrics on OK path look correct (labels: input, output).

Counters increment with total_events and size only for LOGS; matches intent.


361-364: Gauge labeling with output name is consistent.

Chunk capacity gauge uses {output} uniformly across paths.

Also applies to: 384-387, 433-436, 493-496, 520-523


371-387: Drop metrics for LOGS cover both records and bytes.

Updates align with the new router counters (drop_records_total / drop_bytes_total).

Also applies to: 505-523


861-866: LGTM: route mask sized using router with error handling.

Dimensioning based on outputs and checking ret is the right place/time.


327-329: Histogram label schema matches observe callcmt_latency is created with two labels ["input","output"] in the correct order, matching the observe invocation.

src/flb_router.c (2)

273-333: LGTM! Router metrics creation is well-structured.

The four counters follow a consistent naming pattern under the fluentbit.routing_logs namespace with appropriate descriptions. All counters use two labels (input, output) matching the usage in flb_engine.c. Error handling returns -1 on any failure.


335-357: LGTM! Router creation has proper error handling.

The function correctly:

  • Allocates the router structure
  • Creates the cmetrics context
  • Initializes metrics via router_metrics_create
  • Cleans up via flb_router_destroy on any failure
  • Returns NULL on error
include/fluent-bit/flb_routes_mask.h (1)

50-69: No remaining calls use the old flb_config *config; all invocations correctly pass the flb_router * (e.g. via config->router).

src/flb_routes_mask.c (1)

181-194: No action required—bounds already safe
flb_routes_mask_set_size is always called with mk_list_size(&config->outputs), and output IDs are assigned sequentially from 0 up, so router->route_mask_slots (rounded-up slots × FLB_ROUTES_MASK_ELEMENT_BITS) is guaranteed to be ≥ highest output id + 1.

Comment on lines +86 to +87
int flb_router_metrics_create(struct flb_config *config, struct flb_router *router);
struct flb_router *flb_router_create(struct flb_config *config);
Copy link

@coderabbitai coderabbitai bot Sep 30, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

API name/signature mismatch: flb_router_metrics_create vs router_metrics_create

src/flb_router.c calls router_metrics_create(router) (no config arg), while this header declares flb_router_metrics_create(struct flb_config *, struct flb_router *). This likely causes an unresolved/unused symbol scenario.

Run to confirm and decide whether to:

  • remove the public flb_router_metrics_create declaration, keeping a private router_metrics_create, or
  • standardize on a single public symbol and update the call site.

🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n 'flb_router_metrics_create\s*\(' -C2 || true
rg -n 'router_metrics_create\s*\(' -C2 || true
rg -n 'flb_router_create\s*\(' -n -C3 src/flb_router.c || true

Length of output: 1338


Remove or correct flb_router_metrics_create declaration
The header declares int flb_router_metrics_create(struct flb_config *, struct flb_router *) but only a private static int router_metrics_create(struct flb_router *) exists in src/flb_router.c, leading to an unresolved symbol. Either remove the public declaration from include/fluent-bit/flb_router.h or provide a matching implementation.

🤖 Prompt for AI Agents
In include/fluent-bit/flb_router.h around lines 86-87, the header declares
flb_router_metrics_create(struct flb_config *, struct flb_router *) but only a
private static router_metrics_create(struct flb_router *) exists in
src/flb_router.c causing an unresolved symbol; either remove the public
declaration from the header or implement a public flb_router_metrics_create with
the declared signature in src/flb_router.c that adapts/forwards to the existing
router_metrics_create (accepting/using the config param or ignoring it
consistently) and ensure it is non-static and exported.

Copy link
Member Author

Choose a reason for hiding this comment

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

good catch

Copy link

Choose a reason for hiding this comment

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

@edsiper, thank you for confirming! I'm glad I could help identify this issue. 🐰

🌟
┏━━━━━━━━━━━━━━━━━━┓
┃ Happy to help! ┃
┗━━━━━━━━━━━━━━━━━━┛
(_/)
(='.'=)
(")
(")

Comment on lines +287 to 290
slots = flb_routes_mask_get_slots(context->ins->config->router);
memset(&dummy_input_chunk, 0, sizeof(struct flb_input_chunk));
memset(context->dummy_routes_mask, 0, slots * sizeof(flb_route_mask_element));

Copy link

@coderabbitai coderabbitai bot Sep 30, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Use route_mask element count, not slots (bits), for allocation/memset

You’re using flb_routes_mask_get_slots() (bits) to size arrays of flb_route_mask_element. This over-allocates by a factor of element bit-width (typically 64) and repeats during memset. Use the element count from flb_routes_mask_get_size() instead.

Apply:

-    size_t                  slots;
+    size_t                  elements;
@@
-    slots = flb_routes_mask_get_slots(context->ins->config->router);
+    elements = flb_routes_mask_get_size(context->ins->config->router);
     memset(&dummy_input_chunk, 0, sizeof(struct flb_input_chunk));
-    memset(context->dummy_routes_mask, 0, slots * sizeof(flb_route_mask_element));
+    memset(context->dummy_routes_mask, 0, elements * sizeof(flb_route_mask_element));

And at init:

-    size = flb_routes_mask_get_slots(config->router);
-    ctx->dummy_routes_mask = flb_calloc(size, sizeof(flb_route_mask_element));
+    size = flb_routes_mask_get_size(config->router);
+    ctx->dummy_routes_mask = flb_calloc(size, sizeof(flb_route_mask_element));

This prevents unnecessary memory usage and keeps the mask operations within bounds.

Also applies to: 668-671

Copy link
Member Author

Choose a reason for hiding this comment

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

this is fine

Copy link
Member Author

Choose a reason for hiding this comment

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

this is fine

Copy link

Choose a reason for hiding this comment

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

@edsiper, understood! I'll disregard this suggestion. Thank you for clarifying.

Copy link

Choose a reason for hiding this comment

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

@edsiper, understood! I'll defer to your judgment on this. Thank you for the clarification.

Comment on lines 306 to 315
/* Routing */
flb_routes_mask_set_size(1, config);
config->router = flb_router_create(config);
if (!config->router) {
flb_error("[config] could not create router");
flb_cf_destroy(cf);
flb_free(config);
return NULL;
}
flb_routes_mask_set_size(1, config->router);

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Handle flb_routes_mask_set_size() failure to avoid partial-init leaks.

If mask allocation fails, we proceed with a half-initialized router. Bail out and clean up.

-    flb_routes_mask_set_size(1, config->router);
+    ret = flb_routes_mask_set_size(1, config->router);
+    if (ret != 0) {
+        flb_error("[config] routing mask init failed");
+        flb_cf_destroy(cf);
+        flb_router_destroy(config->router);
+        flb_free(config);
+        return NULL;
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/* Routing */
flb_routes_mask_set_size(1, config);
config->router = flb_router_create(config);
if (!config->router) {
flb_error("[config] could not create router");
flb_cf_destroy(cf);
flb_free(config);
return NULL;
}
flb_routes_mask_set_size(1, config->router);
/* Routing */
config->router = flb_router_create(config);
if (!config->router) {
flb_error("[config] could not create router");
flb_cf_destroy(cf);
flb_free(config);
return NULL;
}
ret = flb_routes_mask_set_size(1, config->router);
if (ret != 0) {
flb_error("[config] routing mask init failed");
flb_cf_destroy(cf);
flb_router_destroy(config->router);
flb_free(config);
return NULL;
}
🤖 Prompt for AI Agents
In src/flb_config.c around lines 306 to 315, flb_routes_mask_set_size(...)
return value is not checked so a mask allocation failure would leave a
half-initialized router and leak resources; update the code to check the
function's return (non-zero = failure), log an error, call flb_cf_destroy(cf),
destroy/free the router (e.g. flb_router_destroy(config->router) or the
appropriate cleanup function), free config, and return NULL to fully abort
initialization on failure.

Comment on lines +359 to +369
void flb_router_destroy(struct flb_router *router)
{
flb_routes_empty_mask_destroy(router);

if (router->cmt) {
cmt_destroy(router->cmt);
}

flb_free(router);
router = NULL;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

NULL-guard flb_router_destroy to avoid potential segfaults.

Make destroy idempotent and safe (callers like config exit paths often destroy unconditionally).

-void flb_router_destroy(struct flb_router *router)
+void flb_router_destroy(struct flb_router *router)
 {
-    flb_routes_empty_mask_destroy(router);
+    if (router == NULL) {
+        return;
+    }
+
+    flb_routes_empty_mask_destroy(router);
 
     if (router->cmt) {
         cmt_destroy(router->cmt);
     }
 
     flb_free(router);
-    router = NULL;
+    /* note: caller holds the pointer; setting local param to NULL has no effect */
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
void flb_router_destroy(struct flb_router *router)
{
flb_routes_empty_mask_destroy(router);
if (router->cmt) {
cmt_destroy(router->cmt);
}
flb_free(router);
router = NULL;
}
void flb_router_destroy(struct flb_router *router)
{
if (router == NULL) {
return;
}
flb_routes_empty_mask_destroy(router);
if (router->cmt) {
cmt_destroy(router->cmt);
}
flb_free(router);
/* note: caller holds the pointer; setting local param to NULL has no effect */
}
🤖 Prompt for AI Agents
In src/flb_router.c around lines 359 to 369, make flb_router_destroy NULL-safe
and idempotent by returning immediately if the passed-in router is NULL, keep
the existing cmt NULL-check and destroy call, call flb_routes_empty_mask_destroy
only when router is non-NULL, and remove the ineffective "router = NULL"
assignment after flb_free(router) (since the parameter is passed by value); this
ensures safe repeated/conditional destruction without dereferencing NULL or
leaving misleading code.

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

Caution

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

⚠️ Outside diff range comments (4)
src/flb_routes_mask.c (4)

87-102: Add NULL guard to prevent crash when router is NULL.

The function dereferences router->route_mask_slots at line 93 without validating that router is non-NULL. This will cause a segmentation fault if called with NULL.

Apply this diff:

 void flb_routes_mask_set_bit(flb_route_mask_element *routes_mask, int value,
                              struct flb_router *router)
 {
     int index;
     uint64_t bit;
 
+    if (router == NULL) {
+        flb_warn("[routes_mask] Can't set bit, router is NULL");
+        return;
+    }
+
     if (value < 0 || value >= router->route_mask_slots) {

111-126: Add NULL guard to prevent crash when router is NULL.

The function dereferences router->route_mask_slots at line 117 without validating that router is non-NULL. This will cause a segmentation fault if called with NULL.

Apply this diff:

 void flb_routes_mask_clear_bit(flb_route_mask_element *routes_mask, int value,
                                struct flb_router *router)
 {
     int index;
     uint64_t bit;
 
+    if (router == NULL) {
+        flb_warn("[routes_mask] Can't clear bit, router is NULL");
+        return;
+    }
+
     if (value < 0 || value >= router->route_mask_slots) {

136-151: Add NULL guard to prevent crash when router is NULL.

The function dereferences router->route_mask_slots at line 142 without validating that router is non-NULL. This will cause a segmentation fault if called with NULL.

Apply this diff:

 int flb_routes_mask_get_bit(flb_route_mask_element *routes_mask, int value,
                             struct flb_router *router)
 {
     int index;
     uint64_t bit;
 
+    if (router == NULL) {
+        flb_warn("[routes_mask] Can't get bit, router is NULL");
+        return 0;
+    }
+
     if (value < 0 || value >= router->route_mask_slots) {

192-205: Add NULL guard to prevent crash when router is NULL.

The function dereferences router->route_mask_size and router->route_mask_slots at lines 201-202 without validating that router is non-NULL. This will cause a segmentation fault if called with NULL.

Apply this diff:

 int flb_routes_mask_set_size(size_t mask_size, struct flb_router *router)
 {
+    if (router == NULL) {
+        flb_error("[routes_mask] Cannot set size, router is NULL");
+        return -1;
+    }
+
     if (mask_size < 1) {
♻️ Duplicate comments (1)
src/flb_routes_mask.c (1)

26-34: Add NULL guards in getter functions to prevent crashes.

Both getter functions dereference router without NULL checks. If router is NULL, a segmentation fault will occur. This is inconsistent with flb_routes_mask_is_empty (lines 156-158) which properly guards against NULL.

Apply this diff:

 size_t flb_routes_mask_get_size(struct flb_router *router)
 {
+    if (router == NULL) {
+        return 0;
+    }
     return router->route_mask_size;
 }
 
 size_t flb_routes_mask_get_slots(struct flb_router *router)
 {
+    if (router == NULL) {
+        return 0;
+    }
     return router->route_mask_slots;
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e79a77d and d87b70a.

📒 Files selected for processing (1)
  • src/flb_routes_mask.c (8 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/flb_routes_mask.c (1)
include/fluent-bit/flb_mem.h (2)
  • flb_calloc (84-96)
  • flb_free (126-128)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: pr-windows-build / call-build-windows-package (Windows 64bit, x64, x64-windows-static, 3.31.6)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=On, 3.31.6, gcc, g++)
  • GitHub Check: PR - fuzzing test
  • GitHub Check: pr-compile-without-cxx (3.31.6)
  • GitHub Check: pr-compile-centos-7
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-24.04, clang-14)
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-24.04, clang-14)
🔇 Additional comments (4)
src/flb_routes_mask.c (4)

52-54: LGTM!

The NULL guards for in->config and in->config->router properly prevent potential segmentation faults. The defensive check aligns with best practices.


156-161: LGTM!

The NULL guards and corrected byte count in memcmp (using router->route_mask_size * sizeof(flb_route_mask_element)) properly address the issues identified in previous reviews.


166-168: LGTM!

The NULL guard prevents crashes and the early return pattern is appropriate.


183-189: LGTM!

The NULL guards and defensive double-check before freeing memory follow best practices for safe resource cleanup.

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

Caution

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

⚠️ Outside diff range comments (3)
src/flb_routes_mask.c (3)

87-102: Add NULL check for consistency and safety.

The function dereferences router->route_mask_slots at line 93 without validating that router is non-NULL. This is inconsistent with flb_routes_mask_is_empty, flb_routes_empty_mask_create, and flb_routes_empty_mask_destroy, which all guard against NULL router.

Apply this diff:

 void flb_routes_mask_set_bit(flb_route_mask_element *routes_mask, int value,
                              struct flb_router *router)
 {
     int index;
     uint64_t bit;
 
+    if (router == NULL) {
+        flb_warn("[routes_mask] Can't set bit with NULL router");
+        return;
+    }
+
     if (value < 0 || value >= router->route_mask_slots) {

111-126: Add NULL check for consistency and safety.

The function dereferences router->route_mask_slots at line 117 without validating that router is non-NULL. For consistency with other functions that guard against NULL router, add a defensive check.

Apply this diff:

 void flb_routes_mask_clear_bit(flb_route_mask_element *routes_mask, int value,
                                struct flb_router *router)
 {
     int index;
     uint64_t bit;
 
+    if (router == NULL) {
+        flb_warn("[routes_mask] Can't clear bit with NULL router");
+        return;
+    }
+
     if (value < 0 || value >= router->route_mask_slots) {

136-151: Add NULL check for consistency and safety.

The function dereferences router->route_mask_slots at line 142 without validating that router is non-NULL. For consistency with other functions that guard against NULL router, add a defensive check.

Apply this diff:

 int flb_routes_mask_get_bit(flb_route_mask_element *routes_mask, int value,
                             struct flb_router *router)
 {
     int index;
     uint64_t bit;
 
+    if (router == NULL) {
+        flb_warn("[routes_mask] Can't get bit with NULL router");
+        return 0;
+    }
+
     if (value < 0 || value >= router->route_mask_slots) {
♻️ Duplicate comments (1)
src/flb_routes_mask.c (1)

26-34: Add NULL guards to prevent crashes in getter functions.

Both getter functions directly dereference router without NULL checks. This issue was previously flagged but remains unaddressed. For consistency with flb_routes_mask_is_empty (which guards against NULL at lines 156-158), add defensive checks here as well.

Apply this diff:

 size_t flb_routes_mask_get_size(struct flb_router *router)
 {
+    if (router == NULL) {
+        return 0;
+    }
     return router->route_mask_size;
 }
 
 size_t flb_routes_mask_get_slots(struct flb_router *router)
 {
+    if (router == NULL) {
+        return 0;
+    }
     return router->route_mask_slots;
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d87b70a and 26ca515.

📒 Files selected for processing (1)
  • src/flb_routes_mask.c (7 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/flb_routes_mask.c (1)
include/fluent-bit/flb_mem.h (2)
  • flb_calloc (84-96)
  • flb_free (126-128)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: pr-windows-build / call-build-windows-package (Windows 32bit, x86, x86-windows-static, 3.31.6)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_COVERAGE=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, gcc, g++)
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-22.04, clang-12)
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-24.04, clang-14)
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-22.04, clang-12)
  • GitHub Check: pr-compile-centos-7
  • GitHub Check: pr-compile-without-cxx (3.31.6)
  • GitHub Check: PR - fuzzing test
🔇 Additional comments (4)
src/flb_routes_mask.c (4)

153-162: LGTM! NULL checks and memcmp byte count are correct.

The function properly guards against NULL router and NULL route_empty_mask before dereferencing. The memcmp now correctly uses router->route_mask_size * sizeof(flb_route_mask_element) to compare the full mask bytes.


164-179: LGTM! NULL check and memory handling are correct.

The function properly guards against NULL router before dereferencing. The memory allocation using flb_calloc with router->route_mask_size and proper error handling is correct.


181-190: LGTM! NULL check and cleanup pattern are correct.

The function properly guards against NULL router before dereferencing. The double-check for route_empty_mask and setting it to NULL after freeing follows best practices.


198-198: LGTM! Ceiling division formula is correct.

The formula (mask_size + FLB_ROUTES_MASK_ELEMENT_BITS - 1) / FLB_ROUTES_MASK_ELEMENT_BITS correctly computes the minimal number of elements needed to hold mask_size bits.

#endif
)) {
flb_routes_mask_set_bit(routes_mask, o_ins->id, o_ins->config);
flb_routes_mask_set_bit(routes_mask, o_ins->id, o_ins->config->router);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Validate router before dereferencing.

While the function validates in->config->router at lines 52-54, line 72 dereferences o_ins->config->router without validation. If an output instance has a NULL config or router, this will crash.

Apply this diff:

+        if (o_ins->config == NULL || o_ins->config->router == NULL) {
+            continue;
+        }
         flb_routes_mask_set_bit(routes_mask, o_ins->id, o_ins->config->router);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
flb_routes_mask_set_bit(routes_mask, o_ins->id, o_ins->config->router);
if (o_ins->config == NULL || o_ins->config->router == NULL) {
continue;
}
flb_routes_mask_set_bit(routes_mask, o_ins->id, o_ins->config->router);
🤖 Prompt for AI Agents
In src/flb_routes_mask.c around line 72, the code dereferences
o_ins->config->router without validating o_ins or its config/router; update the
logic to first check that o_ins is non-NULL, o_ins->config is non-NULL and
o_ins->config->router is non-NULL before calling flb_routes_mask_set_bit. If any
of those are NULL, skip the call (or handle accordingly) to avoid a crash.

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