Skip to content

es_out: support Upstream Servers with configuration overriding#7608

Open
mabrarov wants to merge 12 commits intofluent:masterfrom
mabrarov:feature/out_es_upstream_support_extended
Open

es_out: support Upstream Servers with configuration overriding#7608
mabrarov wants to merge 12 commits intofluent:masterfrom
mabrarov:feature/out_es_upstream_support_extended

Conversation

@mabrarov
Copy link
Contributor

@mabrarov mabrarov commented Jun 25, 2023

Implementation of Upstream feature for the Elasticsearch output plugin.

This pull request is based on pull request #1560 and Forward output plugin.

It was tested in a local setup with:

  1. Fluent Bit without Upstream feature connected to a single node of Elasticsearch cluster consisting of 3 master-eligible/data and 1 coordinating nodes.

    Refer to elastic-cluster directory of mabrarov/elastic-stack repository for Docker Compose project used to create target Elasticsearch cluster and Kibana.

    fluent-bit.conf Fluent Bit configuration file used for the test - refer to fluent-bit-es/fluent-bit.conf and (same in YAML format) fluent-bit-es/fluent-bit.yaml in mabrarov/elastic-stack repository.

    Debug log is available at flb_es.log.

  2. Fluent Bit with Upstream feature connected to all Elasticsearch data nodes of Elasticsearch cluster consisting of 3 master-eligible/data and 1 coordinating nodes.

    Refer to elastic-cluster directory of mabrarov/elastic-stack repository for Docker Compose project used to create target Elasticsearch cluster and Kibana.

    fluent-bit.conf Fluent Bit configuration file used for the test - refer to fluent-bit-es-cluster/fluent-bit.conf and (same in YAML format) fluent-bit-es-cluster/fluent-bit.yaml in mabrarov/elastic-stack repository.

    Debug log is available at flb_es_upstream.log.

