diff --git a/plugins/in_tail/tail.c b/plugins/in_tail/tail.c index eb81a813d64..fcdad909e43 100644 --- a/plugins/in_tail/tail.c +++ b/plugins/in_tail/tail.c @@ -569,6 +569,19 @@ static void in_tail_pause(void *data, struct flb_config *config) /* Pause file system backend handlers */ flb_tail_fs_pause(ctx); + +#ifdef FLB_HAVE_PARSER + if (config->is_shutting_down == FLB_TRUE && ctx->ml_ctx != NULL && + ctx->multiline_shutdown_flushed == FLB_FALSE) { + /* + * Flush while processors, routes and outputs are still alive. Mark + * this first: appending the records can re-enter pause on a buffer + * limit, and the engine also pauses inputs again during teardown. + */ + ctx->multiline_shutdown_flushed = FLB_TRUE; + flb_ml_flush_pending_now(ctx->ml_ctx); + } +#endif } static void in_tail_resume(void *data, struct flb_config *config) @@ -890,5 +903,5 @@ struct flb_input_plugin in_tail_plugin = { .cb_resume = in_tail_resume, .cb_exit = in_tail_exit, .config_map = config_map, - .flags = 0 + .flags = FLB_INPUT_SHUTDOWN_FLUSH }; diff --git a/plugins/in_tail/tail_config.h b/plugins/in_tail/tail_config.h index 6790fe1d3b5..296341544e8 100644 --- a/plugins/in_tail/tail_config.h +++ b/plugins/in_tail/tail_config.h @@ -158,6 +158,7 @@ struct flb_tail_config { /* Multiline core engine */ struct flb_ml *ml_ctx; struct mk_list *multiline_parsers; + int multiline_shutdown_flushed; uint64_t files_static_count; /* number of items in the static file list */ struct mk_list files_static; diff --git a/tests/integration/scenarios/in_tail/config/parsers_tail_it.conf b/tests/integration/scenarios/in_tail/config/parsers_tail_it.conf index 35e44f0649d..57e808b749c 100644 --- a/tests/integration/scenarios/in_tail/config/parsers_tail_it.conf +++ b/tests/integration/scenarios/in_tail/config/parsers_tail_it.conf @@ -30,3 +30,24 @@ Name docker_multiline Format regex Regex (?^{"log":"\d{4}-\d{2}-\d{2}.*) + +# Used by the tail shutdown scenario: the multiline engine flushes buffered +# groups on every timer tick, so this CRI compatible parser pins the flush +# timeout to 60 seconds to keep the pending fragment buffered until shutdown. +[PARSER] + Name cri_test + Format regex + Regex ^(?