Problem with the code. Only parsing one grok pattern and not overwriting message field

The reason for the arrays is that you are running multiple grok messages to extract the same fields. After you have run the first grok you have already parsed out timestamp, severity and class and stored everything else in extra. You should use the remaining grok expressions to just parse the extra field, not message. That way you only extract these fields once and avoid arrays.

You can also stop overwriting the message field and potentially also remove the following structure which I see no point in:

if "_grokparsefailure" in [tags] {
                grok {
                        match => {"message" => "%{GREEDYDATA:message}"}
                }
         }