Testing

  • Example configuration files for the change can be found in mabrarov/elastic-stack repository under fluent-bit-es-cluster directory.
  • Debug log output from testing the change - see above.
  • Attached Valgrind output that shows no leaks or memory corruption was found - refer to flb_run_code_analysis.log for the output of command
    TEST_PRESET=valgrind SKIP_TESTS='flb-rt-out_td flb-it-network' ./run_code_analysis.sh
  • [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

Backporting

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

    • HA-aware Elasticsearch output with per-upstream/per-node configuration and upstream-aware formatter flush-context callbacks.
  • Integrations

    • Cloud ID parsing for Elasticsearch endpoints.
    • Optional AWS SigV4 support with STS and unsigned-headers handling.
  • Configuration

    • Consolidated ES property names, added upstream option, and corrected default Elasticsearch port to 9200.
  • Quality

    • Ownership-aware resource handling and improved lifecycle/cleanup.
  • Tests

    • Expanded upstream-focused tests covering formatter, flush-context, and config scenarios.

@mabrarov
Copy link
Contributor Author

Hi reviewers,

Is it possible to approve only workflow for this pull request, so that automated checks and build can start?

Thank you.

@mabrarov mabrarov temporarily deployed to pr June 28, 2023 17:55 — with GitHub Actions Inactive
@mabrarov mabrarov temporarily deployed to pr June 28, 2023 17:55 — with GitHub Actions Inactive
@mabrarov mabrarov temporarily deployed to pr June 28, 2023 17:55 — with GitHub Actions Inactive
@PettitWesley
Copy link
Contributor

@mabrarov sure

@mabrarov mabrarov temporarily deployed to pr June 28, 2023 18:22 — with GitHub Actions Inactive
@mabrarov
Copy link
Contributor Author

mabrarov commented Jun 29, 2023

Hi @PettitWesley,

It looks like all failed checks are around run-macos-unit-tests jobs and caused by the following failed unit tests:

  1. flb-rt-in_event_test
  2. flb-rt-out_tcp

I feel like other pull requests have the same issues, i.e. it doesn't seem that the failed checks are caused by this pull request changes.

Help of maintainers is appreciated.

Thank you.

@mabrarov mabrarov force-pushed the feature/out_es_upstream_support_extended branch from ba3382a to b7cd81b Compare July 8, 2023 10:22
@mabrarov
Copy link
Contributor Author

Hi @PettitWesley,

Is it possible to trigger automated workflow (build) for this pull request one more time? I found & fixed one issue and added tests for the new code since last build happened.

Thank you.

@mabrarov mabrarov temporarily deployed to pr July 10, 2023 12:05 — with GitHub Actions Inactive
@mabrarov mabrarov temporarily deployed to pr July 10, 2023 12:05 — with GitHub Actions Inactive
@mabrarov mabrarov temporarily deployed to pr July 10, 2023 12:05 — with GitHub Actions Inactive
@mabrarov mabrarov temporarily deployed to pr July 10, 2023 12:28 — with GitHub Actions Inactive
@mabrarov
Copy link
Contributor Author

Hi dear reviewers,

Is it possible to get this pull request reviewed / accepted sooner? Is there something pending / waiting from my side to start review?

Thank you.

@mabrarov mabrarov force-pushed the feature/out_es_upstream_support_extended branch from b7cd81b to b81d3f7 Compare July 20, 2023 19:38
@mabrarov
Copy link
Contributor Author

Hi @PettitWesley and @edsiper,

It feels like you are code owners for Elasticsearch output plugin. Is there something pending / waiting from my side to start review of this pull request? This new feature was requested 4 years ago and I feel it is something which multiple users of Fluent Bit (not just my team) would like to have.

Thank you.

@mabrarov mabrarov force-pushed the feature/out_es_upstream_support_extended branch from b81d3f7 to f6431c2 Compare September 30, 2023 13:32
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

🤖 Fix all issues with AI agents
In `@plugins/out_es/es.c`:
- Around line 1074-1078: The warning is misleading because
flb_elasticsearch_target(ctx, &node) failed before any HTTP action; update the
flb_plg_warn call in the failure branch of flb_elasticsearch_target to log a
clear target-resolution error (e.g., "failed to resolve Elasticsearch target" or
similar) and include relevant context such as the node variable or ec/ret values
for diagnostics; remove or replace the "http_do=%i" message so it no longer
implies an HTTP operation occurred.
♻️ Duplicate comments (1)
tests/runtime/out_elasticsearch.c (1)

31-44: Use tmpnam with caller-provided buffer as previously agreed.

The current code uses tmpnam(NULL) which returns a pointer to an internal static buffer, then copies it with flb_strdup. While this addresses the buffer reuse concern, it's cleaner to provide your own buffer as discussed in previous review comments:

-    upstream_conf_filename = tmpnam(NULL);
-    if (upstream_conf_filename == NULL) {
-        return NULL;
-    }
-    upstream_conf_filename = flb_strdup(upstream_conf_filename);
-    if (upstream_conf_filename == NULL) {
-        return NULL;
-    }
+    char tmpname_buf[L_tmpnam];
+    if (tmpnam(tmpname_buf) == NULL) {
+        return NULL;
+    }
+    upstream_conf_filename = flb_strdup(tmpname_buf);
+    if (upstream_conf_filename == NULL) {
+        return NULL;
+    }

This avoids relying on the static internal buffer.

🧹 Nitpick comments (3)
plugins/out_es/es_conf_prop.h (1)

1-65: LGTM! Clean centralization of ES configuration property names.

Defining property names as macros reduces the risk of typos and makes refactoring easier. The AWS-specific properties are correctly guarded by FLB_HAVE_AWS.

Minor nit: The copyright year (2024) differs from other files in this PR (2026). Consider updating for consistency.

plugins/out_es/es_conf.c (2)

100-107: Potential type confusion with size_t comparison to -1.

buffer_size is of type size_t (unsigned), so comparing it to -1 compares against SIZE_MAX. While this works because the config map likely sets the sentinel value as -1 which wraps to SIZE_MAX, it's somewhat confusing. Consider using an explicit constant or adding a comment clarifying this is intentional.

/* buffer_size == (size_t)-1 indicates unlimited, convert to 0 for HTTP client */
if (buffer_size == (size_t)-1) {
    return 0;
}

369-388: Boolean parsing does not validate return value.

flb_utils_bool() returns -1 for invalid boolean strings (e.g., "maybe"), but this value is directly assigned to config fields without validation. While this follows existing Fluent Bit patterns, invalid boolean values in upstream node configs will silently become -1 rather than generating a configuration error.

If strict validation is desired, consider checking the return value:

tmp = flb_upstream_node_get_property(FLB_ES_CONFIG_PROPERTY_SUPPRESS_TYPE_NAME, node);
if (tmp) {
    int bool_val = flb_utils_bool(tmp);
    if (bool_val == -1) {
        flb_plg_error(ctx->ins, "invalid boolean value for suppress_type_name: %s", tmp);
        return -1;
    }
    ec->suppress_type_name = bool_val;
}

This applies to multiple properties in this function.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7e6b33b and 182b292.

📒 Files selected for processing (15)
  • include/fluent-bit/flb_lib.h
  • include/fluent-bit/flb_output.h
  • plugins/out_es/CMakeLists.txt
  • plugins/out_es/es.c
  • plugins/out_es/es.h
  • plugins/out_es/es_conf.c
  • plugins/out_es/es_conf.h
  • plugins/out_es/es_conf_parse.c
  • plugins/out_es/es_conf_parse.h
  • plugins/out_es/es_conf_prop.h
  • plugins/out_es/es_type.c
  • plugins/out_es/es_type.h
  • src/flb_engine_dispatch.c
  • src/flb_lib.c
  • tests/runtime/out_elasticsearch.c
🚧 Files skipped from review as they are similar to previous changes (4)
  • plugins/out_es/es_conf_parse.h
  • src/flb_engine_dispatch.c
  • include/fluent-bit/flb_output.h
  • plugins/out_es/CMakeLists.txt
🧰 Additional context used
🧠 Learnings (13)
📚 Learning: 2025-11-21T06:23:29.770Z
Learnt from: cosmo0920
Repo: fluent/fluent-bit PR: 11171
File: include/fluent-bit/flb_lib.h:52-53
Timestamp: 2025-11-21T06:23:29.770Z
Learning: In Fluent Bit core (fluent/fluent-bit repository), function descriptions/documentation are not required for newly added functions in header files.

Applied to files:

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

Applied to files:

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

Applied to files:

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

Applied to files:

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

Applied to files:

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

Applied to files:

  • include/fluent-bit/flb_lib.h
📚 Learning: 2025-08-31T12:46:11.940Z
Learnt from: ThomasDevoogdt
Repo: fluent/fluent-bit PR: 9277
File: .github/workflows/pr-compile-check.yaml:147-151
Timestamp: 2025-08-31T12:46:11.940Z
Learning: In fluent-bit CMakeLists.txt, the system library preference flags are defined as FLB_PREFER_SYSTEM_LIB_ZSTD and FLB_PREFER_SYSTEM_LIB_KAFKA with the FLB_ prefix.

Applied to files:

  • include/fluent-bit/flb_lib.h
  • plugins/out_es/es.h
📚 Learning: 2025-08-20T02:04:27.220Z
Learnt from: mabrarov
Repo: fluent/fluent-bit PR: 7608
File: plugins/out_es/es.c:648-670
Timestamp: 2025-08-20T02:04:27.220Z
Learning: The author mabrarov prefers function contracts that assume valid parameters for internal functions in the Elasticsearch output plugin, rather than adding defensive null pointer checks, to maintain performance and code clarity.

Applied to files:

  • plugins/out_es/es.c
  • plugins/out_es/es_conf_parse.c
📚 Learning: 2025-09-22T15:59:55.794Z
Learnt from: nicknezis
Repo: fluent/fluent-bit PR: 10882
File: plugins/out_http/http.c:112-116
Timestamp: 2025-09-22T15:59:55.794Z
Learning: When users consider bug fixes out of scope for their focused PRs, it's appropriate to create separate GitHub issues to track those concerns rather than expanding the current PR scope.

Applied to files:

  • plugins/out_es/es.c
📚 Learning: 2025-10-06T17:39:21.606Z
Learnt from: edsiper
Repo: fluent/fluent-bit PR: 10967
File: plugins/in_elasticsearch/in_elasticsearch_bulk_prot.c:266-272
Timestamp: 2025-10-06T17:39:21.606Z
Learning: In the in_elasticsearch plugin, payloads are JSON-based, so tag_key values will always be strings. There's no need to handle binary (FLB_RA_BINARY) values when extracting tags from records in this plugin.

Applied to files:

  • plugins/out_es/es.c
📚 Learning: 2025-11-11T20:33:42.883Z
Learnt from: mabrarov
Repo: fluent/fluent-bit PR: 7608
File: plugins/out_es/es_conf.c:932-946
Timestamp: 2025-11-11T20:33:42.883Z
Learning: The mk_list_is_empty function in Fluent Bit returns 0 when a list IS empty and -1 when a list is NOT empty. Use `mk_list_is_empty(list) == 0` to check if empty, and `mk_list_is_empty(list) != 0` to check if not empty.

Applied to files:

  • plugins/out_es/es_conf.c
📚 Learning: 2025-09-08T11:21:33.975Z
Learnt from: cosmo0920
Repo: fluent/fluent-bit PR: 10851
File: include/fluent-bit/flb_simd.h:60-66
Timestamp: 2025-09-08T11:21:33.975Z
Learning: Fluent Bit currently only supports MSVC compiler on Windows, so additional compiler compatibility guards may be unnecessary for Windows-specific code paths.

Applied to files:

  • plugins/out_es/es_conf_parse.c
📚 Learning: 2025-12-17T18:45:02.283Z
Learnt from: edsiper
Repo: fluent/fluent-bit PR: 11286
File: src/flb_http_client.c:1657-1715
Timestamp: 2025-12-17T18:45:02.283Z
Learning: In the Fluent Bit OAuth2 implementation (src/flb_oauth2.c), the function flb_oauth2_get_access_token returns a pointer to the cached token stored in the OAuth2 context (ctx->access_token), not a new allocation. The OAuth2 context manages the token lifecycle, so callers must not free the returned token pointer.

Applied to files:

  • plugins/out_es/es_conf_parse.c
🧬 Code graph analysis (8)
include/fluent-bit/flb_lib.h (2)
include/fluent-bit/flb_output.h (1)
  • int (583-586)
src/flb_lib.c (1)
  • flb_output_set_test_flush_ctx_callback (617-649)
plugins/out_es/es.c (2)
plugins/out_es/es_conf.c (1)
  • flb_es_upstream_conf (887-901)
src/flb_upstream_ha.c (1)
  • flb_upstream_ha_node_get (88-110)
tests/runtime/out_elasticsearch.c (2)
plugins/out_es/es.c (1)
  • flb_elasticsearch_target (652-674)
src/flb_lib.c (6)
  • flb_output_set_test_flush_ctx_callback (617-649)
  • flb_start (1017-1028)
  • flb_input (266-276)
  • flb_output (279-289)
  • flb_output_set (520-551)
  • flb_output_set_test (584-615)
plugins/out_es/es_conf.c (9)
plugins/out_es/es_type.c (10)
  • flb_es_ra_move_ra (182-190)
  • flb_es_str_copy_str (48-63)
  • flb_es_str_set_str (41-46)
  • flb_es_aws_provider_set (204-215)
  • flb_es_ra_set_ra (172-180)
  • flb_es_sds_copy_str (85-100)
  • flb_es_sds_destroy (65-74)
  • flb_es_ra_destroy (161-170)
  • flb_es_list_destroy (102-112)
  • flb_es_str_destroy (30-39)
src/flb_record_accessor.c (1)
  • flb_ra_create (271-358)
include/fluent-bit/flb_mem.h (2)
  • flb_free (126-128)
  • flb_calloc (84-96)
plugins/out_es/es_conf_parse.c (3)
  • flb_es_conf_set_cloud_auth (142-192)
  • flb_es_conf_set_cloud_credentials (38-73)
  • flb_es_conf_set_aws_provider (279-345)
include/fluent-bit/flb_output.h (1)
  • flb_output_config_map_set (1321-1348)
src/flb_upstream_node.c (1)
  • flb_upstream_node_get_property (183-199)
src/flb_utils.c (1)
  • flb_utils_bool (757-771)
include/fluent-bit/flb_upstream_node.h (2)
  • flb_upstream_node_set_data (82-86)
  • flb_upstream_node_get_data (88-91)
src/flb_upstream.c (1)
  • flb_upstream_create (290-363)
plugins/out_es/es_conf.h (1)
plugins/out_es/es_conf.c (3)
  • flb_es_conf_create (819-852)
  • flb_es_conf_destroy (854-885)
  • flb_es_upstream_conf (887-901)
plugins/out_es/es_conf_parse.c (6)
src/flb_utils.c (2)
  • flb_utils_split (464-467)
  • flb_utils_split_free (477-489)
plugins/out_es/es_type.c (2)
  • flb_es_str_copy_str (48-63)
  • flb_es_list_move_list (123-130)
src/flb_sds.c (2)
  • flb_sds_create (78-90)
  • flb_sds_destroy (389-399)
src/tls/flb_tls.c (1)
  • flb_tls_create (183-232)
include/fluent-bit/flb_mem.h (1)
  • flb_free (126-128)
src/aws/flb_aws_credentials.c (1)
  • flb_standard_chain_provider_create (269-327)
plugins/out_es/es.h (1)
plugins/out_es/es.c (1)
  • flb_elasticsearch_target (652-674)
plugins/out_es/es_type.h (1)
plugins/out_es/es_type.c (19)
  • flb_es_str_destroy (30-39)
  • flb_es_str_set_str (41-46)
  • flb_es_str_copy_str (48-63)
  • flb_es_sds_destroy (65-74)
  • flb_es_sds_set_sds (76-83)
  • flb_es_sds_copy_str (85-100)
  • flb_es_list_destroy (102-112)
  • flb_es_list_set_list (114-121)
  • flb_es_list_move_list (123-130)
  • flb_es_tls_destroy (132-141)
  • flb_es_tls_set_tls (143-150)
  • flb_es_tls_move_tls (152-159)
  • flb_es_ra_destroy (161-170)
  • flb_es_ra_set_ra (172-180)
  • flb_es_ra_move_ra (182-190)
  • flb_es_aws_provider_destroy (193-202)
  • flb_es_aws_provider_set (204-215)
  • flb_es_aws_provider_move (217-228)
  • flb_es_aws_provider_move_provider (230-238)
⏰ 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). (81)
  • GitHub Check: PR - container builds / Windows container images (2025)
  • GitHub Check: PR - container builds / Windows container images (2022)
  • GitHub Check: PR - packages build MacOS / call-build-macos-package (Apple Silicon macOS runner, macos-14, 3.31.6)
  • GitHub Check: PR - packages build MacOS / call-build-macos-package (Intel macOS runner, macos-14-large, 3.31.6)
  • GitHub Check: PR - packages build Linux / debian/bookworm.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / amazonlinux/2023 package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/10 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/bullseye.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/10 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/trixie package build and stage to S3
  • GitHub Check: PR - packages build Linux / ubuntu/24.04.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/trixie.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/8.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/bullseye package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/buster.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / ubuntu/22.04.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / ubuntu/24.04 package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/10.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/bookworm package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/9 package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / raspbian/bookworm package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/buster package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/10.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/9 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / amazonlinux/2023.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/9 package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/8.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/8.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / amazonlinux/2.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / ubuntu/22.04 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/9.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/9.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/7 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/9.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/10.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / amazonlinux/2 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/10 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/7.arm64v8 package build and stage to S3
  • GitHub Check: PR - container builds / arm64/production container image build
  • GitHub Check: PR - container builds / arm/v7/debug container image build
  • GitHub Check: PR - container builds / amd64/production container image build
  • GitHub Check: PR - container builds / amd64/debug container image build
  • GitHub Check: PR - container builds / arm/v7/production container image build
  • GitHub Check: PR - container builds / arm64/debug container image build
  • GitHub Check: PR - packages build Windows / call-build-windows-package (Windows 64bit (Arm64), amd64_arm64, -DCMAKE_SYSTEM_NAME=Windows -DCMA...
  • GitHub Check: PR - packages build Windows / call-build-windows-package (Windows 64bit, x64, x64-windows-static, 3.31.6)
  • GitHub Check: PR - packages build Windows / 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: 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: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=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_COMPILER_STRICT_POINTER_TYPES=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, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_ARROW=On, 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_THREAD=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 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_SANITIZE_MEMORY=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 (-DSANITIZE_ADDRESS=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=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_COVERAGE=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 (-DFLB_JEMALLOC=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: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-22.04, clang-12)
  • GitHub Check: PR - fuzzing test
  • 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, gcc, g++, ubuntu-22.04, clang-12)
  • 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-without-cxx (3.31.6)
🔇 Additional comments (32)
src/flb_lib.c (2)

584-615: LGTM! Clean separation of test setup functions.

The parameter rename from test_ctx to flush_ctx better reflects the purpose, and the implementation correctly stores the context without taking ownership.


617-649: LGTM! New flush context callback API follows existing patterns.

The new flb_output_set_test_flush_ctx_callback function properly mirrors the structure of flb_output_set_test and addresses the prior review feedback about separating concerns. This enables tests to dynamically compute flush context via callback rather than using a static value.

plugins/out_es/es_conf.h (1)

23-40: LGTM! Well-structured header with appropriate forward declarations.

The header cleanly exposes the new upstream configuration API and write operation macros. The void return type for flb_es_conf_destroy aligns with typical destroy function patterns in the codebase.

include/fluent-bit/flb_lib.h (2)

26-27: LGTM! Forward declaration addresses previous review feedback.

Using a forward declaration instead of including flb_input.h reduces coupling and keeps the public API surface clean.


70-81: LGTM! Public API declarations are consistent with implementation.

The updated flb_output_set_test signature with flush_ctx and the new flb_output_set_test_flush_ctx_callback declaration properly expose the testing infrastructure for upstream-aware ES tests.

plugins/out_es/es_conf_parse.c (5)

38-73: LGTM! Cloud credentials parsing with proper OOM handling.

The function correctly handles memory allocation failures and uses flb_es_str_copy_str for ownership-aware string copying.


142-192: LGTM! Cloud auth host extraction and assignment.

The function properly handles the optional port parsing and correctly manages the host.name SDS lifetime by destroying the old value before assignment.


196-215: LGTM! AWS unsigned headers initialization.

The function correctly allocates and initializes the unsigned headers list. The ownership transfer via flb_es_list_move_list ensures proper cleanup on error paths.


217-277: LGTM! STS provider setup with proper resource management.

The function correctly:

  • Generates and frees the session name after provider creation
  • Creates a separate TLS context for STS
  • Moves ownership of the base provider to avoid double-free
  • Reports errors at appropriate points

279-345: LGTM! AWS provider configuration with proper initialization sequence.

The function follows the established Fluent Bit pattern for AWS credential providers:

  1. Creates TLS context
  2. Creates standard chain provider
  3. Optionally wraps with STS provider for role assumption
  4. Initializes in sync mode then switches to async
  5. Sets upstream association

The ownership helpers (flb_es_tls_move_tls, flb_es_aws_provider_move_provider) ensure consistent resource management.

plugins/out_es/es_type.c (1)

1-239: Well-structured ownership wrapper implementation.

The ownership-aware wrapper types provide a clean abstraction for managing shared vs owned resources. The consistent pattern across all types (destroy, set, copy/move) is good.

A few observations for consideration:

  1. Inconsistent behavior between flb_es_str_set_str and flb_es_sds_set_sds: The str version unconditionally sets dest->value and dest->owned after destroy, while the sds version only assigns when src is non-NULL. This could lead to stale owned flags in the sds case when src is NULL.

  2. flb_es_aws_provider_move (lines 217-228): After *dest = *src, the code sets src->value = NULL but doesn't clear src->owned. This leaves a stale owned flag in the source, which could cause confusion if the source is later inspected (though it's likely not a practical issue since value is NULL).

These are minor consistency nits and the current implementation should work correctly in practice.

plugins/out_es/es_type.h (1)

1-402: Well-documented ownership wrapper API.

The header provides comprehensive documentation for the ownership semantics, clearly explaining when direct member access is allowed and how the wrapper functions should be used. The consistent structure across all wrapper types (value + owned flag) makes the API predictable and easy to use.

The use of forward declarations keeps header coupling minimal while still providing all necessary type information.

plugins/out_es/es.h (1)

23-178: Clean restructuring with proper HA support.

The separation between flb_elasticsearch (main context) and flb_elasticsearch_config (per-node configuration) is well-designed. The use of wrapper types for fields that can be shared or owned between the main config and per-node configs addresses the double-free concerns mentioned in PR discussions.

The forward declarations appropriately reduce header coupling as previously discussed.

plugins/out_es/es_conf.c (2)

606-634: Thorough resource cleanup implementation.

The elasticsearch_config_destroy function properly destroys all wrapper types in a consistent order. The cleanup handles both owned and non-owned resources correctly through the wrapper APIs.


636-745: Well-structured HA configuration with proper error handling.

The es_config_ha function properly:

  1. Creates the main config context
  2. Sets up base properties
  3. Creates per-node configs with proper inheritance
  4. Validates each node's config
  5. Has comprehensive error cleanup that nullifies node data and destroys allocated configs on failure

The rollback logic (lines 722-738) correctly handles partial initialization failures.

