@@ -107,15 +107,40 @@ struct record_check container_mix_input[] = {
107107 {"{\"log\": \"dd-err\\n\", \"stream\": \"stderr\", \"time\": \"2021-02-01T16:45:03.01234z\"}" },
108108};
109109
110+ /*
111+ * The docker parser should emit each container fragment as soon as the log
112+ * stream provides a newline. CRI lines handled by the chained parser are
113+ * expected to flush immediately even if the docker stream still has buffered
114+ * fragments waiting for a later newline (e.g. "bb" + "cc" + "dd-out\n").
115+ */
110116struct record_check container_mix_output [] = {
111117 {"a1\n" },
112118 {"a2\n" },
113119 {"ddee\n" },
114- {"bbccdd-out\n" },
115- {"dd-err\n" },
116120 {"single full" },
117121 {"1a. some multiline log" },
118122 {"1b. some multiline log" },
123+ {"bbccdd-out\n" },
124+ {"dd-err\n" },
125+ };
126+
127+ /*
128+ * Regression guard: when docker is the first parser in the chain and a CRI
129+ * record arrives, the docker parser must decline the line so the CRI parser
130+ * can consume it instead of buffering the payload until the flush timer
131+ * expires. The strings below mimic container runtime output without trailing
132+ * newlines as seen in the reported issue.
133+ */
134+ struct record_check docker_cri_chain_input [] = {
135+ {"2025-09-22T19:07:06.115398289Z stdout F first message" },
136+ {"2025-09-22T19:07:06.116725604Z stdout F second message" },
137+ {"2025-09-22T19:07:08.582112316Z stdout F third message" },
138+ };
139+
140+ struct record_check docker_cri_chain_output [] = {
141+ {"first message" },
142+ {"second message" },
143+ {"third message" },
119144};
120145
121146/* Java stacktrace detection */
@@ -603,6 +628,68 @@ static void test_container_mix()
603628 flb_config_exit (config );
604629}
605630
631+ static void test_parser_docker_cri_chain ()
632+ {
633+ int i ;
634+ int len ;
635+ int ret ;
636+ int entries ;
637+ int expected ;
638+ uint64_t stream_id ;
639+ struct record_check * r ;
640+ struct flb_config * config ;
641+ struct flb_time tm ;
642+ struct flb_ml * ml ;
643+ struct flb_ml_parser_ins * mlp_i ;
644+ struct expected_result res = {0 };
645+
646+ /* Expected results context */
647+ res .key = "log" ;
648+ res .out_records = docker_cri_chain_output ;
649+
650+ /* Initialize environment */
651+ config = flb_config_init ();
652+
653+ /* Create docker multiline mode */
654+ ml = flb_ml_create (config , "docker-cri-chain" );
655+ TEST_CHECK (ml != NULL );
656+
657+ /* Generate an instance of multiline docker parser */
658+ mlp_i = flb_ml_parser_instance_create (ml , "docker" );
659+ TEST_CHECK (mlp_i != NULL );
660+
661+ /* Load instances of the parsers for current 'ml' context */
662+ mlp_i = flb_ml_parser_instance_create (ml , "cri" );
663+ TEST_CHECK (mlp_i != NULL );
664+
665+ ret = flb_ml_stream_create (ml , "docker-cri-chain" , -1 , flush_callback ,
666+ (void * ) & res , & stream_id );
667+ TEST_CHECK (ret == 0 );
668+
669+ entries = sizeof (docker_cri_chain_input ) / sizeof (struct record_check );
670+ for (i = 0 ; i < entries ; i ++ ) {
671+ r = & docker_cri_chain_input [i ];
672+ len = strlen (r -> buf );
673+
674+ flb_time_get (& tm );
675+
676+ /* Package as msgpack */
677+ flb_ml_append_text (ml , stream_id , & tm , r -> buf , len );
678+ }
679+
680+ /* Flush any pending data to ensure no buffered records remain */
681+ flb_ml_flush_pending_now (ml );
682+
683+ expected = sizeof (docker_cri_chain_output ) / sizeof (struct record_check );
684+ TEST_CHECK (res .current_record == expected );
685+
686+ if (ml ) {
687+ flb_ml_destroy (ml );
688+ }
689+
690+ flb_config_exit (config );
691+ }
692+
606693static void test_parser_java ()
607694{
608695 int i ;
@@ -1468,7 +1555,6 @@ static void test_buffer_limit_truncation()
14681555 struct flb_ml * ml ;
14691556 struct flb_ml_parser * mlp ;
14701557 struct flb_ml_parser_ins * mlp_i ;
1471- struct flb_parser * p ;
14721558 struct flb_time tm ;
14731559
14741560 /*
@@ -1561,6 +1647,7 @@ TEST_LIST = {
15611647 /* Normal features tests */
15621648 { "parser_docker" , test_parser_docker },
15631649 { "parser_cri" , test_parser_cri },
1650+ { "parser_docker_cri_chain" , test_parser_docker_cri_chain },
15641651 { "parser_java" , test_parser_java },
15651652 { "parser_python" , test_parser_python },
15661653 { "parser_ruby" , test_parser_ruby },
0 commit comments