From 3253a191afcf20ccd9156a435d3d7d6a3fb0fff2 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Mon, 24 Aug 2026 15:16:30 +0900 Subject: [PATCH 1/4] log: Make log suppressions rigidly Signed-off-by: Hiroshi Hatake --- include/fluent-bit/flb_log.h | 6 +++++- src/flb_log.c | 13 +++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/fluent-bit/flb_log.h b/include/fluent-bit/flb_log.h index 4d4d1a78cec..7eb4e3a75d8 100644 --- a/include/fluent-bit/flb_log.h +++ b/include/fluent-bit/flb_log.h @@ -193,6 +193,9 @@ struct flb_log_cache_entry *flb_log_cache_exists(struct flb_log_cache *cache, ch struct flb_log_cache_entry *flb_log_cache_get_target(struct flb_log_cache *cache, uint64_t ts); int flb_log_cache_check_suppress(struct flb_log_cache *cache, char *msg_buf, size_t msg_size); +int flb_log_cache_check_suppress_interval(struct flb_log_cache *cache, + char *msg_buf, size_t msg_size, + int interval_seconds); static inline int flb_log_suppress_check(int log_suppress_interval, const char *fmt, ...) @@ -220,7 +223,8 @@ static inline int flb_log_suppress_check(int log_suppress_interval, const char * return FLB_FALSE; } - ret = flb_log_cache_check_suppress(w->log_cache, buf, size); + ret = flb_log_cache_check_suppress_interval(w->log_cache, buf, size, + log_suppress_interval); return ret; } diff --git a/src/flb_log.c b/src/flb_log.c index 8fb090737c9..5268b1f9879 100644 --- a/src/flb_log.c +++ b/src/flb_log.c @@ -695,7 +695,9 @@ struct flb_log_cache_entry *flb_log_cache_get_target(struct flb_log_cache *cache * * if no similar message exists, then the incoming message is added to the cache. */ -int flb_log_cache_check_suppress(struct flb_log_cache *cache, char *msg_buf, size_t msg_size) +int flb_log_cache_check_suppress_interval(struct flb_log_cache *cache, + char *msg_buf, size_t msg_size, + int interval_seconds) { uint64_t now = 0; flb_sds_t buf; @@ -729,7 +731,7 @@ int flb_log_cache_check_suppress(struct flb_log_cache *cache, char *msg_buf, siz return FLB_FALSE; } else { - if (entry->timestamp + cache->timeout > now) { + if (entry->timestamp + interval_seconds > now) { return FLB_TRUE; } else { @@ -740,6 +742,13 @@ int flb_log_cache_check_suppress(struct flb_log_cache *cache, char *msg_buf, siz return FLB_TRUE; } +int flb_log_cache_check_suppress(struct flb_log_cache *cache, + char *msg_buf, size_t msg_size) +{ + return flb_log_cache_check_suppress_interval(cache, msg_buf, msg_size, + cache->timeout); +} + int flb_log_worker_destroy(struct flb_worker *worker) { (void) worker; From 0b465750320db0fad3250bee8942e9f7e04c2d62 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Mon, 24 Aug 2026 15:17:45 +0900 Subject: [PATCH 2/4] tests: internal: Add test cases for rigid approache of log suppressions Signed-off-by: Hiroshi Hatake --- tests/internal/log.c | 55 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/internal/log.c b/tests/internal/log.c index 10b09fb8b49..6ec5cd4d870 100644 --- a/tests/internal/log.c +++ b/tests/internal/log.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "flb_tests_internal.h" @@ -164,8 +165,62 @@ static void cache_one_slot() flb_log_cache_destroy(cache); } +static void check_suppress_interval(int cache_timeout, int suppress_interval, + int message_age, int expected) +{ + int ret; + struct flb_worker worker = {0}; + struct flb_worker *previous_worker; + struct flb_log_cache_entry *entry; + + worker.log_cache = flb_log_cache_create(cache_timeout, 1); + TEST_CHECK(worker.log_cache != NULL); + if (!worker.log_cache) { + return; + } + + previous_worker = flb_worker_get(); + FLB_TLS_SET(flb_worker_ctx, &worker); + + ret = flb_log_suppress_check(suppress_interval, TEST_RECORD_01); + TEST_CHECK(ret == FLB_FALSE); + + entry = flb_log_cache_exists(worker.log_cache, + TEST_RECORD_01, TEST_RECORD_01_SIZE); + TEST_CHECK(entry != NULL); + if (entry) { + entry->timestamp = time(NULL) - message_age; + } + + ret = flb_log_suppress_check(suppress_interval, TEST_RECORD_01); + if (!TEST_CHECK(ret == expected)) { + TEST_MSG("cache timeout=%d, suppress interval=%d, message age=%d, " + "expected=%d, actual=%d", + cache_timeout, suppress_interval, message_age, expected, ret); + } + + FLB_TLS_SET(flb_worker_ctx, previous_worker); + flb_log_cache_destroy(worker.log_cache); +} + +static void suppress_interval_longer_than_cache_timeout() +{ + /* A two-second-old message is still within the configured interval. */ + check_suppress_interval(1, 3, 2, FLB_TRUE); +} + +static void suppress_interval_shorter_than_cache_timeout() +{ + /* A two-second-old message is outside the configured interval. */ + check_suppress_interval(3, 1, 2, FLB_FALSE); +} + TEST_LIST = { { "cache_basic_timeout" , cache_basic_timeout }, { "cache_one_slot" , cache_one_slot }, + { "suppress_interval_longer_than_cache_timeout", + suppress_interval_longer_than_cache_timeout }, + { "suppress_interval_shorter_than_cache_timeout", + suppress_interval_shorter_than_cache_timeout }, { 0 } }; From b87caffe9a09019585c91feda55cc8bda0f6a221 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Mon, 24 Aug 2026 18:12:44 +0900 Subject: [PATCH 3/4] log: Store entry-specific intervals Signed-off-by: Hiroshi Hatake --- include/fluent-bit/flb_log.h | 1 + src/flb_log.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/fluent-bit/flb_log.h b/include/fluent-bit/flb_log.h index 7eb4e3a75d8..11fb4831326 100644 --- a/include/fluent-bit/flb_log.h +++ b/include/fluent-bit/flb_log.h @@ -124,6 +124,7 @@ struct flb_log { struct flb_log_cache_entry { flb_sds_t buf; uint64_t timestamp; + int interval; struct mk_list _head; }; diff --git a/src/flb_log.c b/src/flb_log.c index 5268b1f9879..35aeaee67bd 100644 --- a/src/flb_log.c +++ b/src/flb_log.c @@ -676,7 +676,7 @@ struct flb_log_cache_entry *flb_log_cache_get_target(struct flb_log_cache *cache } /* expired entry */ - if (entry->timestamp + cache->timeout < ts) { + if (entry->timestamp + entry->interval <= ts) { return entry; } @@ -728,14 +728,17 @@ int flb_log_cache_check_suppress_interval(struct flb_log_cache *cache, entry->buf = buf; entry->timestamp = now; + entry->interval = interval_seconds; return FLB_FALSE; } else { if (entry->timestamp + interval_seconds > now) { + entry->interval = interval_seconds; return FLB_TRUE; } else { entry->timestamp = now; + entry->interval = interval_seconds; return FLB_FALSE; } } From f55e8543a4ae23a3f148d6502aa96367987fa96c Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Mon, 24 Aug 2026 18:13:12 +0900 Subject: [PATCH 4/4] tests: internal: Add a test case for entry-specific interval Signed-off-by: Hiroshi Hatake --- tests/internal/log.c | 59 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/tests/internal/log.c b/tests/internal/log.c index 6ec5cd4d870..c3ab534e91a 100644 --- a/tests/internal/log.c +++ b/tests/internal/log.c @@ -14,6 +14,9 @@ #define TEST_RECORD_02 "other type of message" #define TEST_RECORD_02_SIZE sizeof(TEST_RECORD_02) - 1 +#define TEST_RECORD_03 "third type of message" +#define TEST_RECORD_03_SIZE sizeof(TEST_RECORD_03) - 1 + static int check_clock(uint64_t timeout, struct flb_time *tm_start) { struct flb_time tm_now; @@ -215,6 +218,60 @@ static void suppress_interval_shorter_than_cache_timeout() check_suppress_interval(3, 1, 2, FLB_FALSE); } +static void suppress_interval_preserved_during_cache_replacement() +{ + int ret; + struct flb_worker worker = {0}; + struct flb_worker *previous_worker; + struct flb_log_cache_entry *entry; + + worker.log_cache = flb_log_cache_create(1, 2); + TEST_CHECK(worker.log_cache != NULL); + if (!worker.log_cache) { + return; + } + + previous_worker = flb_worker_get(); + FLB_TLS_SET(flb_worker_ctx, &worker); + + ret = flb_log_suppress_check(3, TEST_RECORD_01); + TEST_CHECK(ret == FLB_FALSE); + + entry = flb_log_cache_exists(worker.log_cache, + TEST_RECORD_01, TEST_RECORD_01_SIZE); + TEST_CHECK(entry != NULL); + if (entry) { + entry->timestamp = time(NULL) - 2; + } + + ret = flb_log_suppress_check(1, TEST_RECORD_02); + TEST_CHECK(ret == FLB_FALSE); + + entry = flb_log_cache_exists(worker.log_cache, + TEST_RECORD_02, TEST_RECORD_02_SIZE); + TEST_CHECK(entry != NULL); + if (entry) { + entry->timestamp = time(NULL) - 2; + } + + ret = flb_log_suppress_check(3, TEST_RECORD_03); + TEST_CHECK(ret == FLB_FALSE); + + entry = flb_log_cache_exists(worker.log_cache, + TEST_RECORD_03, TEST_RECORD_03_SIZE); + TEST_CHECK(entry != NULL); + + entry = flb_log_cache_exists(worker.log_cache, + TEST_RECORD_02, TEST_RECORD_02_SIZE); + TEST_CHECK(entry == NULL); + + ret = flb_log_suppress_check(3, TEST_RECORD_01); + TEST_CHECK(ret == FLB_TRUE); + + FLB_TLS_SET(flb_worker_ctx, previous_worker); + flb_log_cache_destroy(worker.log_cache); +} + TEST_LIST = { { "cache_basic_timeout" , cache_basic_timeout }, { "cache_one_slot" , cache_one_slot }, @@ -222,5 +279,7 @@ TEST_LIST = { suppress_interval_longer_than_cache_timeout }, { "suppress_interval_shorter_than_cache_timeout", suppress_interval_shorter_than_cache_timeout }, + { "suppress_interval_preserved_during_cache_replacement", + suppress_interval_preserved_during_cache_replacement }, { 0 } };