From 5a2fcbd2755c916a3b08a3d6e1d93812abba5c04 Mon Sep 17 00:00:00 2001 From: Ilia Petrov Date: Fri, 8 May 2026 09:59:04 +0300 Subject: [PATCH 01/14] kv: add function flb_kv_get_all_key_values The goal of this enhancement is to extend the key-value store API to support retrieving all elements from the linked list in a single call. Currently, the only way to retrieve all elements is to guess the keys and repeatedly call `flb_kv_get_key_value`, which is especially problematic for plugin writers. Signed-off-by: Ilia Petrov --- include/fluent-bit/flb_kv.h | 1 + src/flb_kv.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/fluent-bit/flb_kv.h b/include/fluent-bit/flb_kv.h index 0c4ad82ce1f..84aaabe0c41 100644 --- a/include/fluent-bit/flb_kv.h +++ b/include/fluent-bit/flb_kv.h @@ -41,5 +41,6 @@ struct flb_kv *flb_kv_item_set(struct mk_list *list, void flb_kv_item_destroy(struct flb_kv *kv); void flb_kv_release(struct mk_list *list); const char *flb_kv_get_key_value(const char *key, struct mk_list *list); +struct flb_kv **flb_kv_get_all_key_values(struct mk_list *list); #endif diff --git a/src/flb_kv.c b/src/flb_kv.c index fc3c3545fad..08aa5946a09 100644 --- a/src/flb_kv.c +++ b/src/flb_kv.c @@ -160,3 +160,35 @@ const char *flb_kv_get_key_value(const char *key, struct mk_list *list) return NULL; } + +struct flb_kv **flb_kv_get_all_key_values(struct mk_list *list) +{ + int count; + int i = 0; + struct mk_list *head; + struct flb_kv *kv; + struct flb_kv **arr; + + if (!list) { + return NULL; + } + + count = mk_list_size(list); + if (count == 0) { + return NULL; + } + + arr = flb_calloc(count, sizeof(struct flb_kv *)); + if (!arr) { + flb_errno(); + return NULL; + } + + mk_list_foreach(head, list) { + kv = mk_list_entry(head, struct flb_kv, _head); + arr[i] = kv; + i++; + } + + return arr; +} From 24549d42e29681dec6ee62361839144db0c849b6 Mon Sep 17 00:00:00 2001 From: Ilia Petrov Date: Fri, 8 May 2026 10:12:47 +0300 Subject: [PATCH 02/14] tests: test the new flb_kv_get_all_key_values function Signed-off-by: Ilia Petrov --- tests/internal/kv.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/internal/kv.c b/tests/internal/kv.c index e20d5184692..b95ba198e90 100644 --- a/tests/internal/kv.c +++ b/tests/internal/kv.c @@ -1,6 +1,7 @@ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include +#include #include "flb_tests_internal.h" static void test_kv_item_set_duplicate() @@ -28,7 +29,43 @@ static void test_kv_item_set_duplicate() flb_kv_release(&list); } +static void test_kv_get_all_key_values() +{ + struct mk_list list; + struct flb_kv **pairs; + + flb_kv_init(&list); + + pairs = flb_kv_get_all_key_values(&list); + TEST_CHECK(pairs == NULL); + + flb_kv_item_set(&list, "host", "localhost"); + flb_kv_item_set(&list, "port", "8080"); + flb_kv_item_set(&list, "path", "/api"); + + pairs = flb_kv_get_all_key_values(&list); + TEST_CHECK(pairs != NULL); + + if (pairs) { + TEST_CHECK(pairs[0] != NULL); + TEST_CHECK(strcmp(pairs[0]->key, "host") == 0); + TEST_CHECK(strcmp(pairs[0]->val, "localhost") == 0); + + TEST_CHECK(pairs[1] != NULL); + TEST_CHECK(strcmp(pairs[1]->key, "port") == 0); + TEST_CHECK(strcmp(pairs[1]->val, "8080") == 0); + + TEST_CHECK(pairs[2] != NULL); + TEST_CHECK(strcmp(pairs[2]->key, "path") == 0); + TEST_CHECK(strcmp(pairs[2]->val, "/api") == 0); + } + + flb_kv_release(&list); + flb_free(pairs); +} + TEST_LIST = { {"kv_item_set_duplicate", test_kv_item_set_duplicate}, + {"kv_get_all_key_values", test_kv_get_all_key_values}, {0} }; From 98978ac1c4e2663ee8f937a00fc31f5eb58fe01c Mon Sep 17 00:00:00 2001 From: Ilia Petrov Date: Fri, 8 May 2026 10:22:36 +0300 Subject: [PATCH 03/14] kv: add out_count parameter to flb_kv_get_all_key_values This out_count parameter is needed so the callers can safely iterate without external assumptions. Signed-off-by: Ilia Petrov --- include/fluent-bit/flb_kv.h | 2 +- src/flb_kv.c | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/fluent-bit/flb_kv.h b/include/fluent-bit/flb_kv.h index 84aaabe0c41..17213186d51 100644 --- a/include/fluent-bit/flb_kv.h +++ b/include/fluent-bit/flb_kv.h @@ -41,6 +41,6 @@ struct flb_kv *flb_kv_item_set(struct mk_list *list, void flb_kv_item_destroy(struct flb_kv *kv); void flb_kv_release(struct mk_list *list); const char *flb_kv_get_key_value(const char *key, struct mk_list *list); -struct flb_kv **flb_kv_get_all_key_values(struct mk_list *list); +struct flb_kv **flb_kv_get_all_key_values(struct mk_list *list, int *out_count); #endif diff --git a/src/flb_kv.c b/src/flb_kv.c index 08aa5946a09..61464fed81a 100644 --- a/src/flb_kv.c +++ b/src/flb_kv.c @@ -161,7 +161,7 @@ const char *flb_kv_get_key_value(const char *key, struct mk_list *list) return NULL; } -struct flb_kv **flb_kv_get_all_key_values(struct mk_list *list) +struct flb_kv **flb_kv_get_all_key_values(struct mk_list *list, int *out_count) { int count; int i = 0; @@ -169,6 +169,10 @@ struct flb_kv **flb_kv_get_all_key_values(struct mk_list *list) struct flb_kv *kv; struct flb_kv **arr; + if (out_count) { + *out_count = 0; + } + if (!list) { return NULL; } @@ -190,5 +194,9 @@ struct flb_kv **flb_kv_get_all_key_values(struct mk_list *list) i++; } + if (out_count) { + *out_count = count; + } + return arr; } From dd48761bc65b859880997561fa29b157f637b3ff Mon Sep 17 00:00:00 2001 From: Ilia Petrov Date: Fri, 8 May 2026 10:28:10 +0300 Subject: [PATCH 04/14] tests: update the tests for flb_kv_get_all_key_values to use out_count parameter Signed-off-by: Ilia Petrov --- tests/internal/kv.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/internal/kv.c b/tests/internal/kv.c index b95ba198e90..e9ca6b1a119 100644 --- a/tests/internal/kv.c +++ b/tests/internal/kv.c @@ -33,18 +33,21 @@ static void test_kv_get_all_key_values() { struct mk_list list; struct flb_kv **pairs; + int count = -1; flb_kv_init(&list); - pairs = flb_kv_get_all_key_values(&list); + pairs = flb_kv_get_all_key_values(&list, &count); TEST_CHECK(pairs == NULL); + TEST_CHECK(count == 0); flb_kv_item_set(&list, "host", "localhost"); flb_kv_item_set(&list, "port", "8080"); flb_kv_item_set(&list, "path", "/api"); - pairs = flb_kv_get_all_key_values(&list); + pairs = flb_kv_get_all_key_values(&list, &count); TEST_CHECK(pairs != NULL); + TEST_CHECK(count == 3); if (pairs) { TEST_CHECK(pairs[0] != NULL); From ff54e1a5a75d6e7e2ebd832b528a25f3fc0b5bf3 Mon Sep 17 00:00:00 2001 From: Ilia Petrov Date: Fri, 8 May 2026 10:30:28 +0300 Subject: [PATCH 05/14] tests: add explicit guards for OOB failure for flb_kv_get_all_key_values Signed-off-by: Ilia Petrov --- tests/internal/kv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/internal/kv.c b/tests/internal/kv.c index e9ca6b1a119..f630fc5dee0 100644 --- a/tests/internal/kv.c +++ b/tests/internal/kv.c @@ -49,7 +49,7 @@ static void test_kv_get_all_key_values() TEST_CHECK(pairs != NULL); TEST_CHECK(count == 3); - if (pairs) { + if (pairs && count == 3) { TEST_CHECK(pairs[0] != NULL); TEST_CHECK(strcmp(pairs[0]->key, "host") == 0); TEST_CHECK(strcmp(pairs[0]->val, "localhost") == 0); From d61f20e9c79e3f6123c6dc1dc3ee53beadd7b14d Mon Sep 17 00:00:00 2001 From: Ilia Petrov Date: Fri, 3 Jul 2026 13:07:58 +0300 Subject: [PATCH 06/14] config: add flb_config_prop_get_all wrapper Introduce flb_config_prop_get_all() as the property-list counterpart of flb_config_prop_get(). It delegates to flb_kv_get_all_key_values() so callers get the full list of properties in one call instead of looking them up one key at a time. Signed-off-by: Ilia Petrov --- include/fluent-bit/flb_config.h | 2 ++ src/flb_config.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/include/fluent-bit/flb_config.h b/include/fluent-bit/flb_config.h index d171ef08167..34a53f5e655 100644 --- a/include/fluent-bit/flb_config.h +++ b/include/fluent-bit/flb_config.h @@ -32,6 +32,7 @@ #include struct flb_router; +struct flb_kv; #define FLB_CONFIG_FLUSH_SECS 1 #define FLB_CONFIG_HTTP_LISTEN "0.0.0.0" @@ -341,6 +342,7 @@ struct flb_config { struct flb_config *flb_config_init(); void flb_config_exit(struct flb_config *config); const char *flb_config_prop_get(const char *key, struct mk_list *list); +struct flb_kv **flb_config_prop_get_all(struct mk_list *list, int *out_count); int flb_config_set_property(struct flb_config *config, const char *k, const char *v); int flb_config_set_program_name(struct flb_config *config, char *name); diff --git a/src/flb_config.c b/src/flb_config.c index 06c76ca78c3..660f76e2d6e 100644 --- a/src/flb_config.c +++ b/src/flb_config.c @@ -676,6 +676,11 @@ const char *flb_config_prop_get(const char *key, struct mk_list *list) return flb_kv_get_key_value(key, list); } +struct flb_kv **flb_config_prop_get_all(struct mk_list *list, int *out_count) +{ + return flb_kv_get_all_key_values(list, out_count); +} + static inline int prop_key_check(const char *key, const char *kv, int k_len) { size_t len; From f80f906c975d7786fe272f756ba60dff50d0f7de Mon Sep 17 00:00:00 2001 From: Ilia Petrov Date: Fri, 3 Jul 2026 13:08:08 +0300 Subject: [PATCH 07/14] output: add flb_output_get_all_properties wrapper Expose flb_output_get_all_properties() so plugin code with only an output instance in hand can obtain every configured property in a single call. Delegates to flb_config_prop_get_all() over the instance's properties list. Signed-off-by: Ilia Petrov --- include/fluent-bit/flb_output.h | 2 ++ src/flb_output.c | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/include/fluent-bit/flb_output.h b/include/fluent-bit/flb_output.h index 8e2b8fc3512..df2b8b84466 100644 --- a/include/fluent-bit/flb_output.h +++ b/include/fluent-bit/flb_output.h @@ -1405,6 +1405,8 @@ const char *flb_output_name(struct flb_output_instance *in); int flb_output_set_property(struct flb_output_instance *out, const char *k, const char *v); const char *flb_output_get_property(const char *key, struct flb_output_instance *ins); +struct flb_kv **flb_output_get_all_properties(struct flb_output_instance *ins, + int *out_count); #ifdef FLB_HAVE_METRICS void *flb_output_get_cmt_instance(struct flb_output_instance *ins); #endif diff --git a/src/flb_output.c b/src/flb_output.c index 26f66ad9e36..426028f6068 100644 --- a/src/flb_output.c +++ b/src/flb_output.c @@ -1179,6 +1179,12 @@ const char *flb_output_get_property(const char *key, struct flb_output_instance return flb_config_prop_get(key, &ins->properties); } +struct flb_kv **flb_output_get_all_properties(struct flb_output_instance *ins, + int *out_count) +{ + return flb_config_prop_get_all(&ins->properties, out_count); +} + #ifdef FLB_HAVE_METRICS void *flb_output_get_cmt_instance(struct flb_output_instance *ins) { From 706277d0a07bf0c71541b4401c37f362b3d1ea4c Mon Sep 17 00:00:00 2001 From: Ilia Petrov Date: Fri, 3 Jul 2026 13:08:21 +0300 Subject: [PATCH 08/14] api: expose output_get_all_properties via flb_api Publish flb_output_get_all_properties() through struct flb_api so Go proxy plugins can retrieve every configured property on an output instance from a single call, matching the individual-getter pattern already provided for output_get_property. Signed-off-by: Ilia Petrov --- include/fluent-bit/flb_api.h | 1 + src/flb_api.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/fluent-bit/flb_api.h b/include/fluent-bit/flb_api.h index cfef53e7160..174ea34c407 100644 --- a/include/fluent-bit/flb_api.h +++ b/include/fluent-bit/flb_api.h @@ -26,6 +26,7 @@ struct flb_api { const char *(*output_get_property) (const char *, struct flb_output_instance *); + struct flb_kv **(*output_get_all_properties) (struct flb_output_instance *, int *); const char *(*input_get_property) (const char *, struct flb_input_instance *); void *(*output_get_cmt_instance) (struct flb_output_instance *); diff --git a/src/flb_api.c b/src/flb_api.c index 0390a005350..6ffa74096ae 100644 --- a/src/flb_api.c +++ b/src/flb_api.c @@ -37,6 +37,7 @@ struct flb_api *flb_api_create() } api->output_get_property = flb_output_get_property; + api->output_get_all_properties = flb_output_get_all_properties; api->input_get_property = flb_input_get_property; api->custom_get_property = flb_custom_get_property; From 33a8bb298c25a56e726cd39f8c486fee30d16bd8 Mon Sep 17 00:00:00 2001 From: Ilia Petrov Date: Fri, 3 Jul 2026 13:08:40 +0300 Subject: [PATCH 09/14] kv: document flb_kv_get_all_key_values Add a docstring describing ownership: the returned array is owned by the caller and released with flb_free(), while the flb_kv entries it points to remain owned by the source list. Also spell out the return semantics for empty/NULL input and allocation failure. Signed-off-by: Ilia Petrov --- src/flb_kv.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/flb_kv.c b/src/flb_kv.c index 61464fed81a..5ca2c4fd8e0 100644 --- a/src/flb_kv.c +++ b/src/flb_kv.c @@ -161,6 +161,16 @@ const char *flb_kv_get_key_value(const char *key, struct mk_list *list) return NULL; } +/* + * Return a heap-allocated array of pointers to every flb_kv entry in 'list', + * preserving insertion order. The array itself is owned by the caller and + * must be released with flb_free(); the flb_kv entries it points to remain + * owned by 'list' and are freed by flb_kv_release()/flb_kv_item_destroy(). + * + * If 'out_count' is non-NULL it receives the number of entries (0 when the + * list is empty or NULL). Returns NULL when the list is empty, NULL, or on + * allocation failure. + */ struct flb_kv **flb_kv_get_all_key_values(struct mk_list *list, int *out_count) { int count; From 92a4533477c2fd41612d243bfa3d5335b53beab3 Mon Sep 17 00:00:00 2001 From: Ilia Petrov Date: Fri, 3 Jul 2026 13:08:46 +0300 Subject: [PATCH 10/14] config: document flb_config_prop_get_all Add a docstring pointing at flb_kv_get_all_key_values() for the full ownership contract, and summarise the caller responsibilities inline. Signed-off-by: Ilia Petrov --- src/flb_config.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/flb_config.c b/src/flb_config.c index 660f76e2d6e..025e42d06bf 100644 --- a/src/flb_config.c +++ b/src/flb_config.c @@ -676,6 +676,13 @@ const char *flb_config_prop_get(const char *key, struct mk_list *list) return flb_kv_get_key_value(key, list); } +/* + * Return a heap-allocated array of pointers to every property in 'list'. + * The caller must release the array with flb_free(); the individual entries + * remain owned by the property list. 'out_count' (optional) receives the + * number of entries. Returns NULL on empty list, NULL input, or allocation + * failure. See flb_kv_get_all_key_values() for the full contract. + */ struct flb_kv **flb_config_prop_get_all(struct mk_list *list, int *out_count) { return flb_kv_get_all_key_values(list, out_count); From 5f49912fd66d57b78df060d9093212f01d5239be Mon Sep 17 00:00:00 2001 From: Ilia Petrov Date: Fri, 3 Jul 2026 13:08:56 +0300 Subject: [PATCH 11/14] output: document flb_output_get_all_properties Add a docstring covering ownership of the returned array, the fate of the underlying flb_kv entries, and the NULL-return conditions. Signed-off-by: Ilia Petrov --- src/flb_output.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/flb_output.c b/src/flb_output.c index 426028f6068..d8852704e60 100644 --- a/src/flb_output.c +++ b/src/flb_output.c @@ -1179,6 +1179,13 @@ const char *flb_output_get_property(const char *key, struct flb_output_instance return flb_config_prop_get(key, &ins->properties); } +/* + * Return a heap-allocated array of pointers to every property configured on + * 'ins'. The caller owns the array and must release it with flb_free(); the + * underlying flb_kv entries remain owned by the output instance. 'out_count' + * (optional) receives the number of properties. Returns NULL when the + * instance has no properties or on allocation failure. + */ struct flb_kv **flb_output_get_all_properties(struct flb_output_instance *ins, int *out_count) { From f977d71962dfb4da8729624cea00642fbfb9cdbe Mon Sep 17 00:00:00 2001 From: Ilia Petrov Date: Fri, 3 Jul 2026 13:09:11 +0300 Subject: [PATCH 12/14] input: add flb_input_get_all_properties wrapper Add the input-side counterpart of flb_output_get_all_properties() so Go proxy plugins on the input path can retrieve every configured property in a single call, matching the parity already established for flb_input_get_property/flb_output_get_property. Signed-off-by: Ilia Petrov --- include/fluent-bit/flb_input.h | 2 ++ src/flb_input.c | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/include/fluent-bit/flb_input.h b/include/fluent-bit/flb_input.h index c2ca41bd75e..0b95868d389 100644 --- a/include/fluent-bit/flb_input.h +++ b/include/fluent-bit/flb_input.h @@ -795,6 +795,8 @@ int flb_input_set_property(struct flb_input_instance *ins, const char *k, const char *v); const char *flb_input_get_property(const char *key, struct flb_input_instance *ins); +struct flb_kv **flb_input_get_all_properties(struct flb_input_instance *ins, + int *out_count); #ifdef FLB_HAVE_METRICS void *flb_input_get_cmt_instance(struct flb_input_instance *ins); #endif diff --git a/src/flb_input.c b/src/flb_input.c index e990eee238c..5a9d466b054 100644 --- a/src/flb_input.c +++ b/src/flb_input.c @@ -952,6 +952,12 @@ const char *flb_input_get_property(const char *key, return flb_config_prop_get(key, &ins->properties); } +struct flb_kv **flb_input_get_all_properties(struct flb_input_instance *ins, + int *out_count) +{ + return flb_config_prop_get_all(&ins->properties, out_count); +} + #ifdef FLB_HAVE_METRICS void *flb_input_get_cmt_instance(struct flb_input_instance *ins) { From fdc39aba175bdcc0521253b14a247db380964742 Mon Sep 17 00:00:00 2001 From: Ilia Petrov Date: Fri, 3 Jul 2026 13:09:18 +0300 Subject: [PATCH 13/14] api: append *_get_all_properties slots for ABI safety Move output_get_all_properties to the end of struct flb_api and add input_get_all_properties beside it, so existing Go plugins compiled against the previous flb_api layout keep pointing at the correct slots. Function-pointer assignment in flb_api_create() is reordered to match. Reported-by: Hiroshi Hatake Signed-off-by: Ilia Petrov --- include/fluent-bit/flb_api.h | 4 +++- src/flb_api.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/fluent-bit/flb_api.h b/include/fluent-bit/flb_api.h index 174ea34c407..69a0cab153c 100644 --- a/include/fluent-bit/flb_api.h +++ b/include/fluent-bit/flb_api.h @@ -26,7 +26,6 @@ struct flb_api { const char *(*output_get_property) (const char *, struct flb_output_instance *); - struct flb_kv **(*output_get_all_properties) (struct flb_output_instance *, int *); const char *(*input_get_property) (const char *, struct flb_input_instance *); void *(*output_get_cmt_instance) (struct flb_output_instance *); @@ -40,6 +39,9 @@ struct flb_api { * input/output definitions. */ const char *(*custom_get_property) (const char *, struct flb_custom_instance *); int (*custom_log_check) (struct flb_custom_instance *, int); + + struct flb_kv **(*output_get_all_properties) (struct flb_output_instance *, int *); + struct flb_kv **(*input_get_all_properties) (struct flb_input_instance *, int *); }; #ifdef FLB_CORE diff --git a/src/flb_api.c b/src/flb_api.c index 6ffa74096ae..e2408cc7738 100644 --- a/src/flb_api.c +++ b/src/flb_api.c @@ -37,7 +37,6 @@ struct flb_api *flb_api_create() } api->output_get_property = flb_output_get_property; - api->output_get_all_properties = flb_output_get_all_properties; api->input_get_property = flb_input_get_property; api->custom_get_property = flb_custom_get_property; @@ -51,6 +50,9 @@ struct flb_api *flb_api_create() api->output_log_check = flb_output_log_check; api->custom_log_check = flb_custom_log_check; + api->output_get_all_properties = flb_output_get_all_properties; + api->input_get_all_properties = flb_input_get_all_properties; + return api; } From 925c83f982f39e98ff12e84312d9a54b4221713f Mon Sep 17 00:00:00 2001 From: Ilia Petrov Date: Wed, 1 Jul 2026 16:06:46 +0300 Subject: [PATCH 14/14] input: add a comment for flb_input_get_all_properties Signed-off-by: Ilia Petrov --- src/flb_input.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/flb_input.c b/src/flb_input.c index 5a9d466b054..e4e3a0008ab 100644 --- a/src/flb_input.c +++ b/src/flb_input.c @@ -952,6 +952,13 @@ const char *flb_input_get_property(const char *key, return flb_config_prop_get(key, &ins->properties); } +/* +* Return a heap-allocated array of pointers to every property configured on +* 'ins'. The caller owns the array and must release it with flb_free(); the +* underlying flb_kv entries remain owned by the input instance. 'out_count' +* (optional) receives the number of properties. Returns NULL when the +* instance has no properties or on allocation failure. +*/ struct flb_kv **flb_input_get_all_properties(struct flb_input_instance *ins, int *out_count) {