tests/runtime/out_elasticsearch.c (3)

113-122: Good flush context extraction callback.

The cb_flush_context callback properly uses flb_elasticsearch_target to extract the per-node configuration, enabling tests to verify that upstream node configurations are correctly applied during formatting.


1076-1137: Comprehensive upstream test implementation.

The flb_test_upstream_write_operation test properly verifies that per-node write_operation overrides the plugin-level setting. The test:

  1. Sets plugin-level Write_Operation to "Upsert"
  2. Sets node-level write_operation to "index" via upstream config
  3. Verifies the output uses "index" operation

This pattern is consistently applied across all new upstream tests, providing good coverage for the configuration override mechanism.


1598-1624: Good test coverage expansion.

The TEST_LIST properly includes all new upstream tests alongside existing ones, ensuring the new HA/upstream functionality is exercised in CI.

plugins/out_es/es.c (14)

33-48: LGTM!

The new includes for flb_upstream_node.h and es_conf_prop.h are appropriate for the upstream server support feature. The forward declaration update correctly reflects the signature change.


50-81: LGTM!

The separation of ctx (for plugin instance/logging) and ec (for configuration values) is clean and enables per-upstream-node AWS authentication configuration.


83-205: LGTM!

The refactoring from ctx to ec is correctly applied throughout the map/array content packing functions. The recursive calls properly propagate the ec parameter.


212-240: LGTM!

Configuration values are correctly read from ec while ctx is retained for logging purposes.


242-279: LGTM!

The function correctly uses ec for configuration values. Since no logging is performed, ctx is not needed here.


325-325: LGTM!

Using flush_ctx to obtain the per-request ec configuration is the correct approach for upstream server support, allowing each flush to use the configuration specific to the target node.


652-674: LGTM!

The target routing logic correctly handles both HA and non-HA modes. The function returns NULL when no valid configuration is available, and callers properly check for this condition. Based on learnings, the function contract approach (assuming valid parameters) is acceptable for this internal function.


835-876: LGTM!

The refactoring correctly:

  • Obtains the target configuration via flb_elasticsearch_target
  • Handles upstream connection acquisition for both HA and non-HA modes
  • Returns FLB_RETRY when no target is available or no connection can be obtained

916-922: LGTM!

The NULL check for flb_http_client was correctly added as previously requested.


1040-1058: LGTM!

The cleanup consolidation using cleanup_and_return and retry labels is well-structured:

  • ret is set before entering cleanup
  • Resources are conditionally cleaned up (HTTP client null-checked)
  • The retry path correctly sets ret = FLB_RETRY and jumps to the common cleanup

1086-1089: LGTM!

The NULL check for flb_http_dummy_client was correctly added as previously requested.


1148-1165: LGTM!

The config map correctly uses the new FLB_ES_CONFIG_PROPERTY_* macros and updates offsets to reference fields within struct flb_elasticsearch_config. The nested offset pattern for wrapper types (like flb_es_str) is appropriate for tracking ownership.


1385-1389: LGTM!

The new UPSTREAM property is correctly added with:

  • FLB_FALSE (not auto-applied, requires special handling)
  • Offset 0 (handled specially in configuration parsing)

287-627: Clean refactoring of elasticsearch_format for per-node configuration.

The function correctly uses ec from flush_ctx for all configuration values while retaining ctx for plugin instance operations. Error handling and resource cleanup remain robust.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@mabrarov
Copy link
Contributor Author

mabrarov commented Jan 14, 2026

Hi @cosmo0920,

It's regarding #7608 (review):

We might want to use slightly different approach for achieving this.

This is because own_* flags are frequently appeared in this PR. So, we wanted to wrap them with the following struct like:

/* A wrapper for flb_sds_t that tracks memory ownership */
typedef struct {
    flb_sds_t sds;   /* The actual string data */
    int       owned; /* A flag indicating if this struct owns the memory */
} flb_es_sds_t;

Then, the wrapped members could be:

/* In es.h, struct flb_elasticsearch_config */
struct flb_elasticsearch_config {
    /* ... other properties ... */

    flb_es_sds_t index;
    flb_es_sds_t type;
    flb_es_sds_t http_user;
    flb_es_sds_t logstash_prefix;
    flb_es_sds_t time_key;

    /* ... etc ... */
};

For just initialization, it could be:

static inline void es_sds_init(flb_es_sds_t *dest, flb_es_sds_t *src)
{
    dest->sds = src->sds;
    dest->owned = FLB_FALSE; /* The new struct does not own the shared memory */
}

For setting up a value, it could be:

static inline int es_sds_set(flb_es_sds_t *wrapper, const char *value)
{
    /* If we previously owned a different string, free it first */
    if (wrapper->owned && wrapper->sds) {
        flb_sds_destroy(wrapper->sds);
    }

    wrapper->sds = flb_sds_create(value);
    if (!wrapper->sds) {
        return -1;
    }
    wrapper->owned = FLB_TRUE;
    return 0;
}

The teardown operation of these values could be:

static inline void es_sds_destroy(flb_es_sds_t *wrapper)
{
    if (wrapper->owned && wrapper->sds) {
        flb_sds_destroy(wrapper->sds);
    }
    wrapper->sds = NULL;
    wrapper->owned = FLB_FALSE;
}

Then, just teardown operation could be:

es_sds_destroy(&ec->index);
es_sds_destroy(&ec->type);
/* ... etc ... */

These changes could be cleaner way to handle shallow copy. We would love to use this type of wrapper to encapsulate for these type of complex operations.

Done in eaba388 with following differences:

  1. The new functions are not inline (debatable, maybe inline is better, because in that case we can use static for internal linkage) and have names with flb_ prefix (because of lack of internal linkage).
  2. No *_init functions (these structs are sometimes initialized as part of plugin configuration where initial configuration is zero filled using flb_calloc).
  3. The new structs and functions have comments about allowed use cases.

Thank you.

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

🤖 Fix all issues with AI agents
In `@plugins/out_es/es_conf.c`:
- Around line 595-604: config_validate currently only rejects configs missing
index when index is NULL and both logstash_format and generate_id are false;
update it to also consider current_time_index so that validation requires at
least one of index (ec->index.value non-NULL), ec->logstash_format == FLB_TRUE,
or ec->current_time_index == FLB_TRUE to be true; change the if condition in
config_validate to include ec->current_time_index check and keep the same error
log (flb_plg_error on ctx->ins) and return -1 when none are set.
♻️ Duplicate comments (1)
plugins/out_es/es.c (1)

1074-1078: Fix misleading error message when target resolution fails.

The warning message "elasticsearch_target=%i" with ret=0 is misleading. At this point, ret is still 0 (initialized at line 1066), and no operation that would set ret has occurred - the failure is in flb_elasticsearch_target. This appears similar to a previously flagged issue that was marked as addressed.

Suggested fix
     ec = flb_elasticsearch_target(ctx, &node);
     if (!ec) {
-      flb_plg_warn(ctx->ins, "elasticsearch_target=%i", ret);
+      flb_plg_warn(ctx->ins, "failed to get target configuration");
       return -2;
     }
🧹 Nitpick comments (1)
plugins/out_es/es.c (1)

547-547: Minor: Extra space before comma.

There's an extra space before the comma in the function call.

Suggested fix
-            id_key_str = es_get_id_value(ctx, ec ,&map);
+            id_key_str = es_get_id_value(ctx, ec, &map);
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe70540 and 7b640b3.

📒 Files selected for processing (7)
  • plugins/out_es/CMakeLists.txt
  • plugins/out_es/es.c
  • plugins/out_es/es.h
  • plugins/out_es/es_conf.c
  • plugins/out_es/es_conf_parse.c
  • plugins/out_es/es_type.c
  • plugins/out_es/es_type.h
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/out_es/es_conf_parse.c
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-08-20T02:04:27.220Z
Learnt from: mabrarov
Repo: fluent/fluent-bit PR: 7608
File: plugins/out_es/es.c:648-670
Timestamp: 2025-08-20T02:04:27.220Z
Learning: The author mabrarov prefers function contracts that assume valid parameters for internal functions in the Elasticsearch output plugin, rather than adding defensive null pointer checks, to maintain performance and code clarity.

Applied to files:

  • plugins/out_es/es.c
📚 Learning: 2025-09-22T15:59:55.794Z
Learnt from: nicknezis
Repo: fluent/fluent-bit PR: 10882
File: plugins/out_http/http.c:112-116
Timestamp: 2025-09-22T15:59:55.794Z
Learning: When users consider bug fixes out of scope for their focused PRs, it's appropriate to create separate GitHub issues to track those concerns rather than expanding the current PR scope.

Applied to files:

  • plugins/out_es/es.c
📚 Learning: 2025-10-06T17:39:21.606Z
Learnt from: edsiper
Repo: fluent/fluent-bit PR: 10967
File: plugins/in_elasticsearch/in_elasticsearch_bulk_prot.c:266-272
Timestamp: 2025-10-06T17:39:21.606Z
Learning: In the in_elasticsearch plugin, payloads are JSON-based, so tag_key values will always be strings. There's no need to handle binary (FLB_RA_BINARY) values when extracting tags from records in this plugin.

Applied to files:

  • plugins/out_es/es.c
📚 Learning: 2025-08-31T12:46:11.940Z
Learnt from: ThomasDevoogdt
Repo: fluent/fluent-bit PR: 9277
File: .github/workflows/pr-compile-check.yaml:147-151
Timestamp: 2025-08-31T12:46:11.940Z
Learning: In fluent-bit CMakeLists.txt, the system library preference flags are defined as FLB_PREFER_SYSTEM_LIB_ZSTD and FLB_PREFER_SYSTEM_LIB_KAFKA with the FLB_ prefix.

Applied to files:

  • plugins/out_es/es.h
📚 Learning: 2025-11-11T20:33:42.883Z
Learnt from: mabrarov
Repo: fluent/fluent-bit PR: 7608
File: plugins/out_es/es_conf.c:932-946
Timestamp: 2025-11-11T20:33:42.883Z
Learning: The mk_list_is_empty function in Fluent Bit returns 0 when a list IS empty and -1 when a list is NOT empty. Use `mk_list_is_empty(list) == 0` to check if empty, and `mk_list_is_empty(list) != 0` to check if not empty.

Applied to files:

  • plugins/out_es/es_conf.c
🧬 Code graph analysis (4)
plugins/out_es/es.c (6)
src/flb_record_accessor.c (1)
  • flb_ra_get_value_object (803-814)
include/fluent-bit/flb_time.h (1)
  • flb_time_copy (81-85)
plugins/out_es/es_conf.c (1)
  • flb_es_upstream_conf (887-901)
src/flb_upstream_ha.c (1)
  • flb_upstream_ha_node_get (88-110)
src/flb_upstream.c (1)
  • flb_upstream_conn_get (711-844)
src/flb_http_client.c (2)
  • flb_http_client (866-911)
  • flb_http_basic_auth (1394-1398)
plugins/out_es/es.h (1)
plugins/out_es/es.c (1)
  • flb_elasticsearch_target (652-674)
plugins/out_es/es_type.h (1)
plugins/out_es/es_type.c (19)
  • flb_es_str_destroy (30-37)
  • flb_es_str_set_str (39-44)
  • flb_es_str_copy_str (46-61)
  • flb_es_sds_destroy (63-70)
  • flb_es_sds_set_sds (72-79)
  • flb_es_sds_copy_str (81-96)
  • flb_es_list_destroy (98-106)
  • flb_es_list_set_list (108-115)
  • flb_es_list_move_list (117-124)
  • flb_es_tls_destroy (126-133)
  • flb_es_tls_set_tls (135-142)
  • flb_es_tls_move_tls (144-151)
  • flb_es_ra_destroy (153-160)
  • flb_es_ra_set_ra (162-170)
  • flb_es_ra_move_ra (172-180)
  • flb_es_aws_provider_destroy (183-190)
  • flb_es_aws_provider_set (192-203)
  • flb_es_aws_provider_move (205-216)
  • flb_es_aws_provider_move_provider (218-226)
plugins/out_es/es_type.c (6)
include/fluent-bit/flb_mem.h (1)
  • flb_free (126-128)
src/flb_sds.c (2)
  • flb_sds_destroy (389-399)
  • flb_sds_create (78-90)
src/flb_slist.c (1)
  • flb_slist_destroy (327-339)
src/tls/flb_tls.c (1)
  • flb_tls_destroy (258-277)
src/flb_record_accessor.c (1)
  • flb_ra_destroy (232-248)
src/aws/flb_aws_credentials.c (1)
  • flb_aws_provider_destroy (769-791)
