Multiline issue with matching repeated lines

I have some data from the IBM nmon Linux/AIX monitoring tool. It's an awkward format with several different delimited and headerless fields. I've managed to create all of its grok patterns and process it (mostly) using the multiline filter.

For example, here's an example of some raw data:

There may be n TOP lines like this before the next timestamp appears, we can't know how many.

The main issue here is that only the first line contains a timestamp, so the event is spread over multiple lines

With some multiline such as:

codec => multiline {
                # Joins all lines between lines with ^ZZZZ into single line.
                # Line feed will still be present in the new 'single' line.
                patterns_dir => "./patterns"
                pattern => "^%{NMON_TOP_LINE}"
                negate => true
                what => previous
filter  {
        mutate {
                #remove \n in message and replaces with LF0A
                gsub => ["message", "\n", "###"]
        } becomes a more manageable (supposedly!) single line:


I'm trying to use these patterns to grok the data:

EOLDATA .*?###
NMON_TOP_LINE TOP,%{NUMBER:PID},%{NMON_TIMETAG:TopTimeTag},%{NUMBER:CPUPercent},%{NUMBER:UsrPercent},%{NUMBER:SysPercent},%{NUMBER:Size},%{NUMBER:ResSet},%{NUMBER:ResText},%{NUMBER:ResData},%{NUMBER:ShdLib},%{NUMBER:MinorFault},%{NUMBER:MajorFault},%{EOLDATA:Command}

and this particular grok line for the final string:


This works fine for one line, but I want to use the same pattern repeatedly, something like:


But that only matches the first line. Same with:


Except this wouldn't work in practice anyway because I won't know how may of these lines will be in the input data.

This works:


and it puts the repeated data into arrays but it really violates the DRY principle and looks ugly, plus like I said I don;t know how many of these I'll need.

How can I re-use the same pattern without overwriting values?