@@ -43,6 +43,11 @@ type DockerJSONReader struct {
4343 // parse CRI flags
4444 criflags bool
4545
46+ // maximum number of bytes to use when reassembling partial CRI/docker log lines;
47+ // limits growth while joining fragments but does not cap the size of the initial chunk.
48+ // A value of 0 means no limit is applied during reassembly.
49+ maxBytes int
50+
4651 parseLine func (message * reader.Message , msg * logLine ) error
4752
4853 stripNewLine func (msg * reader.Message )
@@ -60,12 +65,13 @@ type logLine struct {
6065}
6166
6267// New creates a new reader renaming a field
63- func New (r reader.Reader , stream string , partial bool , format string , CRIFlags bool , logger * logp.Logger ) * DockerJSONReader {
68+ func New (r reader.Reader , stream string , partial bool , format string , CRIFlags bool , maxBytes int , logger * logp.Logger ) * DockerJSONReader {
6469 reader := DockerJSONReader {
6570 stream : stream ,
6671 partial : partial ,
6772 reader : r ,
6873 criflags : CRIFlags ,
74+ maxBytes : maxBytes ,
6975 logger : logger .Named ("reader_docker_json" ),
7076 }
7177
@@ -87,12 +93,13 @@ func New(r reader.Reader, stream string, partial bool, format string, CRIFlags b
8793 return & reader
8894}
8995
90- func NewContainerParser (r reader.Reader , config * ContainerJSONConfig , logger * logp.Logger ) * DockerJSONReader {
96+ func NewContainerParser (r reader.Reader , config * ContainerJSONConfig , maxBytes int , logger * logp.Logger ) * DockerJSONReader {
9197 reader := DockerJSONReader {
9298 stream : config .Stream .String (),
9399 partial : true ,
94100 reader : r ,
95101 criflags : true ,
102+ maxBytes : maxBytes ,
96103 logger : logger .Named ("parser_container" ),
97104 }
98105
@@ -233,6 +240,7 @@ func (p *DockerJSONReader) Next() (reader.Message, error) {
233240 }
234241
235242 // Handle multiline messages, join partial lines
243+ truncated := false
236244 for p .partial && logLine .Partial {
237245 next , err := p .reader .Next ()
238246
@@ -248,7 +256,24 @@ func (p *DockerJSONReader) Next() (reader.Message, error) {
248256 p .logger .Errorf ("Parse line error: %v" , err )
249257 continue
250258 }
251- message .Content = append (message .Content , next .Content ... )
259+
260+ // Enforce max_bytes during partial line reassembly to prevent unbounded
261+ // memory growth. Once the limit is reached, drain remaining partial
262+ // chunks (updating the byte counter only) so the reader stays aligned
263+ // to logical line boundaries for the next Next() call.
264+ if truncated {
265+ continue
266+ }
267+ if p .maxBytes > 0 && len (message .Content )+ len (next .Content ) > p .maxBytes {
268+ remaining := p .maxBytes - len (message .Content )
269+ if remaining > 0 {
270+ message .Content = append (message .Content , next .Content [:remaining ]... )
271+ }
272+ _ = message .AddFlagsWithKey ("log.flags" , "truncated" )
273+ truncated = true
274+ } else {
275+ message .Content = append (message .Content , next .Content ... )
276+ }
252277 }
253278
254279 if p .stream != "all" && p .stream != logLine .Stream {
0 commit comments