⏰ 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). (31)
  • 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: pr-windows-build / call-build-windows-package (Windows 64bit (Arm64), amd64_arm64, -DCMAKE_SYSTEM_NAME=Windows -DCMA...
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=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_SIMD=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_COMPILER_STRICT_POINTER_TYPES=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 (-DFLB_ARROW=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_JEMALLOC=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 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_SANITIZE_THREAD=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_JEMALLOC=On, 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 (-DSANITIZE_ADDRESS=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_SMALL=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_JEMALLOC=Off, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, clang, clang++)
  • GitHub Check: PR - fuzzing test
  • 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-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: pr-compile-without-cxx (3.31.6)
  • 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
🔇 Additional comments (31)
plugins/out_es/CMakeLists.txt (1)

1-10: LGTM!

The build integration correctly adds the new source files es_type.c and es_conf_parse.c to the plugin build.

plugins/out_es/es_type.h (1)

1-402: Well-designed ownership-aware wrapper API.

The wrapper types and their associated functions provide a clean abstraction for managing shared vs. owned resources between plugin-level config and per-upstream-node overrides. The documentation clearly explains ownership semantics and restrictions.

plugins/out_es/es_type.c (2)

30-227: Implementation is consistent and handles ownership correctly.

The destroy/set/copy/move patterns are consistently implemented across all wrapper types. The self-assignment checks in AWS provider functions prevent double-free scenarios. The condition ins->value && ins->owned != FLB_FALSE ensures safe destruction even when move operations leave stale owned flags.


24-24: No action needed - unconditional include is safe.

flb_aws_credentials.h is properly self-guarded with #ifdef FLB_HAVE_AWS at the header level. This allows unconditional includes throughout the codebase (as seen in core files like src/flb_signv4.c, src/aws/*, and other plugins). When FLB_HAVE_AWS is undefined, the include safely provides no declarations; when defined, it provides full AWS support. The AWS-using functions in this file are already guarded at the implementation level (line 182+), following the standard Fluent Bit pattern.

Likely an incorrect or invalid review comment.

plugins/out_es/es.h (3)

23-28: Good reduction of header coupling.

The header now uses forward declarations and includes only what's necessary (mk_list.h and the local es_type.h), addressing the previous review feedback about reducing transitive rebuilds.


53-147: Per-node configuration structure is well-designed.

The flb_elasticsearch_config structure cleanly separates fields that can be overridden per-upstream-node (using wrapper types with ownership tracking) from fixed fields (plain pointers to config-map-managed data). The _head list entry enables tracking multiple configs in HA mode.


149-178: Main context structure and target selection API are appropriate.

The flb_elasticsearch context correctly separates HA-mode fields (ha_mode, ha, ha_upstream) from simple-mode fields (u), with a shared configs list. The flb_elasticsearch_target function provides a clean abstraction for node selection.

plugins/out_es/es_conf.c (14)

42-61: LGTM!

Correctly creates a record accessor from id_key with proper ownership transfer and handles the Generate_ID conflict appropriately.


63-98: LGTM!

The write operation validation and es_action assignment to static strings are correct. The requirement for Id_Key or Generate_Id with update/upsert operations is properly enforced.


100-107: LGTM!

The buffer size adjustment correctly maps the sentinel value to unlimited (0).


117-138: LGTM!

URI construction with proper truncation detection using snprintf return value.


140-177: LGTM!

Correctly handles the logstash prefix key with optional $ prepending, proper memory management of the temporary buffer, and ownership transfer of the record accessor.


179-289: LGTM!

Configuration property setup is comprehensive with proper error handling. The use of flb_es_str_copy_str for URI-derived values ensures owned copies are made.


291-357: Base configuration copy uses correct non-owning semantics.

The flb_es_*_set_* functions correctly establish non-owning references to the base configuration, avoiding double-free when both base and node configs are destroyed.


359-593: Node property overrides handle allocation failures correctly.

Each property override that allocates memory returns -1 on failure, and the caller properly cleans up via elasticsearch_config_destroy, which safely handles partially initialized configs due to flb_calloc zero-initialization.


606-634: LGTM!

Comprehensive cleanup of all owned resources in the config structure. Each destroy function handles NULL/zero values safely.


636-745: HA configuration setup is robust with comprehensive error handling.

The function properly handles allocation failures at each step, with complete cleanup of partially created configs and upstream nodes on error. The separation of base config creation from per-node config creation enables proper error recovery.


747-817: LGTM!

Simple (non-HA) mode configuration correctly sets defaults, creates the upstream, and handles all error paths with appropriate cleanup.


819-852: LGTM!

The entry point correctly initializes the context, dispatches to the appropriate configuration mode, and handles errors appropriately.


854-885: LGTM!

The destroy function correctly handles both HA and simple modes, safely iterates the configs list, and frees all resources.


887-901: LGTM!

The config retrieval function correctly uses mk_list_is_empty semantics (returns 0 when empty) and properly handles both node-based lookup (HA mode) and fallback to the last config (simple mode). Based on learnings about mk_list_is_empty behavior.

plugins/out_es/es.c (10)

33-40: LGTM!

The new includes for flb_upstream_node.h and es_conf_prop.h are appropriate for supporting the upstream servers feature and config property macros.


50-80: LGTM!

The signature change to accept both ctx (for logging via ctx->ins) and ec (for per-node AWS config) correctly supports the upstream servers feature while maintaining proper separation of concerns.


83-205: LGTM!

The refactor to use ec parameter in the recursive packing functions is consistent and correct. The mutual recursion between es_pack_map_content and es_pack_array_content correctly propagates the config context.


212-240: LGTM!

The function correctly uses ctx for logging and ec for accessing the per-node configuration values (ra_id_key.value, id_key.value).


242-279: LGTM!

The function signature change to use ec is appropriate since it doesn't need logging access and only uses config values.


652-674: LGTM!

The flb_elasticsearch_target function correctly implements HA-aware node selection. Based on learnings, the author prefers function contracts that assume valid parameters for internal functions, which is acceptable here since all call sites are controlled within this module.


855-876: LGTM!

The HA-aware connection handling correctly differentiates between upstream mode (using node->u) and non-HA mode (using ctx->u). The null checks for both ec and u_conn are properly handled with appropriate error messages.


1040-1058: LGTM!

The refactored cleanup logic using cleanup_and_return and retry labels is well-structured. The conditional null check for c before destruction and the safe flb_free(pack) call (where pack is initialized to NULL) ensure proper resource cleanup.


1385-1389: LGTM!

The new UPSTREAM configuration property is correctly defined. Using FLB_FALSE with offset 0 is appropriate since the upstream file path is processed separately in es_conf.c rather than being directly stored in the config struct.


1149-1159: The nested offset pattern is valid and works correctly with flb_config_map.

The flb_config_map_set function (src/flb_config_map.c:638–666) uses the offset field via base + m->offset to write values to struct members. The nested offsetof pattern offsetof(struct flb_elasticsearch_config, index) + offsetof(struct flb_es_str, value) correctly computes the byte offset to the .value field within the wrapper struct. This is an unconventional but valid C technique that properly integrates with the config_map mechanism.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

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

🤖 Fix all issues with AI agents
In `@plugins/out_es/es_conf_prop.h`:
- Line 5: Update the copyright year in the header comment of
plugins/out_es/es_conf_prop.h from 2015-2024 to 2015-2026 so it matches other
files in the PR; locate the top-of-file copyright comment (the line containing
"Copyright (C) 2015-2024 The Fluent Bit Authors") and change 2024 to 2026.

In `@plugins/out_es/es_conf.c`:
- Around line 595-604: The current config_validate allows index.value to be NULL
when logstash_format is false but current_time_index is true, which leads to a
NULL format passed to strftime in the code path that formats index names; update
config_validate (function config_validate and struct flb_elasticsearch_config
checks) so that if ec->logstash_format == FLB_FALSE then ec->index.value must be
non-NULL (i.e., change the failing condition to trigger when ec->index.value ==
NULL && ec->logstash_format == FLB_FALSE), preventing the
strftime(index_formatted, ..., ec->index.value, ...) call from receiving NULL.
♻️ Duplicate comments (1)
tests/runtime/out_elasticsearch.c (1)

22-111: Acceptable use of tmpnam() with flb_strdup for test code.

The static buffer issue from past reviews was addressed by immediately duplicating the result with flb_strdup(). "Never use these functions" - "Use mkstemp(3) or tmpfile(3) instead" per Linux man pages, but as discussed in prior review comments, this is test-only code and the author has noted mkstemp is not part of C standard.

Resource cleanup on all error paths (lines 58-61, 82-86, 96-98, 104-107) is properly handled with remove() and flb_free().

🧹 Nitpick comments (1)
plugins/out_es/es_conf.c (1)

100-107: Subtle size_t comparison with -1.

The comparison buffer_size == -1 works because -1 is implicitly converted to SIZE_MAX when compared with size_t. This is an established pattern in Fluent Bit for indicating "unlimited" buffer size. Consider adding a brief comment for clarity.

Optional: Add clarifying comment
 static size_t config_adjust_buffer_size(size_t buffer_size)
 {
-    /* HTTP Payload (response) maximum buffer size (0 == unlimited) */
+    /* HTTP Payload (response) maximum buffer size (0 == unlimited)
+     * Note: -1 (SIZE_MAX when unsigned) indicates unlimited */
     if (buffer_size == -1) {
         return 0;
     }
     return buffer_size;
 }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b640b3 and c714dd5.

📒 Files selected for processing (15)
  • include/fluent-bit/flb_lib.h
  • include/fluent-bit/flb_output.h
  • plugins/out_es/CMakeLists.txt
  • plugins/out_es/es.c
  • plugins/out_es/es.h
  • plugins/out_es/es_conf.c
  • plugins/out_es/es_conf.h
  • plugins/out_es/es_conf_parse.c
  • plugins/out_es/es_conf_parse.h
  • plugins/out_es/es_conf_prop.h
  • plugins/out_es/es_type.c
  • plugins/out_es/es_type.h
  • src/flb_engine_dispatch.c
  • src/flb_lib.c
  • tests/runtime/out_elasticsearch.c
🚧 Files skipped from review as they are similar to previous changes (4)
  • plugins/out_es/es_conf_parse.h
  • plugins/out_es/CMakeLists.txt
  • plugins/out_es/es_conf.h
  • include/fluent-bit/flb_lib.h
🧰 Additional context used
🧠 Learnings (8)
📚 Learning: 2025-11-21T06:23:29.770Z
Learnt from: cosmo0920
Repo: fluent/fluent-bit PR: 11171
File: include/fluent-bit/flb_lib.h:52-53
Timestamp: 2025-11-21T06:23:29.770Z
Learning: In Fluent Bit core (fluent/fluent-bit repository), function descriptions/documentation are not required for newly added functions in header files.

Applied to files:

  • include/fluent-bit/flb_output.h
📚 Learning: 2025-09-08T11:21:33.975Z
Learnt from: cosmo0920
Repo: fluent/fluent-bit PR: 10851
File: include/fluent-bit/flb_simd.h:60-66
Timestamp: 2025-09-08T11:21:33.975Z
Learning: Fluent Bit currently only supports MSVC compiler on Windows, so additional compiler compatibility guards may be unnecessary for Windows-specific code paths.

Applied to files:

  • plugins/out_es/es_conf_parse.c
📚 Learning: 2025-08-20T02:04:27.220Z
Learnt from: mabrarov
Repo: fluent/fluent-bit PR: 7608
File: plugins/out_es/es.c:648-670
Timestamp: 2025-08-20T02:04:27.220Z
Learning: The author mabrarov prefers function contracts that assume valid parameters for internal functions in the Elasticsearch output plugin, rather than adding defensive null pointer checks, to maintain performance and code clarity.

Applied to files:

  • plugins/out_es/es_conf_parse.c
  • plugins/out_es/es.c
📚 Learning: 2025-12-17T18:45:02.283Z
Learnt from: edsiper
Repo: fluent/fluent-bit PR: 11286
File: src/flb_http_client.c:1657-1715
Timestamp: 2025-12-17T18:45:02.283Z
Learning: In the Fluent Bit OAuth2 implementation (src/flb_oauth2.c), the function flb_oauth2_get_access_token returns a pointer to the cached token stored in the OAuth2 context (ctx->access_token), not a new allocation. The OAuth2 context manages the token lifecycle, so callers must not free the returned token pointer.

Applied to files:

  • plugins/out_es/es_conf_parse.c
📚 Learning: 2025-09-22T15:59:55.794Z
Learnt from: nicknezis
Repo: fluent/fluent-bit PR: 10882
File: plugins/out_http/http.c:112-116
Timestamp: 2025-09-22T15:59:55.794Z
Learning: When users consider bug fixes out of scope for their focused PRs, it's appropriate to create separate GitHub issues to track those concerns rather than expanding the current PR scope.

Applied to files:

  • plugins/out_es/es_conf_parse.c
  • plugins/out_es/es.c
📚 Learning: 2025-10-06T17:39:21.606Z
Learnt from: edsiper
Repo: fluent/fluent-bit PR: 10967
File: plugins/in_elasticsearch/in_elasticsearch_bulk_prot.c:266-272
Timestamp: 2025-10-06T17:39:21.606Z
Learning: In the in_elasticsearch plugin, payloads are JSON-based, so tag_key values will always be strings. There's no need to handle binary (FLB_RA_BINARY) values when extracting tags from records in this plugin.

Applied to files:

  • plugins/out_es/es.c
📚 Learning: 2025-08-31T12:46:11.940Z
Learnt from: ThomasDevoogdt
Repo: fluent/fluent-bit PR: 9277
File: .github/workflows/pr-compile-check.yaml:147-151
Timestamp: 2025-08-31T12:46:11.940Z
Learning: In fluent-bit CMakeLists.txt, the system library preference flags are defined as FLB_PREFER_SYSTEM_LIB_ZSTD and FLB_PREFER_SYSTEM_LIB_KAFKA with the FLB_ prefix.

Applied to files:

  • plugins/out_es/es.h
📚 Learning: 2025-11-11T20:33:42.883Z
Learnt from: mabrarov
Repo: fluent/fluent-bit PR: 7608
File: plugins/out_es/es_conf.c:932-946
Timestamp: 2025-11-11T20:33:42.883Z
Learning: The mk_list_is_empty function in Fluent Bit returns 0 when a list IS empty and -1 when a list is NOT empty. Use `mk_list_is_empty(list) == 0` to check if empty, and `mk_list_is_empty(list) != 0` to check if not empty.

Applied to files:

  • plugins/out_es/es_conf.c
🧬 Code graph analysis (6)
plugins/out_es/es_conf_parse.c (8)
src/flb_utils.c (1)
  • flb_utils_split (464-467)
plugins/out_es/es_type.c (5)
  • flb_es_str_copy_str (46-61)
  • flb_es_list_move_list (117-124)
  • flb_es_aws_provider_set (192-203)
  • flb_es_aws_provider_move (205-216)
  • flb_es_aws_provider_move_provider (218-226)
src/flb_sds.c (2)
  • flb_sds_create (78-90)
  • flb_sds_destroy (389-399)
src/flb_slist.c (2)
  • flb_slist_create (27-31)
  • flb_slist_add (70-84)
src/tls/flb_tls.c (1)
  • flb_tls_create (183-232)
include/fluent-bit/flb_mem.h (1)
  • flb_free (126-128)
src/aws/flb_aws_util.c (1)
  • flb_aws_client_generator (289-292)
src/aws/flb_aws_credentials.c (1)
  • flb_standard_chain_provider_create (269-327)
plugins/out_es/es_type.h (1)
plugins/out_es/es_type.c (19)
  • flb_es_str_destroy (30-37)
  • flb_es_str_set_str (39-44)
  • flb_es_str_copy_str (46-61)
  • flb_es_sds_destroy (63-70)
  • flb_es_sds_set_sds (72-79)
  • flb_es_sds_copy_str (81-96)
  • flb_es_list_destroy (98-106)
  • flb_es_list_set_list (108-115)
  • flb_es_list_move_list (117-124)
  • flb_es_tls_destroy (126-133)
  • flb_es_tls_set_tls (135-142)
  • flb_es_tls_move_tls (144-151)
  • flb_es_ra_destroy (153-160)
  • flb_es_ra_set_ra (162-170)
  • flb_es_ra_move_ra (172-180)
  • flb_es_aws_provider_destroy (183-190)
  • flb_es_aws_provider_set (192-203)
  • flb_es_aws_provider_move (205-216)
  • flb_es_aws_provider_move_provider (218-226)
plugins/out_es/es_type.c (6)
include/fluent-bit/flb_mem.h (1)
  • flb_free (126-128)
src/flb_sds.c (2)
  • flb_sds_destroy (389-399)
  • flb_sds_create (78-90)
src/flb_slist.c (1)
  • flb_slist_destroy (327-339)
src/tls/flb_tls.c (1)
  • flb_tls_destroy (258-277)
src/flb_record_accessor.c (1)
  • flb_ra_destroy (232-248)
src/aws/flb_aws_credentials.c (1)
  • flb_aws_provider_destroy (769-791)
tests/runtime/out_elasticsearch.c (2)
plugins/out_es/es.c (1)
  • flb_elasticsearch_target (652-674)
src/flb_lib.c (7)
  • flb_output_set_test_flush_ctx_callback (617-649)
  • flb_start (1017-1028)
  • flb_lib_push (877-904)
  • flb_input (266-276)
  • flb_output (279-289)
  • flb_output_set (520-551)
  • flb_output_set_test (584-615)
plugins/out_es/es.h (1)
plugins/out_es/es.c (1)
  • flb_elasticsearch_target (652-674)
plugins/out_es/es_conf.c (4)
include/fluent-bit/flb_mem.h (2)
  • flb_free (126-128)
  • flb_calloc (84-96)
plugins/out_es/es_conf_parse.c (3)
  • flb_es_conf_set_cloud_auth (142-192)
  • flb_es_conf_set_cloud_credentials (38-73)
  • flb_es_set_aws_unsigned_headers (196-215)
include/fluent-bit/flb_output.h (1)
  • flb_output_config_map_set (1321-1348)
include/fluent-bit/flb_upstream_node.h (2)
  • flb_upstream_node_set_data (82-86)
  • flb_upstream_node_get_data (88-91)
⏰ 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). (81)
  • GitHub Check: PR - container builds / Windows container images (2022)
  • GitHub Check: PR - container builds / Windows container images (2025)
  • GitHub Check: PR - packages build Linux / ubuntu/22.04.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/trixie.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / raspbian/bookworm package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/8.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / ubuntu/22.04 package build and stage to S3
  • GitHub Check: PR - packages build Linux / ubuntu/24.04.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/buster package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/10.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / ubuntu/24.04 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/buster.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/trixie package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/9 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/bookworm.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/bookworm package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/9.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/bullseye package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/10 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/9.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/bullseye.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/9 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/10 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/8.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / amazonlinux/2023 package build and stage to S3
  • GitHub Check: PR - packages build Linux / amazonlinux/2 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/9.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/10.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/10.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/10 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/7 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/8.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / amazonlinux/2023.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/7.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/9 package build and stage to S3
  • GitHub Check: PR - packages build Linux / amazonlinux/2.arm64v8 package build and stage to S3
  • GitHub Check: PR - container builds / amd64/production container image build
  • GitHub Check: PR - container builds / arm/v7/production container image build
  • GitHub Check: PR - container builds / amd64/debug container image build
  • GitHub Check: PR - container builds / arm/v7/debug container image build
  • GitHub Check: PR - container builds / arm64/production container image build
  • GitHub Check: PR - container builds / arm64/debug container image build
  • GitHub Check: PR - packages build Windows / call-build-windows-package (Windows 64bit (Arm64), amd64_arm64, -DCMAKE_SYSTEM_NAME=Windows -DCMA...
  • GitHub Check: PR - packages build Windows / call-build-windows-package (Windows 32bit, x86, x86-windows-static, 3.31.6)
  • GitHub Check: PR - packages build Windows / call-build-windows-package (Windows 64bit, x64, x64-windows-static, 3.31.6)
  • GitHub Check: PR - packages build MacOS / call-build-macos-package (Intel macOS runner, macos-14-large, 3.31.6)
  • GitHub Check: PR - packages build MacOS / call-build-macos-package (Apple Silicon macOS runner, macos-14, 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: pr-windows-build / call-build-windows-package (Windows 32bit, x86, x86-windows-static, 3.31.6)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_COMPILER_STRICT_POINTER_TYPES=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_SANITIZE_THREAD=On, 3.31.6, gcc, g++)
  • 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 (-DFLB_JEMALLOC=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_SANITIZE_MEMORY=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_SIMD=Off, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 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_ADDRESS=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 (-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 (-DSANITIZE_ADDRESS=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 (-DFLB_COVERAGE=On, 3.31.6, gcc, g++)
  • 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-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-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, clang, clang++, ubuntu-24.04, clang-14)
  • GitHub Check: PR - fuzzing test
🔇 Additional comments (38)
plugins/out_es/es_type.h (7)

1-49: Well-structured ownership wrapper design.

The flb_es_str structure and its accompanying API provide a clean encapsulation of ownership semantics. The documentation clearly explains when direct member access is permitted (initialization and modification when owned is FLB_FALSE).


51-121: Consistent wrapper pattern across types.

The flb_es_sds_t, flb_es_list, flb_es_tls, and flb_es_record_accessor structures follow the same ownership pattern. This consistency will make the codebase easier to maintain and understand.


123-141: AWS provider wrapper correctly guarded.

The flb_es_aws_provider structure is properly wrapped in #ifdef FLB_HAVE_AWS to ensure it only compiles when AWS support is enabled.


143-185: Clear API documentation with intersection constraints.

The documentation for flb_es_str_set_str and flb_es_str_copy_str clearly documents the constraint that source and destination values must not intersect. This is important to prevent use-after-free when the destination is destroyed before assignment.


187-262: SDS and list APIs are complete and well-documented.

The APIs for flb_es_sds_t and flb_es_list provide the necessary operations (destroy, set, copy/move) with clear ownership transfer semantics.


264-341: TLS and record accessor APIs follow established pattern.

The flb_es_tls_* and flb_es_ra_* functions provide consistent move semantics for transferring ownership of TLS contexts and record accessors.


343-407: AWS provider API provides additional flexibility.

The flb_es_aws_provider_set, flb_es_aws_provider_move, and flb_es_aws_provider_move_provider functions provide more granular control over ownership transfer, including a self-assignment check (dest == src). This is appropriate given the complexity of AWS provider lifecycle management.

plugins/out_es/es_type.c (6)

30-61: String wrapper implementations are correct.

The flb_es_str_destroy, flb_es_str_set_str, and flb_es_str_copy_str functions correctly implement the ownership semantics:

  • destroy only frees when owned
  • set_str destroys first, then assigns without ownership
  • copy_str creates a duplicate before destroying to handle the allocation failure case gracefully

63-96: SDS wrapper implementations follow the same pattern.

The SDS functions correctly use flb_sds_destroy and flb_sds_create from the Fluent Bit API. The null check in flb_es_sds_set_sds (line 75) properly handles the case where src is NULL by not setting dest->value.


98-124: List wrapper correctly handles both list and container memory.

flb_es_list_destroy properly calls flb_slist_destroy to free list entries and then flb_free to release the list container itself. This matches the expected cleanup for dynamically allocated mk_list structures.


126-180: TLS and record accessor wrappers are correct.

The implementations correctly delegate to flb_tls_destroy and flb_ra_destroy for cleanup, and properly manage the ownership flag during set and move operations.


182-227: AWS provider wrappers handle edge cases well.

The flb_es_aws_provider_move function correctly handles the struct copy and nulls the source value. The self-assignment check (dest == src) prevents issues when the same wrapper is passed as both source and destination.

One minor observation: flb_es_aws_provider_move at line 213 does *dest = *src which copies both value and owned fields, which is the intended behavior for ownership transfer.


20-28: No build issue with this include. The flb_aws_credentials.h header itself is wrapped with #ifdef FLB_HAVE_AWS, so unconditional includes are safe—when the flag is not defined, the preprocessor skips the header's content. This pattern is used consistently across the codebase in kinesis, S3, OpenSearch, CloudWatch, and other AWS-related files without guards.

Likely an incorrect or invalid review comment.

src/flb_engine_dispatch.c (2)

101-119: Clean implementation of dynamic flush context extraction.

The changes to test_run_formatter correctly implement the callback-based flush context mechanism:

  1. Initializes flush_ctx from otf->flush_ctx (line 116)
  2. If flush_ctx_callback is provided, invokes it to potentially override the context (lines 117-119)
  3. The callback receives all necessary context: config, input instance, plugin context, and the base flush_ctx

This enables the ES output plugin tests to extract the appropriate per-upstream-node configuration during test execution.


179-190: Call site correctly updated.

The call to test_run_formatter at line 184 no longer passes flush_ctx as an argument, which aligns with the updated function signature.

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

154-171: Well-documented flush context callback addition.

The flush_ctx_callback function pointer is properly documented and its parameters are clearly labeled:

  • struct flb_config * - Fluent Bit context
  • struct flb_input_instance * - plugin that ingested records
  • void *plugin_context - plugin instance context
  • void *flush_ctx - context for the callback

The comment for flush_ctx (line 154-155) is updated to reflect its role as context for the callback, maintaining clarity about its purpose.

src/flb_lib.c (2)

584-615: Parameter rename improves API clarity.

The rename from test_ctx to flush_ctx (line 587) and assignment to o_ins->test_formatter.flush_ctx (line 608) better reflects the actual usage of this parameter as the flush context for the formatter callback.


617-649: Function designed for use after flb_output_set_test—consider documenting this dependency.

The flb_output_set_test_flush_ctx_callback function follows the intended design. It allows tests to register a dynamic flush context callback in addition to the test formatter callback initialized by flb_output_set_test. Every test case in the codebase (30+ instances in out_elasticsearch.c) calls flb_output_set_test first to initialize the formatter test callback, then calls this function to register the dynamic flush context callback.

Calling flb_output_set_test_flush_ctx_callback alone would not be problematic from a crash perspective—the flush context callback is conditionally invoked at lines 117–119 in test_run_formatter only if set. However, the test would not execute at all because test_run_formatter is only invoked if test_formatter.callback != NULL (checked at line 181 in flb_engine_dispatch.c), a field set exclusively by flb_output_set_test. Documenting this dependency would prevent misuse.

tests/runtime/out_elasticsearch.c (4)

113-122: LGTM!

The callback correctly extracts the Elasticsearch configuration context using flb_elasticsearch_target(), which aligns with the new per-node configuration model. The unused node output parameter is acceptable here since tests only need the configuration.


330-333: LGTM!

The flb_output_set_test_flush_ctx_callback registration is consistently added across all formatter tests. This is necessary for the ec-centric configuration model where elasticsearch_format() receives the configuration via flush_ctx parameter.


1076-1137: Well-structured upstream configuration override test.

This test correctly verifies that per-node configuration (write_operation: index in upstream file) overrides plugin-level configuration (Write_Operation: Upsert). The callback cb_check_write_op_index validates the node-level setting takes precedence.

Cleanup at lines 1135-1136 properly removes the temporary file and frees the allocated filename.


1618-1623: LGTM!

The new upstream tests are properly registered in TEST_LIST, enabling comprehensive testing of the upstream/HA configuration feature.

plugins/out_es/es_conf_parse.c (3)

196-215: Potential memory leak on flb_slist_add failure.

If flb_slist_add() fails at line 210, the function returns -1 without destroying the already-allocated list at ec->aws_unsigned_headers.value. The caller will clean up via elasticsearch_config_destroy(), but that function checks ownership via flb_es_list_destroy() which should handle this correctly.

Actually, upon re-reading flb_es_list_move_list usage and the destroy pattern, the cleanup is handled by the caller invoking elasticsearch_config_destroy. The owned flag ensures proper cleanup.


38-73: LGTM!

OOM handling was addressed per past review comments. The function now properly checks flb_es_str_copy_str return values (lines 57, 64) and frees toks before returning -1 on allocation failure.


279-345: LGTM!

The AWS provider configuration flow properly:

  1. Validates aws_auth and aws_region settings
  2. Creates dedicated TLS contexts for AWS and STS providers
  3. Uses ownership-aware helpers (flb_es_tls_move_tls, flb_es_aws_provider_move_provider)
  4. Initializes credentials synchronously, then switches to async mode
  5. Wires the provider upstream to the instance

Error paths return -1 allowing the caller to cleanup via elasticsearch_config_destroy().

plugins/out_es/es_conf.c (2)

887-901: LGTM!

The mk_list_is_empty check is correct. Based on retrieved learnings, mk_list_is_empty returns 0 when the list IS empty and -1 when NOT empty. The condition == 0 correctly returns NULL for an empty list.


636-745: LGTM!

The HA configuration setup is well-structured:

  1. Creates main ec from plugin properties
  2. Loads upstream nodes and iterates to create per-node ec contexts
  3. Each node ec inherits from main ec then applies node-specific overrides
  4. On any failure, properly cleans up all allocated resources
  5. Registers node data for later retrieval via flb_upstream_node_get_data()
plugins/out_es/es_conf_prop.h (1)

20-65: LGTM!

The property macro definitions provide a single source of truth for configuration property names, reducing the risk of typos and improving maintainability. AWS-specific properties are correctly guarded by FLB_HAVE_AWS.

plugins/out_es/es.c (5)

652-674: LGTM!

The flb_elasticsearch_target function correctly handles both HA and non-HA modes:

  • Non-HA: Returns the single config via flb_es_upstream_conf(ctx, NULL) and sets *node = NULL
  • HA: Gets next node via round-robin (flb_upstream_ha_node_get), retrieves node-specific config

Per retrieved learnings, the author prefers function contracts that assume valid parameters rather than defensive NULL checks.


855-875: LGTM!

The upstream connection acquisition correctly branches on ha_mode:

  • HA mode: Gets connection from the selected node's upstream (node->u)
  • Non-HA mode: Gets connection from the single upstream (ctx->u)

The logic ensures node != NULL when ha_mode == TRUE because flb_elasticsearch_target returns NULL (caught at line 856) if no HA node is available.


1040-1057: LGTM!

The unified cleanup path is well-structured:

  • Conditional HTTP client destruction (handles NULL case from early errors)
  • Pack buffer freed unconditionally (always allocated by this point)
  • Upstream connection released
  • Signature destroyed if allocated

The retry label simply sets ret = FLB_RETRY and falls through to cleanup.


1150-1159: LGTM!

The nested offset calculation pattern is correct for the new ownership-aware wrapper types:

offsetof(struct flb_elasticsearch_config, index) + offsetof(struct flb_es_str, value)

This allows flb_config_map_set to directly populate the .value member while ownership tracking is managed separately by the flb_es_* helper functions.


1385-1389: LGTM!

The new Upstream property enables the HA/upstream servers feature, allowing users to specify a path to an upstream configuration file that defines multiple Elasticsearch nodes.

plugins/out_es/es.h (5)

23-26: LGTM!

The includes are minimal and appropriate. mk_list.h is needed for the linked list member, and es_type.h provides the wrapper types for ownership-aware fields. The forward declaration refactor from the previous review is properly applied.


28-28: Good catch fixing the default port typo.

The Elasticsearch default HTTP port is 9200, not 92000. This was a critical typo that would have caused connection failures when relying on the default port.


149-161: LGTM!

The struct cleanly separates HA mode fields (ha_mode, ha_upstream, ha) from the single-mode upstream handler (u). The configs list enables per-upstream-node configuration overrides, following the pattern established by the Forward output plugin.


163-178: Well-documented API declaration.

The documentation clearly explains the behavior in both HA and non-HA modes, properly documents the output parameter semantics, and describes the return value conditions. The signature matches the implementation in es.c.


53-147: Wrapper-based ownership tracking implementation is correct.

The struct uses wrapper types (flb_es_str, flb_es_sds_t, flb_es_record_accessor, etc.) for fields that can be overridden per upstream node, while keeping raw pointers for fields managed by flb_config_map. This design appropriately addresses ownership tracking.

The es_action field on line 127 is safely implemented as a const char * that points to static constants (es_write_op_index, es_write_op_create, es_write_op_update, es_write_op_upsert defined in es_conf.c). It is derived from the write_operation wrapper field and never independently allocated, making the raw pointer approach sound.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

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

🧹 Nitpick comments (3)
plugins/out_es/es_conf.c (1)

100-107: Signed/unsigned comparison warning likely.

At line 103, comparing size_t buffer_size (unsigned) with -1 (signed) may trigger compiler warnings. The comparison works because -1 is implicitly converted to SIZE_MAX, but consider making this explicit for clarity.

Optional fix for clarity
 static size_t config_adjust_buffer_size(size_t buffer_size)
 {
     /* HTTP Payload (response) maximum buffer size (0 == unlimited) */
-    if (buffer_size == -1) {
+    if (buffer_size == (size_t)-1) {
         return 0;
     }
     return buffer_size;
 }
plugins/out_es/es_type.h (2)

143-183: Consider adding a move variant for flb_es_str for API consistency.

The flb_es_str type has destroy, set_str, and copy_str, but no move function to transfer ownership of an existing allocated string. Other complex types (list, tls, record_accessor) provide move variants.

If callers ever need to transfer an already-allocated char* into the wrapper with ownership, they would benefit from a flb_es_str_move_str function.


357-394: Self-assignment handling is inconsistent across types.

The flb_es_aws_provider_set and flb_es_aws_provider_move functions explicitly handle the dest == src case by doing nothing. However, other types' set and move functions don't document or handle self-assignment scenarios.

For example, if someone calls flb_es_str_set_str(&x, x.value) when x.owned == FLB_TRUE, the implementation would free x.value before assigning it—resulting in a dangling pointer.

Consider either adding self-assignment protection to all types' set/move functions, or explicitly documenting that self-assignment is undefined behavior for the other wrapper types.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c714dd5 and c9370ca.

📒 Files selected for processing (7)
  • plugins/out_es/CMakeLists.txt
  • plugins/out_es/es.c
  • plugins/out_es/es.h
  • plugins/out_es/es_conf.c
  • plugins/out_es/es_conf_parse.c
  • plugins/out_es/es_type.c
  • plugins/out_es/es_type.h
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/out_es/es_type.c
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2025-08-20T02:04:27.220Z
Learnt from: mabrarov
Repo: fluent/fluent-bit PR: 7608
File: plugins/out_es/es.c:648-670
Timestamp: 2025-08-20T02:04:27.220Z
Learning: The author mabrarov prefers function contracts that assume valid parameters for internal functions in the Elasticsearch output plugin, rather than adding defensive null pointer checks, to maintain performance and code clarity.

Applied to files:

  • plugins/out_es/es.c
  • plugins/out_es/es_conf_parse.c
📚 Learning: 2025-09-22T15:59:55.794Z
Learnt from: nicknezis
Repo: fluent/fluent-bit PR: 10882
File: plugins/out_http/http.c:112-116
Timestamp: 2025-09-22T15:59:55.794Z
Learning: When users consider bug fixes out of scope for their focused PRs, it's appropriate to create separate GitHub issues to track those concerns rather than expanding the current PR scope.

Applied to files:

  • plugins/out_es/es.c
  • plugins/out_es/es_conf_parse.c
📚 Learning: 2025-10-06T17:39:21.606Z
Learnt from: edsiper
Repo: fluent/fluent-bit PR: 10967
File: plugins/in_elasticsearch/in_elasticsearch_bulk_prot.c:266-272
Timestamp: 2025-10-06T17:39:21.606Z
Learning: In the in_elasticsearch plugin, payloads are JSON-based, so tag_key values will always be strings. There's no need to handle binary (FLB_RA_BINARY) values when extracting tags from records in this plugin.

Applied to files:

  • plugins/out_es/es.c
📚 Learning: 2025-09-08T11:21:33.975Z
Learnt from: cosmo0920
Repo: fluent/fluent-bit PR: 10851
File: include/fluent-bit/flb_simd.h:60-66
Timestamp: 2025-09-08T11:21:33.975Z
Learning: Fluent Bit currently only supports MSVC compiler on Windows, so additional compiler compatibility guards may be unnecessary for Windows-specific code paths.

Applied to files:

  • plugins/out_es/es_conf_parse.c
📚 Learning: 2025-12-17T18:45:02.283Z
Learnt from: edsiper
Repo: fluent/fluent-bit PR: 11286
File: src/flb_http_client.c:1657-1715
Timestamp: 2025-12-17T18:45:02.283Z
Learning: In the Fluent Bit OAuth2 implementation (src/flb_oauth2.c), the function flb_oauth2_get_access_token returns a pointer to the cached token stored in the OAuth2 context (ctx->access_token), not a new allocation. The OAuth2 context manages the token lifecycle, so callers must not free the returned token pointer.

Applied to files:

  • plugins/out_es/es_conf_parse.c
📚 Learning: 2025-11-11T20:33:42.883Z
Learnt from: mabrarov
Repo: fluent/fluent-bit PR: 7608
File: plugins/out_es/es_conf.c:932-946
Timestamp: 2025-11-11T20:33:42.883Z
Learning: The mk_list_is_empty function in Fluent Bit returns 0 when a list IS empty and -1 when a list is NOT empty. Use `mk_list_is_empty(list) == 0` to check if empty, and `mk_list_is_empty(list) != 0` to check if not empty.

Applied to files:

  • plugins/out_es/es_conf.c
📚 Learning: 2025-08-31T12:46:11.940Z
Learnt from: ThomasDevoogdt
Repo: fluent/fluent-bit PR: 9277
File: .github/workflows/pr-compile-check.yaml:147-151
Timestamp: 2025-08-31T12:46:11.940Z
Learning: In fluent-bit CMakeLists.txt, the system library preference flags are defined as FLB_PREFER_SYSTEM_LIB_ZSTD and FLB_PREFER_SYSTEM_LIB_KAFKA with the FLB_ prefix.

Applied to files:

  • plugins/out_es/es.h
🧬 Code graph analysis (4)
plugins/out_es/es.c (3)
plugins/out_es/es_conf.c (1)
  • flb_es_upstream_conf (887-901)
src/flb_upstream_ha.c (1)
  • flb_upstream_ha_node_get (88-110)
src/flb_upstream.c (1)
  • flb_upstream_conn_get (711-844)
plugins/out_es/es_conf_parse.c (4)
src/flb_utils.c (2)
  • flb_utils_split (464-467)
  • flb_utils_split_free (477-489)
src/flb_sds.c (2)
  • flb_sds_create (78-90)
  • flb_sds_destroy (389-399)
src/flb_slist.c (2)
  • flb_slist_create (27-31)
  • flb_slist_add (70-84)
include/fluent-bit/flb_mem.h (1)
  • flb_free (126-128)
plugins/out_es/es_conf.c (5)
plugins/out_es/es_type.c (5)
  • flb_es_ra_move_ra (172-180)
  • flb_es_str_copy_str (46-61)
  • flb_es_str_set_str (39-44)
  • flb_es_ra_destroy (153-160)
  • flb_es_str_destroy (30-37)
plugins/out_es/es_conf_parse.c (2)
  • flb_es_conf_set_cloud_auth (142-192)
  • flb_es_conf_set_cloud_credentials (38-73)
include/fluent-bit/flb_output.h (1)
  • flb_output_config_map_set (1321-1348)
include/fluent-bit/flb_upstream_node.h (2)
  • flb_upstream_node_set_data (82-86)
  • flb_upstream_node_get_data (88-91)
src/flb_upstream.c (2)
  • flb_upstream_create (290-363)
  • flb_upstream_destroy (656-698)
plugins/out_es/es.h (1)
plugins/out_es/es.c (1)
  • flb_elasticsearch_target (652-674)
⏰ 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). (81)
  • GitHub Check: PR - container builds / Windows container images (2022)
  • GitHub Check: PR - container builds / Windows container images (2025)
  • GitHub Check: PR - packages build Linux / centos/8.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/9 package build and stage to S3
  • GitHub Check: PR - packages build Linux / ubuntu/24.04.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / raspbian/bookworm package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/bullseye.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / ubuntu/22.04.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/bullseye package build and stage to S3
  • GitHub Check: PR - packages build Linux / ubuntu/24.04 package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/8.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/bookworm package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/trixie.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/buster.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/8.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/bookworm.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/9 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/buster package build and stage to S3
  • GitHub Check: PR - packages build Linux / ubuntu/22.04 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/9.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/9.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / debian/trixie package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/10 package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/10.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / almalinux/9.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/10.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/9 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/7.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/10 package build and stage to S3
  • GitHub Check: PR - packages build Linux / rockylinux/8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/10.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/10 package build and stage to S3
  • GitHub Check: PR - packages build Linux / centos/7 package build and stage to S3
  • GitHub Check: PR - packages build Linux / amazonlinux/2023 package build and stage to S3
  • GitHub Check: PR - packages build Linux / amazonlinux/2 package build and stage to S3
  • GitHub Check: PR - packages build Linux / amazonlinux/2.arm64v8 package build and stage to S3
  • GitHub Check: PR - packages build Linux / amazonlinux/2023.arm64v8 package build and stage to S3
  • GitHub Check: PR - container builds / arm/v7/debug container image build
  • GitHub Check: PR - container builds / arm64/production container image build
  • GitHub Check: PR - container builds / amd64/debug container image build
  • GitHub Check: PR - container builds / arm64/debug container image build
  • GitHub Check: PR - container builds / amd64/production container image build
  • GitHub Check: PR - container builds / arm/v7/production container image build
  • GitHub Check: PR - packages build MacOS / call-build-macos-package (Apple Silicon macOS runner, macos-14, 3.31.6)
  • GitHub Check: PR - packages build MacOS / call-build-macos-package (Intel macOS runner, macos-14-large, 3.31.6)
  • GitHub Check: PR - packages build Windows / call-build-windows-package (Windows 64bit, x64, x64-windows-static, 3.31.6)
  • GitHub Check: PR - packages build Windows / call-build-windows-package (Windows 64bit (Arm64), amd64_arm64, -DCMAKE_SYSTEM_NAME=Windows -DCMA...
  • GitHub Check: PR - packages build Windows / 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 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: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-22.04, clang-12)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_COMPILER_STRICT_POINTER_TYPES=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, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=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_SIMD=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=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 (-DFLB_JEMALLOC=Off, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, gcc, g++)
  • 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_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_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_SIMD=Off, 3.31.6, gcc, g++)
  • 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: 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 (-DSANITIZE_ADDRESS=On, 3.31.6, gcc, g++)
  • 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-without-cxx (3.31.6)
  • GitHub Check: PR - fuzzing test
🔇 Additional comments (28)
plugins/out_es/es_conf_parse.c (3)

38-73: Cloud credentials parsing looks correct.

The OOM handling for flb_strdup was addressed per previous review feedback. The function properly cleans up toks on allocation failure and returns -1.

Note: When cloud_passwd allocation fails, cloud_user remains allocated with its ownership flag set. This is intentional - as confirmed in past reviews, the caller (elasticsearch_config_destroy) will clean up partial allocations based on the individual ownership flags.


83-140: Buffer overflow risk tracked in issue #11368.

This is migrated code from the original es_conf.c. The potential buffer overflow with strcpy/strcat operations on cloud_host_buf[256] has already been flagged and tracked in issue #11368 for follow-up.


279-345: AWS provider setup is well-structured.

The function properly:

  • Validates AWS auth and region settings
  • Creates TLS context with proper error handling
  • Initializes credentials synchronously before switching to async mode
  • Wires the provider upstream to Fluent Bit
plugins/out_es/CMakeLists.txt (1)

1-10: Build configuration correctly updated.

The new source files es_type.c and es_conf_parse.c are properly added to the CMake source list, enabling compilation of the new modular ES configuration and type wrapper infrastructure.

plugins/out_es/es_conf.c (12)

36-61: Helper config_set_ra_id_key is correct.

Properly creates a record accessor from id_key, handles NULL input, and warns when generate_id conflicts with id_key.


63-98: Write operation validation is thorough.

The function correctly:

  • Maps write operation strings to static constants
  • Validates that update/upsert operations require Id_Key or Generate_Id
  • Returns clear error messages

117-138: Pipeline/path URI construction is safe.

The function properly uses snprintf with bounds checking and returns -1 if the URI would be truncated.


140-177: Prefix key record accessor setup is correct.

Properly handles the case where the key doesn't start with $ by prepending it, and correctly frees the temporary buffer after creating the record accessor.


179-289: Main configuration property setup is comprehensive.

The function properly orchestrates:

  • Cloud ID/auth handling
  • Config map population
  • Buffer size adjustment
  • Index/type from URI
  • Pipeline and path setup
  • Record accessor initialization
  • AWS authentication (conditionally compiled)

Error handling is consistent with -1 returns on failure.


291-357: Base configuration copy uses proper non-owning references.

The function correctly uses flb_es_str_set_str, flb_es_sds_set_sds, and flb_es_ra_set_ra to create non-owning references from the base config, avoiding double-free issues when both base and node configs share the same underlying data.


359-593: Per-node property overrides are well-structured.

The function correctly:

  • Uses non-owning set_str for properties that reference node-owned strings
  • Uses owning copy_str for properties that need per-node copies
  • Recreates AWS provider when any AWS-related setting changes per-node

The logic at lines 578-590 properly detects when a new AWS provider is needed based on auth changes or provider-specific settings.


595-604: Validation logic preserved from original code.

As noted in past reviews, there's a potential edge case where current_time_index == TRUE with index.value == NULL could pass validation but cause issues in strftime. This is pre-existing behavior from the original code and outside the scope of this PR.


606-634: Resource cleanup is thorough.

The destroy function properly releases all owned resources using the ownership-aware flb_es_*_destroy helpers, ensuring no double-frees when configurations share underlying data.


636-745: HA configuration setup with proper error recovery.

The function:

  • Creates main elasticsearch_config for base properties
  • Loads upstream HA nodes from file
  • Creates per-node configurations with property overrides
  • Properly cleans up all allocated resources on any failure

The cleanup path (lines 722-738) correctly:

  1. Nullifies node data pointers
  2. Removes and destroys per-node configs from the list
  3. Destroys the HA upstream and base config

747-817: Simple (non-HA) configuration setup is correct.

The function properly:

  • Sets default host/port
  • Creates single elasticsearch_config
  • Handles TLS and IPv6 flags
  • Creates upstream connection with proper cleanup on failure

887-901: Upstream config accessor correctly handles empty list.

Per the learned behavior of mk_list_is_empty (returns 0 when empty, -1 when not empty), the check at line 897 correctly returns NULL when the configs list is empty.

Based on learnings, mk_list_is_empty(&ctx->configs) == 0 means the list IS empty.

plugins/out_es/es.c (5)

46-85: AWS auth and pack helpers correctly use ec.

The refactored functions now accept struct flb_elasticsearch_config *ec and properly source AWS region, service name, unsigned headers, and provider from the ec context.


287-327: Format function correctly receives ec via flush_ctx.

The elasticsearch_format function now receives flush_ctx (the per-upstream elasticsearch_config) and uses it for all configuration lookups. This enables per-node configuration in HA mode.


652-674: Target selection with documented contract.

The function correctly implements HA node selection via round-robin and single-mode fallback. The contract (ctx and node must be non-NULL) is documented in es.h lines 163-177.

Based on learnings, defensive null checks are intentionally omitted to maintain performance and code clarity.


835-876: Flush path correctly handles HA and non-HA modes.

The refactored flush callback:

  • Obtains target configuration via flb_elasticsearch_target
  • Gets upstream connection from the appropriate source (node->u in HA mode, ctx->u otherwise)
  • Provides clear error messages distinguishing HA node failures from single-mode failures

1149-1393: Config map correctly targets elasticsearch_config with nested offsets.

The config map entries properly use:

  • FLB_ES_CONFIG_PROPERTY_* macros for property names
  • Nested offsetof expressions to target .value fields within wrapper types (e.g., offsetof(struct flb_elasticsearch_config, index) + offsetof(struct flb_es_str, value))
  • New Upstream property for HA configuration file path
plugins/out_es/es.h (3)

23-51: Header coupling reduced with forward declarations.

As addressed per past review feedback, heavy includes were replaced with forward declarations for:

  • struct flb_upstream
  • struct flb_upstream_ha
  • struct flb_upstream_node
  • struct flb_output_instance

This reduces transitive rebuilds and compile time.


53-161: Configuration structures well-designed for HA mode.

The separation between flb_elasticsearch_config (per-node settings) and flb_elasticsearch (plugin instance with HA routing) enables:

  • Shared base configuration with per-node overrides
  • Safe resource cleanup via ownership-aware wrapper types
  • List-based management of multiple configurations

The _head member enables linking configs for lifecycle management.


163-178: API documentation added for flb_elasticsearch_target.

The documentation clearly specifies:

  • Parameter contracts (non-NULL requirements)
  • Output parameter behavior
  • Return value semantics

This addresses past review feedback about documenting function contracts.

plugins/out_es/es_type.h (4)

33-141: Well-designed ownership wrapper types.

The struct definitions follow a consistent pattern and are well-documented. The ownership flag approach addresses the configuration sharing concern between plugin-level and per-upstream-node configs. The documentation clearly specifies when direct member access is permitted.


396-411: Clear distinction between wrapper and raw pointer operations.

The flb_es_aws_provider_move_provider function clearly indicates it takes a raw flb_aws_provider* rather than a wrapper, distinguishing it from flb_es_aws_provider_move which operates on wrapper-to-wrapper transfers. This naming convention is helpful.


1-32: Well-structured header with appropriate forward declarations.

The header properly includes only what's needed (flb_sds.h) and uses forward declarations for external types (mk_list, flb_tls, flb_record_accessor, flb_aws_provider). This minimizes header dependencies and compilation coupling.


20-21: Include guard naming is correct.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

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

🤖 Fix all issues with AI agents
In `@plugins/out_es/es_conf.c`:
- Around line 385-575: The code allows per-node overrides of generate_id and
id_key without re-checking update/upsert rules because config_set_es_action is
only called when write_operation is overridden; fix by re-validating after
per-node overrides: when processing FLB_ES_CONFIG_PROPERTY_GENERATE_ID or
FLB_ES_CONFIG_PROPERTY_ID_KEY (or after all per-node properties are applied)
call the same validation used by config_set_es_action using
ec->write_operation.value, ec->ra_id_key.value and ec->generate_id (or invoke a
small helper that checks update/upsert require an _id) and return -1 on failure
so invalid per-node configs are rejected; references: generate_id, id_key,
config_set_es_action, FLB_ES_CONFIG_PROPERTY_GENERATE_ID,
FLB_ES_CONFIG_PROPERTY_ID_KEY, ec and ctx.
- Around line 833-848: The output context is set with
flb_output_set_context(ins, ctx) before calling es_config_ha/es_config_simple,
so if those return non-zero we free ctx but leave ins pointing at freed memory;
move or mirror the fix so the output instance never retains a dangling pointer
by either delaying flb_output_set_context(ins, ctx) until after ret == 0 (i.e.,
after successful es_config_ha/es_config_simple) or by calling
flb_output_set_context(ins, NULL) immediately before flb_free(ctx) when ret !=
0; update the init path around flb_output_set_context, ctx, es_config_ha, and
es_config_simple accordingly.

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

🤖 Fix all issues with AI agents
In `@plugins/out_es/es_conf_parse.c`:
- Around line 51-53: Guard against flb_utils_split returning NULL: check the
returned pointer (toks) immediately after calling flb_utils_split((const char
*)cloud_auth, ':', -1) and if it is NULL, log/return an error (or appropriate
failure code from the surrounding function) instead of proceeding; this prevents
mk_list_foreach(head, toks) from dereferencing a NULL pointer. Update the code
around the flb_utils_split call to perform the NULL check and handle the failure
path cleanly before using toks.

In `@plugins/out_es/es_type.h`:
- Around line 224-233: The doc comment for flb_es_slist_destroy incorrectly
references the type flb_es_list; update the parameter description to mention the
correct type flb_es_slist instead. Locate the comment block above the function
declaration flb_es_slist_destroy and replace "flb_es_list" with "flb_es_slist"
so the `@param` description and explanatory text consistently refer to the struct
flb_es_slist.
♻️ Duplicate comments (1)
tests/runtime/out_elasticsearch.c (1)

22-38: Avoid tmpnam(NULL); prefer a caller‑supplied buffer (or mkstemp).

tmpnam(NULL) relies on a static buffer and is prone to race conditions; if POSIX is acceptable, mkstemp is safer, otherwise use tmpnam(buf).

🔧 Suggested fix (C‑standard buffer usage)
-    upstream_conf_filename = tmpnam(NULL);
-    if (upstream_conf_filename == NULL) {
-        return NULL;
-    }
-    upstream_conf_filename = flb_strdup(upstream_conf_filename);
-    if (upstream_conf_filename == NULL) {
-        return NULL;
-    }
+    upstream_conf_filename = flb_malloc(L_tmpnam);
+    if (upstream_conf_filename == NULL) {
+        return NULL;
+    }
+    if (tmpnam(upstream_conf_filename) == NULL) {
+        flb_free(upstream_conf_filename);
+        return NULL;
+    }

@mabrarov
Copy link
Contributor Author

Hi dear reviewers,

I have addressed all comments in this pull request and I consider it ready for review.

Thank you.

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

🤖 Fix all issues with AI agents
In `@plugins/out_es/es_conf.c`:
- Around line 369-506: Several boolean config assignments call flb_utils_bool()
and assign its result directly to flags (e.g., ec->suppress_type_name,
ec->generate_id, ec->has_aws_auth, ec->logstash_format, ec->time_key_nanos,
ec->include_tag_key, ec->replace_dots, ec->current_time_index, ec->trace_output,
ec->trace_error); flb_utils_bool() returns -1 on invalid input so you must treat
that as a config error. For each place where flb_utils_bool(tmp) is used, store
the result in a temporary int (e.g., int val = flb_utils_bool(tmp)); if val ==
-1 return -1 (abort); otherwise assign ec->field = val; apply this pattern to
all boolean overrides read via flb_upstream_node_get_property in this diff.

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

🤖 Fix all issues with AI agents
In `@plugins/out_es/es.c`:
- Around line 1279-1282: The config_map entry for logstash_dateformat is writing
the pointer at the wrong place because logstash_dateformat is a flb_es_sds_t and
its entry is missing the "+ offsetof(struct flb_es_sds_t, value)" adjustment;
update the config_map entry for logstash_dateformat (in the block where
FLB_ES_CONFIG_PROPERTY_LOGSTASH_DATEFORMAT is defined) to use offsetof(struct
flb_elasticsearch_config, logstash_dateformat) + offsetof(struct flb_es_sds_t,
value) so it matches the other flb_es_sds_t fields and prevents corrupting the
flb_es_sds_t wrapper.
🧹 Nitpick comments (5)
tests/runtime/out_elasticsearch.c (1)

22-112: create_upstream_conf_file helper is functional but has a minor portability note.

The tmpnam usage with an owned buffer (per past review discussion) is acceptable for test code. The varargs-based config generation with arg_idx ^= 1 toggling is a compact approach.

One minor note: if first_property is non-NULL but the varargs list has an odd number of entries (missing value for a property name), the loop will write a bare newline for the missing value and continue. This is unlikely in practice since tests use explicit NULL terminators, but documenting the contract (pairs of name/value, NULL-terminated) in a comment would help future test authors.

src/flb_lib.c (1)

617-649: flb_output_set_test_flush_ctx_callback overwrites rt_ctx/rt_ffd but not rt_out_callback/rt_data.

This function sets test_mode, rt_ctx, rt_ffd, flush_ctx, and flush_ctx_callback — but it does not set rt_out_callback or rt_data. This means it's only safe to call after flb_output_set_test has been called (which is the current usage in all tests). If called standalone, the formatter test would run but the runtime result checker would be missing.

Consider either documenting that flb_output_set_test must be called first, or simplifying flb_output_set_test_flush_ctx_callback to only set the two fields it's responsible for (flush_ctx and flush_ctx_callback) without touching other test_formatter members.

Simplified version that only sets the callback-specific fields
 int flb_output_set_test_flush_ctx_callback(flb_ctx_t *ctx, int ffd,
                                            char *test_name,
                                            void *(*flush_ctx_callback) (struct flb_config *,
                                                                         struct flb_input_instance *,
                                                                         void *, void *),
                                            void *flush_ctx)
 {
     struct flb_output_instance *o_ins;
 
     o_ins = out_instance_get(ctx, ffd);
     if (!o_ins) {
         return -1;
     }
 
-    /*
-     * Enabling a test, set the output instance in 'test' mode, so no real
-     * flush callback is invoked, only the desired implemented test.
-     */
-
     /* Formatter test */
     if (strcmp(test_name, "formatter") == 0) {
-        o_ins->test_mode = FLB_TRUE;
-        o_ins->test_formatter.rt_ctx = ctx;
-        o_ins->test_formatter.rt_ffd = ffd;
         o_ins->test_formatter.flush_ctx = flush_ctx;
         o_ins->test_formatter.flush_ctx_callback = flush_ctx_callback;
     }
     else {
         return -1;
     }
 
     return 0;
 }
plugins/out_es/es_conf.c (1)

100-107: size_t compared with -1 — works but is implicit.

buffer_size == -1 where buffer_size is size_t compiles to buffer_size == SIZE_MAX. This is correct but may trigger -Wsign-compare warnings on some compilers. Consider using an explicit constant or cast for clarity.

Optional: make the sentinel explicit
 static size_t config_adjust_buffer_size(size_t buffer_size)
 {
-    /* HTTP Payload (response) maximum buffer size (0 == unlimited) */
-    if (buffer_size == -1) {
+    /* HTTP Payload (response) maximum buffer size (0 == unlimited).
+     * flb_utils_size_to_bytes returns -1 on error, which when cast
+     * to size_t becomes SIZE_MAX. */
+    if (buffer_size == (size_t) -1) {
         return 0;
     }
     return buffer_size;
 }
plugins/out_es/es.h (1)

53-147: Ownership model for flb_elasticsearch_config fields is clear but mixing raw and wrapper types warrants a brief note.

Fields like http_user, http_passwd, http_api_key are plain char * (owned by flb_config_map), while cloud_user/cloud_passwd use struct flb_es_str and logstash fields use struct flb_es_sds_t (shared-ownership wrappers). This asymmetry is intentional per the PR discussion, but a short comment near the raw char * group explaining why they don't need wrappers (e.g., "owned by config_map, never shared across upstream nodes") would help future maintainers.

plugins/out_es/es.c (1)

312-315: Remove commented-out variable declarations.

These four commented-out lines (msgpack_unpacked result, msgpack_object root, msgpack_object *obj) appear to be leftover from refactoring.

♻️ Proposed cleanup
-    // msgpack_unpacked result;
-    // msgpack_object root;
     msgpack_object map;
-    // msgpack_object *obj;

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

🤖 Fix all issues with AI agents
In `@plugins/out_es/es_conf_parse.c`:
- Around line 58-70: The code currently checks ec->cloud_user.value and
ec->cloud_passwd.value after calling flb_es_str_copy_str(), but
flb_es_str_copy_str() returns an error on OOM while preserving the old dest
value, so change the logic in the parsing branch that handles items==1 and
items==2 to capture and check the return value of
flb_es_str_copy_str(&ec->cloud_user, entry->value) and
flb_es_str_copy_str(&ec->cloud_passwd, entry->value); if the call returns
non‑zero, call flb_utils_split_free(toks) and return -1 to reliably detect
allocation failure instead of inspecting dest->value.

In `@plugins/out_es/es_conf.c`:
- Around line 508-511: The code currently obtains tmp via
flb_upstream_node_get_property(FLB_ES_CONFIG_PROPERTY_BUFFER_SIZE) and calls
config_adjust_buffer_size(flb_utils_size_to_bytes(tmp)), which masks invalid
inputs because flb_utils_size_to_bytes() returns -1 for invalid strings; detect
that case before casting/adjusting: call flb_utils_size_to_bytes(tmp), check for
a negative return (e.g. -1) and treat it as a configuration error (log an error
and return/fail the config load for the upstream/node) instead of proceeding to
config_adjust_buffer_size; update the logic around tmp, flb_utils_size_to_bytes,
and ec->buffer_size so only valid positive byte sizes are passed to
config_adjust_buffer_size and assigned to ec->buffer_size.

In `@plugins/out_es/es.c`:
- Around line 917-923: The code currently treats flb_http_client(...) failure as
permanent by setting ret = FLB_ERROR and dropping the chunk; instead treat
allocation/connect failures as transient and return a retry code so Fluent Bit
will requeue the data. In the block that checks if (!c) (the flb_http_client
call creating variable c with u_conn and ec->uri, using pack/pack_size), change
the error handling to log the failure via flb_plg_error(ctx->ins, ...) and set
ret = FLB_RETRY (not FLB_ERROR) before jumping to cleanup_and_return so the
chunk is retried rather than discarded.

@mabrarov
Copy link
Contributor Author

mabrarov commented Feb 9, 2026

Hi @cosmo0920 and @patrick-stephens,

This PR is pending for more than 2.5 years. I appreciate if you could find time and review it again. I believe I have addressed comment of @cosmo0920 which was the only concern at the time the comment was added.

My winter vacation has ended and I won't be able to spend much time on this PR till summer, especially, considering new pending PRs for the same plugin (e.g. #11422 and #11375) - reabasing such changes can be hard.

Thank you.

@mabrarov
Copy link
Contributor Author

mabrarov commented Feb 9, 2026

I believe that similar changes can be implemented / helpful for OpenSearch output plugin (in a dedicated PR).

…wn to parser of Upstream node configuration section are implemented, e.g. "host" and "port"

Signed-off-by: Marat Abrarov <abrarov@gmail.com>
…o the test callback based on configuration of Fluent Bit and based on configuration of plugin

Signed-off-by: Marat Abrarov <abrarov@gmail.com>
…llback contract

Signed-off-by: Marat Abrarov <abrarov@gmail.com>
…with Upstream node configuration

For Elastic cloud authentication these parameters are always taken from plugin configuration and never from Upstream node configuration: cloud_id.

For AWS authentication these parameters are always taken from plugin configuration and never from Upstream node configuration: http_proxy, no_proxy, tls*.

Signed-off-by: Marat Abrarov <abrarov@gmail.com>
Signed-off-by: Marat Abrarov <abrarov@gmail.com>
…o the test callback based on configuration of Fluent Bit and based on configuration of plugin

Signed-off-by: Marat Abrarov <abrarov@gmail.com>
Signed-off-by: Marat Abrarov <abrarov@gmail.com>
…icate username or password used for AWS authentication

Signed-off-by: Marat Abrarov <abrarov@gmail.com>
…on and retrying buffer flush

Signed-off-by: Marat Abrarov <abrarov@gmail.com>
…ent creation failed

Signed-off-by: Marat Abrarov <abrarov@gmail.com>
…iguration data

Signed-off-by: Marat Abrarov <abrarov@gmail.com>
…tials

Signed-off-by: Marat Abrarov <abrarov@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs-required ok-package-test Run PR packaging tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants